]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #70038 - DutchGhost:const-forget-tests, r=RalfJung
authorMazdak Farrokhzad <twingoow@gmail.com>
Sat, 21 Mar 2020 04:33:18 +0000 (05:33 +0100)
committerGitHub <noreply@github.com>
Sat, 21 Mar 2020 04:33:18 +0000 (05:33 +0100)
Remove the call that makes miri fail

Fixes the concern raised in https://github.com/rust-lang/rust/pull/69645/files#r392884274

cc @RalfJung

1479 files changed:
.github/ISSUE_TEMPLATE/tracking_issue.md
.mailmap
CONTRIBUTING.md
Cargo.lock
README.md
config.toml.example
src/README.md
src/bootstrap/README.md
src/bootstrap/builder.rs
src/bootstrap/channel.rs
src/bootstrap/compile.rs
src/bootstrap/dist.rs
src/bootstrap/flags.rs
src/bootstrap/format.rs
src/bootstrap/native.rs
src/bootstrap/test.rs
src/bootstrap/toolstate.rs
src/ci/azure-pipelines/try.yml
src/ci/docker/mingw-check/Dockerfile
src/ci/docker/x86_64-gnu-llvm-7/Dockerfile
src/ci/publish_toolstate.sh
src/ci/scripts/install-msys2-packages.sh
src/doc/embedded-book
src/doc/index.md
src/doc/nomicon
src/doc/reference
src/doc/robots.txt
src/doc/rust-by-example
src/doc/rustc/src/command-line-arguments.md
src/doc/rustc/src/contributing.md
src/doc/rustdoc/src/advanced-features.md
src/doc/rustdoc/src/command-line-arguments.md
src/doc/rustdoc/src/documentation-tests.md
src/doc/rustdoc/src/unstable-features.md
src/doc/rustdoc/src/what-is-rustdoc.md
src/doc/unstable-book/src/language-features/const-eval-limit.md [new file with mode: 0644]
src/doc/unstable-book/src/language-features/const-in-array-repeat-expressions.md
src/doc/unstable-book/src/language-features/doc-spotlight.md [deleted file]
src/doc/unstable-book/src/language-features/impl-trait-in-bindings.md
src/doc/unstable-book/src/language-features/lang-items.md
src/doc/unstable-book/src/language-features/link-cfg.md [new file with mode: 0644]
src/doc/unstable-book/src/language-features/marker-trait-attr.md
src/doc/unstable-book/src/language-features/trait-alias.md
src/doc/unstable-book/src/language-features/transparent-unions.md
src/doc/unstable-book/src/library-features/read-initializer.md [deleted file]
src/doc/unstable-book/src/library-features/tidy-test-never-used-anywhere-else.md [new file with mode: 0644]
src/liballoc/alloc.rs
src/liballoc/alloc/tests.rs
src/liballoc/boxed.rs
src/liballoc/collections/binary_heap.rs
src/liballoc/collections/btree/map.rs
src/liballoc/collections/btree/node.rs
src/liballoc/collections/linked_list.rs
src/liballoc/collections/mod.rs
src/liballoc/collections/vec_deque.rs
src/liballoc/fmt.rs
src/liballoc/lib.rs
src/liballoc/raw_vec.rs
src/liballoc/raw_vec/tests.rs
src/liballoc/rc.rs
src/liballoc/string.rs
src/liballoc/sync.rs
src/liballoc/tests/btree/map.rs
src/liballoc/tests/heap.rs
src/liballoc/tests/slice.rs
src/liballoc/vec.rs
src/libcore/alloc.rs
src/libcore/cell.rs
src/libcore/convert/mod.rs
src/libcore/fmt/float.rs
src/libcore/fmt/mod.rs
src/libcore/fmt/num.rs
src/libcore/future/future.rs
src/libcore/future/mod.rs
src/libcore/hash/sip.rs
src/libcore/intrinsics.rs
src/libcore/iter/adapters/flatten.rs
src/libcore/iter/adapters/mod.rs
src/libcore/iter/mod.rs
src/libcore/iter/traits/exact_size.rs
src/libcore/iter/traits/iterator.rs
src/libcore/lib.rs
src/libcore/macros/mod.rs
src/libcore/marker.rs
src/libcore/mem/manually_drop.rs
src/libcore/mem/maybe_uninit.rs
src/libcore/mem/mod.rs
src/libcore/num/f32.rs
src/libcore/num/f64.rs
src/libcore/num/i128.rs
src/libcore/num/i16.rs
src/libcore/num/i32.rs
src/libcore/num/i64.rs
src/libcore/num/i8.rs
src/libcore/num/int_macros.rs
src/libcore/num/isize.rs
src/libcore/num/mod.rs
src/libcore/num/u128.rs
src/libcore/num/u16.rs
src/libcore/num/u32.rs
src/libcore/num/u64.rs
src/libcore/num/u8.rs
src/libcore/num/uint_macros.rs [deleted file]
src/libcore/num/usize.rs
src/libcore/ops/arith.rs
src/libcore/ops/generator.rs
src/libcore/ops/mod.rs
src/libcore/option.rs
src/libcore/panicking.rs
src/libcore/pin.rs
src/libcore/prelude/v1.rs
src/libcore/ptr/const_ptr.rs
src/libcore/ptr/mod.rs
src/libcore/ptr/mut_ptr.rs
src/libcore/slice/mod.rs
src/libcore/str/mod.rs
src/libcore/str/pattern.rs
src/libcore/sync/atomic.rs
src/libcore/tests/alloc.rs
src/libcore/tests/hash/sip.rs
src/libcore/tests/iter.rs
src/libcore/tests/lib.rs
src/libcore/unicode/printable.rs
src/libcore/unicode/unicode_data.rs
src/libfmt_macros/lib.rs
src/libpanic_abort/lib.rs
src/libpanic_unwind/dummy.rs
src/libpanic_unwind/emcc.rs
src/libpanic_unwind/gcc.rs
src/libpanic_unwind/hermit.rs
src/libpanic_unwind/lib.rs
src/libpanic_unwind/miri.rs [new file with mode: 0644]
src/libpanic_unwind/seh.rs
src/libproc_macro/bridge/client.rs
src/libproc_macro/diagnostic.rs
src/libproc_macro/lib.rs
src/librustc/Cargo.toml
src/librustc/README.md
src/librustc/arena.rs
src/librustc/dep_graph/README.md
src/librustc/dep_graph/dep_node.rs
src/librustc/dep_graph/graph.rs
src/librustc/dep_graph/mod.rs
src/librustc/hir/map/blocks.rs
src/librustc/hir/map/collector.rs
src/librustc/hir/map/definitions.rs
src/librustc/hir/map/hir_id_validator.rs
src/librustc/hir/map/mod.rs
src/librustc/hir/mod.rs
src/librustc/ich/hcx.rs
src/librustc/ich/impls_hir.rs
src/librustc/ich/impls_syntax.rs
src/librustc/infer/canonical.rs
src/librustc/lib.rs
src/librustc/lint.rs
src/librustc/middle/codegen_fn_attrs.rs
src/librustc/middle/cstore.rs
src/librustc/middle/dependency_format.rs
src/librustc/middle/lang_items.rs
src/librustc/middle/limits.rs [new file with mode: 0644]
src/librustc/middle/mod.rs
src/librustc/middle/recursion_limit.rs [deleted file]
src/librustc/middle/region.rs
src/librustc/middle/stability.rs
src/librustc/mir/interpret/allocation.rs
src/librustc/mir/interpret/error.rs
src/librustc/mir/interpret/mod.rs
src/librustc/mir/interpret/pointer.rs
src/librustc/mir/interpret/value.rs
src/librustc/mir/mod.rs
src/librustc/mir/mono.rs
src/librustc/mir/visit.rs
src/librustc/query/mod.rs
src/librustc/traits/mod.rs
src/librustc/traits/select.rs
src/librustc/traits/specialization_graph.rs
src/librustc/traits/structural_impls.rs
src/librustc/ty/context.rs
src/librustc/ty/flags.rs
src/librustc/ty/fold.rs
src/librustc/ty/inhabitedness/mod.rs
src/librustc/ty/instance.rs
src/librustc/ty/layout.rs
src/librustc/ty/mod.rs
src/librustc/ty/normalize_erasing_regions.rs
src/librustc/ty/print/mod.rs
src/librustc/ty/print/pretty.rs
src/librustc/ty/query/README.md
src/librustc/ty/query/config.rs
src/librustc/ty/query/keys.rs
src/librustc/ty/query/mod.rs
src/librustc/ty/query/on_disk_cache.rs
src/librustc/ty/query/plumbing.rs
src/librustc/ty/relate.rs
src/librustc/ty/sty.rs
src/librustc/ty/trait_def.rs
src/librustc/ty/util.rs
src/librustc_ast/README.md
src/librustc_ast/ast.rs
src/librustc_ast/attr/mod.rs
src/librustc_ast/lib.rs
src/librustc_ast/mut_visit.rs
src/librustc_ast/node_id.rs
src/librustc_ast/token.rs
src/librustc_ast/tokenstream.rs
src/librustc_ast/util/literal.rs
src/librustc_ast/visit.rs
src/librustc_ast_lowering/expr.rs
src/librustc_ast_lowering/item.rs
src/librustc_ast_lowering/lib.rs
src/librustc_ast_lowering/pat.rs
src/librustc_ast_lowering/path.rs
src/librustc_ast_passes/ast_validation.rs
src/librustc_ast_passes/feature_gate.rs
src/librustc_ast_passes/lib.rs
src/librustc_ast_passes/node_count.rs
src/librustc_ast_passes/show_span.rs
src/librustc_ast_pretty/pprust.rs
src/librustc_attr/builtin.rs
src/librustc_builtin_macros/assert.rs
src/librustc_builtin_macros/cfg_accessible.rs [new file with mode: 0644]
src/librustc_builtin_macros/deriving/generic/mod.rs
src/librustc_builtin_macros/deriving/mod.rs
src/librustc_builtin_macros/format.rs
src/librustc_builtin_macros/global_allocator.rs
src/librustc_builtin_macros/lib.rs
src/librustc_builtin_macros/proc_macro_harness.rs
src/librustc_builtin_macros/source_util.rs
src/librustc_builtin_macros/standard_library_imports.rs
src/librustc_builtin_macros/test.rs
src/librustc_builtin_macros/test_harness.rs
src/librustc_builtin_macros/util.rs
src/librustc_codegen_llvm/README.md
src/librustc_codegen_llvm/abi.rs
src/librustc_codegen_llvm/allocator.rs
src/librustc_codegen_llvm/asm.rs
src/librustc_codegen_llvm/attributes.rs
src/librustc_codegen_llvm/back/archive.rs
src/librustc_codegen_llvm/back/lto.rs
src/librustc_codegen_llvm/back/profiling.rs
src/librustc_codegen_llvm/back/write.rs
src/librustc_codegen_llvm/base.rs
src/librustc_codegen_llvm/builder.rs
src/librustc_codegen_llvm/common.rs
src/librustc_codegen_llvm/context.rs
src/librustc_codegen_llvm/debuginfo/create_scope_map.rs
src/librustc_codegen_llvm/debuginfo/gdb.rs
src/librustc_codegen_llvm/debuginfo/metadata.rs
src/librustc_codegen_llvm/debuginfo/mod.rs
src/librustc_codegen_llvm/debuginfo/namespace.rs
src/librustc_codegen_llvm/debuginfo/source_loc.rs
src/librustc_codegen_llvm/debuginfo/utils.rs
src/librustc_codegen_llvm/declare.rs
src/librustc_codegen_llvm/intrinsic.rs
src/librustc_codegen_llvm/lib.rs
src/librustc_codegen_llvm/llvm/ffi.rs
src/librustc_codegen_llvm/llvm/mod.rs
src/librustc_codegen_llvm/llvm_util.rs
src/librustc_codegen_llvm/type_.rs
src/librustc_codegen_llvm/va_arg.rs
src/librustc_codegen_ssa/README.md
src/librustc_codegen_ssa/back/archive.rs
src/librustc_codegen_ssa/back/link.rs
src/librustc_codegen_ssa/back/linker.rs
src/librustc_codegen_ssa/back/symbol_export.rs
src/librustc_codegen_ssa/back/write.rs
src/librustc_codegen_ssa/base.rs
src/librustc_codegen_ssa/common.rs
src/librustc_codegen_ssa/lib.rs
src/librustc_codegen_ssa/mir/analyze.rs
src/librustc_codegen_ssa/mir/block.rs
src/librustc_codegen_ssa/mir/debuginfo.rs
src/librustc_codegen_ssa/mir/mod.rs
src/librustc_codegen_ssa/mir/operand.rs
src/librustc_codegen_ssa/mir/place.rs
src/librustc_codegen_ssa/traits/backend.rs
src/librustc_codegen_ssa/traits/misc.rs
src/librustc_codegen_ssa/traits/mod.rs
src/librustc_codegen_utils/Cargo.toml
src/librustc_codegen_utils/codegen_backend.rs
src/librustc_codegen_utils/link.rs
src/librustc_codegen_utils/symbol_names.rs
src/librustc_data_structures/box_region.rs
src/librustc_data_structures/frozen.rs [new file with mode: 0644]
src/librustc_data_structures/graph/scc/mod.rs
src/librustc_data_structures/graph/vec_graph/mod.rs
src/librustc_data_structures/graph/vec_graph/tests.rs
src/librustc_data_structures/lib.rs
src/librustc_data_structures/sharded.rs
src/librustc_driver/Cargo.toml
src/librustc_driver/README.md
src/librustc_driver/lib.rs
src/librustc_driver/pretty.rs
src/librustc_error_codes/error_codes.rs
src/librustc_error_codes/error_codes/E0117.md
src/librustc_error_codes/error_codes/E0308.md
src/librustc_error_codes/error_codes/E0326.md
src/librustc_error_codes/error_codes/E0374.md
src/librustc_error_codes/error_codes/E0375.md
src/librustc_error_codes/error_codes/E0376.md
src/librustc_error_codes/error_codes/E0378.md
src/librustc_error_codes/error_codes/E0379.md
src/librustc_error_codes/error_codes/E0380.md
src/librustc_error_codes/error_codes/E0382.md
src/librustc_error_codes/error_codes/E0384.md
src/librustc_error_codes/error_codes/E0390.md
src/librustc_error_codes/error_codes/E0391.md
src/librustc_error_codes/error_codes/E0392.md
src/librustc_error_codes/error_codes/E0393.md
src/librustc_error_codes/error_codes/E0412.md
src/librustc_error_codes/error_codes/E0422.md
src/librustc_error_codes/error_codes/E0423.md
src/librustc_error_codes/error_codes/E0434.md
src/librustc_error_codes/error_codes/E0437.md
src/librustc_error_codes/error_codes/E0438.md
src/librustc_error_codes/error_codes/E0591.md
src/librustc_error_codes/error_codes/E0628.md [new file with mode: 0644]
src/librustc_error_codes/error_codes/E0634.md [new file with mode: 0644]
src/librustc_error_codes/error_codes/E0693.md [new file with mode: 0644]
src/librustc_error_codes/error_codes/E0719.md [new file with mode: 0644]
src/librustc_error_codes/error_codes/E0739.md [new file with mode: 0644]
src/librustc_error_codes/lib.rs
src/librustc_errors/diagnostic_builder.rs
src/librustc_errors/emitter.rs
src/librustc_errors/json.rs
src/librustc_errors/lib.rs
src/librustc_errors/registry.rs
src/librustc_expand/base.rs
src/librustc_expand/config.rs [new file with mode: 0644]
src/librustc_expand/expand.rs
src/librustc_expand/lib.rs
src/librustc_expand/mbe/macro_check.rs
src/librustc_expand/mbe/macro_parser.rs
src/librustc_expand/mbe/macro_rules.rs
src/librustc_expand/mbe/transcribe.rs
src/librustc_expand/module.rs [new file with mode: 0644]
src/librustc_expand/mut_visit/tests.rs
src/librustc_expand/parse/tests.rs
src/librustc_expand/placeholders.rs
src/librustc_expand/proc_macro.rs
src/librustc_feature/active.rs
src/librustc_feature/builtin_attrs.rs
src/librustc_feature/removed.rs
src/librustc_hir/def.rs
src/librustc_hir/hir.rs
src/librustc_hir/hir_id.rs
src/librustc_hir/intravisit.rs
src/librustc_hir/lang_items.rs
src/librustc_hir/lib.rs
src/librustc_hir/print.rs
src/librustc_hir/stable_hash_impls.rs
src/librustc_hir/target.rs
src/librustc_hir/weak_lang_items.rs
src/librustc_incremental/assert_dep_graph.rs
src/librustc_incremental/assert_module_sources.rs
src/librustc_incremental/persist/README.md
src/librustc_incremental/persist/dirty_clean.rs
src/librustc_incremental/persist/file_format.rs
src/librustc_incremental/persist/fs.rs
src/librustc_incremental/persist/load.rs
src/librustc_incremental/persist/save.rs
src/librustc_incremental/persist/work_product.rs
src/librustc_index/lib.rs
src/librustc_index/vec.rs
src/librustc_infer/Cargo.toml
src/librustc_infer/infer/at.rs
src/librustc_infer/infer/canonical/canonicalizer.rs
src/librustc_infer/infer/canonical/mod.rs
src/librustc_infer/infer/canonical/query_response.rs
src/librustc_infer/infer/canonical/substitute.rs
src/librustc_infer/infer/equate.rs
src/librustc_infer/infer/error_reporting/mod.rs
src/librustc_infer/infer/error_reporting/need_type_info.rs
src/librustc_infer/infer/error_reporting/nice_region_error/different_lifetimes.rs
src/librustc_infer/infer/error_reporting/nice_region_error/find_anon_type.rs
src/librustc_infer/infer/error_reporting/nice_region_error/mod.rs
src/librustc_infer/infer/error_reporting/nice_region_error/util.rs
src/librustc_infer/infer/freshen.rs
src/librustc_infer/infer/glb.rs
src/librustc_infer/infer/higher_ranked/README.md
src/librustc_infer/infer/higher_ranked/mod.rs
src/librustc_infer/infer/lexical_region_resolve/README.md
src/librustc_infer/infer/lexical_region_resolve/mod.rs
src/librustc_infer/infer/lub.rs
src/librustc_infer/infer/mod.rs
src/librustc_infer/infer/nll_relate/mod.rs
src/librustc_infer/infer/opaque_types/mod.rs [deleted file]
src/librustc_infer/infer/outlives/env.rs
src/librustc_infer/infer/outlives/mod.rs
src/librustc_infer/infer/region_constraints/README.md
src/librustc_infer/infer/region_constraints/leak_check.rs
src/librustc_infer/infer/region_constraints/mod.rs
src/librustc_infer/infer/resolve.rs
src/librustc_infer/infer/sub.rs
src/librustc_infer/lib.rs
src/librustc_infer/traits/auto_trait.rs [deleted file]
src/librustc_infer/traits/chalk_fulfill.rs [deleted file]
src/librustc_infer/traits/codegen/mod.rs [deleted file]
src/librustc_infer/traits/coherence.rs [deleted file]
src/librustc_infer/traits/engine.rs
src/librustc_infer/traits/error_reporting/mod.rs
src/librustc_infer/traits/error_reporting/on_unimplemented.rs [deleted file]
src/librustc_infer/traits/error_reporting/suggestions.rs [deleted file]
src/librustc_infer/traits/fulfill.rs [deleted file]
src/librustc_infer/traits/misc.rs [deleted file]
src/librustc_infer/traits/mod.rs
src/librustc_infer/traits/object_safety.rs [deleted file]
src/librustc_infer/traits/on_unimplemented.rs [deleted file]
src/librustc_infer/traits/project.rs
src/librustc_infer/traits/query/dropck_outlives.rs [deleted file]
src/librustc_infer/traits/query/evaluate_obligation.rs [deleted file]
src/librustc_infer/traits/query/method_autoderef.rs [deleted file]
src/librustc_infer/traits/query/mod.rs [deleted file]
src/librustc_infer/traits/query/normalize.rs [deleted file]
src/librustc_infer/traits/query/outlives_bounds.rs [deleted file]
src/librustc_infer/traits/query/type_op/ascribe_user_type.rs [deleted file]
src/librustc_infer/traits/query/type_op/custom.rs [deleted file]
src/librustc_infer/traits/query/type_op/eq.rs [deleted file]
src/librustc_infer/traits/query/type_op/implied_outlives_bounds.rs [deleted file]
src/librustc_infer/traits/query/type_op/mod.rs [deleted file]
src/librustc_infer/traits/query/type_op/normalize.rs [deleted file]
src/librustc_infer/traits/query/type_op/outlives.rs [deleted file]
src/librustc_infer/traits/query/type_op/prove_predicate.rs [deleted file]
src/librustc_infer/traits/query/type_op/subtype.rs [deleted file]
src/librustc_infer/traits/select.rs [deleted file]
src/librustc_infer/traits/specialize/mod.rs [deleted file]
src/librustc_infer/traits/specialize/specialization_graph.rs [deleted file]
src/librustc_infer/traits/structural_match.rs [deleted file]
src/librustc_infer/traits/util.rs
src/librustc_infer/traits/wf.rs [deleted file]
src/librustc_interface/Cargo.toml
src/librustc_interface/interface.rs
src/librustc_interface/passes.rs
src/librustc_interface/queries.rs
src/librustc_interface/tests.rs
src/librustc_interface/util.rs
src/librustc_lexer/src/unescape.rs
src/librustc_lint/Cargo.toml
src/librustc_lint/builtin.rs
src/librustc_lint/context.rs
src/librustc_lint/early.rs
src/librustc_lint/internal.rs
src/librustc_lint/late.rs
src/librustc_lint/levels.rs
src/librustc_lint/lib.rs
src/librustc_lint/nonstandard_style.rs
src/librustc_lint/passes.rs
src/librustc_lint/redundant_semicolon.rs
src/librustc_lint/types.rs
src/librustc_lint/unused.rs
src/librustc_macros/src/query.rs
src/librustc_macros/src/symbols.rs
src/librustc_metadata/Cargo.toml
src/librustc_metadata/creader.rs
src/librustc_metadata/dependency_format.rs
src/librustc_metadata/lib.rs
src/librustc_metadata/link_args.rs
src/librustc_metadata/locator.rs
src/librustc_metadata/native_libs.rs
src/librustc_metadata/rmeta/decoder.rs
src/librustc_metadata/rmeta/decoder/cstore_impl.rs
src/librustc_metadata/rmeta/encoder.rs
src/librustc_metadata/rmeta/mod.rs
src/librustc_mir/Cargo.toml
src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs
src/librustc_mir/borrow_check/diagnostics/mod.rs
src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs
src/librustc_mir/borrow_check/diagnostics/region_errors.rs
src/librustc_mir/borrow_check/diagnostics/region_name.rs
src/librustc_mir/borrow_check/facts.rs
src/librustc_mir/borrow_check/invalidation.rs
src/librustc_mir/borrow_check/member_constraints.rs
src/librustc_mir/borrow_check/mod.rs
src/librustc_mir/borrow_check/nll.rs
src/librustc_mir/borrow_check/places_conflict.rs
src/librustc_mir/borrow_check/prefixes.rs
src/librustc_mir/borrow_check/region_infer/mod.rs
src/librustc_mir/borrow_check/region_infer/opaque_types.rs
src/librustc_mir/borrow_check/region_infer/values.rs
src/librustc_mir/borrow_check/type_check/free_region_relations.rs
src/librustc_mir/borrow_check/type_check/input_output.rs
src/librustc_mir/borrow_check/type_check/liveness/polonius.rs
src/librustc_mir/borrow_check/type_check/liveness/trace.rs
src/librustc_mir/borrow_check/type_check/mod.rs
src/librustc_mir/borrow_check/type_check/relate_tys.rs
src/librustc_mir/borrow_check/universal_regions.rs
src/librustc_mir/const_eval/eval_queries.rs
src/librustc_mir/const_eval/fn_queries.rs
src/librustc_mir/const_eval/machine.rs
src/librustc_mir/const_eval/mod.rs
src/librustc_mir/dataflow/generic/cursor.rs
src/librustc_mir/dataflow/generic/engine.rs
src/librustc_mir/dataflow/generic/graphviz.rs
src/librustc_mir/dataflow/generic/mod.rs
src/librustc_mir/dataflow/generic/tests.rs
src/librustc_mir/dataflow/generic/visitor.rs
src/librustc_mir/dataflow/graphviz.rs
src/librustc_mir/dataflow/impls/storage_liveness.rs
src/librustc_mir/dataflow/mod.rs
src/librustc_mir/dataflow/move_paths/builder.rs
src/librustc_mir/dataflow/move_paths/mod.rs
src/librustc_mir/interpret/cast.rs
src/librustc_mir/interpret/eval_context.rs
src/librustc_mir/interpret/intern.rs
src/librustc_mir/interpret/intrinsics.rs
src/librustc_mir/interpret/intrinsics/type_name.rs
src/librustc_mir/interpret/machine.rs
src/librustc_mir/interpret/memory.rs
src/librustc_mir/interpret/mod.rs
src/librustc_mir/interpret/operand.rs
src/librustc_mir/interpret/operator.rs
src/librustc_mir/interpret/place.rs
src/librustc_mir/interpret/snapshot.rs
src/librustc_mir/interpret/step.rs
src/librustc_mir/interpret/terminator.rs
src/librustc_mir/interpret/validity.rs
src/librustc_mir/interpret/visitor.rs
src/librustc_mir/lib.rs
src/librustc_mir/monomorphize/collector.rs
src/librustc_mir/monomorphize/mod.rs
src/librustc_mir/shim.rs
src/librustc_mir/transform/add_retag.rs
src/librustc_mir/transform/check_consts/ops.rs
src/librustc_mir/transform/check_consts/qualifs.rs
src/librustc_mir/transform/check_consts/resolver.rs
src/librustc_mir/transform/check_consts/validation.rs
src/librustc_mir/transform/check_unsafety.rs
src/librustc_mir/transform/const_prop.rs
src/librustc_mir/transform/dump_mir.rs
src/librustc_mir/transform/generator.rs
src/librustc_mir/transform/inline.rs
src/librustc_mir/transform/mod.rs
src/librustc_mir/transform/promote_consts.rs
src/librustc_mir/transform/rustc_peek.rs
src/librustc_mir/transform/simplify.rs
src/librustc_mir/util/elaborate_drops.rs
src/librustc_mir/util/liveness.rs
src/librustc_mir/util/pretty.rs
src/librustc_mir_build/Cargo.toml
src/librustc_mir_build/build/matches/simplify.rs
src/librustc_mir_build/build/matches/test.rs
src/librustc_mir_build/build/mod.rs
src/librustc_mir_build/hair/cx/block.rs
src/librustc_mir_build/hair/cx/expr.rs
src/librustc_mir_build/hair/cx/mod.rs
src/librustc_mir_build/hair/pattern/_match.rs
src/librustc_mir_build/hair/pattern/check_match.rs
src/librustc_mir_build/hair/pattern/const_to_pat.rs
src/librustc_mir_build/hair/pattern/mod.rs
src/librustc_mir_build/lib.rs
src/librustc_mir_build/lints.rs
src/librustc_parse/config.rs [deleted file]
src/librustc_parse/lexer/tokentrees.rs
src/librustc_parse/lib.rs
src/librustc_parse/parser/attr.rs
src/librustc_parse/parser/diagnostics.rs
src/librustc_parse/parser/expr.rs
src/librustc_parse/parser/item.rs
src/librustc_parse/parser/mod.rs
src/librustc_parse/parser/module.rs [deleted file]
src/librustc_parse/parser/pat.rs
src/librustc_parse/parser/path.rs
src/librustc_parse/parser/stmt.rs
src/librustc_parse/parser/ty.rs
src/librustc_parse/validate_attr.rs
src/librustc_passes/Cargo.toml
src/librustc_passes/check_attr.rs
src/librustc_passes/check_const.rs
src/librustc_passes/dead.rs
src/librustc_passes/entry.rs
src/librustc_passes/hir_stats.rs
src/librustc_passes/intrinsicck.rs
src/librustc_passes/lang_items.rs
src/librustc_passes/lib_features.rs
src/librustc_passes/liveness.rs
src/librustc_passes/loops.rs
src/librustc_passes/reachable.rs
src/librustc_passes/region.rs
src/librustc_passes/stability.rs
src/librustc_passes/upvars.rs
src/librustc_passes/weak_lang_items.rs
src/librustc_plugin_impl/Cargo.toml
src/librustc_plugin_impl/load.rs
src/librustc_privacy/Cargo.toml
src/librustc_privacy/lib.rs
src/librustc_resolve/Cargo.toml
src/librustc_resolve/build_reduced_graph.rs
src/librustc_resolve/check_unused.rs
src/librustc_resolve/def_collector.rs
src/librustc_resolve/diagnostics.rs
src/librustc_resolve/imports.rs
src/librustc_resolve/late.rs
src/librustc_resolve/late/diagnostics.rs
src/librustc_resolve/late/lifetimes.rs
src/librustc_resolve/lib.rs
src/librustc_resolve/macros.rs
src/librustc_save_analysis/Cargo.toml
src/librustc_save_analysis/dump_visitor.rs
src/librustc_save_analysis/lib.rs
src/librustc_save_analysis/sig.rs
src/librustc_save_analysis/span_utils.rs
src/librustc_session/code_stats.rs
src/librustc_session/config.rs
src/librustc_session/options.rs
src/librustc_session/session.rs
src/librustc_span/def_id.rs
src/librustc_span/hygiene.rs
src/librustc_span/lib.rs
src/librustc_span/source_map.rs
src/librustc_span/symbol.rs
src/librustc_target/README.md
src/librustc_target/abi/call/mod.rs
src/librustc_target/abi/mod.rs
src/librustc_target/lib.rs
src/librustc_target/spec/aarch64_apple_ios.rs
src/librustc_target/spec/aarch64_apple_tvos.rs [new file with mode: 0644]
src/librustc_target/spec/apple_ios_base.rs [deleted file]
src/librustc_target/spec/apple_sdk_base.rs [new file with mode: 0644]
src/librustc_target/spec/armv7_apple_ios.rs
src/librustc_target/spec/armv7s_apple_ios.rs
src/librustc_target/spec/i386_apple_ios.rs
src/librustc_target/spec/i686_unknown_uefi.rs
src/librustc_target/spec/mod.rs
src/librustc_target/spec/nvptx64_nvidia_cuda.rs
src/librustc_target/spec/windows_base.rs
src/librustc_target/spec/windows_uwp_base.rs
src/librustc_target/spec/x86_64_apple_ios.rs
src/librustc_target/spec/x86_64_apple_ios_macabi.rs
src/librustc_target/spec/x86_64_apple_tvos.rs [new file with mode: 0644]
src/librustc_trait_selection/Cargo.toml [new file with mode: 0644]
src/librustc_trait_selection/infer.rs [new file with mode: 0644]
src/librustc_trait_selection/lib.rs [new file with mode: 0644]
src/librustc_trait_selection/opaque_types.rs [new file with mode: 0644]
src/librustc_trait_selection/traits/auto_trait.rs [new file with mode: 0644]
src/librustc_trait_selection/traits/codegen/mod.rs [new file with mode: 0644]
src/librustc_trait_selection/traits/coherence.rs [new file with mode: 0644]
src/librustc_trait_selection/traits/engine.rs [new file with mode: 0644]
src/librustc_trait_selection/traits/error_reporting/mod.rs [new file with mode: 0644]
src/librustc_trait_selection/traits/error_reporting/on_unimplemented.rs [new file with mode: 0644]
src/librustc_trait_selection/traits/error_reporting/suggestions.rs [new file with mode: 0644]
src/librustc_trait_selection/traits/fulfill.rs [new file with mode: 0644]
src/librustc_trait_selection/traits/misc.rs [new file with mode: 0644]
src/librustc_trait_selection/traits/mod.rs [new file with mode: 0644]
src/librustc_trait_selection/traits/object_safety.rs [new file with mode: 0644]
src/librustc_trait_selection/traits/on_unimplemented.rs [new file with mode: 0644]
src/librustc_trait_selection/traits/project.rs [new file with mode: 0644]
src/librustc_trait_selection/traits/query/dropck_outlives.rs [new file with mode: 0644]
src/librustc_trait_selection/traits/query/evaluate_obligation.rs [new file with mode: 0644]
src/librustc_trait_selection/traits/query/method_autoderef.rs [new file with mode: 0644]
src/librustc_trait_selection/traits/query/mod.rs [new file with mode: 0644]
src/librustc_trait_selection/traits/query/normalize.rs [new file with mode: 0644]
src/librustc_trait_selection/traits/query/outlives_bounds.rs [new file with mode: 0644]
src/librustc_trait_selection/traits/query/type_op/ascribe_user_type.rs [new file with mode: 0644]
src/librustc_trait_selection/traits/query/type_op/custom.rs [new file with mode: 0644]
src/librustc_trait_selection/traits/query/type_op/eq.rs [new file with mode: 0644]
src/librustc_trait_selection/traits/query/type_op/implied_outlives_bounds.rs [new file with mode: 0644]
src/librustc_trait_selection/traits/query/type_op/mod.rs [new file with mode: 0644]
src/librustc_trait_selection/traits/query/type_op/normalize.rs [new file with mode: 0644]
src/librustc_trait_selection/traits/query/type_op/outlives.rs [new file with mode: 0644]
src/librustc_trait_selection/traits/query/type_op/prove_predicate.rs [new file with mode: 0644]
src/librustc_trait_selection/traits/query/type_op/subtype.rs [new file with mode: 0644]
src/librustc_trait_selection/traits/select.rs [new file with mode: 0644]
src/librustc_trait_selection/traits/specialize/mod.rs [new file with mode: 0644]
src/librustc_trait_selection/traits/specialize/specialization_graph.rs [new file with mode: 0644]
src/librustc_trait_selection/traits/structural_match.rs [new file with mode: 0644]
src/librustc_trait_selection/traits/util.rs [new file with mode: 0644]
src/librustc_trait_selection/traits/wf.rs [new file with mode: 0644]
src/librustc_traits/Cargo.toml
src/librustc_traits/chalk_context/mod.rs [deleted file]
src/librustc_traits/chalk_context/program_clauses/builtin.rs [deleted file]
src/librustc_traits/chalk_context/program_clauses/mod.rs [deleted file]
src/librustc_traits/chalk_context/program_clauses/primitive.rs [deleted file]
src/librustc_traits/chalk_context/resolvent_ops.rs [deleted file]
src/librustc_traits/chalk_context/unify.rs [deleted file]
src/librustc_traits/dropck_outlives.rs
src/librustc_traits/evaluate_obligation.rs
src/librustc_traits/generic_types.rs [deleted file]
src/librustc_traits/implied_outlives_bounds.rs
src/librustc_traits/lib.rs
src/librustc_traits/lowering/environment.rs
src/librustc_traits/lowering/mod.rs
src/librustc_traits/normalize_erasing_regions.rs
src/librustc_traits/normalize_projection_ty.rs
src/librustc_traits/type_op.rs
src/librustc_ty/Cargo.toml
src/librustc_ty/common_traits.rs
src/librustc_ty/instance.rs
src/librustc_ty/ty.rs
src/librustc_typeck/Cargo.toml
src/librustc_typeck/README.md
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/_match.rs
src/librustc_typeck/check/autoderef.rs
src/librustc_typeck/check/cast.rs
src/librustc_typeck/check/closure.rs
src/librustc_typeck/check/coercion.rs
src/librustc_typeck/check/compare_method.rs
src/librustc_typeck/check/demand.rs
src/librustc_typeck/check/dropck.rs
src/librustc_typeck/check/expr.rs
src/librustc_typeck/check/generator_interior.rs
src/librustc_typeck/check/intrinsic.rs
src/librustc_typeck/check/method/confirm.rs
src/librustc_typeck/check/method/mod.rs
src/librustc_typeck/check/method/probe.rs
src/librustc_typeck/check/method/suggest.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/op.rs
src/librustc_typeck/check/pat.rs
src/librustc_typeck/check/regionck.rs
src/librustc_typeck/check/upvar.rs
src/librustc_typeck/check/wfcheck.rs
src/librustc_typeck/check/writeback.rs
src/librustc_typeck/check_unused.rs
src/librustc_typeck/coherence/builtin.rs
src/librustc_typeck/coherence/inherent_impls_overlap.rs
src/librustc_typeck/coherence/mod.rs
src/librustc_typeck/coherence/orphan.rs
src/librustc_typeck/coherence/unsafety.rs
src/librustc_typeck/collect.rs
src/librustc_typeck/collect/type_of.rs
src/librustc_typeck/constrained_generic_params.rs
src/librustc_typeck/expr_use_visitor.rs
src/librustc_typeck/impl_wf_check.rs
src/librustc_typeck/impl_wf_check/min_specialization.rs [new file with mode: 0644]
src/librustc_typeck/lib.rs
src/librustc_typeck/mem_categorization.rs
src/librustc_typeck/outlives/implicit_infer.rs
src/librustc_typeck/structured_errors.rs
src/librustc_typeck/variance/constraints.rs
src/librustc_typeck/variance/mod.rs
src/librustc_typeck/variance/terms.rs
src/librustdoc/README.md
src/librustdoc/clean/auto_trait.rs
src/librustdoc/clean/blanket_impl.rs
src/librustdoc/clean/inline.rs
src/librustdoc/clean/mod.rs
src/librustdoc/clean/types.rs
src/librustdoc/clean/utils.rs
src/librustdoc/config.rs
src/librustdoc/core.rs
src/librustdoc/docfs.rs
src/librustdoc/doctree.rs
src/librustdoc/html/format.rs
src/librustdoc/html/highlight.rs
src/librustdoc/html/item_type.rs
src/librustdoc/html/markdown.rs
src/librustdoc/html/render.rs
src/librustdoc/html/render/cache.rs
src/librustdoc/html/sources.rs
src/librustdoc/html/static/main.js
src/librustdoc/html/static/rustdoc.css
src/librustdoc/html/static/themes/dark.css
src/librustdoc/html/static/themes/light.css
src/librustdoc/html/static_files.rs
src/librustdoc/lib.rs
src/librustdoc/passes/calculate_doc_coverage.rs
src/librustdoc/passes/collect_intra_doc_links.rs
src/librustdoc/passes/mod.rs
src/librustdoc/test.rs
src/librustdoc/visit_ast.rs
src/libstd/alloc.rs
src/libstd/backtrace.rs
src/libstd/collections/hash/map.rs
src/libstd/env.rs
src/libstd/error.rs
src/libstd/f32.rs
src/libstd/f64.rs
src/libstd/fs.rs
src/libstd/future.rs
src/libstd/io/cursor.rs
src/libstd/io/mod.rs
src/libstd/io/stdio.rs
src/libstd/keyword_docs.rs
src/libstd/lib.rs
src/libstd/macros.rs
src/libstd/net/addr.rs
src/libstd/net/ip.rs
src/libstd/net/parser.rs
src/libstd/os/linux/fs.rs
src/libstd/panicking.rs
src/libstd/prelude/v1.rs
src/libstd/primitive_docs.rs
src/libstd/sync/mpsc/spsc_queue.rs
src/libstd/sync/mutex.rs
src/libstd/sync/once.rs
src/libstd/sync/rwlock.rs
src/libstd/sys/cloudabi/io.rs
src/libstd/sys/hermit/io.rs
src/libstd/sys/sgx/abi/usercalls/alloc.rs
src/libstd/sys/sgx/io.rs
src/libstd/sys/unix/io.rs
src/libstd/sys/unix/mod.rs
src/libstd/sys/unix/net.rs
src/libstd/sys/unix/process/process_common.rs
src/libstd/sys/unix/stack_overflow.rs
src/libstd/sys/vxworks/io.rs
src/libstd/sys/vxworks/mod.rs
src/libstd/sys/wasi/io.rs
src/libstd/sys/wasm/io.rs
src/libstd/sys/windows/c.rs
src/libstd/sys/windows/io.rs
src/libstd/sys/windows/time.rs
src/libstd/sys_common/backtrace.rs
src/libstd/sys_common/process.rs
src/libstd/sys_common/wtf8.rs
src/libtest/cli.rs
src/libtest/console.rs
src/libtest/formatters/mod.rs
src/libtest/lib.rs
src/libtest/options.rs
src/libtest/stats.rs
src/libtest/test_result.rs
src/libtest/types.rs
src/libunwind/build.rs
src/rtstartup/rsbegin.rs
src/rustllvm/PassWrapper.cpp
src/rustllvm/RustWrapper.cpp
src/stage0.txt
src/test/COMPILER_TESTS.md
src/test/codegen/catch-unwind.rs [new file with mode: 0644]
src/test/codegen/consts.rs
src/test/codegen/debug-column-msvc.rs [new file with mode: 0644]
src/test/codegen/debug-column.rs [new file with mode: 0644]
src/test/codegen/enum-discriminant-value.rs [new file with mode: 0644]
src/test/codegen/remap_path_prefix/main.rs
src/test/codegen/repeat-trusted-len.rs
src/test/codegen/sanitizer-recover.rs
src/test/codegen/try-panic-abort.rs [new file with mode: 0644]
src/test/compile-fail/auxiliary/panic-runtime-lang-items.rs
src/test/compile-fail/chalkify/chalk_initial_program.rs [deleted file]
src/test/compile-fail/chalkify/generic_impls.rs [deleted file]
src/test/compile-fail/chalkify/impl_wf.rs [deleted file]
src/test/compile-fail/chalkify/recursive_where_clause_on_type.rs [deleted file]
src/test/compile-fail/chalkify/type_wf.rs [deleted file]
src/test/debuginfo/no-debug-attribute.rs [deleted file]
src/test/incremental/change_symbol_export_status.rs
src/test/incremental/cyclic-trait-hierarchy.rs
src/test/incremental/hashes/call_expressions.rs
src/test/incremental/hashes/closure_expressions.rs
src/test/incremental/hashes/consts.rs
src/test/incremental/hashes/enum_constructors.rs
src/test/incremental/hashes/enum_defs.rs
src/test/incremental/hashes/exported_vs_not.rs
src/test/incremental/hashes/for_loops.rs
src/test/incremental/hashes/function_interfaces.rs
src/test/incremental/hashes/if_expressions.rs
src/test/incremental/hashes/indexing_expressions.rs
src/test/incremental/hashes/inherent_impls.rs
src/test/incremental/hashes/inline_asm.rs
src/test/incremental/hashes/let_expressions.rs
src/test/incremental/hashes/loop_expressions.rs
src/test/incremental/hashes/match_expressions.rs
src/test/incremental/hashes/panic_exprs.rs
src/test/incremental/hashes/statics.rs
src/test/incremental/hashes/struct_constructors.rs
src/test/incremental/hashes/struct_defs.rs
src/test/incremental/hashes/trait_defs.rs
src/test/incremental/hashes/trait_impls.rs
src/test/incremental/hashes/type_defs.rs
src/test/incremental/hashes/unary_and_binary_exprs.rs
src/test/incremental/hashes/while_let_loops.rs
src/test/incremental/hashes/while_loops.rs
src/test/incremental/ich_method_call_trait_scope.rs
src/test/incremental/ich_nested_items.rs
src/test/incremental/ich_resolve_results.rs
src/test/incremental/inlined_hir_34991/main.rs
src/test/incremental/issue-69596.rs [new file with mode: 0644]
src/test/incremental/source_loc_macros.rs
src/test/incremental/span_hash_stable/auxiliary/sub1.rs
src/test/incremental/span_hash_stable/auxiliary/sub2.rs
src/test/incremental/spans_significant_w_debuginfo.rs
src/test/incremental/string_constant.rs
src/test/incremental/thinlto/cgu_invalidated_when_import_added.rs
src/test/incremental/thinlto/cgu_invalidated_when_import_removed.rs
src/test/incremental/unchecked_dirty_clean.rs
src/test/mir-opt/const-promotion-extern-static.rs
src/test/mir-opt/const_prop/discriminant.rs
src/test/mir-opt/const_prop/issue-66971.rs
src/test/mir-opt/const_prop/read_immutable_static.rs
src/test/mir-opt/generator-tiny.rs [new file with mode: 0644]
src/test/mir-opt/no-drop-for-inactive-variant.rs [new file with mode: 0644]
src/test/mir-opt/remove_fake_borrows.rs
src/test/mir-opt/simplify-locals-removes-unused-consts.rs
src/test/mir-opt/storage_live_dead_in_statics.rs
src/test/pretty/attr-literals.rs
src/test/pretty/delimited-token-groups.rs
src/test/pretty/if-attr.rs [new file with mode: 0644]
src/test/pretty/issue-12590-a.rs
src/test/pretty/issue-4264.pp
src/test/pretty/issue-68710-field-attr-proc-mac-lost.rs
src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs
src/test/run-make-fulldeps/issue-19371/foo.rs
src/test/run-make-fulldeps/issue-69368/Makefile [new file with mode: 0644]
src/test/run-make-fulldeps/issue-69368/a.rs [new file with mode: 0644]
src/test/run-make-fulldeps/issue-69368/b.rs [new file with mode: 0644]
src/test/run-make-fulldeps/issue-69368/c.rs [new file with mode: 0644]
src/test/rustdoc-js-std/return-specific-literal.js [new file with mode: 0644]
src/test/rustdoc-js-std/return-specific.js [new file with mode: 0644]
src/test/rustdoc-ui/coverage/html.rs [new file with mode: 0644]
src/test/rustdoc-ui/coverage/html.stderr [new file with mode: 0644]
src/test/rustdoc-ui/coverage/json.rs [new file with mode: 0644]
src/test/rustdoc-ui/coverage/json.stdout [new file with mode: 0644]
src/test/rustdoc-ui/issue-61732.rs
src/test/rustdoc-ui/issue-61732.stderr
src/test/rustdoc/attributes.rs
src/test/rustdoc/crate-version-escape.rs [new file with mode: 0644]
src/test/rustdoc/doc-spotlight.rs [deleted file]
src/test/rustdoc/issue-26606.rs
src/test/ui-fulldeps/auxiliary/linkage-visibility.rs
src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs
src/test/ui-fulldeps/auxiliary/lint-for-crate.rs
src/test/ui/allocator/custom.rs
src/test/ui/allocator/xcrate-use.rs
src/test/ui/anon-params-denied-2018.rs [deleted file]
src/test/ui/anon-params-denied-2018.stderr [deleted file]
src/test/ui/anon-params-deprecated.fixed [deleted file]
src/test/ui/anon-params-deprecated.rs [deleted file]
src/test/ui/anon-params-deprecated.stderr [deleted file]
src/test/ui/anon-params/anon-params-denied-2018.rs [new file with mode: 0644]
src/test/ui/anon-params/anon-params-denied-2018.stderr [new file with mode: 0644]
src/test/ui/anon-params/anon-params-deprecated.fixed [new file with mode: 0644]
src/test/ui/anon-params/anon-params-deprecated.rs [new file with mode: 0644]
src/test/ui/anon-params/anon-params-deprecated.stderr [new file with mode: 0644]
src/test/ui/anon-params/anon-params-edition-hygiene.rs [new file with mode: 0644]
src/test/ui/anon-params/auxiliary/anon-params-edition-hygiene.rs [new file with mode: 0644]
src/test/ui/asm/issue-62046.rs [new file with mode: 0644]
src/test/ui/asm/issue-62046.stderr [new file with mode: 0644]
src/test/ui/asm/issue-69092.rs [new file with mode: 0644]
src/test/ui/asm/issue-69092.stderr [new file with mode: 0644]
src/test/ui/assign-to-method.rs [deleted file]
src/test/ui/assign-to-method.stderr [deleted file]
src/test/ui/associated-item/associated-item-enum.stderr
src/test/ui/associated-type-bounds/duplicate.stderr
src/test/ui/async-await/async-fn-size-moved-locals.rs
src/test/ui/async-await/async-fn-size-uninit-locals.rs
src/test/ui/async-await/async-fn-size.rs
src/test/ui/async-await/dont-print-desugared-async.stderr
src/test/ui/async-await/expansion-in-attrs.rs [new file with mode: 0644]
src/test/ui/async-await/issue-54239-private-type-triggers-lint.rs [new file with mode: 0644]
src/test/ui/async-await/issues/issue-62009-1.stderr
src/test/ui/async-await/issues/issue-62097.nll.stderr
src/test/ui/async-await/issues/issue-63388-1.nll.stderr
src/test/ui/async-await/no-const-async.stderr
src/test/ui/async-await/no-std.rs [new file with mode: 0644]
src/test/ui/auto-ref-slice-plus-ref.stderr
src/test/ui/auto-trait-validation.stderr
src/test/ui/binding/ambiguity-item.rs [new file with mode: 0644]
src/test/ui/binding/ambiguity-item.stderr [new file with mode: 0644]
src/test/ui/binding/const-param.rs [new file with mode: 0644]
src/test/ui/binding/const-param.stderr [new file with mode: 0644]
src/test/ui/blind/blind-item-block-middle.stderr
src/test/ui/block-expr-precedence.stderr
src/test/ui/block-result/issue-3563.stderr
src/test/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs [new file with mode: 0644]
src/test/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.stderr [new file with mode: 0644]
src/test/ui/chalkify/builtin-copy-clone.rs [deleted file]
src/test/ui/chalkify/inherent_impl.rs [deleted file]
src/test/ui/chalkify/lower_env1.rs [deleted file]
src/test/ui/chalkify/lower_env1.stderr [deleted file]
src/test/ui/chalkify/lower_env2.rs [deleted file]
src/test/ui/chalkify/lower_env2.stderr [deleted file]
src/test/ui/chalkify/lower_env3.rs [deleted file]
src/test/ui/chalkify/lower_env3.stderr [deleted file]
src/test/ui/chalkify/lower_impl.rs [deleted file]
src/test/ui/chalkify/lower_impl.stderr [deleted file]
src/test/ui/chalkify/lower_struct.rs [deleted file]
src/test/ui/chalkify/lower_struct.stderr [deleted file]
src/test/ui/chalkify/lower_trait.rs [deleted file]
src/test/ui/chalkify/lower_trait.stderr [deleted file]
src/test/ui/chalkify/lower_trait_higher_rank.rs [deleted file]
src/test/ui/chalkify/lower_trait_higher_rank.stderr [deleted file]
src/test/ui/chalkify/lower_trait_where_clause.rs [deleted file]
src/test/ui/chalkify/lower_trait_where_clause.stderr [deleted file]
src/test/ui/chalkify/projection.rs [deleted file]
src/test/ui/chalkify/super_trait.rs [deleted file]
src/test/ui/chalkify/trait_implied_bound.rs [deleted file]
src/test/ui/chalkify/type_implied_bound.rs [deleted file]
src/test/ui/chalkify/type_inference.rs [deleted file]
src/test/ui/chalkify/type_inference.stderr [deleted file]
src/test/ui/coherence/coherence-negative-impls-safe.stderr
src/test/ui/conditional-compilation/cfg_accessible-input-validation.rs [new file with mode: 0644]
src/test/ui/conditional-compilation/cfg_accessible-input-validation.stderr [new file with mode: 0644]
src/test/ui/conditional-compilation/cfg_accessible-stuck.rs [new file with mode: 0644]
src/test/ui/conditional-compilation/cfg_accessible-stuck.stderr [new file with mode: 0644]
src/test/ui/conditional-compilation/cfg_accessible-unstable.rs [new file with mode: 0644]
src/test/ui/conditional-compilation/cfg_accessible-unstable.stderr [new file with mode: 0644]
src/test/ui/conditional-compilation/cfg_accessible.rs [new file with mode: 0644]
src/test/ui/conditional-compilation/cfg_accessible.stderr [new file with mode: 0644]
src/test/ui/conflicting-repr-hints.stderr
src/test/ui/const-generics/array-impls/into-iter-no-impls-length-33.stderr
src/test/ui/const-generics/cannot-infer-const-args.stderr
src/test/ui/const-generics/const-generic-type_name.rs
src/test/ui/const-generics/fn-const-param-infer.stderr
src/test/ui/const-generics/issues/issue-62456.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-62456.stderr [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-62504.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-62504.stderr [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-65675.rs [deleted file]
src/test/ui/const-generics/issues/issue-65675.stderr [deleted file]
src/test/ui/const-generics/issues/issue-67739.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-67739.stderr [new file with mode: 0644]
src/test/ui/const-generics/raw-ptr-const-param.rs
src/test/ui/const-generics/raw-ptr-const-param.stderr
src/test/ui/consts/const-eval/const-pointer-values-in-various-types.stderr
src/test/ui/consts/const-eval/const_panic_libcore_main.rs
src/test/ui/consts/const-eval/const_prop_errors.rs
src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr
src/test/ui/consts/const-eval/const_signed_pat.rs
src/test/ui/consts/const-eval/dangling.rs
src/test/ui/consts/const-eval/dangling.stderr
src/test/ui/consts/const-eval/double_check.rs
src/test/ui/consts/const-eval/double_promotion.rs
src/test/ui/consts/const-eval/duration_conversion.rs
src/test/ui/consts/const-eval/extern_fat_pointer.rs
src/test/ui/consts/const-eval/ice-generic-assoc-const.rs
src/test/ui/consts/const-eval/ice-packed.rs
src/test/ui/consts/const-eval/issue-47971.rs
src/test/ui/consts/const-eval/issue-49296.stderr
src/test/ui/consts/const-eval/issue-50706.rs
src/test/ui/consts/const-eval/issue-51300.rs
src/test/ui/consts/const-eval/issue-53157.rs
src/test/ui/consts/const-eval/issue-53401.rs
src/test/ui/consts/const-eval/issue-55541.rs
src/test/ui/consts/const-eval/no_lint_for_statically_known_error.rs
src/test/ui/consts/const-eval/promote_mutable_zst_mir_borrowck.rs
src/test/ui/consts/const-eval/pub_const_err.rs
src/test/ui/consts/const-eval/pub_const_err_bin.rs
src/test/ui/consts/const-eval/simple_with_undef.rs
src/test/ui/consts/const-eval/transmute-const.stderr
src/test/ui/consts/const-eval/ub-enum.rs
src/test/ui/consts/const-eval/ub-enum.stderr
src/test/ui/consts/const-eval/ub-nonnull.rs
src/test/ui/consts/const-eval/ub-nonnull.stderr
src/test/ui/consts/const-eval/ub-ref.rs
src/test/ui/consts/const-eval/ub-ref.stderr
src/test/ui/consts/const-eval/ub-uninhabit.rs
src/test/ui/consts/const-eval/ub-uninhabit.stderr
src/test/ui/consts/const-eval/ub-upvars.stderr
src/test/ui/consts/const-eval/ub-wide-ptr.rs
src/test/ui/consts/const-eval/ub-wide-ptr.stderr
src/test/ui/consts/const-eval/union-ub.stderr
src/test/ui/consts/const-eval/validate_uninhabited_zsts.stderr
src/test/ui/consts/const-eval/zst_operand_eval.rs
src/test/ui/consts/const-int-arithmetic-overflow.rs
src/test/ui/consts/const-int-conversion-rpass.rs
src/test/ui/consts/const-int-unchecked.stderr
src/test/ui/consts/const-points-to-static.stderr
src/test/ui/consts/const_discriminant.rs [new file with mode: 0644]
src/test/ui/consts/const_let_eq.rs
src/test/ui/consts/const_let_eq_float.rs
src/test/ui/consts/const_limit/const_eval_limit_not_reached.rs [new file with mode: 0644]
src/test/ui/consts/const_limit/const_eval_limit_overflow.rs [new file with mode: 0644]
src/test/ui/consts/const_limit/const_eval_limit_overflow.stderr [new file with mode: 0644]
src/test/ui/consts/const_limit/const_eval_limit_reached.rs [new file with mode: 0644]
src/test/ui/consts/const_limit/const_eval_limit_reached.stderr [new file with mode: 0644]
src/test/ui/consts/const_limit/feature-gate-const_eval_limit.rs [new file with mode: 0644]
src/test/ui/consts/const_limit/feature-gate-const_eval_limit.stderr [new file with mode: 0644]
src/test/ui/consts/dangling-alloc-id-ice.stderr
src/test/ui/consts/dangling_raw_ptr.stderr
src/test/ui/consts/issue-63952.stderr
src/test/ui/consts/issue-69191-ice-on-uninhabited-enum-field.rs [new file with mode: 0644]
src/test/ui/consts/min_const_fn/allow_const_fn_ptr_feature_gate.stderr
src/test/ui/consts/miri_unleashed/abi-mismatch.stderr
src/test/ui/consts/miri_unleashed/const_refers_to_static.stderr
src/test/ui/consts/miri_unleashed/mutable_const.stderr
src/test/ui/consts/miri_unleashed/mutable_const2.stderr
src/test/ui/consts/offset_from_ub.stderr
src/test/ui/consts/transmute-size-mismatch-before-typeck.stderr
src/test/ui/consts/validate_never_arrays.stderr
src/test/ui/definition-reachable/nested-fn.rs
src/test/ui/did_you_mean/issue-40006.stderr
src/test/ui/directory_ownership/macro-expanded-mod.rs
src/test/ui/directory_ownership/macro-expanded-mod.stderr
src/test/ui/directory_ownership/non-inline-mod-restriction.stderr
src/test/ui/drop/dynamic-drop.rs
src/test/ui/editions/edition-keywords-2015-2018-expansion.stderr
src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr
src/test/ui/editions/edition-keywords-2018-2018-expansion.stderr
src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr
src/test/ui/enum/enum-discrim-too-small2.stderr
src/test/ui/error-codes/E0121.stderr
src/test/ui/error-codes/E0197.stderr
src/test/ui/error-codes/E0198.stderr
src/test/ui/error-codes/E0396-fixed.stderr
src/test/ui/error-codes/E0583.stderr
src/test/ui/error-codes/E0624.rs
src/test/ui/error-codes/E0624.stderr
src/test/ui/error-codes/E0719.stderr
src/test/ui/explain.stdout
src/test/ui/explore-issue-38412.stderr
src/test/ui/feature-gates/feature-gate-doc_spotlight.rs [deleted file]
src/test/ui/feature-gates/feature-gate-doc_spotlight.stderr [deleted file]
src/test/ui/feature-gates/feature-gate-no-debug-2.rs [deleted file]
src/test/ui/feature-gates/feature-gate-no-debug-2.stderr [deleted file]
src/test/ui/feature-gates/feature-gate-no-debug.rs [deleted file]
src/test/ui/feature-gates/feature-gate-no-debug.stderr [deleted file]
src/test/ui/feature-gates/feature-gate-optin-builtin-traits.stderr
src/test/ui/feature-gates/feature-gate-rustc-attrs-1.stderr
src/test/ui/feature-gates/feature-gate-rustc-attrs.stderr
src/test/ui/fn-in-pat.rs
src/test/ui/fn-in-pat.stderr
src/test/ui/generator-yielding-or-returning-itself.rs [deleted file]
src/test/ui/generator-yielding-or-returning-itself.stderr [deleted file]
src/test/ui/generator/discriminant.rs [new file with mode: 0644]
src/test/ui/generator/generator-yielding-or-returning-itself.rs [new file with mode: 0644]
src/test/ui/generator/generator-yielding-or-returning-itself.stderr [new file with mode: 0644]
src/test/ui/generator/issue-64620-yield-array-element.rs [new file with mode: 0644]
src/test/ui/generator/issue-64620-yield-array-element.stderr [new file with mode: 0644]
src/test/ui/generator/issue-69039.rs
src/test/ui/generator/resume-arg-size.rs [new file with mode: 0644]
src/test/ui/generator/size-moved-locals.rs
src/test/ui/generator/too-many-parameters.stderr
src/test/ui/generic-associated-types/empty_generics.rs
src/test/ui/generic-associated-types/empty_generics.stderr
src/test/ui/hygiene/macro-metavars-legacy.rs [new file with mode: 0644]
src/test/ui/hygiene/macro-metavars-transparent.rs [new file with mode: 0644]
src/test/ui/if-attrs/bad-cfg.rs [new file with mode: 0644]
src/test/ui/if-attrs/bad-cfg.stderr [new file with mode: 0644]
src/test/ui/if-attrs/builtin-if-attr.rs [new file with mode: 0644]
src/test/ui/if-attrs/cfg-false-if-attr.rs [new file with mode: 0644]
src/test/ui/if-attrs/else-attrs.rs [new file with mode: 0644]
src/test/ui/if-attrs/else-attrs.stderr [new file with mode: 0644]
src/test/ui/if-attrs/gate-whole-expr.rs [new file with mode: 0644]
src/test/ui/if-attrs/let-chains-attr.rs [new file with mode: 0644]
src/test/ui/if-attrs/let-chains-attr.stderr [new file with mode: 0644]
src/test/ui/if-attrs/stmt-expr-gated.rs [new file with mode: 0644]
src/test/ui/if-attrs/stmt-expr-gated.stderr [new file with mode: 0644]
src/test/ui/impl-trait/issue-57200.rs [new file with mode: 0644]
src/test/ui/impl-trait/issue-57200.stderr [new file with mode: 0644]
src/test/ui/impl-trait/issue-57201.rs [new file with mode: 0644]
src/test/ui/impl-trait/issue-57201.stderr [new file with mode: 0644]
src/test/ui/impl-trait/issue-60473.rs [new file with mode: 0644]
src/test/ui/impl-trait/issue-60473.stderr [new file with mode: 0644]
src/test/ui/impl-trait/issue-67166.rs [new file with mode: 0644]
src/test/ui/impl-trait/issue-67166.stderr [new file with mode: 0644]
src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs
src/test/ui/imports/issue-55884-2.stderr
src/test/ui/imports/reexports.stderr
src/test/ui/init-large-type.rs
src/test/ui/init-unsafe.rs [deleted file]
src/test/ui/init-unsafe.stderr [deleted file]
src/test/ui/intrinsics/intrinsic-move-val.rs
src/test/ui/intrinsics/intrinsic-uninit.rs [deleted file]
src/test/ui/intrinsics/panic-uninitialized-zeroed.rs [new file with mode: 0644]
src/test/ui/invalid-module-declaration/invalid-module-declaration.stderr
src/test/ui/issues/auxiliary/issue-69725.rs [new file with mode: 0644]
src/test/ui/issues/issue-16683.nll.stderr
src/test/ui/issues/issue-17758.nll.stderr
src/test/ui/issues/issue-20616-8.rs
src/test/ui/issues/issue-20616-8.stderr
src/test/ui/issues/issue-20616-9.rs
src/test/ui/issues/issue-20616-9.stderr
src/test/ui/issues/issue-21174.stderr
src/test/ui/issues/issue-21202.rs
src/test/ui/issues/issue-21202.stderr
src/test/ui/issues/issue-23080-2.rs
src/test/ui/issues/issue-23080-2.stderr
src/test/ui/issues/issue-23080.rs
src/test/ui/issues/issue-23080.stderr
src/test/ui/issues/issue-28344.stderr
src/test/ui/issues/issue-33504.stderr
src/test/ui/issues/issue-3763.rs
src/test/ui/issues/issue-3763.stderr
src/test/ui/issues/issue-40883.rs
src/test/ui/issues/issue-4968.stderr
src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr
src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr
src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr
src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr
src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr
src/test/ui/issues/issue-5100.stderr
src/test/ui/issues/issue-53498.rs
src/test/ui/issues/issue-53498.stderr
src/test/ui/issues/issue-55587.stderr
src/test/ui/issues/issue-63364.stderr
src/test/ui/issues/issue-66473.rs
src/test/ui/issues/issue-66473.stderr
src/test/ui/issues/issue-69396-const-no-type-in-macro.rs [new file with mode: 0644]
src/test/ui/issues/issue-69396-const-no-type-in-macro.stderr [new file with mode: 0644]
src/test/ui/issues/issue-69602-type-err-during-codegen-ice.rs [new file with mode: 0644]
src/test/ui/issues/issue-69602-type-err-during-codegen-ice.stderr [new file with mode: 0644]
src/test/ui/issues/issue-69725.rs [new file with mode: 0644]
src/test/ui/issues/issue-69725.stderr [new file with mode: 0644]
src/test/ui/issues/issue-7867.stderr
src/test/ui/json-bom-plus-crlf-multifile.stderr
src/test/ui/json-bom-plus-crlf.stderr
src/test/ui/keyword/extern/keyword-extern-as-identifier-use.rs
src/test/ui/keyword/extern/keyword-extern-as-identifier-use.stderr
src/test/ui/label/label_break_value_illegal_uses.stderr
src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.nll.stderr
src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.nll.stderr
src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-self-is-anon.nll.stderr
src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.nll.stderr
src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-self-is-anon.nll.stderr
src/test/ui/lint/deny-overflowing-literals.stderr
src/test/ui/lint/issue-69485-var-size-diffs-too-large.rs [new file with mode: 0644]
src/test/ui/lint/issue-69485-var-size-diffs-too-large.stderr [new file with mode: 0644]
src/test/ui/lint/lint-pre-expansion-extern-module.rs [new file with mode: 0644]
src/test/ui/lint/lint-pre-expansion-extern-module.stderr [new file with mode: 0644]
src/test/ui/lint/lint-range-endpoint-overflow.stderr
src/test/ui/lint/lint-type-limits2.stderr
src/test/ui/lint/lint-type-limits3.stderr
src/test/ui/lint/lint-type-overflow.stderr
src/test/ui/lint/lint-type-overflow2.stderr
src/test/ui/lint/lint_pre_expansion_extern_module_aux.rs [new file with mode: 0644]
src/test/ui/lint/redundant-semicolon/redundant-semi-proc-macro.rs
src/test/ui/lint/redundant-semicolon/redundant-semi-proc-macro.stderr
src/test/ui/lint/suggestions.rs
src/test/ui/lint/suggestions.stderr
src/test/ui/lint/type-overflow.stderr
src/test/ui/lint/uninitialized-zeroed.stderr
src/test/ui/lint/use_suggestion_json.stderr
src/test/ui/macro_backtrace/main.-Zmacro-backtrace.stderr
src/test/ui/macros/assert-trailing-junk.rs
src/test/ui/macros/assert-trailing-junk.stderr
src/test/ui/macros/issue-58490.rs [new file with mode: 0644]
src/test/ui/macros/issue-58490.stderr [new file with mode: 0644]
src/test/ui/macros/macro-comma-behavior.core.stderr
src/test/ui/macros/macro-comma-behavior.rs
src/test/ui/macros/macro-comma-behavior.std.stderr
src/test/ui/macros/trace-macro.stderr
src/test/ui/macros/unknown-builtin.rs
src/test/ui/macros/unknown-builtin.stderr
src/test/ui/match/match-fn-call.stderr
src/test/ui/match/match-tag-nullary.stderr
src/test/ui/methods/assign-to-method.rs [new file with mode: 0644]
src/test/ui/methods/assign-to-method.stderr [new file with mode: 0644]
src/test/ui/methods/method-on-ambiguous-numeric-type.stderr
src/test/ui/methods/method-path-in-pattern.rs
src/test/ui/methods/method-path-in-pattern.stderr
src/test/ui/methods/method-resolvable-path-in-pattern.rs
src/test/ui/methods/method-resolvable-path-in-pattern.stderr
src/test/ui/mir/issue-60390.rs [new file with mode: 0644]
src/test/ui/mir/mir_assign_eval_order.rs
src/test/ui/mismatched_types/E0409.stderr
src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod.stderr
src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod_inline.stderr
src/test/ui/mod/mod_file_disambig.rs
src/test/ui/mod/mod_file_disambig.stderr
src/test/ui/never_type/panic-uninitialized-zeroed.rs [deleted file]
src/test/ui/nll/dont-print-desugared.stderr
src/test/ui/nll/issue-54556-used-vs-unused-tails.rs
src/test/ui/nll/outlives-suggestion-simple.rs
src/test/ui/nll/outlives-suggestion-simple.stderr
src/test/ui/nll/user-annotations/type-annotation-with-hrtb.rs [new file with mode: 0644]
src/test/ui/no-landing-pads.rs [deleted file]
src/test/ui/no_owned_box_lang_item.rs
src/test/ui/on-unimplemented/feature-gate-on-unimplemented.stderr
src/test/ui/or-patterns/box-patterns.rs [new file with mode: 0644]
src/test/ui/or-patterns/inconsistent-modes.rs
src/test/ui/or-patterns/inconsistent-modes.stderr
src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs [new file with mode: 0644]
src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr [new file with mode: 0644]
src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier.rs [new file with mode: 0644]
src/test/ui/or-patterns/or-patterns-binding-type-mismatch.stderr
src/test/ui/or-patterns/slice-patterns.rs [new file with mode: 0644]
src/test/ui/panic-runtime/auxiliary/panic-runtime-lang-items.rs
src/test/ui/panic-while-printing.rs [new file with mode: 0644]
src/test/ui/parser/attr-dangling-in-fn.stderr
src/test/ui/parser/attr-stmt-expr-attr-bad.rs
src/test/ui/parser/attr-stmt-expr-attr-bad.stderr
src/test/ui/parser/bad-interpolated-block.rs [new file with mode: 0644]
src/test/ui/parser/bad-interpolated-block.stderr [new file with mode: 0644]
src/test/ui/parser/block-no-opening-brace.rs [new file with mode: 0644]
src/test/ui/parser/block-no-opening-brace.stderr [new file with mode: 0644]
src/test/ui/parser/bounds-lifetime.rs
src/test/ui/parser/bounds-lifetime.stderr
src/test/ui/parser/circular_modules_main.rs
src/test/ui/parser/circular_modules_main.stderr
src/test/ui/parser/closure-return-syntax.rs
src/test/ui/parser/closure-return-syntax.stderr
src/test/ui/parser/column-offset-1-based.rs
src/test/ui/parser/column-offset-1-based.stderr
src/test/ui/parser/doc-before-semi.rs
src/test/ui/parser/doc-before-semi.stderr
src/test/ui/parser/doc-comment-in-if-statement.rs
src/test/ui/parser/doc-comment-in-if-statement.stderr
src/test/ui/parser/fn-body-eq-expr-semi.rs [new file with mode: 0644]
src/test/ui/parser/fn-body-eq-expr-semi.stderr [new file with mode: 0644]
src/test/ui/parser/fn-header-semantic-fail.stderr
src/test/ui/parser/inner-attr-after-doc-comment.stderr
src/test/ui/parser/inner-attr.stderr
src/test/ui/parser/issue-1655.rs
src/test/ui/parser/issue-1655.stderr
src/test/ui/parser/issue-35813-postfix-after-cast.rs [new file with mode: 0644]
src/test/ui/parser/issue-35813-postfix-after-cast.stderr [new file with mode: 0644]
src/test/ui/parser/issue-5806.stderr
src/test/ui/parser/issue-63116.stderr
src/test/ui/parser/issue-63135.rs
src/test/ui/parser/issue-63135.stderr
src/test/ui/parser/issue-68730.rs
src/test/ui/parser/issue-68730.stderr
src/test/ui/parser/issue-68890-2.rs [new file with mode: 0644]
src/test/ui/parser/issue-68890-2.stderr [new file with mode: 0644]
src/test/ui/parser/issue-68890.rs
src/test/ui/parser/issue-68890.stderr
src/test/ui/parser/labeled-no-colon-expr.rs [new file with mode: 0644]
src/test/ui/parser/labeled-no-colon-expr.stderr [new file with mode: 0644]
src/test/ui/parser/macro/trait-object-macro-matcher.rs
src/test/ui/parser/macro/trait-object-macro-matcher.stderr
src/test/ui/parser/mismatched-delim-brace-empty-block.stderr
src/test/ui/parser/mod_file_not_exist.rs
src/test/ui/parser/mod_file_not_exist.stderr
src/test/ui/parser/mod_file_not_exist_windows.rs
src/test/ui/parser/mod_file_not_exist_windows.stderr
src/test/ui/parser/mod_file_with_path_attr.stderr
src/test/ui/parser/recovery-attr-on-if.rs [deleted file]
src/test/ui/parser/recovery-attr-on-if.stderr [deleted file]
src/test/ui/parser/regions-out-of-scope-slice.rs
src/test/ui/parser/regions-out-of-scope-slice.stderr
src/test/ui/parser/stripped-nested-outline-mod-pass.rs [new file with mode: 0644]
src/test/ui/parser/trait-object-lifetime-parens.rs
src/test/ui/parser/trait-object-lifetime-parens.stderr
src/test/ui/parser/trait-object-trait-parens.rs
src/test/ui/parser/trait-object-trait-parens.stderr
src/test/ui/pattern/bindings-after-at/box-patterns.rs [new file with mode: 0644]
src/test/ui/pattern/bindings-after-at/or-patterns-box-patterns.rs [new file with mode: 0644]
src/test/ui/pattern/bindings-after-at/or-patterns-slice-patterns.rs [new file with mode: 0644]
src/test/ui/pattern/bindings-after-at/or-patterns.rs [new file with mode: 0644]
src/test/ui/pattern/bindings-after-at/slice-patterns.rs [new file with mode: 0644]
src/test/ui/pattern/usefulness/always-inhabited-union-ref.rs
src/test/ui/pattern/usefulness/always-inhabited-union-ref.stderr
src/test/ui/privacy/privacy1.rs
src/test/ui/privacy/privacy1.stderr
src/test/ui/privacy/privacy2.stderr
src/test/ui/privacy/private-impl-method.rs
src/test/ui/privacy/private-impl-method.stderr
src/test/ui/privacy/private-method-cross-crate.rs
src/test/ui/privacy/private-method-cross-crate.stderr
src/test/ui/privacy/private-method-inherited.rs
src/test/ui/privacy/private-method-inherited.stderr
src/test/ui/privacy/private-method.rs
src/test/ui/privacy/private-method.stderr
src/test/ui/privacy/restricted/test.stderr
src/test/ui/proc-macro/attribute-spans-preserved.stdout
src/test/ui/proc-macro/auxiliary/derive-unstable.rs
src/test/ui/proc-macro/crt-static.rs [new file with mode: 0644]
src/test/ui/proc-macro/dollar-crate-issue-57089.stdout
src/test/ui/proc-macro/dollar-crate-issue-62325.stdout
src/test/ui/proc-macro/dollar-crate.stdout
src/test/ui/proc-macro/expand-to-unstable-2.stderr
src/test/ui/proc-macro/mixed-site-span.stderr
src/test/ui/proc-macro/multispan.stderr
src/test/ui/proc-macro/span-api-tests.rs
src/test/ui/proc-macro/three-equals.stderr
src/test/ui/qualified/qualified-path-params.rs
src/test/ui/qualified/qualified-path-params.stderr
src/test/ui/range/issue-54505-no-std.rs
src/test/ui/range/issue-54505-no-std.stderr
src/test/ui/realloc-16687.rs
src/test/ui/recursion_limit/empty.rs
src/test/ui/recursion_limit/empty.stderr
src/test/ui/recursion_limit/invalid_digit.rs
src/test/ui/recursion_limit/invalid_digit.stderr
src/test/ui/recursion_limit/overflow.rs
src/test/ui/recursion_limit/overflow.stderr
src/test/ui/recursion_limit/zero.rs
src/test/ui/regions/regions-free-region-ordering-caller.migrate.stderr
src/test/ui/regions/regions-free-region-ordering-caller.rs
src/test/ui/regions/regions-mock-codegen.rs
src/test/ui/repr/repr-align-assign.stderr
src/test/ui/reserved/reserved-attr-on-macro.stderr
src/test/ui/resolve/raw-ident-in-path.rs [new file with mode: 0644]
src/test/ui/resolve/raw-ident-in-path.stderr [new file with mode: 0644]
src/test/ui/resolve/resolve-inconsistent-binding-mode.rs
src/test/ui/resolve/resolve-inconsistent-binding-mode.stderr
src/test/ui/resolve/resolve-inconsistent-names.rs
src/test/ui/resolve/resolve-inconsistent-names.stderr
src/test/ui/rfc-2005-default-binding-mode/const.stderr
src/test/ui/rfc-2005-default-binding-mode/issue-44912-or.rs
src/test/ui/rfc-2005-default-binding-mode/issue-44912-or.stderr
src/test/ui/rfc-2091-track-caller/only-for-fns.stderr
src/test/ui/rfc-2632-const-trait-impl/inherent-impl.stderr
src/test/ui/rust-2018/macro-use-warned-against.rs
src/test/ui/rust-2018/macro-use-warned-against.stderr
src/test/ui/sanitize/address.rs
src/test/ui/sanitize/badfree.rs [new file with mode: 0644]
src/test/ui/sanitize/new-llvm-pass-manager-thin-lto.rs [new file with mode: 0644]
src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.nll.stderr
src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.nll.stderr
src/test/ui/self/elision/lt-ref-self-async.nll.stderr
src/test/ui/self/elision/lt-ref-self.nll.stderr
src/test/ui/self/elision/ref-mut-self-async.nll.stderr
src/test/ui/self/elision/ref-mut-self.nll.stderr
src/test/ui/self/elision/ref-mut-struct-async.nll.stderr
src/test/ui/self/elision/ref-mut-struct.nll.stderr
src/test/ui/self/elision/ref-self.nll.stderr
src/test/ui/self/elision/ref-struct-async.nll.stderr
src/test/ui/self/elision/ref-struct.nll.stderr
src/test/ui/shadowed/shadowed-use-visibility.stderr
src/test/ui/span/auxiliary/transitive_dep_three.rs [new file with mode: 0644]
src/test/ui/span/auxiliary/transitive_dep_two.rs [new file with mode: 0644]
src/test/ui/span/transitive-dep-span.rs [new file with mode: 0644]
src/test/ui/span/transitive-dep-span.stderr [new file with mode: 0644]
src/test/ui/span/type-annotations-needed-expr.stderr
src/test/ui/specialization/defaultimpl/validation.stderr
src/test/ui/specialization/min_specialization/auxiliary/specialization-trait.rs [new file with mode: 0644]
src/test/ui/specialization/min_specialization/dyn-trait-assoc-types.rs [new file with mode: 0644]
src/test/ui/specialization/min_specialization/dyn-trait-assoc-types.stderr [new file with mode: 0644]
src/test/ui/specialization/min_specialization/impl_specialization_trait.rs [new file with mode: 0644]
src/test/ui/specialization/min_specialization/impl_specialization_trait.stderr [new file with mode: 0644]
src/test/ui/specialization/min_specialization/implcit-well-formed-bounds.rs [new file with mode: 0644]
src/test/ui/specialization/min_specialization/repeated_projection_type.rs [new file with mode: 0644]
src/test/ui/specialization/min_specialization/repeated_projection_type.stderr [new file with mode: 0644]
src/test/ui/specialization/min_specialization/repeating_lifetimes.rs [new file with mode: 0644]
src/test/ui/specialization/min_specialization/repeating_lifetimes.stderr [new file with mode: 0644]
src/test/ui/specialization/min_specialization/repeating_param.rs [new file with mode: 0644]
src/test/ui/specialization/min_specialization/repeating_param.stderr [new file with mode: 0644]
src/test/ui/specialization/min_specialization/spec-iter.rs [new file with mode: 0644]
src/test/ui/specialization/min_specialization/spec-reference.rs [new file with mode: 0644]
src/test/ui/specialization/min_specialization/specialization_marker.rs [new file with mode: 0644]
src/test/ui/specialization/min_specialization/specialization_marker.stderr [new file with mode: 0644]
src/test/ui/specialization/min_specialization/specialization_super_trait.rs [new file with mode: 0644]
src/test/ui/specialization/min_specialization/specialization_super_trait.stderr [new file with mode: 0644]
src/test/ui/specialization/min_specialization/specialization_trait.rs [new file with mode: 0644]
src/test/ui/specialization/min_specialization/specialization_trait.stderr [new file with mode: 0644]
src/test/ui/specialization/min_specialization/specialize_on_marker.rs [new file with mode: 0644]
src/test/ui/specialization/min_specialization/specialize_on_spec_trait.rs [new file with mode: 0644]
src/test/ui/specialization/min_specialization/specialize_on_static.rs [new file with mode: 0644]
src/test/ui/specialization/min_specialization/specialize_on_static.stderr [new file with mode: 0644]
src/test/ui/specialization/min_specialization/specialize_on_trait.rs [new file with mode: 0644]
src/test/ui/specialization/min_specialization/specialize_on_trait.stderr [new file with mode: 0644]
src/test/ui/static/static-method-privacy.rs
src/test/ui/static/static-method-privacy.stderr
src/test/ui/suggestions/attribute-typos.stderr
src/test/ui/suggestions/const-in-struct-pat.rs [new file with mode: 0644]
src/test/ui/suggestions/const-in-struct-pat.stderr [new file with mode: 0644]
src/test/ui/suggestions/const-no-type.rs
src/test/ui/suggestions/const-no-type.stderr
src/test/ui/suggestions/suggest-methods.stderr
src/test/ui/syntax-trait-polarity-feature-gate.stderr
src/test/ui/syntax-trait-polarity.stderr
src/test/ui/test-panic-while-printing.rs [new file with mode: 0644]
src/test/ui/tool-attributes/diagnostic_item.stderr
src/test/ui/traits/trait-item-privacy.rs
src/test/ui/traits/trait-item-privacy.stderr
src/test/ui/traits/trait-method-private.stderr
src/test/ui/traits/trait-safety-inherent-impl.stderr
src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.stderr
src/test/ui/transmute/main.stderr
src/test/ui/type-alias-impl-trait/issue-55099-lifetime-inference.rs [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/issue-65918.rs
src/test/ui/type-alias-impl-trait/issue-67844-nested-opaque.rs
src/test/ui/type-inference/or_else-multiple-type-params.stderr
src/test/ui/type-inference/sort_by_key.stderr
src/test/ui/type/ascription/issue-54516.rs
src/test/ui/type/ascription/issue-54516.stderr
src/test/ui/type/ascription/issue-60933.rs
src/test/ui/type/ascription/issue-60933.stderr
src/test/ui/typeck/issue-52082-type-param-shadows-existing-type.rs
src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.stderr
src/test/ui/typeck/typeck-auto-trait-no-supertraits.stderr
src/test/ui/typeck/typeck_type_placeholder_item.stderr
src/test/ui/ufcs/ufcs-partially-resolved.rs
src/test/ui/ufcs/ufcs-partially-resolved.stderr
src/test/ui/unsafe/unsafe-block-without-braces.stderr
src/test/ui/wf/wf-array-elem-sized.rs
src/test/ui/xc-private-method.rs
src/test/ui/xc-private-method.stderr
src/test/ui/xc-private-method2.rs
src/test/ui/xc-private-method2.stderr
src/tools/cargo
src/tools/clippy
src/tools/compiletest/src/errors.rs
src/tools/compiletest/src/header/tests.rs
src/tools/compiletest/src/runtest.rs
src/tools/miri
src/tools/publish_toolstate.py
src/tools/rustdoc-js-std/tester.js
src/tools/rustdoc-js/tester.js
src/tools/tidy/Cargo.toml
src/tools/tidy/src/deps.rs
src/tools/tidy/src/features.rs
src/tools/tidy/src/main.rs
src/tools/tidy/src/pal.rs
src/tools/tidy/src/unstable_book.rs
src/tools/unicode-table-generator/src/main.rs
triagebot.toml

index f93591204cd98cbdff70b5c4341c60d56c105995..9457cce11afbeb3e16022e552dea673f32c1d974 100644 (file)
@@ -36,11 +36,11 @@ for larger features an implementation could be broken up into multiple PRs.
 
 - [ ] Implement the RFC (cc @rust-lang/XXX -- can anyone write up mentoring
       instructions?)
-- [ ] Adjust documentation ([see instructions on rustc-guide][doc-guide])
-- [ ] Stabilization PR ([see instructions on rustc-guide][stabilization-guide])
+- [ ] Adjust documentation ([see instructions on rustc-dev-guide][doc-guide])
+- [ ] Stabilization PR ([see instructions on rustc-dev-guide][stabilization-guide])
 
-[stabilization-guide]: https://rust-lang.github.io/rustc-guide/stabilization_guide.html#stabilization-pr
-[doc-guide]: https://rust-lang.github.io/rustc-guide/stabilization_guide.html#documentation-prs
+[stabilization-guide]: https://rustc-dev-guide.rust-lang.org/stabilization_guide.html#stabilization-pr
+[doc-guide]: https://rustc-dev-guide.rust-lang.org/stabilization_guide.html#documentation-prs
 
 ### Unresolved Questions
 <!--
index e5aad52ef4b792b1d1f52e23a100a5fea6b38f12..78c3c3019af5090e6ef26eed1633bb5fc59cbda3 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -5,7 +5,6 @@
 # email addresses.
 #
 
-Aaron Power <theaaronepower@gmail.com> Erin Power <xampprocky@gmail.com>
 Aaron Todd <github@opprobrio.us>
 Abhishek Chanda <abhishek.becs@gmail.com> Abhishek Chanda <abhishek@cloudscaling.com>
 Adolfo Ochagavía <aochagavia92@gmail.com>
@@ -84,6 +83,8 @@ Eric Holk <eric.holk@gmail.com> <eholk@mozilla.com>
 Eric Holmes <eric@ejholmes.net>
 Eric Reed <ecreed@cs.washington.edu> <ereed@mozilla.com>
 Erick Tryzelaar <erick.tryzelaar@gmail.com> <etryzelaar@iqt.org>
+Erin Power <xampprocky@gmail.com> <theaaronepower@gmail.com>
+Erin Power <xampprocky@gmail.com> <Aaronepower@users.noreply.github.com>
 Esteban Küber <esteban@kuber.com.ar> <esteban@commure.com>
 Esteban Küber <esteban@kuber.com.ar> <estebank@users.noreply.github.com>
 Esteban Küber <esteban@kuber.com.ar> <github@kuber.com.ar>
@@ -171,6 +172,9 @@ Mateusz Mikuła <matti@marinelayer.io> <mati865@gmail.com>
 Mateusz Mikuła <matti@marinelayer.io> <mati865@users.noreply.github.com>
 Matt Brubeck <mbrubeck@limpet.net> <mbrubeck@cs.hmc.edu>
 Matthew Auld <matthew.auld@intel.com>
+Matthew Kraai <kraai@ftbfs.org>
+Matthew Kraai <kraai@ftbfs.org> <matt.kraai@abbott.com>
+Matthew Kraai <kraai@ftbfs.org> <mkraai@its.jnj.com>
 Matthew McPherrin <matthew@mcpherrin.ca> <matt@mcpherrin.ca>
 Matthijs Hofstra <thiezz@gmail.com>
 Melody Horn <melody@boringcactus.com> <mathphreak@gmail.com>
index d6840b20c89ac013d612c527d15fdca7552c825c..2843944b2e1812c10e304756a2c26a8c62735d4f 100644 (file)
@@ -19,7 +19,7 @@ hop on the [Rust Discord server][rust-discord] or [Rust Zulip server][rust-zulip
 
 As a reminder, all contributors are expected to follow our [Code of Conduct][coc].
 
-The [rustc-guide] is your friend! It describes how the compiler works and how
+The [rustc-dev-guide] is your friend! It describes how the compiler works and how
 to contribute to it in more detail than this document.
 
 If this is your first time contributing, the [walkthrough] chapter of the guide
@@ -29,8 +29,8 @@ can give you a good example of how a typical contribution would go.
 [rust-discord]: http://discord.gg/rust-lang
 [rust-zulip]: https://rust-lang.zulipchat.com
 [coc]: https://www.rust-lang.org/conduct.html
-[rustc-guide]: https://rust-lang.github.io/rustc-guide/
-[walkthrough]: https://rust-lang.github.io/rustc-guide/walkthrough.html
+[rustc-dev-guide]: https://rustc-dev-guide.rust-lang.org/
+[walkthrough]: https://rustc-dev-guide.rust-lang.org/walkthrough.html
 
 ## Feature Requests
 [feature-requests]: #feature-requests
@@ -103,12 +103,12 @@ $ RUST_BACKTRACE=1 rustc ...
 ## The Build System
 
 For info on how to configure and build the compiler, please see [this
-chapter][rustcguidebuild] of the rustc-guide. This chapter contains info for
+chapter][rustcguidebuild] of the rustc-dev-guide. This chapter contains info for
 contributions to the compiler and the standard library. It also lists some
 really useful commands to the build system (`./x.py`), which could save you a
 lot of time.
 
-[rustcguidebuild]: https://rust-lang.github.io/rustc-guide/building/how-to-build-and-run.html
+[rustcguidebuild]: https://rustc-dev-guide.rust-lang.org/building/how-to-build-and-run.html
 
 ## Pull Requests
 [pull-requests]: #pull-requests
@@ -142,7 +142,7 @@ the issue in question.
 Please make sure your pull request is in compliance with Rust's style
 guidelines by running
 
-    $ python x.py test src/tools/tidy
+    $ python x.py test tidy
 
 Make this check before every pull request (and every new commit in a pull
 request); you can add [git hooks](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks)
@@ -336,9 +336,9 @@ to check small fixes. For example, `rustdoc src/doc/reference.md` will render
 reference to `doc/reference.html`. The CSS might be messed up, but you can
 verify that the HTML is right.
 
-Additionally, contributions to the [rustc-guide] are always welcome. Contributions
+Additionally, contributions to the [rustc-dev-guide] are always welcome. Contributions
 can be made directly at [the
-rust-lang/rustc-guide](https://github.com/rust-lang/rustc-guide) repo. The issue
+rust-lang/rustc-dev-guide](https://github.com/rust-lang/rustc-dev-guide) repo. The issue
 tracker in that repo is also a great way to find things that need doing. There
 are issues for beginners and advanced compiler devs alike!
 
@@ -434,7 +434,7 @@ For people new to Rust, and just starting to contribute, or even for
 more seasoned developers, some useful places to look for information
 are:
 
-* The [rustc guide] contains information about how various parts of the compiler work and how to contribute to the compiler
+* The [rustc dev guide] contains information about how various parts of the compiler work and how to contribute to the compiler
 * [Rust Forge][rustforge] contains additional documentation, including write-ups of how to achieve common tasks
 * The [Rust Internals forum][rif], a place to ask questions and
   discuss Rust's internals
@@ -448,7 +448,7 @@ are:
 * **Google!** ([search only in Rust Documentation][gsearchdocs] to find types, traits, etc. quickly)
 * Don't be afraid to ask! The Rust community is friendly and helpful.
 
-[rustc guide]: https://rust-lang.github.io/rustc-guide/about-this-guide.html
+[rustc dev guide]: https://rustc-dev-guide.rust-lang.org/about-this-guide.html
 [gdfrustc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/
 [gsearchdocs]: https://www.google.com/search?q=site:doc.rust-lang.org+your+query+here
 [rif]: http://internals.rust-lang.org
@@ -456,5 +456,5 @@ are:
 [rustforge]: https://forge.rust-lang.org/
 [tlgba]: http://tomlee.co/2014/04/a-more-detailed-tour-of-the-rust-compiler/
 [ro]: http://www.rustaceans.org/
-[rctd]: https://rust-lang.github.io/rustc-guide/tests/intro.html
+[rctd]: https://rustc-dev-guide.rust-lang.org/tests/intro.html
 [cheatsheet]: https://buildbot2.rust-lang.org/homu/
index f639095fae75984792f72b3540d1e127eabe740c..1b0516f71613efaf72ff13b62797996a6fa58731 100644 (file)
@@ -281,7 +281,7 @@ dependencies = [
 
 [[package]]
 name = "cargo"
-version = "0.44.0"
+version = "0.45.0"
 dependencies = [
  "anyhow",
  "atty",
@@ -292,7 +292,6 @@ dependencies = [
  "clap",
  "core-foundation 0.7.0",
  "crates-io",
- "crossbeam-channel",
  "crossbeam-utils 0.7.0",
  "crypto-hash",
  "curl",
@@ -338,6 +337,7 @@ dependencies = [
  "termcolor",
  "toml",
  "unicode-width",
+ "unicode-xid 0.2.0",
  "url 2.1.0",
  "walkdir",
  "winapi 0.3.8",
@@ -386,9 +386,9 @@ dependencies = [
 
 [[package]]
 name = "cargo_metadata"
-version = "0.9.0"
+version = "0.9.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8d2d1617e838936c0d2323a65cc151e03ae19a7678dd24f72bccf27119b90a5d"
+checksum = "46e3374c604fb39d1a2f35ed5e4a4e30e60d01fab49446e08f1b3e9a90aef202"
 dependencies = [
  "semver",
  "serde",
@@ -419,25 +419,6 @@ dependencies = [
  "rustc-std-workspace-core",
 ]
 
-[[package]]
-name = "chalk-engine"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "17ec698a6f053a23bfbe646d9f2fde4b02abc19125595270a99e6f44ae0bdd1a"
-dependencies = [
- "chalk-macros",
- "rustc-hash",
-]
-
-[[package]]
-name = "chalk-macros"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "295635afd6853aa9f20baeb7f0204862440c0fe994c5a253d5f479dac41d047e"
-dependencies = [
- "lazy_static 0.2.11",
-]
-
 [[package]]
 name = "chrono"
 version = "0.4.6"
@@ -469,12 +450,11 @@ dependencies = [
 name = "clippy"
 version = "0.0.212"
 dependencies = [
- "cargo_metadata 0.9.0",
+ "cargo_metadata 0.9.1",
  "clippy-mini-macro-test",
  "clippy_lints",
  "compiletest_rs",
  "derive-new",
- "git2",
  "lazy_static 1.4.0",
  "regex",
  "rustc-workspace-hack",
@@ -493,9 +473,9 @@ version = "0.2.0"
 name = "clippy_lints"
 version = "0.0.212"
 dependencies = [
- "cargo_metadata 0.9.0",
+ "cargo_metadata 0.9.1",
  "if_chain",
- "itertools 0.8.0",
+ "itertools 0.9.0",
  "lazy_static 1.4.0",
  "matches",
  "pulldown-cmark 0.7.0",
@@ -1254,9 +1234,9 @@ dependencies = [
 
 [[package]]
 name = "git2"
-version = "0.11.0"
+version = "0.13.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "77519ef7c5beee314d0804d4534f01e0f9e8d9acdee2b7a48627e590b27e0ec4"
+checksum = "b7da16ceafe24cedd9ba02c4463a2b506b6493baf4317c79c5acb553134a3c15"
 dependencies = [
  "bitflags",
  "libc",
@@ -1269,9 +1249,9 @@ dependencies = [
 
 [[package]]
 name = "git2-curl"
-version = "0.12.0"
+version = "0.14.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d2559abb1d87d27668d31bd868a000f0e2e0065d10e78961b62da95d7a7f1cc7"
+checksum = "502d532a2d06184beb3bc869d4d90236e60934e3382c921b203fa3c33e212bd7"
 dependencies = [
  "curl",
  "git2",
@@ -1623,6 +1603,15 @@ dependencies = [
  "either",
 ]
 
+[[package]]
+name = "itertools"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b"
+dependencies = [
+ "either",
+]
+
 [[package]]
 name = "itoa"
 version = "0.4.4"
@@ -1789,9 +1778,9 @@ dependencies = [
 
 [[package]]
 name = "libgit2-sys"
-version = "0.10.0"
+version = "0.12.0+0.99.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9ec6bca50549d34a392611dde775123086acbd994e3fff64954777ce2dc2e51"
+checksum = "05dff41ac39e7b653f5f1550886cf00ba52f8e7f57210b633cdeedb3de5b236c"
 dependencies = [
  "cc",
  "libc",
@@ -2143,7 +2132,7 @@ name = "miri"
 version = "0.1.0"
 dependencies = [
  "byteorder",
- "cargo_metadata 0.9.0",
+ "cargo_metadata 0.9.1",
  "colored",
  "compiletest_rs",
  "directories",
@@ -2156,6 +2145,7 @@ dependencies = [
  "rustc-workspace-hack",
  "rustc_version",
  "serde",
+ "serde_json",
  "shell-escape",
  "vergen",
 ]
@@ -2494,9 +2484,9 @@ checksum = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677"
 
 [[package]]
 name = "polonius-engine"
-version = "0.11.0"
+version = "0.12.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e478d7c38eb785c6416cbe58df12aa55d7aefa3759b6d3e044b2ed03f423cec"
+checksum = "04d8ef65e3f89ecaec9ca7cb0e0911b4617352d4494018bcf934992f03f2024c"
 dependencies = [
  "datafrog",
  "log",
@@ -3110,7 +3100,6 @@ dependencies = [
  "backtrace",
  "bitflags",
  "byteorder",
- "chalk-engine",
  "jobserver",
  "log",
  "measureme",
@@ -3635,6 +3624,7 @@ dependencies = [
  "rustc_data_structures",
  "rustc_hir",
  "rustc_metadata",
+ "rustc_session",
  "rustc_span",
  "rustc_target",
 ]
@@ -3688,6 +3678,7 @@ dependencies = [
  "rustc_parse",
  "rustc_plugin_impl",
  "rustc_save_analysis",
+ "rustc_session",
  "rustc_span",
  "rustc_target",
  "serialize",
@@ -3793,14 +3784,11 @@ dependencies = [
 name = "rustc_infer"
 version = "0.0.0"
 dependencies = [
- "fmt_macros",
  "graphviz",
  "log",
  "rustc",
  "rustc_ast",
- "rustc_attr",
  "rustc_data_structures",
- "rustc_error_codes",
  "rustc_errors",
  "rustc_hir",
  "rustc_index",
@@ -3845,6 +3833,7 @@ dependencies = [
  "rustc_session",
  "rustc_span",
  "rustc_target",
+ "rustc_trait_selection",
  "rustc_traits",
  "rustc_ty",
  "rustc_typeck",
@@ -3879,6 +3868,7 @@ dependencies = [
  "rustc_session",
  "rustc_span",
  "rustc_target",
+ "rustc_trait_selection",
  "unicode-security",
 ]
 
@@ -3910,14 +3900,13 @@ dependencies = [
  "memmap",
  "rustc",
  "rustc_ast",
- "rustc_ast_pretty",
  "rustc_attr",
  "rustc_data_structures",
  "rustc_errors",
  "rustc_expand",
  "rustc_hir",
  "rustc_index",
- "rustc_parse",
+ "rustc_session",
  "rustc_span",
  "rustc_target",
  "serialize",
@@ -3948,8 +3937,10 @@ dependencies = [
  "rustc_infer",
  "rustc_lexer",
  "rustc_macros",
+ "rustc_session",
  "rustc_span",
  "rustc_target",
+ "rustc_trait_selection",
  "serialize",
  "smallvec 1.0.0",
 ]
@@ -3973,6 +3964,7 @@ dependencies = [
  "rustc_session",
  "rustc_span",
  "rustc_target",
+ "rustc_trait_selection",
  "serialize",
  "smallvec 1.0.0",
 ]
@@ -4013,6 +4005,7 @@ dependencies = [
  "rustc_session",
  "rustc_span",
  "rustc_target",
+ "rustc_trait_selection",
 ]
 
 [[package]]
@@ -4025,6 +4018,7 @@ dependencies = [
  "rustc_hir",
  "rustc_lint",
  "rustc_metadata",
+ "rustc_session",
  "rustc_span",
 ]
 
@@ -4039,6 +4033,7 @@ dependencies = [
  "rustc_data_structures",
  "rustc_errors",
  "rustc_hir",
+ "rustc_session",
  "rustc_span",
  "rustc_typeck",
 ]
@@ -4060,7 +4055,6 @@ dependencies = [
  "rustc_expand",
  "rustc_feature",
  "rustc_hir",
- "rustc_infer",
  "rustc_metadata",
  "rustc_session",
  "rustc_span",
@@ -4081,6 +4075,7 @@ dependencies = [
  "rustc_data_structures",
  "rustc_hir",
  "rustc_parse",
+ "rustc_session",
  "rustc_span",
  "serde_json",
 ]
@@ -4140,11 +4135,31 @@ version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b725dadae9fabc488df69a287f5a99c5eaf5d10853842a8a3dfac52476f544ee"
 
+[[package]]
+name = "rustc_trait_selection"
+version = "0.0.0"
+dependencies = [
+ "fmt_macros",
+ "log",
+ "rustc",
+ "rustc_ast",
+ "rustc_attr",
+ "rustc_data_structures",
+ "rustc_errors",
+ "rustc_hir",
+ "rustc_index",
+ "rustc_infer",
+ "rustc_macros",
+ "rustc_session",
+ "rustc_span",
+ "rustc_target",
+ "smallvec 1.0.0",
+]
+
 [[package]]
 name = "rustc_traits"
 version = "0.0.0"
 dependencies = [
- "chalk-engine",
  "log",
  "rustc",
  "rustc_ast",
@@ -4154,6 +4169,7 @@ dependencies = [
  "rustc_macros",
  "rustc_span",
  "rustc_target",
+ "rustc_trait_selection",
  "smallvec 1.0.0",
 ]
 
@@ -4166,8 +4182,10 @@ dependencies = [
  "rustc_data_structures",
  "rustc_hir",
  "rustc_infer",
+ "rustc_session",
  "rustc_span",
  "rustc_target",
+ "rustc_trait_selection",
 ]
 
 [[package]]
@@ -4184,8 +4202,10 @@ dependencies = [
  "rustc_hir",
  "rustc_index",
  "rustc_infer",
+ "rustc_session",
  "rustc_span",
  "rustc_target",
+ "rustc_trait_selection",
  "smallvec 1.0.0",
 ]
 
@@ -4840,10 +4860,9 @@ dependencies = [
 name = "tidy"
 version = "0.1.0"
 dependencies = [
+ "cargo_metadata 0.9.1",
  "lazy_static 1.4.0",
  "regex",
- "serde",
- "serde_json",
  "walkdir",
 ]
 
index 61d3c9e1157203f0c4ed5165608d92294eaca808..1cd9b8a3a2ae1855e6ea2011d23a14ce9957a09d 100644 (file)
--- a/README.md
+++ b/README.md
@@ -15,13 +15,13 @@ Read ["Installation"] from [The Book].
 ## Installing from Source
 
 _Note: If you wish to contribute to the compiler, you should read [this
-chapter][rustcguidebuild] of the rustc-guide instead of this section._
+chapter][rustcguidebuild] of the rustc-dev-guide instead of this section._
 
 The Rust build system has a Python script called `x.py` to bootstrap building
 the compiler. More information about it may be found by running `./x.py --help`
-or reading the [rustc guide][rustcguidebuild].
+or reading the [rustc dev guide][rustcguidebuild].
 
-[rustcguidebuild]: https://rust-lang.github.io/rustc-guide/building/how-to-build-and-run.html
+[rustcguidebuild]: https://rustc-dev-guide.rust-lang.org/building/how-to-build-and-run.html
 
 ### Building on *nix
 1. Make sure you have installed the dependencies:
@@ -249,13 +249,13 @@ Most real-time collaboration happens in a variety of channels on the
 community, documentation, and all major contribution areas in the Rust ecosystem.
 A good place to ask for help would be the #help channel.
 
-The [rustc guide] might be a good place to start if you want to find out how
+The [rustc dev 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
-[rustc guide]: https://rust-lang.github.io/rustc-guide/about-this-guide.html
+[rustc dev guide]: https://rustc-dev-guide.rust-lang.org/about-this-guide.html
 [rustdocs]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/
 
 ## License
index 9b7327ea69e0b1663f3c83b5ed6f9f0bacf36ed0..ce21b63467f53f566b302a3021479f42e49ca066 100644 (file)
 # `0` - no debug info
 # `1` - line tables only
 # `2` - full debug info with variable and type information
-# Can be overriden for specific subsets of Rust code (rustc, std or tools).
+# Can be overridden for specific subsets of Rust code (rustc, std or tools).
 # Debuginfo for tests run with compiletest is not controlled by this option
 # and needs to be enabled separately with `debuginfo-level-tests`.
 #debuginfo-level = if debug { 2 } else { 0 }
index 2f7cf90c5f0305b433880a533ed6fd26621255e7..b69a92a723778b4b4224dfc37e1f85fb40c92cdb 100644 (file)
@@ -3,6 +3,6 @@ This directory contains the source code of the rust project, including:
 - `libstd`
 - Various submodules for tools, like rustdoc, rls, etc.
 
-For more information on how various parts of the compiler work, see the [rustc guide].
+For more information on how various parts of the compiler work, see the [rustc dev guide].
 
-[rustc guide]: https://rust-lang.github.io/rustc-guide/about-this-guide.html
+[rustc dev guide]: https://rustc-dev-guide.rust-lang.org/about-this-guide.html
index c501378bff5491b0bba6cb39a3738f7e7f5845f4..87da7327fe619b433fb1af2756360c1ee601240f 100644 (file)
@@ -55,6 +55,9 @@ The script accepts commands, flags, and arguments to determine what to do:
   # run all unit tests
   ./x.py test
 
+  # execute tool tests
+  ./x.py test tidy
+
   # execute the UI test suite
   ./x.py test src/test/ui
 
index e4b57cddfb891e86e1ed005d0e996216e230010f..602e4511ea583c82414e7d718406772cf10f61a7 100644 (file)
@@ -725,7 +725,7 @@ pub fn cargo(
             self.clear_if_dirty(&my_out, &rustdoc);
         }
 
-        cargo.env("CARGO_TARGET_DIR", &out_dir).arg(cmd).arg("-Zconfig-profile");
+        cargo.env("CARGO_TARGET_DIR", &out_dir).arg(cmd);
 
         let profile_var = |name: &str| {
             let profile = if self.config.rust_optimize { "RELEASE" } else { "DEV" };
@@ -847,13 +847,7 @@ pub fn cargo(
             rustflags.arg("-Zforce-unstable-if-unmarked");
         }
 
-        // cfg(bootstrap): the flag was renamed from `-Zexternal-macro-backtrace`
-        // to `-Zmacro-backtrace`, keep only the latter after beta promotion.
-        if stage == 0 {
-            rustflags.arg("-Zexternal-macro-backtrace");
-        } else {
-            rustflags.arg("-Zmacro-backtrace");
-        }
+        rustflags.arg("-Zmacro-backtrace");
 
         let want_rustdoc = self.doc_tests != DocTests::No;
 
index 504cba45570c17faf8d171e02a2120a50df9ea0a..be2b0f36d14a7ef0a2d002d3ce1c73cc5df68bc4 100644 (file)
@@ -13,7 +13,7 @@
 use crate::Build;
 
 // The version number
-pub const CFG_RELEASE_NUM: &str = "1.43.0";
+pub const CFG_RELEASE_NUM: &str = "1.44.0";
 
 pub struct GitInfo {
     inner: Option<Info>,
index 7dded96e18efde448effb85f955c42128f61a0ea..65a00db33949ed8037ab26c83b5257d28cf9e10b 100644 (file)
@@ -141,7 +141,7 @@ fn copy_third_party_objects(
         copy_and_stamp(&srcdir, "crt1.o");
     }
 
-    // Copies libunwind.a compiled to be linked wit x86_64-fortanix-unknown-sgx.
+    // Copies libunwind.a compiled to be linked with x86_64-fortanix-unknown-sgx.
     //
     // This target needs to be linked to Fortanix's port of llvm's libunwind.
     // libunwind requires support for rwlock and printing to stderr,
index 76478abd0dea78ecbab27b65ce8c9edecfca6f9a..8215211ea1c9d7fb9683b631198d27826989e819 100644 (file)
@@ -1002,8 +1002,6 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
             "src/tools/rustc-std-workspace-core",
             "src/tools/rustc-std-workspace-alloc",
             "src/tools/rustc-std-workspace-std",
-            "src/librustc",
-            "src/librustc_ast",
         ];
 
         copy_src_dirs(builder, &std_src_dirs[..], &[], &dst_src);
index 516be6a30c235125e546239742d7bb73e56affc4..d8831c6d9e566d34db206c416d1a29000b794e3e 100644 (file)
@@ -33,7 +33,7 @@ pub struct Flags {
     pub rustc_error_format: Option<String>,
     pub dry_run: bool,
 
-    // This overrides the deny-warnings configuation option,
+    // This overrides the deny-warnings configuration option,
     // which passes -Dwarnings to the compiler invocations.
     //
     // true => deny, false => warn
@@ -359,7 +359,7 @@ pub fn parse(args: &[String]) -> Flags {
                 subcommand_help.push_str(
                     "\n
 Arguments:
-    This subcommand accepts a number of paths to directories to tests that
+    This subcommand accepts a number of paths to test directories that
     should be compiled and run. For example:
 
         ./x.py test src/test/ui
@@ -372,6 +372,10 @@ pub fn parse(args: &[String]) -> Flags {
     just like `build src/libstd --stage N` it tests the compiler produced by the previous
     stage.
 
+    Execute tool tests with a tool name argument:
+
+        ./x.py test tidy
+
     If no arguments are passed then the complete artifacts for that stage are
     compiled and tested.
 
index a4acb14ee4b149fdf141441764a8f8a4985dbadc..1616ae15d31d6abc45025c6c4ecd91eaf6cf63b3 100644 (file)
@@ -37,6 +37,9 @@ struct RustfmtConfig {
 }
 
 pub fn format(build: &Build, check: bool) {
+    if build.config.dry_run {
+        return;
+    }
     let mut builder = ignore::types::TypesBuilder::new();
     builder.add_defaults();
     builder.select("rust");
index c22c2a336f1240e16d08d6ed9e80f329d5a215a8..d4d66abd520a12b10dd9146f53e69ec9d2c97e02 100644 (file)
@@ -11,6 +11,7 @@
 use std::env;
 use std::ffi::OsString;
 use std::fs::{self, File};
+use std::io;
 use std::path::{Path, PathBuf};
 use std::process::Command;
 
@@ -54,7 +55,6 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
             }
         }
 
-        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);
@@ -65,40 +65,35 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
 
         let build_llvm_config =
             llvm_config_ret_dir.join(exe("llvm-config", &*builder.config.build));
-        let done_stamp = out_dir.join("llvm-finished-building");
 
-        if done_stamp.exists() {
-            if builder.config.llvm_skip_rebuild {
-                builder.info(
-                    "Warning: \
-                    Using a potentially stale build of LLVM; \
-                    This may not behave well.",
-                );
-                return build_llvm_config;
-            }
+        let stamp = out_dir.join("llvm-finished-building");
+        let stamp = HashStamp::new(stamp, builder.in_tree_llvm_info.sha());
 
-            if let Some(llvm_commit) = llvm_info.sha() {
-                let done_contents = t!(fs::read(&done_stamp));
+        if builder.config.llvm_skip_rebuild && stamp.path.exists() {
+            builder.info(
+                "Warning: \
+                Using a potentially stale build of LLVM; \
+                This may not behave well.",
+            );
+            return build_llvm_config;
+        }
 
-                // If LLVM was already built previously and the submodule's commit didn't change
-                // from the previous build, then no action is required.
-                if done_contents == llvm_commit.as_bytes() {
-                    return build_llvm_config;
-                }
-            } else {
+        if stamp.is_done() {
+            if stamp.hash.is_none() {
                 builder.info(
                     "Could not determine the LLVM submodule commit hash. \
                      Assuming that an LLVM rebuild is not necessary.",
                 );
                 builder.info(&format!(
                     "To force LLVM to rebuild, remove the file `{}`",
-                    done_stamp.display()
+                    stamp.path.display()
                 ));
-                return build_llvm_config;
             }
+            return build_llvm_config;
         }
 
         builder.info(&format!("Building LLVM for {}", target));
+        t!(stamp.remove());
         let _time = util::timeit(&builder);
         t!(fs::create_dir_all(&out_dir));
 
@@ -271,7 +266,7 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
 
         cfg.build();
 
-        t!(fs::write(&done_stamp, llvm_info.sha().unwrap_or("")));
+        t!(stamp.write());
 
         build_llvm_config
     }
@@ -584,17 +579,21 @@ fn run(self, builder: &Builder<'_>) -> Self::Output {
             return runtimes;
         }
 
-        let done_stamp = out_dir.join("sanitizers-finished-building");
-        if done_stamp.exists() {
-            builder.info(&format!(
-                "Assuming that sanitizers rebuild is not necessary. \
-                To force a rebuild, remove the file `{}`",
-                done_stamp.display()
-            ));
+        let stamp = out_dir.join("sanitizers-finished-building");
+        let stamp = HashStamp::new(stamp, builder.in_tree_llvm_info.sha());
+
+        if stamp.is_done() {
+            if stamp.hash.is_none() {
+                builder.info(&format!(
+                    "Rebuild sanitizers by removing the file `{}`",
+                    stamp.path.display()
+                ));
+            }
             return runtimes;
         }
 
         builder.info(&format!("Building sanitizers for {}", self.target));
+        t!(stamp.remove());
         let _time = util::timeit(&builder);
 
         let mut cfg = cmake::Config::new(&compiler_rt_dir);
@@ -623,8 +622,7 @@ fn run(self, builder: &Builder<'_>) -> Self::Output {
             cfg.build_target(&runtime.cmake_target);
             cfg.build();
         }
-
-        t!(fs::write(&done_stamp, b""));
+        t!(stamp.write());
 
         runtimes
     }
@@ -689,3 +687,41 @@ fn supported_sanitizers(
     }
     result
 }
+
+struct HashStamp {
+    path: PathBuf,
+    hash: Option<Vec<u8>>,
+}
+
+impl HashStamp {
+    fn new(path: PathBuf, hash: Option<&str>) -> Self {
+        HashStamp { path, hash: hash.map(|s| s.as_bytes().to_owned()) }
+    }
+
+    fn is_done(&self) -> bool {
+        match fs::read(&self.path) {
+            Ok(h) => self.hash.as_deref().unwrap_or(b"") == h.as_slice(),
+            Err(e) if e.kind() == io::ErrorKind::NotFound => false,
+            Err(e) => {
+                panic!("failed to read stamp file `{}`: {}", self.path.display(), e);
+            }
+        }
+    }
+
+    fn remove(&self) -> io::Result<()> {
+        match fs::remove_file(&self.path) {
+            Ok(()) => Ok(()),
+            Err(e) => {
+                if e.kind() == io::ErrorKind::NotFound {
+                    Ok(())
+                } else {
+                    Err(e)
+                }
+            }
+        }
+    }
+
+    fn write(&self) -> io::Result<()> {
+        fs::write(&self.path, self.hash.as_deref().unwrap_or(b""))
+    }
+}
index 4cfda606c4bc8a45a4b977a5a8dcbc84ee4de177..aa1d1b7c424130d565db34a9a74c2bde13baaeca 100644 (file)
@@ -391,7 +391,7 @@ fn run(self, builder: &Builder<'_>) {
             // Overwrite bootstrap's `rustc` wrapper overwriting our flags.
             cargo.env("RUSTC_DEBUG_ASSERTIONS", "true");
             // Let cargo-miri know where xargo ended up.
-            cargo.env("XARGO", builder.out.join("bin").join("xargo"));
+            cargo.env("XARGO_CHECK", builder.out.join("bin").join("xargo-check"));
 
             let mut cargo = Command::from(cargo);
             if !try_run(builder, &mut cargo) {
@@ -607,7 +607,6 @@ fn run(self, builder: &Builder<'_>) {
 
 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
 pub struct RustdocJSStd {
-    pub host: Interned<String>,
     pub target: Interned<String>,
 }
 
@@ -621,13 +620,16 @@ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
     }
 
     fn make_run(run: RunConfig<'_>) {
-        run.builder.ensure(RustdocJSStd { host: run.host, target: run.target });
+        run.builder.ensure(RustdocJSStd { target: run.target });
     }
 
     fn run(self, builder: &Builder<'_>) {
         if let Some(ref nodejs) = builder.config.nodejs {
             let mut command = Command::new(nodejs);
-            command.args(&["src/tools/rustdoc-js-std/tester.js", &*self.host]);
+            command
+                .arg(builder.src.join("src/tools/rustdoc-js-std/tester.js"))
+                .arg(builder.doc_out(self.target))
+                .arg(builder.src.join("src/test/rustdoc-js-std"));
             builder.ensure(crate::doc::Std { target: self.target, stage: builder.top_stage });
             builder.run(&mut command);
         } else {
@@ -726,9 +728,6 @@ fn run(self, builder: &Builder<'_>) {
         let mut cmd = builder.tool_cmd(Tool::Tidy);
         cmd.arg(builder.src.join("src"));
         cmd.arg(&builder.initial_cargo);
-        if !builder.config.vendor {
-            cmd.arg("--no-vendor");
-        }
         if builder.is_verbose() {
             cmd.arg("--verbose");
         }
index bb012a38855117e741a9810da13763d8d5ce0c8f..f0e0f92af55fc3e7b2abab1f78cd1eaf3f909c0f 100644 (file)
@@ -6,7 +6,7 @@
 use std::fmt;
 use std::fs;
 use std::io::{Seek, SeekFrom};
-use std::path::PathBuf;
+use std::path::{Path, PathBuf};
 use std::process::Command;
 use std::time;
 
@@ -24,7 +24,7 @@
 
 type ToolstateData = HashMap<Box<str>, ToolState>;
 
-#[derive(Copy, Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
+#[derive(Copy, Clone, Debug, Deserialize, Serialize, PartialEq, Eq, PartialOrd)]
 #[serde(rename_all = "kebab-case")]
 /// Whether a tool can be compiled, tested or neither
 pub enum ToolState {
@@ -143,10 +143,31 @@ fn check_changed_files(toolstates: &HashMap<Box<str>, ToolState>) {
 impl Step for ToolStateCheck {
     type Output = ();
 
-    /// Runs the `linkchecker` tool as compiled in `stage` by the `host` compiler.
+    /// Checks tool state status.
     ///
-    /// This tool in `src/tools` will verify the validity of all our links in the
-    /// documentation to ensure we don't have a bunch of dead ones.
+    /// This is intended to be used in the `checktools.sh` script. To use
+    /// this, set `save-toolstates` in `config.toml` so that tool status will
+    /// be saved to a JSON file. Then, run `x.py test --no-fail-fast` for all
+    /// of the tools to populate the JSON file. After that is done, this
+    /// command can be run to check for any status failures, and exits with an
+    /// error if there are any.
+    ///
+    /// This also handles publishing the results to the `history` directory of
+    /// the toolstate repo https://github.com/rust-lang-nursery/rust-toolstate
+    /// if the env var `TOOLSTATE_PUBLISH` is set. Note that there is a
+    /// *separate* step of updating the `latest.json` file and creating GitHub
+    /// issues and comments in `src/ci/publish_toolstate.sh`, which is only
+    /// performed on master. (The shell/python code is intended to be migrated
+    /// here eventually.)
+    ///
+    /// The rules for failure are:
+    /// * If the PR modifies a tool, the status must be test-pass.
+    ///   NOTE: There is intent to change this, see
+    ///   https://github.com/rust-lang/rust/issues/65000.
+    /// * All "stable" tools must be test-pass on the stable or beta branches.
+    /// * During beta promotion week, a PR is not allowed to "regress" a
+    ///   stable tool. That is, the status is not allowed to get worse
+    ///   (test-pass to test-fail or build-fail).
     fn run(self, builder: &Builder<'_>) {
         if builder.config.dry_run {
             return;
@@ -171,6 +192,8 @@ fn run(self, builder: &Builder<'_>) {
         }
 
         check_changed_files(&toolstates);
+        checkout_toolstate_repo();
+        let old_toolstate = read_old_toolstate();
 
         for (tool, _) in STABLE_TOOLS.iter() {
             let state = toolstates[*tool];
@@ -180,12 +203,33 @@ fn run(self, builder: &Builder<'_>) {
                     did_error = true;
                     eprintln!("error: Tool `{}` should be test-pass but is {}", tool, state);
                 } else if in_beta_week {
-                    did_error = true;
-                    eprintln!(
-                        "error: Tool `{}` should be test-pass but is {} during beta week.",
-                        tool, state
-                    );
+                    let old_state = old_toolstate
+                        .iter()
+                        .find(|ts| ts.tool == *tool)
+                        .expect("latest.json missing tool")
+                        .state();
+                    if state < old_state {
+                        did_error = true;
+                        eprintln!(
+                            "error: Tool `{}` has regressed from {} to {} during beta week.",
+                            tool, old_state, state
+                        );
+                    } else {
+                        // This warning only appears in the logs, which most
+                        // people won't read. It's mostly here for testing and
+                        // debugging.
+                        eprintln!(
+                            "warning: Tool `{}` is not test-pass (is `{}`), \
+                            this should be fixed before beta is branched.",
+                            tool, state
+                        );
+                    }
                 }
+                // `publish_toolstate.py` is responsible for updating
+                // `latest.json` and creating comments/issues warning people
+                // if there is a regression. That all happens in a separate CI
+                // job on the master branch once the PR has passed all tests
+                // on the `auto` branch.
             }
         }
 
@@ -194,7 +238,7 @@ fn run(self, builder: &Builder<'_>) {
         }
 
         if builder.config.channel == "nightly" && env::var_os("TOOLSTATE_PUBLISH").is_some() {
-            commit_toolstate_change(&toolstates, in_beta_week);
+            commit_toolstate_change(&toolstates);
         }
     }
 
@@ -247,6 +291,70 @@ pub fn save_toolstate(&self, tool: &str, state: ToolState) {
     }
 }
 
+fn toolstate_repo() -> String {
+    env::var("TOOLSTATE_REPO")
+        .unwrap_or_else(|_| "https://github.com/rust-lang-nursery/rust-toolstate.git".to_string())
+}
+
+/// Directory where the toolstate repo is checked out.
+const TOOLSTATE_DIR: &str = "rust-toolstate";
+
+/// Checks out the toolstate repo into `TOOLSTATE_DIR`.
+fn checkout_toolstate_repo() {
+    if let Ok(token) = env::var("TOOLSTATE_REPO_ACCESS_TOKEN") {
+        prepare_toolstate_config(&token);
+    }
+    if Path::new(TOOLSTATE_DIR).exists() {
+        eprintln!("Cleaning old toolstate directory...");
+        t!(fs::remove_dir_all(TOOLSTATE_DIR));
+    }
+
+    let status = Command::new("git")
+        .arg("clone")
+        .arg("--depth=1")
+        .arg(toolstate_repo())
+        .arg(TOOLSTATE_DIR)
+        .status();
+    let success = match status {
+        Ok(s) => s.success(),
+        Err(_) => false,
+    };
+    if !success {
+        panic!("git clone unsuccessful (status: {:?})", status);
+    }
+}
+
+/// Sets up config and authentication for modifying the toolstate repo.
+fn prepare_toolstate_config(token: &str) {
+    fn git_config(key: &str, value: &str) {
+        let status = Command::new("git").arg("config").arg("--global").arg(key).arg(value).status();
+        let success = match status {
+            Ok(s) => s.success(),
+            Err(_) => false,
+        };
+        if !success {
+            panic!("git config key={} value={} failed (status: {:?})", key, value, status);
+        }
+    }
+
+    // If changing anything here, then please check that `src/ci/publish_toolstate.sh` is up to date
+    // as well.
+    git_config("user.email", "7378925+rust-toolstate-update@users.noreply.github.com");
+    git_config("user.name", "Rust Toolstate Update");
+    git_config("credential.helper", "store");
+
+    let credential = format!("https://{}:x-oauth-basic@github.com\n", token,);
+    let git_credential_path = PathBuf::from(t!(env::var("HOME"))).join(".git-credentials");
+    t!(fs::write(&git_credential_path, credential));
+}
+
+/// Reads the latest toolstate from the toolstate repo.
+fn read_old_toolstate() -> Vec<RepoState> {
+    let latest_path = Path::new(TOOLSTATE_DIR).join("_data").join("latest.json");
+    let old_toolstate = t!(fs::read(latest_path));
+    t!(serde_json::from_slice(&old_toolstate))
+}
+
 /// This function `commit_toolstate_change` provides functionality for pushing a change
 /// to the `rust-toolstate` repository.
 ///
@@ -273,56 +381,18 @@ pub fn save_toolstate(&self, tool: &str, state: ToolState) {
 ///
 ///       * See <https://help.github.com/articles/about-commit-email-addresses/>
 ///           if a private email by GitHub is wanted.
-fn commit_toolstate_change(current_toolstate: &ToolstateData, in_beta_week: bool) {
-    fn git_config(key: &str, value: &str) {
-        let status = Command::new("git").arg("config").arg("--global").arg(key).arg(value).status();
-        let success = match status {
-            Ok(s) => s.success(),
-            Err(_) => false,
-        };
-        if !success {
-            panic!("git config key={} value={} successful (status: {:?})", key, value, status);
-        }
-    }
-
-    // If changing anything here, then please check that src/ci/publish_toolstate.sh is up to date
-    // as well.
-    git_config("user.email", "7378925+rust-toolstate-update@users.noreply.github.com");
-    git_config("user.name", "Rust Toolstate Update");
-    git_config("credential.helper", "store");
-
-    let credential = format!(
-        "https://{}:x-oauth-basic@github.com\n",
-        t!(env::var("TOOLSTATE_REPO_ACCESS_TOKEN")),
-    );
-    let git_credential_path = PathBuf::from(t!(env::var("HOME"))).join(".git-credentials");
-    t!(fs::write(&git_credential_path, credential));
-
-    let status = Command::new("git")
-        .arg("clone")
-        .arg("--depth=1")
-        .arg(t!(env::var("TOOLSTATE_REPO")))
-        .status();
-    let success = match status {
-        Ok(s) => s.success(),
-        Err(_) => false,
-    };
-    if !success {
-        panic!("git clone successful (status: {:?})", status);
-    }
-
-    let old_toolstate = t!(fs::read("rust-toolstate/_data/latest.json"));
-    let old_toolstate: Vec<RepoState> = t!(serde_json::from_slice(&old_toolstate));
-
+fn commit_toolstate_change(current_toolstate: &ToolstateData) {
     let message = format!("({} CI update)", OS.expect("linux/windows only"));
     let mut success = false;
     for _ in 1..=5 {
-        // Update the toolstate results (the new commit-to-toolstate mapping) in the toolstate repo.
-        change_toolstate(&current_toolstate, &old_toolstate, in_beta_week);
+        // Upload the test results (the new commit-to-toolstate mapping) to the toolstate repo.
+        // This does *not* change the "current toolstate"; that only happens post-landing
+        // via `src/ci/docker/publish_toolstate.sh`.
+        publish_test_results(&current_toolstate);
 
         // `git commit` failing means nothing to commit.
         let status = t!(Command::new("git")
-            .current_dir("rust-toolstate")
+            .current_dir(TOOLSTATE_DIR)
             .arg("commit")
             .arg("-a")
             .arg("-m")
@@ -334,7 +404,7 @@ fn git_config(key: &str, value: &str) {
         }
 
         let status = t!(Command::new("git")
-            .current_dir("rust-toolstate")
+            .current_dir(TOOLSTATE_DIR)
             .arg("push")
             .arg("origin")
             .arg("master")
@@ -347,14 +417,14 @@ fn git_config(key: &str, value: &str) {
         eprintln!("Sleeping for 3 seconds before retrying push");
         std::thread::sleep(std::time::Duration::from_secs(3));
         let status = t!(Command::new("git")
-            .current_dir("rust-toolstate")
+            .current_dir(TOOLSTATE_DIR)
             .arg("fetch")
             .arg("origin")
             .arg("master")
             .status());
         assert!(status.success());
         let status = t!(Command::new("git")
-            .current_dir("rust-toolstate")
+            .current_dir(TOOLSTATE_DIR)
             .arg("reset")
             .arg("--hard")
             .arg("origin/master")
@@ -367,43 +437,20 @@ fn git_config(key: &str, value: &str) {
     }
 }
 
-fn change_toolstate(
-    current_toolstate: &ToolstateData,
-    old_toolstate: &[RepoState],
-    in_beta_week: bool,
-) {
-    let mut regressed = false;
-    for repo_state in old_toolstate {
-        let tool = &repo_state.tool;
-        let state = if cfg!(target_os = "linux") {
-            &repo_state.linux
-        } else if cfg!(windows) {
-            &repo_state.windows
-        } else {
-            unimplemented!()
-        };
-        let new_state = current_toolstate[tool.as_str()];
-
-        if new_state != *state {
-            eprintln!("The state of `{}` has changed from `{}` to `{}`", tool, state, new_state);
-            if (new_state as u8) < (*state as u8) {
-                if !["rustc-guide", "miri", "embedded-book"].contains(&tool.as_str()) {
-                    regressed = true;
-                }
-            }
-        }
-    }
-
-    if regressed && in_beta_week {
-        std::process::exit(1);
-    }
-
+/// Updates the "history" files with the latest results.
+///
+/// These results will later be promoted to `latest.json` by the
+/// `publish_toolstate.py` script if the PR passes all tests and is merged to
+/// master.
+fn publish_test_results(current_toolstate: &ToolstateData) {
     let commit = t!(std::process::Command::new("git").arg("rev-parse").arg("HEAD").output());
     let commit = t!(String::from_utf8(commit.stdout));
 
     let toolstate_serialized = t!(serde_json::to_string(&current_toolstate));
 
-    let history_path = format!("rust-toolstate/history/{}.tsv", OS.expect("linux/windows only"));
+    let history_path = Path::new(TOOLSTATE_DIR)
+        .join("history")
+        .join(format!("{}.tsv", OS.expect("linux/windows only")));
     let mut file = t!(fs::read_to_string(&history_path));
     let end_of_first_line = file.find('\n').unwrap();
     file.insert_str(end_of_first_line, &format!("\n{}\t{}", commit.trim(), toolstate_serialized));
@@ -418,3 +465,15 @@ struct RepoState {
     commit: String,
     datetime: String,
 }
+
+impl RepoState {
+    fn state(&self) -> ToolState {
+        if cfg!(target_os = "linux") {
+            self.linux
+        } else if cfg!(windows) {
+            self.windows
+        } else {
+            unimplemented!()
+        }
+    }
+}
index f8ddf0eb46cfd1d23b29f01960ad17962724d33c..a29d6f9ae1ec652bb543774e212a610abb1ff404 100644 (file)
@@ -20,7 +20,7 @@ jobs:
 
 # The macOS and Windows builds here are currently disabled due to them not being
 # overly necessary on `try` builds. We also don't actually have anything that
-# consumes the artifacts currently. Perhaps one day we can reenable, but for now
+# consumes the artifacts currently. Perhaps one day we can re-enable, but for now
 # it helps free up capacity on Azure.
 # - job: macOS
 #   timeoutInMinutes: 600
index b2d96aed2a9e80370010739bd24f7da54eb66481..e973ba2e33c64340ac3435a903d15d9ddbff5305 100644 (file)
@@ -25,4 +25,5 @@ ENV RUN_CHECK_WITH_PARALLEL_QUERIES 1
 ENV SCRIPT python2.7 ../x.py check --target=i686-pc-windows-gnu --host=i686-pc-windows-gnu && \
            python2.7 ../x.py build --stage 0 src/tools/build-manifest && \
            python2.7 ../x.py test --stage 0 src/tools/compiletest && \
+           python2.7 ../x.py test src/tools/tidy && \
            /scripts/validate-toolstate.sh
index dc90c286f5cd166aec3f0879883768ed6e48d261..4b5d5cac5163cc1f46cacbe3c9f806dcbe1adcb7 100644 (file)
@@ -16,7 +16,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   libssl-dev \
   pkg-config \
   zlib1g-dev \
-  xz-utils
+  xz-utils \
+  nodejs
 
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
@@ -28,7 +29,7 @@ ENV RUST_CONFIGURE_ARGS \
       --enable-llvm-link-shared \
       --set rust.thin-lto-import-instr-limit=10
 
-ENV SCRIPT python2.7 ../x.py test src/tools/tidy && python2.7 ../x.py test
+ENV SCRIPT python2.7 ../x.py test --exclude src/tools/tidy && python2.7 ../x.py test src/tools/tidy
 
 # The purpose of this container isn't to test with debug assertions and
 # this is run on all PRs, so let's get speedier builds by disabling these extra
index 7c43d034d8b7f70118010289502c920696548be5..691df04e754a6fac9d1ccb6824ec4d63b1ca2ed4 100755 (executable)
@@ -23,7 +23,9 @@ GIT_COMMIT_MSG="$(git log --format=%s -n1 HEAD)"
 cd rust-toolstate
 FAILURE=1
 for RETRY_COUNT in 1 2 3 4 5; do
-    #  The purpose is to publish the new "current" toolstate in the toolstate repo.
+    # The purpose of this is to publish the new "current" toolstate in the toolstate repo.
+    # This happens post-landing, on master.
+    # (Publishing the per-commit test results happens pre-landing in src/bootstrap/toolstate.rs).
     "$(ciCheckoutPath)/src/tools/publish_toolstate.py" "$GIT_COMMIT" \
         "$GIT_COMMIT_MSG" \
         "$MESSAGE_FILE" \
index 843a2bf2d5e55a488e8c97ca952bb1ae0e9edc71..22b9854ad5eb4e5c15b7b0135388db89ebde44ee 100755 (executable)
@@ -13,6 +13,7 @@ if isWindows; then
     # one way or another. The msys interpreters seem to have weird path conversions
     # baked in which break LLVM's build system one way or another, so let's use the
     # native version which keeps everything as native as possible.
-    cp C:/Python27amd64/python.exe C:/Python27amd64/python2.7.exe
-    ciCommandAddPath "C:\\Python27amd64"
+    python_home="C:/hostedtoolcache/windows/Python/2.7.17/x64"
+    cp "${python_home}/python.exe" "${python_home}/python2.7.exe"
+    ciCommandAddPath "C:\\hostedtoolcache\\windows\\Python\\2.7.17\\x64"
 fi
index b2e1092bf67bd4d7686c4553f186edbb7f5f92db..d22a9c487c78095afc4584f1d9b4ec43529d713c 160000 (submodule)
@@ -1 +1 @@
-Subproject commit b2e1092bf67bd4d7686c4553f186edbb7f5f92db
+Subproject commit d22a9c487c78095afc4584f1d9b4ec43529d713c
index 0a2a80e8fd6e2b4d62dcf9a93f2dc5983b0da249..2d10230ffcf7a9d49d4108501470a9da6fc7f4d3 100644 (file)
@@ -120,7 +120,7 @@ Rust. It's also sometimes called "the 'nomicon."
 
 ## The `rustc` Contribution Guide
 
-[The `rustc` Guide](https://rust-lang.github.io/rustc-guide/) documents how
+[The `rustc` Guide](https://rustc-dev-guide.rust-lang.org/) documents how
 the compiler works and how to contribute to it. This is useful if you want to build
 or modify the Rust compiler from source (e.g. to target something non-standard).
 
index 3e6e1001dc6e095dbd5c88005e80969f60e384e1..9f797e65e6bcc79419975b17aff8e21c9adc039f 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 3e6e1001dc6e095dbd5c88005e80969f60e384e1
+Subproject commit 9f797e65e6bcc79419975b17aff8e21c9adc039f
index 64239df6d173562b9deb4f012e4c3e6e960c4754..e2f11fe4d6a5ecb471c70323197da43c70cb96b6 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 64239df6d173562b9deb4f012e4c3e6e960c4754
+Subproject commit e2f11fe4d6a5ecb471c70323197da43c70cb96b6
index d119cc464731b2df094e3018ec86d4fb6ae90252..3a2552e9a159bcafe7244be5b96055b11c8d7d28 100644 (file)
@@ -1,21 +1,6 @@
 User-agent: *
-Disallow: /0.3/
-Disallow: /0.4/
-Disallow: /0.5/
-Disallow: /0.6/
-Disallow: /0.7/
-Disallow: /0.8/
-Disallow: /0.9/
-Disallow: /0.10/
-Disallow: /0.11.0/
-Disallow: /0.12.0/
-Disallow: /1.0.0-alpha/
-Disallow: /1.0.0-alpha.2/
-Disallow: /1.0.0-beta/
-Disallow: /1.0.0-beta.2/
-Disallow: /1.0.0-beta.3/
-Disallow: /1.0.0-beta.4/
-Disallow: /1.0.0-beta.5/
+Disallow: /1.
+Disallow: /0.
 Disallow: /book/first-edition/
 Disallow: /book/second-edition/
 Disallow: /stable/book/first-edition/
index 32facd5522ddbbf37baf01e4e4b6562bc55c071a..cb369ae95ca36b841960182d26f6d5d9b2e3cc18 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 32facd5522ddbbf37baf01e4e4b6562bc55c071a
+Subproject commit cb369ae95ca36b841960182d26f6d5d9b2e3cc18
index 659f8f65e65d2defdbdcdfbe3a461f3991ac551b..7a7838d965bc77f5255c184fcbf03698a9991510 100644 (file)
@@ -146,6 +146,7 @@ The valid types of print values are:
 - `crate-name` — The name of the crate.
 - `file-names` — The names of the files created by the `link` emit kind.
 - `sysroot` — Path to the sysroot.
+- `target-libdir` - Path to the target libdir.
 - `cfg` — List of cfg values. See [conditional compilation] for more
   information about cfg values.
 - `target-list` — List of known targets. The target may be selected with the
index 25a5c97b0a1200dbad7b9e9266f663602c5649f5..3b552e7cc0a741ed3410f3fbfb6be6b111dd5e1b 100644 (file)
@@ -1,12 +1,12 @@
 # Contributing to rustc
 
 We'd love to have your help improving `rustc`! To that end, we've written [a
-whole book][rustc_guide] on its
+whole book][rustc_dev_guide] on its
 internals, how it works, and how to get started working on it. To learn
 more, you'll want to check that out.
 
 If you would like to contribute to _this_ book, you can find its source in the
 rustc source at [src/doc/rustc][rustc_book].
 
-[rustc_guide]: https://rust-lang.github.io/rustc-guide/
+[rustc_dev_guide]: https://rustc-dev-guide.rust-lang.org/
 [rustc_book]: https://github.com/rust-lang/rust/tree/master/src/doc/rustc
index 47bef3cdde1877c2e669305d033072bb101308cb..7c12d23e6495c381bc6fcfdb5b59a09852c1c5d6 100644 (file)
@@ -4,7 +4,7 @@ The features listed on this page fall outside the rest of the main categories.
 
 ## `#[cfg(doc)]`: Documenting platform-/feature-specific information
 
-For conditional compilation, Rustdoc treats your crate the same way the compiler does: Only things
+For conditional compilation, Rustdoc treats your crate the same way the compiler does. Only things
 from the host target are available (or from the given `--target` if present), and everything else is
 "filtered out" from the crate. This can cause problems if your crate is providing different things
 on different targets and you want your documentation to reflect all the available items you
index 2e32ce31ecae0eb0a9c76805eff79e1c73d2c7ea..ddbe26389fdc82206ff3d36b1c9824b91676702c 100644 (file)
@@ -79,8 +79,8 @@ Rustdoc only supports HTML output, and so this flag is redundant today.
 Using this flag looks like this:
 
 ```bash
-$ rustdoc src/lib.rs -o target\\doc
-$ rustdoc src/lib.rs --output target\\doc
+$ rustdoc src/lib.rs -o target/doc
+$ rustdoc src/lib.rs --output target/doc
 ```
 
 By default, `rustdoc`'s output appears in a directory named `doc` in
index 96fa4344b04b726525805979156a6a12ba25219a..78181156e250f50cbfabf2e9e67ff49b9e230c6e 100644 (file)
@@ -314,7 +314,7 @@ only shows the part you care about.
 `should_panic` tells `rustdoc` that the code should compile correctly, but
 not actually pass as a test.
 
-```text
+```rust
 /// ```no_run
 /// loop {
 ///     println!("Hello, world");
index a48526d39fd0a5fcaa0ccaca99ca909e6c4aa5bc..f704fe8e099b85faab4279c6bf743c781ecf1db8 100644 (file)
@@ -138,27 +138,6 @@ Book][unstable-doc-cfg] and [its tracking issue][issue-doc-cfg].
 [unstable-doc-cfg]: ../unstable-book/language-features/doc-cfg.html
 [issue-doc-cfg]: https://github.com/rust-lang/rust/issues/43781
 
-### Adding your trait to the "Important Traits" dialog
-
-Rustdoc keeps a list of a few traits that are believed to be "fundamental" to a given type when
-implemented on it. These traits are intended to be the primary interface for their types, and are
-often the only thing available to be documented on their types. For this reason, Rustdoc will track
-when a given type implements one of these traits and call special attention to it when a function
-returns one of these types. This is the "Important Traits" dialog, visible as a circle-i button next
-to the function, which, when clicked, shows the dialog.
-
-In the standard library, the traits that qualify for inclusion are `Iterator`, `io::Read`, and
-`io::Write`. However, rather than being implemented as a hard-coded list, these traits have a
-special marker attribute on them: `#[doc(spotlight)]`. This means that you could apply this
-attribute to your own trait to include it in the "Important Traits" dialog in documentation.
-
-The `#[doc(spotlight)]` attribute currently requires the `#![feature(doc_spotlight)]` feature gate.
-For more information, see [its chapter in the Unstable Book][unstable-spotlight] and [its tracking
-issue][issue-spotlight].
-
-[unstable-spotlight]: ../unstable-book/language-features/doc-spotlight.html
-[issue-spotlight]: https://github.com/rust-lang/rust/issues/45040
-
 ### Exclude certain dependencies from documentation
 
 The standard library uses several dependencies which, in turn, use several types and traits from the
@@ -453,7 +432,7 @@ override `ignore`.
 
 ### `--runtool`, `--runtool-arg`: program to run tests with; args to pass to it
 
-Using thses options looks like this:
+Using these options looks like this:
 
 ```bash
 $ rustdoc src/lib.rs -Z unstable-options --runtool runner --runtool-arg --do-thing --runtool-arg --do-other-thing
index bbcacb7f3d5d9b05111fb1e2a1c52e105e2111c5..adcebc832bc0bb9c8640826a1eebfd3912eee24f 100644 (file)
@@ -78,8 +78,8 @@ $ cargo doc
 Internally, this calls out to `rustdoc` like this:
 
 ```bash
-$ rustdoc --crate-name docs srclib.rs -o <path>\docs\target\doc -L
-dependency=<path>docs\target\debug\deps
+$ rustdoc --crate-name docs src/lib.rs -o <path>/docs/target/doc -L
+dependency=<path>/docs/target/debug/deps
 ```
 
 You can see this with `cargo doc --verbose`.
@@ -128,4 +128,4 @@ Cargo currently does not understand standalone Markdown files, unfortunately.
 ## Summary
 
 This covers the simplest use-cases of `rustdoc`. The rest of this book will
-explain all of the options that `rustdoc` has, and how to use them.
\ No newline at end of file
+explain all of the options that `rustdoc` has, and how to use them.
diff --git a/src/doc/unstable-book/src/language-features/const-eval-limit.md b/src/doc/unstable-book/src/language-features/const-eval-limit.md
new file mode 100644 (file)
index 0000000..df68e83
--- /dev/null
@@ -0,0 +1,7 @@
+# `const_eval_limit`
+
+The tracking issue for this feature is: [#67217]
+
+[#67217]: https://github.com/rust-lang/rust/issues/67217
+
+The `const_eval_limit` allows someone to limit the evaluation steps the CTFE undertakes to evaluate a `const fn`.
index 09d1b19b4c3c382868c7500a2557a48c241f4cba..940916944bdaa6f5b8e78c7da1cde91a6ec9c35e 100644 (file)
@@ -2,7 +2,7 @@
 
 The tracking issue for this feature is: [#49147]
 
-[#44109]: https://github.com/rust-lang/rust/issues/49147
+[#49147]: https://github.com/rust-lang/rust/issues/49147
 
 ------------------------
 
diff --git a/src/doc/unstable-book/src/language-features/doc-spotlight.md b/src/doc/unstable-book/src/language-features/doc-spotlight.md
deleted file mode 100644 (file)
index 8117755..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-# `doc_spotlight`
-
-The tracking issue for this feature is: [#45040]
-
-The `doc_spotlight` feature allows the use of the `spotlight` parameter to the `#[doc]` attribute,
-to "spotlight" a specific trait on the return values of functions. Adding a `#[doc(spotlight)]`
-attribute to a trait definition will make rustdoc print extra information for functions which return
-a type that implements that trait. This attribute is applied to the `Iterator`, `io::Read`, and
-`io::Write` traits in the standard library.
-
-You can do this on your own traits, like this:
-
-```
-#![feature(doc_spotlight)]
-
-#[doc(spotlight)]
-pub trait MyTrait {}
-
-pub struct MyStruct;
-impl MyTrait for MyStruct {}
-
-/// The docs for this function will have an extra line about `MyStruct` implementing `MyTrait`,
-/// without having to write that yourself!
-pub fn my_fn() -> MyStruct { MyStruct }
-```
-
-This feature was originally implemented in PR [#45039].
-
-[#45040]: https://github.com/rust-lang/rust/issues/45040
-[#45039]: https://github.com/rust-lang/rust/pull/45039
index 896465cf64978552c2bf283554f6446798aca0c8..5c6aa912c1b24ec3ff7c7e95887aadf6f2d4c860 100644 (file)
@@ -1,8 +1,8 @@
 # `impl_trait_in_bindings`
 
-The tracking issue for this feature is: [#34511]
+The tracking issue for this feature is: [#63065]
 
-[#34511]: https://github.com/rust-lang/rust/issues/34511
+[#63065]: https://github.com/rust-lang/rust/issues/63065
 
 ------------------------
 
index 6f096e582f575864f24668bfc52e4d79d05241a8..250824321920d97d75abee30eb88e9375e5da4fd 100644 (file)
@@ -52,7 +52,6 @@ fn main(_argc: isize, _argv: *const *const u8) -> isize {
 
 #[lang = "eh_personality"] extern fn rust_eh_personality() {}
 #[lang = "panic_impl"] extern fn rust_begin_panic(info: &PanicInfo) -> ! { unsafe { intrinsics::abort() } }
-#[lang = "eh_unwind_resume"] extern fn rust_eh_unwind_resume() {}
 #[no_mangle] pub extern fn rust_eh_register_frames () {}
 #[no_mangle] pub extern fn rust_eh_unregister_frames () {}
 ```
@@ -67,7 +66,7 @@ Other features provided by lang items include:
   marked with lang items; those specific four are `eq`, `ord`,
   `deref`, and `add` respectively.
 - stack unwinding and general failure; the `eh_personality`,
-  `eh_unwind_resume`, `fail` and `fail_bounds_checks` lang items.
+  `panic` and `panic_bounds_checks` lang items.
 - the traits in `std::marker` used to indicate types of
   various kinds; lang items `send`, `sync` and `copy`.
 - the marker types and variance indicators found in
@@ -130,12 +129,6 @@ fn start(_argc: isize, _argv: *const *const u8) -> isize {
 pub extern fn rust_eh_personality() {
 }
 
-// This function may be needed based on the compilation target.
-#[lang = "eh_unwind_resume"]
-#[no_mangle]
-pub extern fn rust_eh_unwind_resume() {
-}
-
 #[lang = "panic_impl"]
 #[no_mangle]
 pub extern fn rust_begin_panic(info: &PanicInfo) -> ! {
@@ -173,12 +166,6 @@ pub extern fn main(_argc: i32, _argv: *const *const u8) -> i32 {
 pub extern fn rust_eh_personality() {
 }
 
-// This function may be needed based on the compilation target.
-#[lang = "eh_unwind_resume"]
-#[no_mangle]
-pub extern fn rust_eh_unwind_resume() {
-}
-
 #[lang = "panic_impl"]
 #[no_mangle]
 pub extern fn rust_begin_panic(info: &PanicInfo) -> ! {
@@ -211,10 +198,8 @@ compiler. When a panic happens, this controls the message that's displayed on
 the screen. While the language item's name is `panic_impl`, the symbol name is
 `rust_begin_panic`.
 
-A third function, `rust_eh_unwind_resume`, is also needed if the `custom_unwind_resume`
-flag is set in the options of the compilation target. It allows customizing the
-process of resuming unwind at the end of the landing pads. The language item's name
-is `eh_unwind_resume`.
+Finally, a `eh_catch_typeinfo` static is needed for certain targets which
+implement Rust panics on top of C++ exceptions.
 
 ## List of all language items
 
@@ -247,8 +232,6 @@ the source code.
   - `eh_personality`: `libpanic_unwind/emcc.rs` (EMCC)
   - `eh_personality`: `libpanic_unwind/gcc.rs` (GNU)
   - `eh_personality`: `libpanic_unwind/seh.rs` (SEH)
-  - `eh_unwind_resume`: `libpanic_unwind/gcc.rs` (GCC)
-  - `eh_catch_typeinfo`: `libpanic_unwind/seh.rs` (SEH)
   - `eh_catch_typeinfo`: `libpanic_unwind/emcc.rs` (EMCC)
   - `panic`: `libcore/panicking.rs`
   - `panic_bounds_check`: `libcore/panicking.rs`
diff --git a/src/doc/unstable-book/src/language-features/link-cfg.md b/src/doc/unstable-book/src/language-features/link-cfg.md
new file mode 100644 (file)
index 0000000..ee0fd5b
--- /dev/null
@@ -0,0 +1,5 @@
+# `link_cfg`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
index dedc7d3015d4d65c88c7568d8c6be850dac291aa..be350cd61696454f7d3f1d10df7b3c3997680ba7 100644 (file)
@@ -21,7 +21,7 @@ when they'd need to do the same thing for every type anyway).
 
 impl<T: Copy> CheapToClone for T {}
 
-// These could potentally overlap with the blanket implementation above,
+// These could potentially overlap with the blanket implementation above,
 // so are only allowed because CheapToClone is a marker trait.
 impl<T: CheapToClone, U: CheapToClone> CheapToClone for (T, U) {}
 impl<T: CheapToClone> CheapToClone for std::ops::Range<T> {}
index 4f2db040160c33b969b0569e1e5bef2c2bcfd177..f1be053ddc42ec9bddb17e85b194406e64aa53e9 100644 (file)
@@ -2,7 +2,7 @@
 
 The tracking issue for this feature is: [#41517]
 
-[#41417]: https://github.com/rust-lang/rust/issues/41517
+[#41517]: https://github.com/rust-lang/rust/issues/41517
 
 ------------------------
 
index b731c9ea6d0123c23d536828891a28403e3a564c..9b39b8971644fbab4051c29a157e19f2336de079 100644 (file)
@@ -2,7 +2,7 @@
 
 The tracking issue for this feature is [#60405]
 
-[60405]: https://github.com/rust-lang/rust/issues/60405
+[#60405]: https://github.com/rust-lang/rust/issues/60405
 
 ----
 
diff --git a/src/doc/unstable-book/src/library-features/read-initializer.md b/src/doc/unstable-book/src/library-features/read-initializer.md
deleted file mode 100644 (file)
index 898fe58..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-# `read_initializer`
-
-The tracking issue for this feature is: [#42788]
-
-[#0]: https://github.com/rust-lang/rust/issues/42788
-
-------------------------
diff --git a/src/doc/unstable-book/src/library-features/tidy-test-never-used-anywhere-else.md b/src/doc/unstable-book/src/library-features/tidy-test-never-used-anywhere-else.md
new file mode 100644 (file)
index 0000000..c194d79
--- /dev/null
@@ -0,0 +1,5 @@
+# `tidy_test_never_used_anywhere_else`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
index f41404bf8cab97ff5eb94a1084393e9297e90fad..9f82b2c6fa66d6a27085d71c1bb144387ff470c4 100644 (file)
@@ -165,13 +165,19 @@ pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 {
 #[unstable(feature = "allocator_api", issue = "32838")]
 unsafe impl AllocRef for Global {
     #[inline]
-    unsafe fn alloc(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr> {
-        NonNull::new(alloc(layout)).ok_or(AllocErr)
+    fn alloc(&mut self, layout: Layout) -> Result<(NonNull<u8>, usize), AllocErr> {
+        if layout.size() == 0 {
+            Ok((layout.dangling(), 0))
+        } else {
+            unsafe { NonNull::new(alloc(layout)).ok_or(AllocErr).map(|p| (p, layout.size())) }
+        }
     }
 
     #[inline]
     unsafe fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout) {
-        dealloc(ptr.as_ptr(), layout)
+        if layout.size() != 0 {
+            dealloc(ptr.as_ptr(), layout)
+        }
     }
 
     #[inline]
@@ -180,13 +186,29 @@ unsafe fn realloc(
         ptr: NonNull<u8>,
         layout: Layout,
         new_size: usize,
-    ) -> Result<NonNull<u8>, AllocErr> {
-        NonNull::new(realloc(ptr.as_ptr(), layout, new_size)).ok_or(AllocErr)
+    ) -> Result<(NonNull<u8>, usize), AllocErr> {
+        match (layout.size(), new_size) {
+            (0, 0) => Ok((layout.dangling(), 0)),
+            (0, _) => self.alloc(Layout::from_size_align_unchecked(new_size, layout.align())),
+            (_, 0) => {
+                self.dealloc(ptr, layout);
+                Ok((layout.dangling(), 0))
+            }
+            (_, _) => NonNull::new(realloc(ptr.as_ptr(), layout, new_size))
+                .ok_or(AllocErr)
+                .map(|p| (p, new_size)),
+        }
     }
 
     #[inline]
-    unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr> {
-        NonNull::new(alloc_zeroed(layout)).ok_or(AllocErr)
+    fn alloc_zeroed(&mut self, layout: Layout) -> Result<(NonNull<u8>, usize), AllocErr> {
+        if layout.size() == 0 {
+            Ok((layout.dangling(), 0))
+        } else {
+            unsafe {
+                NonNull::new(alloc_zeroed(layout)).ok_or(AllocErr).map(|p| (p, layout.size()))
+            }
+        }
     }
 }
 
@@ -201,7 +223,7 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 {
     } else {
         let layout = Layout::from_size_align_unchecked(size, align);
         match Global.alloc(layout) {
-            Ok(ptr) => ptr.as_ptr(),
+            Ok((ptr, _)) => ptr.as_ptr(),
             Err(_) => handle_alloc_error(layout),
         }
     }
index c902971638b8e02615420f38341ab663e2b87077..55944398e16772b65b7533d7722b220be6ebf22c 100644 (file)
@@ -8,7 +8,7 @@
 fn allocate_zeroed() {
     unsafe {
         let layout = Layout::from_size_align(1024, 1).unwrap();
-        let ptr =
+        let (ptr, _) =
             Global.alloc_zeroed(layout.clone()).unwrap_or_else(|_| handle_alloc_error(layout));
 
         let mut i = ptr.cast::<u8>().as_ptr();
index 81b0e9817d261f65315f810a10b52a320f065771..36641284a769b00a8f234153a9bf1ec3fbc9a776 100644 (file)
@@ -200,7 +200,7 @@ pub fn new_uninit() -> Box<mem::MaybeUninit<T>> {
             let ptr = if layout.size() == 0 {
                 NonNull::dangling()
             } else {
-                Global.alloc(layout).unwrap_or_else(|_| alloc::handle_alloc_error(layout)).cast()
+                Global.alloc(layout).unwrap_or_else(|_| alloc::handle_alloc_error(layout)).0.cast()
             };
             Box::from_raw(ptr.as_ptr())
         }
@@ -270,7 +270,7 @@ pub fn new_uninit_slice(len: usize) -> Box<[mem::MaybeUninit<T>]> {
             let ptr = if layout.size() == 0 {
                 NonNull::dangling()
             } else {
-                Global.alloc(layout).unwrap_or_else(|_| alloc::handle_alloc_error(layout)).cast()
+                Global.alloc(layout).unwrap_or_else(|_| alloc::handle_alloc_error(layout)).0.cast()
             };
             Box::from_raw(slice::from_raw_parts_mut(ptr.as_ptr(), len))
         }
@@ -1105,29 +1105,6 @@ fn as_mut(&mut self) -> &mut T {
 #[stable(feature = "pin", since = "1.33.0")]
 impl<T: ?Sized> Unpin for Box<T> {}
 
-#[cfg(bootstrap)]
-#[unstable(feature = "generator_trait", issue = "43122")]
-impl<G: ?Sized + Generator + Unpin> Generator for Box<G> {
-    type Yield = G::Yield;
-    type Return = G::Return;
-
-    fn resume(mut self: Pin<&mut Self>) -> GeneratorState<Self::Yield, Self::Return> {
-        G::resume(Pin::new(&mut *self))
-    }
-}
-
-#[cfg(bootstrap)]
-#[unstable(feature = "generator_trait", issue = "43122")]
-impl<G: ?Sized + Generator> Generator for Pin<Box<G>> {
-    type Yield = G::Yield;
-    type Return = G::Return;
-
-    fn resume(mut self: Pin<&mut Self>) -> GeneratorState<Self::Yield, Self::Return> {
-        G::resume((*self).as_mut())
-    }
-}
-
-#[cfg(not(bootstrap))]
 #[unstable(feature = "generator_trait", issue = "43122")]
 impl<G: ?Sized + Generator<R> + Unpin, R> Generator<R> for Box<G> {
     type Yield = G::Yield;
@@ -1138,7 +1115,6 @@ fn resume(mut self: Pin<&mut Self>, arg: R) -> GeneratorState<Self::Yield, Self:
     }
 }
 
-#[cfg(not(bootstrap))]
 #[unstable(feature = "generator_trait", issue = "43122")]
 impl<G: ?Sized + Generator<R>, R> Generator<R> for Pin<Box<G>> {
     type Yield = G::Yield;
index f38fe997b732c8effae96bbbd60722cc9673369e..9908a3049763a1eca04e6b8fbf3b3cf191e6b0e2 100644 (file)
@@ -536,7 +536,7 @@ fn sift_down_range(&mut self, pos: usize, end: usize) {
             while child < end {
                 let right = child + 1;
                 // compare with the greater of the two children
-                if right < end && !(hole.get(child) > hole.get(right)) {
+                if right < end && hole.get(child) <= hole.get(right) {
                     child = right;
                 }
                 // if we are already in order, stop.
@@ -568,7 +568,7 @@ fn sift_down_to_bottom(&mut self, mut pos: usize) {
             while child < end {
                 let right = child + 1;
                 // compare with the greater of the two children
-                if right < end && !(hole.get(child) > hole.get(right)) {
+                if right < end && hole.get(child) <= hole.get(right) {
                     child = right;
                 }
                 hole.move_to(child);
index 8b9ffdfb49b4676cce2b7edb907445c22a37679c..9da324ba2d4f14c3d73fc910394c000658cbd12b 100644 (file)
@@ -1477,6 +1477,14 @@ fn drop(&mut self) {
                 // Continue the same loop we perform below. This only runs when unwinding, so we
                 // don't have to care about panics this time (they'll abort).
                 while let Some(_) = self.0.next() {}
+
+                // No need to avoid the shared root, because the tree was definitely not empty.
+                unsafe {
+                    let mut node = ptr::read(&self.0.front).into_node().forget_type();
+                    while let Some(parent) = node.deallocate_and_ascend() {
+                        node = parent.into_node().forget_type();
+                    }
+                }
             }
         }
 
@@ -1491,7 +1499,8 @@ fn drop(&mut self) {
             if node.is_shared_root() {
                 return;
             }
-
+            // Most of the nodes have been deallocated while traversing
+            // but one pile from a leaf up to the root is left standing.
             while let Some(parent) = node.deallocate_and_ascend() {
                 node = parent.into_node().forget_type();
             }
index c1bd68a020a688e200f76fe4463f602cd1edcfee..1132ffdaf80053e5db662d88de2a816c13f2ddd6 100644 (file)
@@ -153,10 +153,15 @@ unsafe fn new() -> Self {
     }
 }
 
-/// An owned pointer to a node. This basically is either `Box<LeafNode<K, V>>` or
-/// `Box<InternalNode<K, V>>`. However, it contains no information as to which of the two types
-/// of nodes is actually behind the box, and, partially due to this lack of information, has no
-/// destructor.
+/// A managed, non-null pointer to a node. This is either an owned pointer to
+/// `LeafNode<K, V>`, an owned pointer to `InternalNode<K, V>`, or a (not owned)
+/// pointer to `NodeHeader<(), ()` (more specifically, the pointer to EMPTY_ROOT_NODE).
+/// All of these types have a `NodeHeader<K, V>` prefix, meaning that they have at
+/// least the same size as `NodeHeader<K, V>` and store the same kinds of data at the same
+/// offsets; and they have a pointer alignment at least as large as `NodeHeader<K, V>`'s.
+/// However, `BoxedNode` contains no information as to which of the three types
+/// of nodes it actually contains, and, partially due to this lack of information,
+/// has no destructor.
 struct BoxedNode<K, V> {
     ptr: Unique<LeafNode<K, V>>,
 }
@@ -167,9 +172,7 @@ fn from_leaf(node: Box<LeafNode<K, V>>) -> Self {
     }
 
     fn from_internal(node: Box<InternalNode<K, V>>) -> Self {
-        unsafe {
-            BoxedNode { ptr: Unique::new_unchecked(Box::into_raw(node) as *mut LeafNode<K, V>) }
-        }
+        BoxedNode { ptr: Box::into_unique(node).cast() }
     }
 
     unsafe fn from_ptr(ptr: NonNull<LeafNode<K, V>>) -> Self {
@@ -181,10 +184,11 @@ fn as_ptr(&self) -> NonNull<LeafNode<K, V>> {
     }
 }
 
-/// An owned tree. Note that despite being owned, this does not have a destructor,
-/// and must be cleaned up manually.
+/// Either an owned tree or a shared, empty tree.  Note that this does not have a destructor,
+/// and must be cleaned up manually if it is an owned tree.
 pub struct Root<K, V> {
     node: BoxedNode<K, V>,
+    /// The number of levels below the root node.
     height: usize,
 }
 
@@ -192,21 +196,21 @@ unsafe impl<K: Sync, V: Sync> Sync for Root<K, V> {}
 unsafe impl<K: Send, V: Send> Send for Root<K, V> {}
 
 impl<K, V> Root<K, V> {
+    /// Whether the instance of `Root` wraps a shared, empty root node. If not,
+    /// the entire tree is uniquely owned by the owner of the `Root` instance.
     pub fn is_shared_root(&self) -> bool {
         self.as_ref().is_shared_root()
     }
 
+    /// Returns a shared tree, wrapping a shared root node that is eternally empty.
     pub fn shared_empty_root() -> Self {
         Root {
-            node: unsafe {
-                BoxedNode::from_ptr(NonNull::new_unchecked(
-                    &EMPTY_ROOT_NODE as *const _ as *const LeafNode<K, V> as *mut _,
-                ))
-            },
+            node: unsafe { BoxedNode::from_ptr(NonNull::from(&EMPTY_ROOT_NODE).cast()) },
             height: 0,
         }
     }
 
+    /// Returns a new owned tree, with its own root node that is initially empty.
     pub fn new_leaf() -> Self {
         Root { node: BoxedNode::from_leaf(Box::new(unsafe { LeafNode::new() })), height: 0 }
     }
@@ -306,10 +310,11 @@ pub fn pop_level(&mut self) {
 ///   `NodeRef` could be pointing to either type of node.
 ///   Note that in case of a leaf node, this might still be the shared root!
 ///   Only turn this into a `LeafNode` reference if you know it is not the shared root!
-///   Shared references must be dereferencable *for the entire size of their pointee*,
+///   Shared references must be dereferenceable *for the entire size of their pointee*,
 ///   so '&LeafNode` or `&InternalNode` pointing to the shared root is undefined behavior.
 ///   Turning this into a `NodeHeader` reference is always safe.
 pub struct NodeRef<BorrowType, K, V, Type> {
+    /// The number of levels below the node.
     height: usize,
     node: NonNull<LeafNode<K, V>>,
     // `root` is null unless the borrow type is `Mut`
@@ -1191,7 +1196,7 @@ pub fn merge(
         let right_len = right_node.len();
 
         // necessary for correctness, but in a private module
-        assert!(left_len + right_len + 1 <= CAPACITY);
+        assert!(left_len + right_len < CAPACITY);
 
         unsafe {
             ptr::write(
index a9b4e3e4706b80dbde8281823290abf574076fa4..53d4f7239b76ea15a6e0db3b884d014c89bb650b 100644 (file)
@@ -841,10 +841,10 @@ pub fn pop_back(&mut self) -> Option<T> {
     /// d.push_front(2);
     /// d.push_front(3);
     ///
-    /// let mut splitted = d.split_off(2);
+    /// let mut split = d.split_off(2);
     ///
-    /// assert_eq!(splitted.pop_front(), Some(1));
-    /// assert_eq!(splitted.pop_front(), None);
+    /// assert_eq!(split.pop_front(), Some(1));
+    /// assert_eq!(split.pop_front(), None);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn split_off(&mut self, at: usize) -> LinkedList<T> {
@@ -959,7 +959,7 @@ pub fn drain_filter<F>(&mut self, filter: F) -> DrainFilter<'_, T, F>
         let it = self.head;
         let old_len = self.len;
 
-        DrainFilter { list: self, it: it, pred: filter, idx: 0, old_len: old_len }
+        DrainFilter { list: self, it, pred: filter, idx: 0, old_len }
     }
 }
 
@@ -1427,7 +1427,7 @@ pub fn peek_prev(&mut self) -> Option<&mut T> {
     /// `CursorMut`, which means it cannot outlive the `CursorMut` and that the
     /// `CursorMut` is frozen for the lifetime of the `Cursor`.
     #[unstable(feature = "linked_list_cursors", issue = "58533")]
-    pub fn as_cursor<'cm>(&'cm self) -> Cursor<'cm, T> {
+    pub fn as_cursor(&self) -> Cursor<'_, T> {
         Cursor { list: self.list, current: self.current, index: self.index }
     }
 }
index 0bb62373fab1e2b0655c8d92c85903294e2c80b4..6b21e54f66aa0dcb6adf98a607d1d31297e1753a 100644 (file)
@@ -42,6 +42,7 @@ pub mod btree_set {
 pub use vec_deque::VecDeque;
 
 use crate::alloc::{Layout, LayoutErr};
+use core::fmt::Display;
 
 /// The error type for `try_reserve` methods.
 #[derive(Clone, PartialEq, Eq, Debug)]
@@ -77,6 +78,23 @@ fn from(_: LayoutErr) -> Self {
     }
 }
 
+#[unstable(feature = "try_reserve", reason = "new API", issue = "48043")]
+impl Display for TryReserveError {
+    fn fmt(
+        &self,
+        fmt: &mut core::fmt::Formatter<'_>,
+    ) -> core::result::Result<(), core::fmt::Error> {
+        fmt.write_str("memory allocation failed")?;
+        let reason = match &self {
+            TryReserveError::CapacityOverflow => {
+                " because the computed capacity exceeded the collection's maximum"
+            }
+            TryReserveError::AllocError { .. } => " because the memory allocator returned a error",
+        };
+        fmt.write_str(reason)
+    }
+}
+
 /// An intermediate trait for specialization of `Extend`.
 #[doc(hidden)]
 trait SpecExtend<I: IntoIterator> {
index 85d1d98b8a9c23bfb3b908baeb7f7f78d99f481c..9d56f17700a857f90abb58b7891fa96dff29b735 100644 (file)
@@ -2132,7 +2132,7 @@ pub fn rotate_right(&mut self, k: usize) {
     // Safety: the following two methods require that the rotation amount
     // be less than half the length of the deque.
     //
-    // `wrap_copy` requres that `min(x, cap() - x) + copy_len <= cap()`,
+    // `wrap_copy` requires that `min(x, cap() - x) + copy_len <= cap()`,
     // but than `min` is never more than half the capacity, regardless of x,
     // so it's sound to call here because we're calling with something
     // less than half the length, which is never above half the capacity.
index e6162e0f571e2aaa2fa4cf7f4ec982c6829095d9..13ef2f063f95faa5e0b584650bc48a39124acb13 100644 (file)
 //! Hello, `     123` has 3 right-aligned characters
 //! ```
 //!
+//! ## Localization
+//!
+//! In some programming languages, the behavior of string formatting functions
+//! depends on the operating system's locale setting. The format functions
+//! provided by Rust's standard library do not have any concept of locale, and
+//! will produce the same results on all systems regardless of user
+//! configuration.
+//!
+//! For example, the following code will always print `1.5` even if the system
+//! locale uses a decimal separator other than a dot.
+//!
+//! ```
+//! println!("The value is {}", 1.5);
+//! ```
+//!
 //! # Escaping
 //!
 //! The literal characters `{` and `}` may be included in a string by preceding
index ffa4176cc7969533012b20bc4e3ceb1879cb0f2b..d877ac6ac5c7944558007b37c3fe317af5999f2d 100644 (file)
@@ -80,6 +80,7 @@
 #![feature(box_into_raw_non_null)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
+#![feature(cfg_sanitize)]
 #![feature(cfg_target_has_atomic)]
 #![feature(coerce_unsized)]
 #![feature(const_generic_impls_guard)]
index 144654946a2acb53225ac5dedb413f4a2aa95dd4..b31fec7f037c966ba48bba4bf079827b20757430 100644 (file)
@@ -72,28 +72,29 @@ pub fn with_capacity_zeroed_in(capacity: usize, a: A) -> Self {
         RawVec::allocate_in(capacity, true, a)
     }
 
-    fn allocate_in(capacity: usize, zeroed: bool, mut a: A) -> Self {
-        unsafe {
-            let elem_size = mem::size_of::<T>();
+    fn allocate_in(mut capacity: usize, zeroed: bool, mut a: A) -> Self {
+        let elem_size = mem::size_of::<T>();
 
-            let alloc_size = capacity.checked_mul(elem_size).unwrap_or_else(|| capacity_overflow());
-            alloc_guard(alloc_size).unwrap_or_else(|_| capacity_overflow());
+        let alloc_size = capacity.checked_mul(elem_size).unwrap_or_else(|| capacity_overflow());
+        alloc_guard(alloc_size).unwrap_or_else(|_| capacity_overflow());
 
-            // Handles ZSTs and `capacity == 0` alike.
-            let ptr = if alloc_size == 0 {
-                NonNull::<T>::dangling()
-            } else {
-                let align = mem::align_of::<T>();
-                let layout = Layout::from_size_align(alloc_size, align).unwrap();
-                let result = if zeroed { a.alloc_zeroed(layout) } else { a.alloc(layout) };
-                match result {
-                    Ok(ptr) => ptr.cast(),
-                    Err(_) => handle_alloc_error(layout),
+        // Handles ZSTs and `capacity == 0` alike.
+        let ptr = if alloc_size == 0 {
+            NonNull::<T>::dangling()
+        } else {
+            let align = mem::align_of::<T>();
+            let layout = Layout::from_size_align(alloc_size, align).unwrap();
+            let result = if zeroed { a.alloc_zeroed(layout) } else { a.alloc(layout) };
+            match result {
+                Ok((ptr, size)) => {
+                    capacity = size / elem_size;
+                    ptr.cast()
                 }
-            };
+                Err(_) => handle_alloc_error(layout),
+            }
+        };
 
-            RawVec { ptr: ptr.into(), cap: capacity, a }
-        }
+        RawVec { ptr: ptr.into(), cap: capacity, a }
     }
 }
 
@@ -280,7 +281,7 @@ pub fn double(&mut self) {
             // 0, getting to here necessarily means the `RawVec` is overfull.
             assert!(elem_size != 0, "capacity overflow");
 
-            let (new_cap, ptr) = match self.current_layout() {
+            let (ptr, new_cap) = match self.current_layout() {
                 Some(cur) => {
                     // Since we guarantee that we never allocate more than
                     // `isize::MAX` bytes, `elem_size * self.cap <= isize::MAX` as
@@ -297,7 +298,7 @@ pub fn double(&mut self) {
                     alloc_guard(new_size).unwrap_or_else(|_| capacity_overflow());
                     let ptr_res = self.a.realloc(NonNull::from(self.ptr).cast(), cur, new_size);
                     match ptr_res {
-                        Ok(ptr) => (new_cap, ptr),
+                        Ok((ptr, new_size)) => (ptr, new_size / elem_size),
                         Err(_) => handle_alloc_error(Layout::from_size_align_unchecked(
                             new_size,
                             cur.align(),
@@ -310,7 +311,7 @@ pub fn double(&mut self) {
                     let new_cap = if elem_size > (!0) / 8 { 1 } else { 4 };
                     let layout = Layout::array::<T>(new_cap).unwrap();
                     match self.a.alloc(layout) {
-                        Ok(ptr) => (new_cap, ptr),
+                        Ok((ptr, new_size)) => (ptr, new_size / elem_size),
                         Err(_) => handle_alloc_error(layout),
                     }
                 }
@@ -598,7 +599,7 @@ pub fn shrink_to_fit(&mut self, amount: usize) {
                 let align = mem::align_of::<T>();
                 let old_layout = Layout::from_size_align_unchecked(old_size, align);
                 match self.a.realloc(NonNull::from(self.ptr).cast(), old_layout, new_size) {
-                    Ok(p) => self.ptr = p.cast().into(),
+                    Ok((ptr, _)) => self.ptr = ptr.cast().into(),
                     Err(_) => {
                         handle_alloc_error(Layout::from_size_align_unchecked(new_size, align))
                     }
@@ -631,6 +632,8 @@ fn reserve_internal(
         fallibility: Fallibility,
         strategy: ReserveStrategy,
     ) -> Result<(), TryReserveError> {
+        let elem_size = mem::size_of::<T>();
+
         unsafe {
             // NOTE: we don't early branch on ZSTs here because we want this
             // to actually catch "asking for more than usize::MAX" in that case.
@@ -662,7 +665,7 @@ fn reserve_internal(
                 None => self.a.alloc(new_layout),
             };
 
-            let ptr = match (res, fallibility) {
+            let (ptr, new_cap) = match (res, fallibility) {
                 (Err(AllocErr), Infallible) => handle_alloc_error(new_layout),
                 (Err(AllocErr), Fallible) => {
                     return Err(TryReserveError::AllocError {
@@ -670,7 +673,7 @@ fn reserve_internal(
                         non_exhaustive: (),
                     });
                 }
-                (Ok(ptr), _) => ptr,
+                (Ok((ptr, new_size)), _) => (ptr, new_size / elem_size),
             };
 
             self.ptr = ptr.cast().into();
index 63087501f0e27684e4c4525f62c795d042813bc9..21a8a76d0a75b179b8c7d5208f432d1295d57654 100644 (file)
@@ -20,7 +20,7 @@ struct BoundedAlloc {
         fuel: usize,
     }
     unsafe impl AllocRef for BoundedAlloc {
-        unsafe fn alloc(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr> {
+        fn alloc(&mut self, layout: Layout) -> Result<(NonNull<u8>, usize), AllocErr> {
             let size = layout.size();
             if size > self.fuel {
                 return Err(AllocErr);
index 6ee128f4fa1d2a352968f14faab1172b94a7d434..9c286298aa65cd908d20eb4348bef33fa86d5102 100644 (file)
@@ -923,7 +923,7 @@ unsafe fn allocate_for_layout(
         let layout = Layout::new::<RcBox<()>>().extend(value_layout).unwrap().0.pad_to_align();
 
         // Allocate for the layout.
-        let mem = Global.alloc(layout).unwrap_or_else(|_| handle_alloc_error(layout));
+        let (mem, _) = Global.alloc(layout).unwrap_or_else(|_| handle_alloc_error(layout));
 
         // Initialize the RcBox
         let inner = mem_to_rcbox(mem.as_ptr());
index f5afea15d655ee76ffc4587a28f22dd1fda46e84..0e48f1548e6d1f668db64b2838411a70ffc5f8e5 100644 (file)
@@ -407,7 +407,7 @@ pub const fn new() -> String {
     ///
     /// assert_eq!(s.capacity(), cap);
     ///
-    /// // ...but this may make the vector reallocate
+    /// // ...but this may make the string reallocate
     /// s.push('a');
     /// ```
     #[inline]
@@ -2225,6 +2225,17 @@ fn from(s: &str) -> String {
     }
 }
 
+#[stable(feature = "from_mut_str_for_string", since = "1.44.0")]
+impl From<&mut str> for String {
+    /// Converts a `&mut str` into a `String`.
+    ///
+    /// The result is allocated on the heap.
+    #[inline]
+    fn from(s: &mut str) -> String {
+        s.to_owned()
+    }
+}
+
 #[stable(feature = "from_ref_string", since = "1.35.0")]
 impl From<&String> for String {
     #[inline]
index 9bd708c0f595c22df1814489dd1697cedede1e45..d9b54fb0b177ad05a81cc06c52fec3186fc06303 100644 (file)
 /// necessarily) at _exactly_ `MAX_REFCOUNT + 1` references.
 const MAX_REFCOUNT: usize = (isize::MAX) as usize;
 
+#[cfg(not(sanitize = "thread"))]
+macro_rules! acquire {
+    ($x:expr) => {
+        atomic::fence(Acquire)
+    };
+}
+
+// ThreadSanitizer does not support memory fences. To avoid false positive
+// reports in Arc / Weak implementation use atomic loads for synchronization
+// instead.
+#[cfg(sanitize = "thread")]
+macro_rules! acquire {
+    ($x:expr) => {
+        $x.load(Acquire)
+    };
+}
+
 /// A thread-safe reference-counting pointer. 'Arc' stands for 'Atomically
 /// Reference Counted'.
 ///
@@ -402,7 +419,7 @@ pub fn try_unwrap(this: Self) -> Result<T, Self> {
             return Err(this);
         }
 
-        atomic::fence(Acquire);
+        acquire!(this.inner().strong);
 
         unsafe {
             let elem = ptr::read(&this.ptr.as_ref().data);
@@ -739,7 +756,7 @@ unsafe fn drop_slow(&mut self) {
         ptr::drop_in_place(&mut self.ptr.as_mut().data);
 
         if self.inner().weak.fetch_sub(1, Release) == 1 {
-            atomic::fence(Acquire);
+            acquire!(self.inner().weak);
             Global.dealloc(self.ptr.cast(), Layout::for_value(self.ptr.as_ref()))
         }
     }
@@ -784,7 +801,7 @@ unsafe fn allocate_for_layout(
         // reference (see #54908).
         let layout = Layout::new::<ArcInner<()>>().extend(value_layout).unwrap().0.pad_to_align();
 
-        let mem = Global.alloc(layout).unwrap_or_else(|_| handle_alloc_error(layout));
+        let (mem, _) = Global.alloc(layout).unwrap_or_else(|_| handle_alloc_error(layout));
 
         // Initialize the ArcInner
         let inner = mem_to_arcinner(mem.as_ptr());
@@ -1243,7 +1260,7 @@ fn drop(&mut self) {
         //
         // [1]: (www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html)
         // [2]: (https://github.com/rust-lang/rust/pull/41714)
-        atomic::fence(Acquire);
+        acquire!(self.inner().strong);
 
         unsafe {
             self.drop_slow();
@@ -1701,7 +1718,7 @@ fn drop(&mut self) {
         let inner = if let Some(inner) = self.inner() { inner } else { return };
 
         if inner.weak.fetch_sub(1, Release) == 1 {
-            atomic::fence(Acquire);
+            acquire!(inner.weak);
             unsafe { Global.dealloc(self.ptr.cast(), Layout::for_value(self.ptr.as_ref())) }
         }
     }
index fd07a4d3926c3897bf26e789fc30ca5386ba5da2..d05eec19346de86e9ea93deaba8b492a837d6fae 100644 (file)
@@ -1021,7 +1021,7 @@ fn test_split_off_large_random_sorted() {
 }
 
 #[test]
-fn test_into_iter_drop_leak() {
+fn test_into_iter_drop_leak_1() {
     static DROPS: AtomicU32 = AtomicU32::new(0);
 
     struct D;
@@ -1045,3 +1045,27 @@ fn drop(&mut self) {
 
     assert_eq!(DROPS.load(Ordering::SeqCst), 5);
 }
+
+#[test]
+fn test_into_iter_drop_leak_2() {
+    let size = 12; // to obtain tree with 2 levels (having edges to leaf nodes)
+    static DROPS: AtomicU32 = AtomicU32::new(0);
+    static PANIC_POINT: AtomicU32 = AtomicU32::new(0);
+
+    struct D;
+    impl Drop for D {
+        fn drop(&mut self) {
+            if DROPS.fetch_add(1, Ordering::SeqCst) == PANIC_POINT.load(Ordering::SeqCst) {
+                panic!("panic in `drop`");
+            }
+        }
+    }
+
+    for panic_point in vec![0, 1, size - 2, size - 1] {
+        DROPS.store(0, Ordering::SeqCst);
+        PANIC_POINT.store(panic_point, Ordering::SeqCst);
+        let map: BTreeMap<_, _> = (0..size).map(|i| (i, D)).collect();
+        catch_unwind(move || drop(map.into_iter())).ok();
+        assert_eq!(DROPS.load(Ordering::SeqCst), size);
+    }
+}
index 7fcfcf9b2945d26184d9ae9e9738c30c1068df69..d159126f426c52070b7290f0025dfe191d093c75 100644 (file)
@@ -20,7 +20,7 @@ fn check_overalign_requests<T: AllocRef>(mut allocator: T) {
             unsafe {
                 let pointers: Vec<_> = (0..iterations)
                     .map(|_| {
-                        allocator.alloc(Layout::from_size_align(size, align).unwrap()).unwrap()
+                        allocator.alloc(Layout::from_size_align(size, align).unwrap()).unwrap().0
                     })
                     .collect();
                 for &ptr in &pointers {
index 3d6b4bff5e06046fff2321769cda7c812bdb80ea..8e49e6d8ebad9e35144793f5c84c8272016e28fb 100644 (file)
@@ -1733,9 +1733,9 @@ fn panic_safe() {
     let moduli = &[5, 20, 50];
 
     #[cfg(miri)]
-    let lens = 1..13;
+    let lens = 1..10;
     #[cfg(miri)]
-    let moduli = &[10];
+    let moduli = &[5];
 
     for len in lens {
         for &modulus in moduli {
index fc50d06b33c579c062e5b44b3e48a608bb65cabf..d1956270f135fc937143974e5577c4f6038f3071 100644 (file)
@@ -317,7 +317,7 @@ impl<T> Vec<T> {
     /// let mut vec: Vec<i32> = Vec::new();
     /// ```
     #[inline]
-    #[rustc_const_stable(feature = "const_vec_new", since = "1.32.0")]
+    #[rustc_const_stable(feature = "const_vec_new", since = "1.39.0")]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub const fn new() -> Vec<T> {
         Vec { buf: RawVec::NEW, len: 0 }
@@ -1476,8 +1476,9 @@ impl<T: Clone> Vec<T> {
     /// difference, with each additional slot filled with `value`.
     /// If `new_len` is less than `len`, the `Vec` is simply truncated.
     ///
-    /// This method requires [`Clone`] to be able clone the passed value. If
-    /// you need more flexibility (or want to rely on [`Default`] instead of
+    /// This method requires `T` to implement [`Clone`],
+    /// in order to be able to clone the passed value.
+    /// If you need more flexibility (or want to rely on [`Default`] instead of
     /// [`Clone`]), use [`resize_with`].
     ///
     /// # Examples
@@ -1658,7 +1659,7 @@ struct SetLenOnDrop<'a> {
 impl<'a> SetLenOnDrop<'a> {
     #[inline]
     fn new(len: &'a mut usize) -> Self {
-        SetLenOnDrop { local_len: *len, len: len }
+        SetLenOnDrop { local_len: *len, len }
     }
 
     #[inline]
@@ -2625,13 +2626,21 @@ fn clone(&self) -> IntoIter<T> {
 #[stable(feature = "rust1", since = "1.0.0")]
 unsafe impl<#[may_dangle] T> Drop for IntoIter<T> {
     fn drop(&mut self) {
+        struct DropGuard<'a, T>(&'a mut IntoIter<T>);
+
+        impl<T> Drop for DropGuard<'_, T> {
+            fn drop(&mut self) {
+                // RawVec handles deallocation
+                let _ = unsafe { RawVec::from_raw_parts(self.0.buf.as_ptr(), self.0.cap) };
+            }
+        }
+
+        let guard = DropGuard(self);
         // destroy the remaining elements
         unsafe {
-            ptr::drop_in_place(self.as_mut_slice());
+            ptr::drop_in_place(guard.0.as_mut_slice());
         }
-
-        // RawVec handles deallocation
-        let _ = unsafe { RawVec::from_raw_parts(self.buf.as_ptr(), self.cap) };
+        // now `guard` will be dropped and do the rest
     }
 }
 
@@ -2893,7 +2902,7 @@ pub struct DrainFilter<'a, T, F>
     /// The filter test predicate.
     pred: F,
     /// A flag that indicates a panic has occurred in the filter test prodicate.
-    /// This is used as a hint in the drop implmentation to prevent consumption
+    /// This is used as a hint in the drop implementation to prevent consumption
     /// of the remainder of the `DrainFilter`. Any unprocessed items will be
     /// backshifted in the `vec`, but no further items will be dropped or
     /// tested by the filter predicate.
index a04e75bc7ce7c6d32ab0644ffba781203006b11b..d2a513451ccb6bda48317f696b93098e0800d10c 100644 (file)
 use crate::ptr::{self, NonNull};
 use crate::usize;
 
-/// Represents the combination of a starting address and
-/// a total capacity of the returned block.
-#[unstable(feature = "allocator_api", issue = "32838")]
-#[derive(Debug)]
-pub struct Excess(pub NonNull<u8>, pub usize);
-
 const fn size_align<T>() -> (usize, usize) {
     (mem::size_of::<T>(), mem::align_of::<T>())
 }
@@ -146,6 +140,18 @@ pub fn for_value<T: ?Sized>(t: &T) -> Self {
         unsafe { Layout::from_size_align_unchecked(size, align) }
     }
 
+    /// Creates a `NonNull` that is dangling, but well-aligned for this Layout.
+    ///
+    /// Note that the pointer value may potentially represent a valid pointer,
+    /// which means this must not be used as a "not yet initialized"
+    /// sentinel value. Types that lazily allocate must track initialization by
+    /// some other means.
+    #[unstable(feature = "alloc_layout_extra", issue = "55724")]
+    pub const fn dangling(&self) -> NonNull<u8> {
+        // align is non-zero and a power of two
+        unsafe { NonNull::new_unchecked(self.align() as *mut u8) }
+    }
+
     /// Creates a layout describing the record that can hold a value
     /// of the same layout as `self`, but that also is aligned to
     /// alignment `align` (measured in bytes).
@@ -241,13 +247,11 @@ pub fn pad_to_align(&self) -> Layout {
     #[unstable(feature = "alloc_layout_extra", issue = "55724")]
     #[inline]
     pub fn repeat(&self, n: usize) -> Result<(Self, usize), LayoutErr> {
-        // Warning, removing the checked_add here led to segfaults in #67174. Further
-        // analysis in #69225 seems to indicate that this is an LTO-related
-        // miscompilation, so #67174 might be able to be reapplied in the future.
-        let padded_size = self
-            .size()
-            .checked_add(self.padding_needed_for(self.align()))
-            .ok_or(LayoutErr { private: () })?;
+        // This cannot overflow. Quoting from the invariant of Layout:
+        // > `size`, when rounded up to the nearest multiple of `align`,
+        // > must not overflow (i.e., the rounded value must be less than
+        // > `usize::MAX`)
+        let padded_size = self.size() + self.padding_needed_for(self.align());
         let alloc_size = padded_size.checked_mul(n).ok_or(LayoutErr { private: () })?;
 
         unsafe {
@@ -595,28 +599,18 @@ unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut
 ///
 /// * the starting address for that memory block was previously
 ///   returned by a previous call to an allocation method (`alloc`,
-///   `alloc_zeroed`, `alloc_excess`) or reallocation method
-///   (`realloc`, `realloc_excess`), and
+///   `alloc_zeroed`) or reallocation method (`realloc`), and
 ///
 /// * the memory block has not been subsequently deallocated, where
 ///   blocks are deallocated either by being passed to a deallocation
-///   method (`dealloc`, `dealloc_one`, `dealloc_array`) or by being
-///   passed to a reallocation method (see above) that returns `Ok`.
+///   method (`dealloc`) or by being passed to a reallocation method
+///  (see above) that returns `Ok`.
 ///
-/// A note regarding zero-sized types and zero-sized layouts: many
-/// methods in the `AllocRef` trait state that allocation requests
-/// must be non-zero size, or else undefined behavior can result.
-///
-/// * If an `AllocRef` implementation chooses to return `Ok` in this
-///   case (i.e., the pointer denotes a zero-sized inaccessible block)
-///   then that returned pointer must be considered "currently
-///   allocated". On such an allocator, *all* methods that take
-///   currently-allocated pointers as inputs must accept these
-///   zero-sized pointers, *without* causing undefined behavior.
-///
-/// * In other words, if a zero-sized pointer can flow out of an
-///   allocator, then that allocator must likewise accept that pointer
-///   flowing back into its deallocation and reallocation methods.
+/// Unlike [`GlobalAlloc`], zero-sized allocations are allowed in
+/// `AllocRef`. If an underlying allocator does not support this (like
+/// jemalloc) or return a null pointer (such as `libc::malloc`), this case
+/// must be caught. In this case [`Layout::dangling()`] can be used to
+/// create a dangling, but aligned `NonNull<u8>`.
 ///
 /// Some of the methods require that a layout *fit* a memory block.
 /// What it means for a layout to "fit" a memory block means (or
@@ -627,11 +621,9 @@ unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut
 ///
 /// 2. The block's size must fall in the range `[use_min, use_max]`, where:
 ///
-///    * `use_min` is `self.usable_size(layout).0`, and
+///    * `use_min` is `layout.size()`, and
 ///
-///    * `use_max` is the capacity that was (or would have been)
-///      returned when (if) the block was allocated via a call to
-///      `alloc_excess` or `realloc_excess`.
+///    * `use_max` is the capacity that was returned.
 ///
 /// Note that:
 ///
@@ -645,6 +637,12 @@ unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut
 ///    currently allocated via an allocator `a`, then it is legal to
 ///    use that layout to deallocate it, i.e., `a.dealloc(ptr, k);`.
 ///
+///  * if an allocator does not support overallocating, it is fine to
+///    simply return `layout.size()` as the allocated size.
+///
+/// [`GlobalAlloc`]: self::GlobalAlloc
+/// [`Layout::dangling()`]: self::Layout::dangling
+///
 /// # Safety
 ///
 /// The `AllocRef` trait is an `unsafe` trait for a number of reasons, and
@@ -665,16 +663,9 @@ unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut
 /// the future.
 #[unstable(feature = "allocator_api", issue = "32838")]
 pub unsafe trait AllocRef {
-    // (Note: some existing allocators have unspecified but well-defined
-    // behavior in response to a zero size allocation request ;
-    // e.g., in C, `malloc` of 0 will either return a null pointer or a
-    // unique pointer, but will not have arbitrary undefined
-    // behavior.
-    // However in jemalloc for example,
-    // `mallocx(0)` is documented as undefined behavior.)
-
-    /// Returns a pointer meeting the size and alignment guarantees of
-    /// `layout`.
+    /// On success, returns a pointer meeting the size and alignment
+    /// guarantees of `layout` and the actual size of the allocated block,
+    /// which must be greater than or equal to `layout.size()`.
     ///
     /// If this method returns an `Ok(addr)`, then the `addr` returned
     /// will be non-null address pointing to a block of storage
@@ -685,15 +676,6 @@ pub unsafe trait AllocRef {
     /// behavior, e.g., to ensure initialization to particular sets of
     /// bit patterns.)
     ///
-    /// # Safety
-    ///
-    /// This function is unsafe because undefined behavior can result
-    /// if the caller does not ensure that `layout` has non-zero size.
-    ///
-    /// (Extension subtraits might provide more specific bounds on
-    /// behavior, e.g., guarantee a sentinel address or a null pointer
-    /// in response to a zero-size allocation request.)
-    ///
     /// # Errors
     ///
     /// Returning `Err` indicates that either memory is exhausted or
@@ -711,7 +693,7 @@ pub unsafe trait AllocRef {
     /// rather than directly invoking `panic!` or similar.
     ///
     /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
-    unsafe fn alloc(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr>;
+    fn alloc(&mut self, layout: Layout) -> Result<(NonNull<u8>, usize), AllocErr>;
 
     /// Deallocate the memory referenced by `ptr`.
     ///
@@ -730,48 +712,38 @@ pub unsafe trait AllocRef {
     ///   to allocate that block of memory.
     unsafe fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout);
 
-    // == ALLOCATOR-SPECIFIC QUANTITIES AND LIMITS ==
-    // usable_size
-
-    /// Returns bounds on the guaranteed usable size of a successful
-    /// allocation created with the specified `layout`.
-    ///
-    /// In particular, if one has a memory block allocated via a given
-    /// allocator `a` and layout `k` where `a.usable_size(k)` returns
-    /// `(l, u)`, then one can pass that block to `a.dealloc()` with a
-    /// layout in the size range [l, u].
-    ///
-    /// (All implementors of `usable_size` must ensure that
-    /// `l <= k.size() <= u`)
-    ///
-    /// Both the lower- and upper-bounds (`l` and `u` respectively)
-    /// are provided, because an allocator based on size classes could
-    /// misbehave if one attempts to deallocate a block without
-    /// providing a correct value for its size (i.e., one within the
-    /// range `[l, u]`).
-    ///
-    /// Clients who wish to make use of excess capacity are encouraged
-    /// to use the `alloc_excess` and `realloc_excess` instead, as
-    /// this method is constrained to report conservative values that
-    /// serve as valid bounds for *all possible* allocation method
-    /// calls.
-    ///
-    /// However, for clients that do not wish to track the capacity
-    /// returned by `alloc_excess` locally, this method is likely to
-    /// produce useful results.
-    #[inline]
-    fn usable_size(&self, layout: &Layout) -> (usize, usize) {
-        (layout.size(), layout.size())
+    /// Behaves like `alloc`, but also ensures that the contents
+    /// are set to zero before being returned.
+    ///
+    /// # Errors
+    ///
+    /// Returning `Err` indicates that either memory is exhausted or
+    /// `layout` does not meet allocator's size or alignment
+    /// constraints, just as in `alloc`.
+    ///
+    /// Clients wishing to abort computation in response to an
+    /// allocation error are encouraged to call the [`handle_alloc_error`] function,
+    /// rather than directly invoking `panic!` or similar.
+    ///
+    /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
+    fn alloc_zeroed(&mut self, layout: Layout) -> Result<(NonNull<u8>, usize), AllocErr> {
+        let size = layout.size();
+        let result = self.alloc(layout);
+        if let Ok((p, _)) = result {
+            unsafe { ptr::write_bytes(p.as_ptr(), 0, size) }
+        }
+        result
     }
 
     // == METHODS FOR MEMORY REUSE ==
-    // realloc. alloc_excess, realloc_excess
+    // realloc, realloc_zeroed, grow_in_place, grow_in_place_zeroed, shrink_in_place
 
     /// Returns a pointer suitable for holding data described by
     /// a new layout with `layout`’s alignment and a size given
-    /// by `new_size`. To
-    /// accomplish this, this may extend or shrink the allocation
-    /// referenced by `ptr` to fit the new layout.
+    /// by `new_size` and the actual size of the allocated block.
+    /// The latter is greater than or equal to `layout.size()`.
+    /// To accomplish this, the allocator may extend or shrink
+    /// the allocation referenced by `ptr` to fit the new layout.
     ///
     /// If this returns `Ok`, then ownership of the memory block
     /// referenced by `ptr` has been transferred to this
@@ -794,8 +766,6 @@ fn usable_size(&self, layout: &Layout) -> (usize, usize) {
     /// * `layout` must *fit* the `ptr` (see above). (The `new_size`
     ///   argument need not fit it.)
     ///
-    /// * `new_size` must be greater than zero.
-    ///
     /// * `new_size`, when rounded up to the nearest multiple of `layout.align()`,
     ///   must not overflow (i.e., the rounded value must be less than `usize::MAX`).
     ///
@@ -826,23 +796,25 @@ unsafe fn realloc(
         ptr: NonNull<u8>,
         layout: Layout,
         new_size: usize,
-    ) -> Result<NonNull<u8>, AllocErr> {
+    ) -> Result<(NonNull<u8>, usize), AllocErr> {
         let old_size = layout.size();
 
-        if new_size >= old_size {
-            if let Ok(()) = self.grow_in_place(ptr, layout, new_size) {
-                return Ok(ptr);
+        if new_size > old_size {
+            if let Ok(size) = self.grow_in_place(ptr, layout, new_size) {
+                return Ok((ptr, size));
             }
         } else if new_size < old_size {
-            if let Ok(()) = self.shrink_in_place(ptr, layout, new_size) {
-                return Ok(ptr);
+            if let Ok(size) = self.shrink_in_place(ptr, layout, new_size) {
+                return Ok((ptr, size));
             }
+        } else {
+            return Ok((ptr, new_size));
         }
 
         // otherwise, fall back on alloc + copy + dealloc.
         let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
         let result = self.alloc(new_layout);
-        if let Ok(new_ptr) = result {
+        if let Ok((new_ptr, _)) = result {
             ptr::copy_nonoverlapping(ptr.as_ptr(), new_ptr.as_ptr(), cmp::min(old_size, new_size));
             self.dealloc(ptr, layout);
         }
@@ -879,174 +851,40 @@ unsafe fn realloc_zeroed(
         ptr: NonNull<u8>,
         layout: Layout,
         new_size: usize,
-    ) -> Result<NonNull<u8>, AllocErr> {
+    ) -> Result<(NonNull<u8>, usize), AllocErr> {
         let old_size = layout.size();
 
-        if new_size >= old_size {
-            if let Ok(()) = self.grow_in_place_zeroed(ptr, layout, new_size) {
-                return Ok(ptr);
+        if new_size > old_size {
+            if let Ok(size) = self.grow_in_place_zeroed(ptr, layout, new_size) {
+                return Ok((ptr, size));
             }
         } else if new_size < old_size {
-            if let Ok(()) = self.shrink_in_place(ptr, layout, new_size) {
-                return Ok(ptr);
+            if let Ok(size) = self.shrink_in_place(ptr, layout, new_size) {
+                return Ok((ptr, size));
             }
+        } else {
+            return Ok((ptr, new_size));
         }
 
         // otherwise, fall back on alloc + copy + dealloc.
         let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
         let result = self.alloc_zeroed(new_layout);
-        if let Ok(new_ptr) = result {
+        if let Ok((new_ptr, _)) = result {
             ptr::copy_nonoverlapping(ptr.as_ptr(), new_ptr.as_ptr(), cmp::min(old_size, new_size));
             self.dealloc(ptr, layout);
         }
         result
     }
 
-    /// Behaves like `alloc`, but also ensures that the contents
-    /// are set to zero before being returned.
-    ///
-    /// # Safety
-    ///
-    /// This function is unsafe for the same reasons that `alloc` is.
-    ///
-    /// # Errors
-    ///
-    /// Returning `Err` indicates that either memory is exhausted or
-    /// `layout` does not meet allocator's size or alignment
-    /// constraints, just as in `alloc`.
-    ///
-    /// Clients wishing to abort computation in response to an
-    /// allocation error are encouraged to call the [`handle_alloc_error`] function,
-    /// rather than directly invoking `panic!` or similar.
-    ///
-    /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
-    unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr> {
-        let size = layout.size();
-        let p = self.alloc(layout);
-        if let Ok(p) = p {
-            ptr::write_bytes(p.as_ptr(), 0, size);
-        }
-        p
-    }
-
-    /// Behaves like `alloc`, but also returns the whole size of
-    /// the returned block. For some `layout` inputs, like arrays, this
-    /// may include extra storage usable for additional data.
-    ///
-    /// # Safety
-    ///
-    /// This function is unsafe for the same reasons that `alloc` is.
-    ///
-    /// # Errors
-    ///
-    /// Returning `Err` indicates that either memory is exhausted or
-    /// `layout` does not meet allocator's size or alignment
-    /// constraints, just as in `alloc`.
-    ///
-    /// Clients wishing to abort computation in response to an
-    /// allocation error are encouraged to call the [`handle_alloc_error`] function,
-    /// rather than directly invoking `panic!` or similar.
-    ///
-    /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
-    unsafe fn alloc_excess(&mut self, layout: Layout) -> Result<Excess, AllocErr> {
-        let usable_size = self.usable_size(&layout);
-        self.alloc(layout).map(|p| Excess(p, usable_size.1))
-    }
-
-    /// Behaves like `alloc`, but also returns the whole size of
-    /// the returned block. For some `layout` inputs, like arrays, this
-    /// may include extra storage usable for additional data.
-    /// Also it ensures that the contents are set to zero before being returned.
-    ///
-    /// # Safety
-    ///
-    /// This function is unsafe for the same reasons that `alloc` is.
-    ///
-    /// # Errors
-    ///
-    /// Returning `Err` indicates that either memory is exhausted or
-    /// `layout` does not meet allocator's size or alignment
-    /// constraints, just as in `alloc`.
-    ///
-    /// Clients wishing to abort computation in response to an
-    /// allocation error are encouraged to call the [`handle_alloc_error`] function,
-    /// rather than directly invoking `panic!` or similar.
-    ///
-    /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
-    unsafe fn alloc_excess_zeroed(&mut self, layout: Layout) -> Result<Excess, AllocErr> {
-        let usable_size = self.usable_size(&layout);
-        self.alloc_zeroed(layout).map(|p| Excess(p, usable_size.1))
-    }
-
-    /// Behaves like `realloc`, but also returns the whole size of
-    /// the returned block. For some `layout` inputs, like arrays, this
-    /// may include extra storage usable for additional data.
-    ///
-    /// # Safety
-    ///
-    /// This function is unsafe for the same reasons that `realloc` is.
-    ///
-    /// # Errors
-    ///
-    /// Returning `Err` indicates that either memory is exhausted or
-    /// `layout` does not meet allocator's size or alignment
-    /// constraints, just as in `realloc`.
-    ///
-    /// Clients wishing to abort computation in response to a
-    /// reallocation error are encouraged to call the [`handle_alloc_error`] function,
-    /// rather than directly invoking `panic!` or similar.
-    ///
-    /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
-    unsafe fn realloc_excess(
-        &mut self,
-        ptr: NonNull<u8>,
-        layout: Layout,
-        new_size: usize,
-    ) -> Result<Excess, AllocErr> {
-        let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
-        let usable_size = self.usable_size(&new_layout);
-        self.realloc(ptr, layout, new_size).map(|p| Excess(p, usable_size.1))
-    }
-
-    /// Behaves like `realloc`, but also returns the whole size of
-    /// the returned block. For some `layout` inputs, like arrays, this
-    /// may include extra storage usable for additional data.
-    /// Also it ensures that the contents are set to zero before being returned.
-    ///
-    /// # Safety
-    ///
-    /// This function is unsafe for the same reasons that `realloc` is.
-    ///
-    /// # Errors
-    ///
-    /// Returning `Err` indicates that either memory is exhausted or
-    /// `layout` does not meet allocator's size or alignment
-    /// constraints, just as in `realloc`.
-    ///
-    /// Clients wishing to abort computation in response to a
-    /// reallocation error are encouraged to call the [`handle_alloc_error`] function,
-    /// rather than directly invoking `panic!` or similar.
-    ///
-    /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
-    unsafe fn realloc_excess_zeroed(
-        &mut self,
-        ptr: NonNull<u8>,
-        layout: Layout,
-        new_size: usize,
-    ) -> Result<Excess, AllocErr> {
-        let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
-        let usable_size = self.usable_size(&new_layout);
-        self.realloc_zeroed(ptr, layout, new_size).map(|p| Excess(p, usable_size.1))
-    }
-
     /// Attempts to extend the allocation referenced by `ptr` to fit `new_size`.
     ///
     /// If this returns `Ok`, then the allocator has asserted that the
     /// memory block referenced by `ptr` now fits `new_size`, and thus can
     /// be used to carry data of a layout of that size and same alignment as
-    /// `layout`. (The allocator is allowed to
-    /// expend effort to accomplish this, such as extending the memory block to
-    /// include successor blocks, or virtual memory tricks.)
+    /// `layout`. The returned value is the new size of the allocated block.
+    /// (The allocator is allowed to expend effort to accomplish this, such
+    /// as extending the memory block to include successor blocks, or virtual
+    /// memory tricks.)
     ///
     /// Regardless of what this method returns, ownership of the
     /// memory block referenced by `ptr` has not been transferred, and
@@ -1074,18 +912,17 @@ unsafe fn realloc_excess_zeroed(
     /// function; clients are expected either to be able to recover from
     /// `grow_in_place` failures without aborting, or to fall back on
     /// another reallocation method before resorting to an abort.
+    #[inline]
     unsafe fn grow_in_place(
         &mut self,
         ptr: NonNull<u8>,
         layout: Layout,
         new_size: usize,
-    ) -> Result<(), CannotReallocInPlace> {
-        let _ = ptr; // this default implementation doesn't care about the actual address.
-        debug_assert!(new_size >= layout.size());
-        let (_l, u) = self.usable_size(&layout);
-        // _l <= layout.size()                       [guaranteed by usable_size()]
-        //       layout.size() <= new_layout.size()  [required by this method]
-        if new_size <= u { Ok(()) } else { Err(CannotReallocInPlace) }
+    ) -> Result<usize, CannotReallocInPlace> {
+        let _ = ptr;
+        let _ = layout;
+        let _ = new_size;
+        Err(CannotReallocInPlace)
     }
 
     /// Behaves like `grow_in_place`, but also ensures that the new
@@ -1110,10 +947,10 @@ unsafe fn grow_in_place_zeroed(
         ptr: NonNull<u8>,
         layout: Layout,
         new_size: usize,
-    ) -> Result<(), CannotReallocInPlace> {
-        self.grow_in_place(ptr, layout, new_size)?;
+    ) -> Result<usize, CannotReallocInPlace> {
+        let size = self.grow_in_place(ptr, layout, new_size)?;
         ptr.as_ptr().add(layout.size()).write_bytes(0, new_size - layout.size());
-        Ok(())
+        Ok(size)
     }
 
     /// Attempts to shrink the allocation referenced by `ptr` to fit `new_size`.
@@ -1121,7 +958,8 @@ unsafe fn grow_in_place_zeroed(
     /// If this returns `Ok`, then the allocator has asserted that the
     /// memory block referenced by `ptr` now fits `new_size`, and
     /// thus can only be used to carry data of that smaller
-    /// layout. (The allocator is allowed to take advantage of this,
+    /// layout. The returned value is the new size the allocated block.
+    /// (The allocator is allowed to take advantage of this,
     /// carving off portions of the block for reuse elsewhere.) The
     /// truncated contents of the block within the smaller layout are
     /// unaltered, and ownership of block has not been transferred.
@@ -1142,8 +980,7 @@ unsafe fn grow_in_place_zeroed(
     /// * `layout` must *fit* the `ptr` (see above); note the
     ///   `new_size` argument need not fit it,
     ///
-    /// * `new_size` must not be greater than `layout.size()`
-    ///   (and must be greater than zero),
+    /// * `new_size` must not be greater than `layout.size()`,
     ///
     /// # Errors
     ///
@@ -1155,17 +992,16 @@ unsafe fn grow_in_place_zeroed(
     /// function; clients are expected either to be able to recover from
     /// `shrink_in_place` failures without aborting, or to fall back
     /// on another reallocation method before resorting to an abort.
+    #[inline]
     unsafe fn shrink_in_place(
         &mut self,
         ptr: NonNull<u8>,
         layout: Layout,
         new_size: usize,
-    ) -> Result<(), CannotReallocInPlace> {
-        let _ = ptr; // this default implementation doesn't care about the actual address.
-        debug_assert!(new_size <= layout.size());
-        let (l, _u) = self.usable_size(&layout);
-        //                      layout.size() <= _u  [guaranteed by usable_size()]
-        // new_layout.size() <= layout.size()        [required by this method]
-        if l <= new_size { Ok(()) } else { Err(CannotReallocInPlace) }
+    ) -> Result<usize, CannotReallocInPlace> {
+        let _ = ptr;
+        let _ = layout;
+        let _ = new_size;
+        Err(CannotReallocInPlace)
     }
 }
index 9ebb317641875ae42b31634c61f3eeff9781cff2..a922d4f118b5afa893beccb3dea507a802b34160 100644 (file)
@@ -958,6 +958,33 @@ pub fn get_mut(&mut self) -> &mut T {
         unsafe { &mut *self.value.get() }
     }
 
+    /// Undo the effect of leaked guards on the borrow state of the `RefCell`.
+    ///
+    /// This call is similar to [`get_mut`] but more specialized. It borrows `RefCell` mutably to
+    /// ensure no borrows exist and then resets the state tracking shared borrows. This is relevant
+    /// if some `Ref` or `RefMut` borrows have been leaked.
+    ///
+    /// [`get_mut`]: #method.get_mut
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(cell_leak)]
+    /// use std::cell::RefCell;
+    ///
+    /// let mut c = RefCell::new(0);
+    /// std::mem::forget(c.borrow_mut());
+    ///
+    /// assert!(c.try_borrow().is_err());
+    /// c.undo_leak();
+    /// assert!(c.try_borrow().is_ok());
+    /// ```
+    #[unstable(feature = "cell_leak", issue = "69099")]
+    pub fn undo_leak(&mut self) -> &mut T {
+        *self.borrow.get_mut() = UNUSED;
+        self.get_mut()
+    }
+
     /// Immutably borrows the wrapped value, returning an error if the value is
     /// currently mutably borrowed.
     ///
@@ -1272,8 +1299,10 @@ pub fn map_split<U: ?Sized, V: ?Sized, F>(orig: Ref<'b, T>, f: F) -> (Ref<'b, U>
     /// ```
     #[unstable(feature = "cell_leak", issue = "69099")]
     pub fn leak(orig: Ref<'b, T>) -> &'b T {
-        // By forgetting this Ref we ensure that the borrow counter in the RefCell never goes back
-        // to UNUSED again. No further mutable references can be created from the original cell.
+        // By forgetting this Ref we ensure that the borrow counter in the RefCell can't go back to
+        // UNUSED within the lifetime `'b`. Resetting the reference tracking state would require a
+        // unique reference to the borrowed RefCell. No further mutable references can be created
+        // from the original cell.
         mem::forget(orig.borrow);
         orig.value
     }
@@ -1387,9 +1416,11 @@ pub fn map_split<U: ?Sized, V: ?Sized, F>(
     /// ```
     #[unstable(feature = "cell_leak", issue = "69099")]
     pub fn leak(orig: RefMut<'b, T>) -> &'b mut T {
-        // By forgetting this BorrowRefMut we ensure that the borrow counter in the RefCell never
-        // goes back to UNUSED again. No further references can be created from the original cell,
-        // making the current borrow the only reference for the remaining lifetime.
+        // By forgetting this BorrowRefMut we ensure that the borrow counter in the RefCell can't
+        // go back to UNUSED within the lifetime `'b`. Resetting the reference tracking state would
+        // require a unique reference to the borrowed RefCell. No further references can be created
+        // from the original cell within that lifetime, making the current borrow the only
+        // reference for the remaining lifetime.
         mem::forget(orig.borrow);
         orig.value
     }
@@ -1538,7 +1569,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 #[lang = "unsafe_cell"]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[repr(transparent)]
-#[cfg_attr(not(bootstrap), repr(no_niche))] // rust-lang/rust#68303.
+#[repr(no_niche)] // rust-lang/rust#68303.
 pub struct UnsafeCell<T: ?Sized> {
     value: T,
 }
index 959fd63df51c2928e7617c9e26f3d439c2b63002..47ab8715cfa14b0aea2a8c396a7afdc30701aa41 100644 (file)
@@ -229,7 +229,7 @@ pub trait AsMut<T: ?Sized> {
 ///
 /// # Implementing [`Into`] for conversions to external types in old versions of Rust
 ///
-/// Prior to Rust 1.40, if the destination type was not part of the current crate
+/// Prior to Rust 1.41, if the destination type was not part of the current crate
 /// then you couldn't implement [`From`] directly.
 /// For example, take this code:
 ///
index 5ef673009bb6d8469d765d081344db442194d33a..52d8349bc9a8770567f4079c2651b205bdaeab73 100644 (file)
@@ -2,8 +2,6 @@
 use crate::mem::MaybeUninit;
 use crate::num::flt2dec;
 
-// ignore-tidy-undocumented-unsafe
-
 // Don't inline this so callers don't use the stack space this function
 // requires unless they have to.
 #[inline(never)]
@@ -16,6 +14,7 @@ fn float_to_decimal_common_exact<T>(
 where
     T: flt2dec::DecodableFloat,
 {
+    // SAFETY: Possible undefined behavior, see FIXME(#53491)
     unsafe {
         let mut buf = MaybeUninit::<[u8; 1024]>::uninit(); // enough for f32 and f64
         let mut parts = MaybeUninit::<[flt2dec::Part<'_>; 4]>::uninit();
@@ -48,6 +47,7 @@ fn float_to_decimal_common_shortest<T>(
 where
     T: flt2dec::DecodableFloat,
 {
+    // SAFETY: Possible undefined behavior, see FIXME(#53491)
     unsafe {
         // enough for f32 and f64
         let mut buf = MaybeUninit::<[u8; flt2dec::MAX_SIG_DIGITS]>::uninit();
@@ -103,6 +103,7 @@ fn float_to_exponential_common_exact<T>(
 where
     T: flt2dec::DecodableFloat,
 {
+    // SAFETY: Possible undefined behavior, see FIXME(#53491)
     unsafe {
         let mut buf = MaybeUninit::<[u8; 1024]>::uninit(); // enough for f32 and f64
         let mut parts = MaybeUninit::<[flt2dec::Part<'_>; 6]>::uninit();
@@ -132,6 +133,7 @@ fn float_to_exponential_common_shortest<T>(
 where
     T: flt2dec::DecodableFloat,
 {
+    // SAFETY: Possible undefined behavior, see FIXME(#53491)
     unsafe {
         // enough for f32 and f64
         let mut buf = MaybeUninit::<[u8; flt2dec::MAX_SIG_DIGITS]>::uninit();
index 993b1073493e9dd731b54217675dc6da4fd0d5fb..a93b34fc46cb935294d5f304d18771e47eeb4dd4 100644 (file)
@@ -1,7 +1,5 @@
 //! Utilities for formatting and printing strings.
 
-// ignore-tidy-undocumented-unsafe
-
 #![stable(feature = "rust1", since = "1.0.0")]
 
 use crate::cell::{Cell, Ref, RefCell, RefMut, UnsafeCell};
@@ -255,7 +253,7 @@ pub struct ArgumentV1<'a> {
     formatter: fn(&Opaque, &mut Formatter<'_>) -> Result,
 }
 
-// This gurantees a single stable value for the function pointer associated with
+// This guarantees a single stable value for the function pointer associated with
 // indices/counts in the formatting infrastructure.
 //
 // Note that a function defined as such would not be correct as functions are
@@ -264,13 +262,31 @@ pub struct ArgumentV1<'a> {
 // could have been miscompiled. In practice, we never call as_usize on non-usize
 // containing data (as a matter of static generation of the formatting
 // arguments), so this is merely an additional check.
+//
+// We primarily want to ensure that the function pointer at `USIZE_MARKER` has
+// an address corresponding *only* to functions that also take `&usize` as their
+// first argument. The read_volatile here ensures that we can safely ready out a
+// usize from the passed reference and that this address does not point at a
+// non-usize taking function.
 #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
-static USIZE_MARKER: fn(&usize, &mut Formatter<'_>) -> Result = |_, _| loop {};
+static USIZE_MARKER: fn(&usize, &mut Formatter<'_>) -> Result = |ptr, _| {
+    // SAFETY: ptr is a reference
+    let _v: usize = unsafe { crate::ptr::read_volatile(ptr) };
+    loop {}
+};
 
 impl<'a> ArgumentV1<'a> {
     #[doc(hidden)]
     #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
     pub fn new<'b, T>(x: &'b T, f: fn(&T, &mut Formatter<'_>) -> Result) -> ArgumentV1<'b> {
+        // SAFETY: `mem::transmute(x)` is safe because
+        //     1. `&'b T` keeps the lifetime it originated with `'b`
+        //              (so as to not have an unbounded lifetime)
+        //     2. `&'b T` and `&'b Void` have the same memory layout
+        //              (when `T` is `Sized`, as it is here)
+        // `mem::transmute(f)` is safe since `fn(&T, &mut Formatter<'_>) -> Result`
+        // and `fn(&Void, &mut Formatter<'_>) -> Result` have the same ABI
+        // (as long as `T` is `Sized`)
         unsafe { ArgumentV1 { formatter: mem::transmute(f), value: mem::transmute(x) } }
     }
 
@@ -1389,6 +1405,14 @@ fn pad_formatted_parts(&mut self, formatted: &flt2dec::Formatted<'_>) -> Result
 
     fn write_formatted_parts(&mut self, formatted: &flt2dec::Formatted<'_>) -> Result {
         fn write_bytes(buf: &mut dyn Write, s: &[u8]) -> Result {
+            // SAFETY: This is used for `flt2dec::Part::Num` and `flt2dec::Part::Copy`.
+            // It's safe to use for `flt2dec::Part::Num` since every char `c` is between
+            // `b'0'` and `b'9'`, which means `s` is valid UTF-8.
+            // It's also probably safe in practice to use for `flt2dec::Part::Copy(buf)`
+            // since `buf` should be plain ASCII, but it's possible for someone to pass
+            // in a bad value for `buf` into `flt2dec::to_shortest_str` since it is a
+            // public function.
+            // FIXME: Determine whether this could result in UB.
             buf.write_str(unsafe { str::from_utf8_unchecked(s) })
         }
 
index 5dfd3a8ecdbd695672699c9621995f40229fac16..7d77e33d743785f1c6f795b51659d411865b684a 100644 (file)
@@ -1,7 +1,5 @@
 //! Integer and floating-point number formatting
 
-// ignore-tidy-undocumented-unsafe
-
 use crate::fmt;
 use crate::mem::MaybeUninit;
 use crate::num::flt2dec;
@@ -84,6 +82,8 @@ fn fmt_int<T: Int>(&self, mut x: T, f: &mut fmt::Formatter<'_>) -> fmt::Result {
             }
         }
         let buf = &buf[curr..];
+        // SAFETY: The only chars in `buf` are created by `Self::digit` which are assumed to be
+        // valid UTF-8
         let buf = unsafe {
             str::from_utf8_unchecked(slice::from_raw_parts(MaybeUninit::first_ptr(buf), buf.len()))
         };
@@ -189,11 +189,19 @@ macro_rules! integer {
 macro_rules! impl_Display {
     ($($t:ident),* as $u:ident via $conv_fn:ident named $name:ident) => {
         fn $name(mut n: $u, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+            // 2^128 is about 3*10^38, so 39 gives an extra byte of space
             let mut buf = [MaybeUninit::<u8>::uninit(); 39];
             let mut curr = buf.len() as isize;
             let buf_ptr = MaybeUninit::first_ptr_mut(&mut buf);
             let lut_ptr = DEC_DIGITS_LUT.as_ptr();
 
+            // SAFETY: Since `d1` and `d2` are always less than or equal to `198`, we
+            // can copy from `lut_ptr[d1..d1 + 1]` and `lut_ptr[d2..d2 + 1]`. To show
+            // that it's OK to copy into `buf_ptr`, notice that at the beginning
+            // `curr == buf.len() == 39 > log(n)` since `n < 2^128 < 10^39`, and at
+            // each step this is kept the same as `n` is divided. Since `n` is always
+            // non-negative, this means that `curr > 0` so `buf_ptr[curr..curr + 1]`
+            // is safe to access.
             unsafe {
                 // need at least 16 bits for the 4-characters-at-a-time to work.
                 assert!(crate::mem::size_of::<$u>() >= 2);
@@ -206,6 +214,10 @@ fn $name(mut n: $u, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Re
                     let d1 = (rem / 100) << 1;
                     let d2 = (rem % 100) << 1;
                     curr -= 4;
+
+                    // We are allowed to copy to `buf_ptr[curr..curr + 3]` here since
+                    // otherwise `curr < 0`. But then `n` was originally at least `10000^10`
+                    // which is `10^40 > 2^128 > n`.
                     ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
                     ptr::copy_nonoverlapping(lut_ptr.offset(d2), buf_ptr.offset(curr + 2), 2);
                 }
@@ -232,6 +244,8 @@ fn $name(mut n: $u, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Re
                 }
             }
 
+            // SAFETY: `curr` > 0 (since we made `buf` large enough), and all the chars are valid
+            // UTF-8 since `DEC_DIGITS_LUT` is
             let buf_slice = unsafe {
                 str::from_utf8_unchecked(
                     slice::from_raw_parts(buf_ptr.offset(curr), buf.len() - curr as usize))
@@ -304,6 +318,8 @@ fn $name(
             };
 
             // 39 digits (worst case u128) + . = 40
+            // Since `curr` always decreases by the number of digits copied, this means
+            // that `curr >= 0`.
             let mut buf = [MaybeUninit::<u8>::uninit(); 40];
             let mut curr = buf.len() as isize; //index for buf
             let buf_ptr = MaybeUninit::first_ptr_mut(&mut buf);
@@ -313,6 +329,8 @@ fn $name(
             while n >= 100 {
                 let d1 = ((n % 100) as isize) << 1;
                 curr -= 2;
+                // SAFETY: `d1 <= 198`, so we can copy from `lut_ptr[d1..d1 + 2]` since
+                // `DEC_DIGITS_LUT` has a length of 200.
                 unsafe {
                     ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
                 }
@@ -324,6 +342,7 @@ fn $name(
             // decode second-to-last character
             if n >= 10 {
                 curr -= 1;
+                // SAFETY: Safe since `40 > curr >= 0` (see comment)
                 unsafe {
                     *buf_ptr.offset(curr) = (n as u8 % 10_u8) + b'0';
                 }
@@ -333,11 +352,13 @@ fn $name(
             // add decimal point iff >1 mantissa digit will be printed
             if exponent != trailing_zeros || added_precision != 0 {
                 curr -= 1;
+                // SAFETY: Safe since `40 > curr >= 0`
                 unsafe {
                     *buf_ptr.offset(curr) = b'.';
                 }
             }
 
+            // SAFETY: Safe since `40 > curr >= 0`
             let buf_slice = unsafe {
                 // decode last character
                 curr -= 1;
@@ -350,6 +371,8 @@ fn $name(
             // stores 'e' (or 'E') and the up to 2-digit exponent
             let mut exp_buf = [MaybeUninit::<u8>::uninit(); 3];
             let exp_ptr = MaybeUninit::first_ptr_mut(&mut exp_buf);
+            // SAFETY: In either case, `exp_buf` is written within bounds and `exp_ptr[..len]`
+            // is contained within `exp_buf` since `len <= 3`.
             let exp_slice = unsafe {
                 *exp_ptr.offset(0) = if upper {b'E'} else {b'e'};
                 let len = if exponent < 10 {
index f14ed38b9b0f27c4c5a39bd8450b466a4d07cc3d..00a171e6b5fb11b19b2bbae03d45da32c2f187f4 100644 (file)
@@ -24,7 +24,6 @@
 /// `.await` the value.
 ///
 /// [`Waker`]: ../task/struct.Waker.html
-#[doc(spotlight)]
 #[must_use = "futures do nothing unless you `.await` or poll them"]
 #[stable(feature = "futures_api", since = "1.36.0")]
 #[lang = "future_trait"]
index 89ea4713cfdaaa43b377e9bc18fa49735940a48b..8dfda7a4a32366447668ff4b6ed79662457be66e 100644 (file)
@@ -2,6 +2,84 @@
 
 //! Asynchronous values.
 
+#[cfg(not(bootstrap))]
+use crate::{
+    ops::{Generator, GeneratorState},
+    pin::Pin,
+    ptr::NonNull,
+    task::{Context, Poll},
+};
+
 mod future;
 #[stable(feature = "futures_api", since = "1.36.0")]
 pub use self::future::Future;
+
+/// This type is needed because:
+///
+/// a) Generators cannot implement `for<'a, 'b> Generator<&'a mut Context<'b>>`, so we need to pass
+///    a raw pointer (see https://github.com/rust-lang/rust/issues/68923).
+/// b) Raw pointers and `NonNull` aren't `Send` or `Sync`, so that would make every single future
+///    non-Send/Sync as well, and we don't want that.
+///
+/// It also simplifies the HIR lowering of `.await`.
+#[doc(hidden)]
+#[unstable(feature = "gen_future", issue = "50547")]
+#[cfg(not(bootstrap))]
+#[derive(Debug, Copy, Clone)]
+pub struct ResumeTy(NonNull<Context<'static>>);
+
+#[unstable(feature = "gen_future", issue = "50547")]
+#[cfg(not(bootstrap))]
+unsafe impl Send for ResumeTy {}
+
+#[unstable(feature = "gen_future", issue = "50547")]
+#[cfg(not(bootstrap))]
+unsafe impl Sync for ResumeTy {}
+
+/// Wrap a generator in a future.
+///
+/// This function returns a `GenFuture` underneath, but hides it in `impl Trait` to give
+/// better error messages (`impl Future` rather than `GenFuture<[closure.....]>`).
+// This is `const` to avoid extra errors after we recover from `const async fn`
+#[doc(hidden)]
+#[unstable(feature = "gen_future", issue = "50547")]
+#[cfg(not(bootstrap))]
+#[inline]
+pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
+where
+    T: Generator<ResumeTy, Yield = ()>,
+{
+    struct GenFuture<T: Generator<ResumeTy, Yield = ()>>(T);
+
+    // We rely on the fact that async/await futures are immovable in order to create
+    // self-referential borrows in the underlying generator.
+    impl<T: Generator<ResumeTy, Yield = ()>> !Unpin for GenFuture<T> {}
+
+    impl<T: Generator<ResumeTy, Yield = ()>> Future for GenFuture<T> {
+        type Output = T::Return;
+        fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+            // Safety: Safe because we're !Unpin + !Drop, and this is just a field projection.
+            let gen = unsafe { Pin::map_unchecked_mut(self, |s| &mut s.0) };
+
+            // Resume the generator, turning the `&mut Context` into a `NonNull` raw pointer. The
+            // `.await` lowering will safely cast that back to a `&mut Context`.
+            match gen.resume(ResumeTy(NonNull::from(cx).cast::<Context<'static>>())) {
+                GeneratorState::Yielded(()) => Poll::Pending,
+                GeneratorState::Complete(x) => Poll::Ready(x),
+            }
+        }
+    }
+
+    GenFuture(gen)
+}
+
+#[doc(hidden)]
+#[unstable(feature = "gen_future", issue = "50547")]
+#[cfg(not(bootstrap))]
+#[inline]
+pub unsafe fn poll_with_context<F>(f: Pin<&mut F>, mut cx: ResumeTy) -> Poll<F::Output>
+where
+    F: Future,
+{
+    F::poll(f, cx.0.as_mut())
+}
index aa50e7cdf578d5bae60bd9a5ecb2ed36d502faaf..adfbe243512bd5bb00c1e0ab7665c57579bb1d7b 100644 (file)
@@ -220,37 +220,6 @@ fn reset(&mut self) {
         self.state.v3 = self.k1 ^ 0x7465646279746573;
         self.ntail = 0;
     }
-
-    // Specialized write function that is only valid for buffers with len <= 8.
-    // It's used to force inlining of write_u8 and write_usize, those would normally be inlined
-    // except for composite types (that includes slices and str hashing because of delimiter).
-    // Without this extra push the compiler is very reluctant to inline delimiter writes,
-    // degrading performance substantially for the most common use cases.
-    #[inline]
-    fn short_write(&mut self, msg: &[u8]) {
-        debug_assert!(msg.len() <= 8);
-        let length = msg.len();
-        self.length += length;
-
-        let needed = 8 - self.ntail;
-        let fill = cmp::min(length, needed);
-        if fill == 8 {
-            self.tail = unsafe { load_int_le!(msg, 0, u64) };
-        } else {
-            self.tail |= unsafe { u8to64_le(msg, 0, fill) } << (8 * self.ntail);
-            if length < needed {
-                self.ntail += length;
-                return;
-            }
-        }
-        self.state.v3 ^= self.tail;
-        S::c_rounds(&mut self.state);
-        self.state.v0 ^= self.tail;
-
-        // Buffered tail is now flushed, process new input.
-        self.ntail = length - needed;
-        self.tail = unsafe { u8to64_le(msg, needed, self.ntail) };
-    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -280,21 +249,13 @@ fn finish(&self) -> u64 {
 }
 
 impl<S: Sip> super::Hasher for Hasher<S> {
-    // see short_write comment for explanation
-    #[inline]
-    fn write_usize(&mut self, i: usize) {
-        let bytes = unsafe {
-            crate::slice::from_raw_parts(&i as *const usize as *const u8, mem::size_of::<usize>())
-        };
-        self.short_write(bytes);
-    }
-
-    // see short_write comment for explanation
-    #[inline]
-    fn write_u8(&mut self, i: u8) {
-        self.short_write(&[i]);
-    }
-
+    // Note: no integer hashing methods (`write_u*`, `write_i*`) are defined
+    // for this type. We could add them, copy the `short_write` implementation
+    // in librustc_data_structures/sip128.rs, and add `write_u*`/`write_i*`
+    // methods to `SipHasher`, `SipHasher13`, and `DefaultHasher`. This would
+    // greatly speed up integer hashing by those hashers, at the cost of
+    // slightly slowing down compile speeds on some benchmarks. See #69152 for
+    // details.
     #[inline]
     fn write(&mut self, msg: &[u8]) {
         let length = msg.len();
index fca2c3d31d946e348d2969325ec861e779e6c088..f7ecbd80cbcdce94c02d257938d19260e37bb6ef 100644 (file)
@@ -68,6 +68,7 @@
     // memory, which is not valid for either `&` or `&mut`.
 
     /// Stores a value if the current value is the same as the `old` value.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `compare_exchange` method by passing
     /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html)
@@ -77,6 +78,7 @@
     /// [compare_exchange]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange
     pub fn atomic_cxchg<T>(dst: *mut T, old: T, src: T) -> (T, bool);
     /// Stores a value if the current value is the same as the `old` value.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `compare_exchange` method by passing
     /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html)
@@ -86,6 +88,7 @@
     /// [compare_exchange]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange
     pub fn atomic_cxchg_acq<T>(dst: *mut T, old: T, src: T) -> (T, bool);
     /// Stores a value if the current value is the same as the `old` value.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `compare_exchange` method by passing
     /// [`Ordering::Release`](../../std/sync/atomic/enum.Ordering.html)
     /// [compare_exchange]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange
     pub fn atomic_cxchg_rel<T>(dst: *mut T, old: T, src: T) -> (T, bool);
     /// Stores a value if the current value is the same as the `old` value.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `compare_exchange` method by passing
     /// [`Ordering::AcqRel`](../../std/sync/atomic/enum.Ordering.html)
     /// [compare_exchange]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange
     pub fn atomic_cxchg_acqrel<T>(dst: *mut T, old: T, src: T) -> (T, bool);
     /// Stores a value if the current value is the same as the `old` value.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `compare_exchange` method by passing
     /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html)
     /// [compare_exchange]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange
     pub fn atomic_cxchg_relaxed<T>(dst: *mut T, old: T, src: T) -> (T, bool);
     /// Stores a value if the current value is the same as the `old` value.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `compare_exchange` method by passing
     /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html)
     /// [compare_exchange]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange
     pub fn atomic_cxchg_failrelaxed<T>(dst: *mut T, old: T, src: T) -> (T, bool);
     /// Stores a value if the current value is the same as the `old` value.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `compare_exchange` method by passing
     /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html)
     /// [compare_exchange]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange
     pub fn atomic_cxchg_failacq<T>(dst: *mut T, old: T, src: T) -> (T, bool);
     /// Stores a value if the current value is the same as the `old` value.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `compare_exchange` method by passing
     /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html)
     /// [compare_exchange]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange
     pub fn atomic_cxchg_acq_failrelaxed<T>(dst: *mut T, old: T, src: T) -> (T, bool);
     /// Stores a value if the current value is the same as the `old` value.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `compare_exchange` method by passing
     /// [`Ordering::AcqRel`](../../std/sync/atomic/enum.Ordering.html)
     pub fn atomic_cxchg_acqrel_failrelaxed<T>(dst: *mut T, old: T, src: T) -> (T, bool);
 
     /// Stores a value if the current value is the same as the `old` value.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `compare_exchange_weak` method by passing
     /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html)
     /// [cew]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak
     pub fn atomic_cxchgweak<T>(dst: *mut T, old: T, src: T) -> (T, bool);
     /// Stores a value if the current value is the same as the `old` value.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `compare_exchange_weak` method by passing
     /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html)
     /// [cew]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak
     pub fn atomic_cxchgweak_acq<T>(dst: *mut T, old: T, src: T) -> (T, bool);
     /// Stores a value if the current value is the same as the `old` value.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `compare_exchange_weak` method by passing
     /// [`Ordering::Release`](../../std/sync/atomic/enum.Ordering.html)
     /// [cew]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak
     pub fn atomic_cxchgweak_rel<T>(dst: *mut T, old: T, src: T) -> (T, bool);
     /// Stores a value if the current value is the same as the `old` value.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `compare_exchange_weak` method by passing
     /// [`Ordering::AcqRel`](../../std/sync/atomic/enum.Ordering.html)
     /// [cew]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak
     pub fn atomic_cxchgweak_acqrel<T>(dst: *mut T, old: T, src: T) -> (T, bool);
     /// Stores a value if the current value is the same as the `old` value.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `compare_exchange_weak` method by passing
     /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html)
     /// [cew]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak
     pub fn atomic_cxchgweak_relaxed<T>(dst: *mut T, old: T, src: T) -> (T, bool);
     /// Stores a value if the current value is the same as the `old` value.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `compare_exchange_weak` method by passing
     /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html)
     /// [cew]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak
     pub fn atomic_cxchgweak_failrelaxed<T>(dst: *mut T, old: T, src: T) -> (T, bool);
     /// Stores a value if the current value is the same as the `old` value.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `compare_exchange_weak` method by passing
     /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html)
     /// [cew]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak
     pub fn atomic_cxchgweak_failacq<T>(dst: *mut T, old: T, src: T) -> (T, bool);
     /// Stores a value if the current value is the same as the `old` value.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `compare_exchange_weak` method by passing
     /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html)
     /// [cew]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak
     pub fn atomic_cxchgweak_acq_failrelaxed<T>(dst: *mut T, old: T, src: T) -> (T, bool);
     /// Stores a value if the current value is the same as the `old` value.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `compare_exchange_weak` method by passing
     /// [`Ordering::AcqRel`](../../std/sync/atomic/enum.Ordering.html)
     pub fn atomic_cxchgweak_acqrel_failrelaxed<T>(dst: *mut T, old: T, src: T) -> (T, bool);
 
     /// Loads the current value of the pointer.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `load` method by passing
     /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html)
     /// [`AtomicBool::load`](../../std/sync/atomic/struct.AtomicBool.html#method.load).
     pub fn atomic_load<T>(src: *const T) -> T;
     /// Loads the current value of the pointer.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `load` method by passing
     /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html)
     /// [`AtomicBool::load`](../../std/sync/atomic/struct.AtomicBool.html#method.load).
     pub fn atomic_load_acq<T>(src: *const T) -> T;
     /// Loads the current value of the pointer.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `load` method by passing
     /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html)
     pub fn atomic_load_unordered<T>(src: *const T) -> T;
 
     /// Stores the value at the specified memory location.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `store` method by passing
     /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html)
     /// [`AtomicBool::store`](../../std/sync/atomic/struct.AtomicBool.html#method.store).
     pub fn atomic_store<T>(dst: *mut T, val: T);
     /// Stores the value at the specified memory location.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `store` method by passing
     /// [`Ordering::Release`](../../std/sync/atomic/enum.Ordering.html)
     /// [`AtomicBool::store`](../../std/sync/atomic/struct.AtomicBool.html#method.store).
     pub fn atomic_store_rel<T>(dst: *mut T, val: T);
     /// Stores the value at the specified memory location.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `store` method by passing
     /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html)
     pub fn atomic_store_unordered<T>(dst: *mut T, val: T);
 
     /// Stores the value at the specified memory location, returning the old value.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `swap` method by passing
     /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html)
     /// [`AtomicBool::swap`](../../std/sync/atomic/struct.AtomicBool.html#method.swap).
     pub fn atomic_xchg<T>(dst: *mut T, src: T) -> T;
     /// Stores the value at the specified memory location, returning the old value.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `swap` method by passing
     /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html)
     /// [`AtomicBool::swap`](../../std/sync/atomic/struct.AtomicBool.html#method.swap).
     pub fn atomic_xchg_acq<T>(dst: *mut T, src: T) -> T;
     /// Stores the value at the specified memory location, returning the old value.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `swap` method by passing
     /// [`Ordering::Release`](../../std/sync/atomic/enum.Ordering.html)
     /// [`AtomicBool::swap`](../../std/sync/atomic/struct.AtomicBool.html#method.swap).
     pub fn atomic_xchg_rel<T>(dst: *mut T, src: T) -> T;
     /// Stores the value at the specified memory location, returning the old value.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `swap` method by passing
     /// [`Ordering::AcqRel`](../../std/sync/atomic/enum.Ordering.html)
     /// [`AtomicBool::swap`](../../std/sync/atomic/struct.AtomicBool.html#method.swap).
     pub fn atomic_xchg_acqrel<T>(dst: *mut T, src: T) -> T;
     /// Stores the value at the specified memory location, returning the old value.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `swap` method by passing
     /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html)
     pub fn atomic_xchg_relaxed<T>(dst: *mut T, src: T) -> T;
 
     /// Adds to the current value, returning the previous value.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `fetch_add` method by passing
     /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html)
     /// [`AtomicIsize::fetch_add`](../../std/sync/atomic/struct.AtomicIsize.html#method.fetch_add).
     pub fn atomic_xadd<T>(dst: *mut T, src: T) -> T;
     /// Adds to the current value, returning the previous value.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `fetch_add` method by passing
     /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html)
     /// [`AtomicIsize::fetch_add`](../../std/sync/atomic/struct.AtomicIsize.html#method.fetch_add).
     pub fn atomic_xadd_acq<T>(dst: *mut T, src: T) -> T;
     /// Adds to the current value, returning the previous value.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `fetch_add` method by passing
     /// [`Ordering::Release`](../../std/sync/atomic/enum.Ordering.html)
     /// [`AtomicIsize::fetch_add`](../../std/sync/atomic/struct.AtomicIsize.html#method.fetch_add).
     pub fn atomic_xadd_rel<T>(dst: *mut T, src: T) -> T;
     /// Adds to the current value, returning the previous value.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `fetch_add` method by passing
     /// [`Ordering::AcqRel`](../../std/sync/atomic/enum.Ordering.html)
     /// [`AtomicIsize::fetch_add`](../../std/sync/atomic/struct.AtomicIsize.html#method.fetch_add).
     pub fn atomic_xadd_acqrel<T>(dst: *mut T, src: T) -> T;
     /// Adds to the current value, returning the previous value.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `fetch_add` method by passing
     /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html)
     pub fn atomic_xadd_relaxed<T>(dst: *mut T, src: T) -> T;
 
     /// Subtract from the current value, returning the previous value.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `fetch_sub` method by passing
     /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html)
     /// [`AtomicIsize::fetch_sub`](../../std/sync/atomic/struct.AtomicIsize.html#method.fetch_sub).
     pub fn atomic_xsub<T>(dst: *mut T, src: T) -> T;
     /// Subtract from the current value, returning the previous value.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `fetch_sub` method by passing
     /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html)
     /// [`AtomicIsize::fetch_sub`](../../std/sync/atomic/struct.AtomicIsize.html#method.fetch_sub).
     pub fn atomic_xsub_acq<T>(dst: *mut T, src: T) -> T;
     /// Subtract from the current value, returning the previous value.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `fetch_sub` method by passing
     /// [`Ordering::Release`](../../std/sync/atomic/enum.Ordering.html)
     /// [`AtomicIsize::fetch_sub`](../../std/sync/atomic/struct.AtomicIsize.html#method.fetch_sub).
     pub fn atomic_xsub_rel<T>(dst: *mut T, src: T) -> T;
     /// Subtract from the current value, returning the previous value.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `fetch_sub` method by passing
     /// [`Ordering::AcqRel`](../../std/sync/atomic/enum.Ordering.html)
     /// [`AtomicIsize::fetch_sub`](../../std/sync/atomic/struct.AtomicIsize.html#method.fetch_sub).
     pub fn atomic_xsub_acqrel<T>(dst: *mut T, src: T) -> T;
     /// Subtract from the current value, returning the previous value.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `fetch_sub` method by passing
     /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html)
     pub fn atomic_xsub_relaxed<T>(dst: *mut T, src: T) -> T;
 
     /// Bitwise and with the current value, returning the previous value.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `fetch_and` method by passing
     /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html)
     /// [`AtomicBool::fetch_and`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_and).
     pub fn atomic_and<T>(dst: *mut T, src: T) -> T;
     /// Bitwise and with the current value, returning the previous value.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `fetch_and` method by passing
     /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html)
     /// [`AtomicBool::fetch_and`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_and).
     pub fn atomic_and_acq<T>(dst: *mut T, src: T) -> T;
     /// Bitwise and with the current value, returning the previous value.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `fetch_and` method by passing
     /// [`Ordering::Release`](../../std/sync/atomic/enum.Ordering.html)
     /// [`AtomicBool::fetch_and`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_and).
     pub fn atomic_and_rel<T>(dst: *mut T, src: T) -> T;
     /// Bitwise and with the current value, returning the previous value.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `fetch_and` method by passing
     /// [`Ordering::AcqRel`](../../std/sync/atomic/enum.Ordering.html)
     /// [`AtomicBool::fetch_and`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_and).
     pub fn atomic_and_acqrel<T>(dst: *mut T, src: T) -> T;
     /// Bitwise and with the current value, returning the previous value.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `fetch_and` method by passing
     /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html)
     pub fn atomic_and_relaxed<T>(dst: *mut T, src: T) -> T;
 
     /// Bitwise nand with the current value, returning the previous value.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic::AtomicBool` type via the `fetch_nand` method by passing
     /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html)
     /// [`AtomicBool::fetch_nand`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_nand).
     pub fn atomic_nand<T>(dst: *mut T, src: T) -> T;
     /// Bitwise nand with the current value, returning the previous value.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic::AtomicBool` type via the `fetch_nand` method by passing
     /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html)
     /// [`AtomicBool::fetch_nand`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_nand).
     pub fn atomic_nand_acq<T>(dst: *mut T, src: T) -> T;
     /// Bitwise nand with the current value, returning the previous value.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic::AtomicBool` type via the `fetch_nand` method by passing
     /// [`Ordering::Release`](../../std/sync/atomic/enum.Ordering.html)
     /// [`AtomicBool::fetch_nand`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_nand).
     pub fn atomic_nand_rel<T>(dst: *mut T, src: T) -> T;
     /// Bitwise nand with the current value, returning the previous value.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic::AtomicBool` type via the `fetch_nand` method by passing
     /// [`Ordering::AcqRel`](../../std/sync/atomic/enum.Ordering.html)
     /// [`AtomicBool::fetch_nand`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_nand).
     pub fn atomic_nand_acqrel<T>(dst: *mut T, src: T) -> T;
     /// Bitwise nand with the current value, returning the previous value.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic::AtomicBool` type via the `fetch_nand` method by passing
     /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html)
     pub fn atomic_nand_relaxed<T>(dst: *mut T, src: T) -> T;
 
     /// Bitwise or with the current value, returning the previous value.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `fetch_or` method by passing
     /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html)
     /// [`AtomicBool::fetch_or`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_or).
     pub fn atomic_or<T>(dst: *mut T, src: T) -> T;
     /// Bitwise or with the current value, returning the previous value.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `fetch_or` method by passing
     /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html)
     /// [`AtomicBool::fetch_or`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_or).
     pub fn atomic_or_acq<T>(dst: *mut T, src: T) -> T;
     /// Bitwise or with the current value, returning the previous value.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `fetch_or` method by passing
     /// [`Ordering::Release`](../../std/sync/atomic/enum.Ordering.html)
     /// [`AtomicBool::fetch_or`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_or).
     pub fn atomic_or_rel<T>(dst: *mut T, src: T) -> T;
     /// Bitwise or with the current value, returning the previous value.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `fetch_or` method by passing
     /// [`Ordering::AcqRel`](../../std/sync/atomic/enum.Ordering.html)
     /// [`AtomicBool::fetch_or`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_or).
     pub fn atomic_or_acqrel<T>(dst: *mut T, src: T) -> T;
     /// Bitwise or with the current value, returning the previous value.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `fetch_or` method by passing
     /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html)
     pub fn atomic_or_relaxed<T>(dst: *mut T, src: T) -> T;
 
     /// Bitwise xor with the current value, returning the previous value.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `fetch_xor` method by passing
     /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html)
     /// [`AtomicBool::fetch_xor`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_xor).
     pub fn atomic_xor<T>(dst: *mut T, src: T) -> T;
     /// Bitwise xor with the current value, returning the previous value.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `fetch_xor` method by passing
     /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html)
     /// [`AtomicBool::fetch_xor`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_xor).
     pub fn atomic_xor_acq<T>(dst: *mut T, src: T) -> T;
     /// Bitwise xor with the current value, returning the previous value.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `fetch_xor` method by passing
     /// [`Ordering::Release`](../../std/sync/atomic/enum.Ordering.html)
     /// [`AtomicBool::fetch_xor`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_xor).
     pub fn atomic_xor_rel<T>(dst: *mut T, src: T) -> T;
     /// Bitwise xor with the current value, returning the previous value.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `fetch_xor` method by passing
     /// [`Ordering::AcqRel`](../../std/sync/atomic/enum.Ordering.html)
     /// [`AtomicBool::fetch_xor`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_xor).
     pub fn atomic_xor_acqrel<T>(dst: *mut T, src: T) -> T;
     /// Bitwise xor with the current value, returning the previous value.
+    ///
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `fetch_xor` method by passing
     /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html)
     /// [`AtomicBool::fetch_xor`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_xor).
     pub fn atomic_xor_relaxed<T>(dst: *mut T, src: T) -> T;
 
+    /// Maximum with the current value using a signed comparison.
+    ///
+    /// The stabilized version of this intrinsic is available on the
+    /// `std::sync::atomic` signed integer types via the `fetch_max` method by passing
+    /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html#variant.SeqCst)
+    /// as the `order`. For example,
+    /// [`AtomicI32::fetch_max`](../../std/sync/atomic/struct.AtomicI32.html#method.fetch_max).
     pub fn atomic_max<T>(dst: *mut T, src: T) -> T;
+    /// Maximum with the current value using a signed comparison.
+    ///
+    /// The stabilized version of this intrinsic is available on the
+    /// `std::sync::atomic` signed integer types via the `fetch_max` method by passing
+    /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html#variant.Acquire)
+    /// as the `order`. For example,
+    /// [`AtomicI32::fetch_max`](../../std/sync/atomic/struct.AtomicI32.html#method.fetch_max).
     pub fn atomic_max_acq<T>(dst: *mut T, src: T) -> T;
+    /// Maximum with the current value using a signed comparison.
+    ///
+    /// The stabilized version of this intrinsic is available on the
+    /// `std::sync::atomic` signed integer types via the `fetch_max` method by passing
+    /// [`Ordering::Release`](../../std/sync/atomic/enum.Ordering.html#variant.Release)
+    /// as the `order`. For example,
+    /// [`AtomicI32::fetch_max`](../../std/sync/atomic/struct.AtomicI32.html#method.fetch_max).
     pub fn atomic_max_rel<T>(dst: *mut T, src: T) -> T;
+    /// Maximum with the current value using a signed comparison.
+    ///
+    /// The stabilized version of this intrinsic is available on the
+    /// `std::sync::atomic` signed integer types via the `fetch_max` method by passing
+    /// [`Ordering::AcqRel`](../../std/sync/atomic/enum.Ordering.html#variant.AcqRel)
+    /// as the `order`. For example,
+    /// [`AtomicI32::fetch_max`](../../std/sync/atomic/struct.AtomicI32.html#method.fetch_max).
     pub fn atomic_max_acqrel<T>(dst: *mut T, src: T) -> T;
+    /// Maximum with the current value.
+    ///
+    /// The stabilized version of this intrinsic is available on the
+    /// `std::sync::atomic` signed integer types via the `fetch_max` method by passing
+    /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html#variant.Relaxed)
+    /// as the `order`. For example,
+    /// [`AtomicI32::fetch_max`](../../std/sync/atomic/struct.AtomicI32.html#method.fetch_max).
     pub fn atomic_max_relaxed<T>(dst: *mut T, src: T) -> T;
 
+    /// Minimum with the current value using a signed comparison.
+    ///
+    /// The stabilized version of this intrinsic is available on the
+    /// `std::sync::atomic` signed integer types via the `fetch_min` method by passing
+    /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html#variant.SeqCst)
+    /// as the `order`. For example,
+    /// [`AtomicI32::fetch_min`](../../std/sync/atomic/struct.AtomicI32.html#method.fetch_min).
     pub fn atomic_min<T>(dst: *mut T, src: T) -> T;
+    /// Minimum with the current value using a signed comparison.
+    ///
+    /// The stabilized version of this intrinsic is available on the
+    /// `std::sync::atomic` signed integer types via the `fetch_min` method by passing
+    /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html#variant.Acquire)
+    /// as the `order`. For example,
+    /// [`AtomicI32::fetch_min`](../../std/sync/atomic/struct.AtomicI32.html#method.fetch_min).
     pub fn atomic_min_acq<T>(dst: *mut T, src: T) -> T;
+    /// Minimum with the current value using a signed comparison.
+    ///
+    /// The stabilized version of this intrinsic is available on the
+    /// `std::sync::atomic` signed integer types via the `fetch_min` method by passing
+    /// [`Ordering::Release`](../../std/sync/atomic/enum.Ordering.html#variant.Release)
+    /// as the `order`. For example,
+    /// [`AtomicI32::fetch_min`](../../std/sync/atomic/struct.AtomicI32.html#method.fetch_min).
     pub fn atomic_min_rel<T>(dst: *mut T, src: T) -> T;
+    /// Minimum with the current value using a signed comparison.
+    ///
+    /// The stabilized version of this intrinsic is available on the
+    /// `std::sync::atomic` signed integer types via the `fetch_min` method by passing
+    /// [`Ordering::AcqRel`](../../std/sync/atomic/enum.Ordering.html#variant.AcqRel)
+    /// as the `order`. For example,
+    /// [`AtomicI32::fetch_min`](../../std/sync/atomic/struct.AtomicI32.html#method.fetch_min).
     pub fn atomic_min_acqrel<T>(dst: *mut T, src: T) -> T;
+    /// Minimum with the current value using a signed comparison.
+    ///
+    /// The stabilized version of this intrinsic is available on the
+    /// `std::sync::atomic` signed integer types via the `fetch_min` method by passing
+    /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html#variant.Relaxed)
+    /// as the `order`. For example,
+    /// [`AtomicI32::fetch_min`](../../std/sync/atomic/struct.AtomicI32.html#method.fetch_min).
     pub fn atomic_min_relaxed<T>(dst: *mut T, src: T) -> T;
 
+    /// Minimum with the current value using an unsigned comparison.
+    ///
+    /// The stabilized version of this intrinsic is available on the
+    /// `std::sync::atomic` unsigned integer types via the `fetch_min` method by passing
+    /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html#variant.SeqCst)
+    /// as the `order`. For example,
+    /// [`AtomicU32::fetch_min`](../../std/sync/atomic/struct.AtomicU32.html#method.fetch_min).
     pub fn atomic_umin<T>(dst: *mut T, src: T) -> T;
+    /// Minimum with the current value using an unsigned comparison.
+    ///
+    /// The stabilized version of this intrinsic is available on the
+    /// `std::sync::atomic` unsigned integer types via the `fetch_min` method by passing
+    /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html#variant.Acquire)
+    /// as the `order`. For example,
+    /// [`AtomicU32::fetch_min`](../../std/sync/atomic/struct.AtomicU32.html#method.fetch_min).
     pub fn atomic_umin_acq<T>(dst: *mut T, src: T) -> T;
+    /// Minimum with the current value using an unsigned comparison.
+    ///
+    /// The stabilized version of this intrinsic is available on the
+    /// `std::sync::atomic` unsigned integer types via the `fetch_min` method by passing
+    /// [`Ordering::Release`](../../std/sync/atomic/enum.Ordering.html#variant.Release)
+    /// as the `order`. For example,
+    /// [`AtomicU32::fetch_min`](../../std/sync/atomic/struct.AtomicU32.html#method.fetch_min).
     pub fn atomic_umin_rel<T>(dst: *mut T, src: T) -> T;
+    /// Minimum with the current value using an unsigned comparison.
+    ///
+    /// The stabilized version of this intrinsic is available on the
+    /// `std::sync::atomic` unsigned integer types via the `fetch_min` method by passing
+    /// [`Ordering::AcqRel`](../../std/sync/atomic/enum.Ordering.html#variant.AcqRel)
+    /// as the `order`. For example,
+    /// [`AtomicU32::fetch_min`](../../std/sync/atomic/struct.AtomicU32.html#method.fetch_min).
     pub fn atomic_umin_acqrel<T>(dst: *mut T, src: T) -> T;
+    /// Minimum with the current value using an unsigned comparison.
+    ///
+    /// The stabilized version of this intrinsic is available on the
+    /// `std::sync::atomic` unsigned integer types via the `fetch_min` method by passing
+    /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html#variant.Relaxed)
+    /// as the `order`. For example,
+    /// [`AtomicU32::fetch_min`](../../std/sync/atomic/struct.AtomicU32.html#method.fetch_min).
     pub fn atomic_umin_relaxed<T>(dst: *mut T, src: T) -> T;
 
+    /// Maximum with the current value using an unsigned comparison.
+    ///
+    /// The stabilized version of this intrinsic is available on the
+    /// `std::sync::atomic` unsigned integer types via the `fetch_max` method by passing
+    /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html#variant.SeqCst)
+    /// as the `order`. For example,
+    /// [`AtomicU32::fetch_max`](../../std/sync/atomic/struct.AtomicU32.html#method.fetch_max).
     pub fn atomic_umax<T>(dst: *mut T, src: T) -> T;
+    /// Maximum with the current value using an unsigned comparison.
+    ///
+    /// The stabilized version of this intrinsic is available on the
+    /// `std::sync::atomic` unsigned integer types via the `fetch_max` method by passing
+    /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html#variant.Acquire)
+    /// as the `order`. For example,
+    /// [`AtomicU32::fetch_max`](../../std/sync/atomic/struct.AtomicU32.html#method.fetch_max).
     pub fn atomic_umax_acq<T>(dst: *mut T, src: T) -> T;
+    /// Maximum with the current value using an unsigned comparison.
+    ///
+    /// The stabilized version of this intrinsic is available on the
+    /// `std::sync::atomic` unsigned integer types via the `fetch_max` method by passing
+    /// [`Ordering::Release`](../../std/sync/atomic/enum.Ordering.html#variant.Release)
+    /// as the `order`. For example,
+    /// [`AtomicU32::fetch_max`](../../std/sync/atomic/struct.AtomicU32.html#method.fetch_max).
     pub fn atomic_umax_rel<T>(dst: *mut T, src: T) -> T;
+    /// Maximum with the current value using an unsigned comparison.
+    ///
+    /// The stabilized version of this intrinsic is available on the
+    /// `std::sync::atomic` unsigned integer types via the `fetch_max` method by passing
+    /// [`Ordering::AcqRel`](../../std/sync/atomic/enum.Ordering.html#variant.AcqRel)
+    /// as the `order`. For example,
+    /// [`AtomicU32::fetch_max`](../../std/sync/atomic/struct.AtomicU32.html#method.fetch_max).
     pub fn atomic_umax_acqrel<T>(dst: *mut T, src: T) -> T;
+    /// Maximum with the current value using an unsigned comparison.
+    ///
+    /// The stabilized version of this intrinsic is available on the
+    /// `std::sync::atomic` unsigned integer types via the `fetch_max` method by passing
+    /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html#variant.Relaxed)
+    /// as the `order`. For example,
+    /// [`AtomicU32::fetch_max`](../../std/sync/atomic/struct.AtomicU32.html#method.fetch_max).
     pub fn atomic_umax_relaxed<T>(dst: *mut T, src: T) -> T;
 
     /// The `prefetch` intrinsic is a hint to the code generator to insert a prefetch instruction
 
 extern "rust-intrinsic" {
 
+    /// An atomic fence.
+    ///
+    /// The stabilized version of this intrinsic is available in
+    /// [`std::sync::atomic::fence`](../../std/sync/atomic/fn.fence.html)
+    /// by passing
+    /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html#variant.SeqCst)
+    /// as the `order`.
     pub fn atomic_fence();
+    /// An atomic fence.
+    ///
+    /// The stabilized version of this intrinsic is available in
+    /// [`std::sync::atomic::fence`](../../std/sync/atomic/fn.fence.html)
+    /// by passing
+    /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html#variant.Acquire)
+    /// as the `order`.
     pub fn atomic_fence_acq();
+    /// An atomic fence.
+    ///
+    /// The stabilized version of this intrinsic is available in
+    /// [`std::sync::atomic::fence`](../../std/sync/atomic/fn.fence.html)
+    /// by passing
+    /// [`Ordering::Release`](../../std/sync/atomic/enum.Ordering.html#variant.Release)
+    /// as the `order`.
     pub fn atomic_fence_rel();
+    /// An atomic fence.
+    ///
+    /// The stabilized version of this intrinsic is available in
+    /// [`std::sync::atomic::fence`](../../std/sync/atomic/fn.fence.html)
+    /// by passing
+    /// [`Ordering::AcqRel`](../../std/sync/atomic/enum.Ordering.html#variant.AcqRel)
+    /// as the `order`.
     pub fn atomic_fence_acqrel();
 
     /// A compiler-only memory barrier.
     /// compiler, but no instructions will be emitted for it. This is
     /// appropriate for operations on the same thread that may be preempted,
     /// such as when interacting with signal handlers.
+    ///
+    /// The stabilized version of this intrinsic is available in
+    /// [`std::sync::atomic::compiler_fence`](../../std/sync/atomic/fn.compiler_fence.html)
+    /// by passing
+    /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html#variant.SeqCst)
+    /// as the `order`.
     pub fn atomic_singlethreadfence();
+    /// A compiler-only memory barrier.
+    ///
+    /// Memory accesses will never be reordered across this barrier by the
+    /// compiler, but no instructions will be emitted for it. This is
+    /// appropriate for operations on the same thread that may be preempted,
+    /// such as when interacting with signal handlers.
+    ///
+    /// The stabilized version of this intrinsic is available in
+    /// [`std::sync::atomic::compiler_fence`](../../std/sync/atomic/fn.compiler_fence.html)
+    /// by passing
+    /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html#variant.Acquire)
+    /// as the `order`.
     pub fn atomic_singlethreadfence_acq();
+    /// A compiler-only memory barrier.
+    ///
+    /// Memory accesses will never be reordered across this barrier by the
+    /// compiler, but no instructions will be emitted for it. This is
+    /// appropriate for operations on the same thread that may be preempted,
+    /// such as when interacting with signal handlers.
+    ///
+    /// The stabilized version of this intrinsic is available in
+    /// [`std::sync::atomic::compiler_fence`](../../std/sync/atomic/fn.compiler_fence.html)
+    /// by passing
+    /// [`Ordering::Release`](../../std/sync/atomic/enum.Ordering.html#variant.Release)
+    /// as the `order`.
     pub fn atomic_singlethreadfence_rel();
+    /// A compiler-only memory barrier.
+    ///
+    /// Memory accesses will never be reordered across this barrier by the
+    /// compiler, but no instructions will be emitted for it. This is
+    /// appropriate for operations on the same thread that may be preempted,
+    /// such as when interacting with signal handlers.
+    ///
+    /// The stabilized version of this intrinsic is available in
+    /// [`std::sync::atomic::compiler_fence`](../../std/sync/atomic/fn.compiler_fence.html)
+    /// by passing
+    /// [`Ordering::AcqRel`](../../std/sync/atomic/enum.Ordering.html#variant.AcqRel)
+    /// as the `order`.
     pub fn atomic_singlethreadfence_acqrel();
 
     /// Magic intrinsic that derives its meaning from attributes
     /// Moves a value to an uninitialized memory location.
     ///
     /// Drop glue is not run on the destination.
+    ///
+    /// The stabilized version of this intrinsic is
+    /// [`std::ptr::write`](../../std/ptr/fn.write.html).
     pub fn move_val_init<T>(dst: *mut T, src: T);
 
+    /// The minimum alignment of a type.
+    ///
+    /// The stabilized version of this intrinsic is
+    /// [`std::mem::align_of`](../../std/mem/fn.align_of.html).
     #[rustc_const_stable(feature = "const_min_align_of", since = "1.40.0")]
     pub fn min_align_of<T>() -> usize;
     #[rustc_const_unstable(feature = "const_pref_align_of", issue = "none")]
     /// The stabilized version of this intrinsic is
     /// [`std::mem::size_of_val`](../../std/mem/fn.size_of_val.html).
     pub fn size_of_val<T: ?Sized>(_: &T) -> usize;
+    /// The minimum alignment of the type of the value that `val` points to.
+    ///
+    /// The stabilized version of this intrinsic is
+    /// [`std::mem::min_align_of_val`](../../std/mem/fn.min_align_of_val.html).
     pub fn min_align_of_val<T: ?Sized>(_: &T) -> usize;
 
     /// Gets a static string slice containing the name of a type.
+    ///
+    /// The stabilized version of this intrinsic is
+    /// [`std::any::type_name`](../../std/any/fn.type_name.html)
     #[rustc_const_unstable(feature = "const_type_name", issue = "none")]
     pub fn type_name<T: ?Sized>() -> &'static str;
 
     /// Gets an identifier which is globally unique to the specified type. This
     /// function will return the same value for a type regardless of whichever
     /// crate it is invoked in.
+    ///
+    /// The stabilized version of this intrinsic is
+    /// [`std::any::TypeId::of`](../../std/any/struct.TypeId.html#method.of)
     #[rustc_const_unstable(feature = "const_type_id", issue = "none")]
     pub fn type_id<T: ?Sized + 'static>() -> u64;
 
     /// A guard for unsafe functions that cannot ever be executed if `T` is uninhabited:
     /// This will statically either panic, or do nothing.
+    #[cfg(bootstrap)]
     pub fn panic_if_uninhabited<T>();
 
+    /// A guard for unsafe functions that cannot ever be executed if `T` is uninhabited:
+    /// This will statically either panic, or do nothing.
+    #[cfg(not(bootstrap))]
+    pub fn assert_inhabited<T>();
+
+    /// A guard for unsafe functions that cannot ever be executed if `T` does not permit
+    /// zero-initialization: This will statically either panic, or do nothing.
+    #[cfg(not(bootstrap))]
+    pub fn assert_zero_valid<T>();
+
+    /// A guard for unsafe functions that cannot ever be executed if `T` has invalid
+    /// bit patterns: This will statically either panic, or do nothing.
+    #[cfg(not(bootstrap))]
+    pub fn assert_uninit_valid<T>();
+
     /// Gets a reference to a static `Location` indicating where it was called.
     #[rustc_const_unstable(feature = "const_caller_location", issue = "47809")]
     pub fn caller_location() -> &'static crate::panic::Location<'static>;
 
-    /// Creates a value initialized to zero.
-    ///
-    /// `init` is unsafe because it returns a zeroed-out datum,
-    /// which is unsafe unless `T` is `Copy`. Also, even if T is
-    /// `Copy`, an all-zero value may not correspond to any legitimate
-    /// state for the type in question.
-    #[unstable(
-        feature = "core_intrinsics",
-        reason = "intrinsics are unlikely to ever be stabilized, instead \
-                         they should be used through stabilized interfaces \
-                         in the rest of the standard library",
-        issue = "none"
-    )]
-    #[rustc_deprecated(reason = "superseded by MaybeUninit, removal planned", since = "1.38.0")]
-    pub fn init<T>() -> T;
-
-    /// Creates an uninitialized value.
-    ///
-    /// `uninit` is unsafe because there is no guarantee of what its
-    /// contents are. In particular its drop-flag may be set to any
-    /// state, which means it may claim either dropped or
-    /// undropped. In the general case one must use `ptr::write` to
-    /// initialize memory previous set to the result of `uninit`.
-    #[unstable(
-        feature = "core_intrinsics",
-        reason = "intrinsics are unlikely to ever be stabilized, instead \
-                         they should be used through stabilized interfaces \
-                         in the rest of the standard library",
-        issue = "none"
-    )]
-    #[rustc_deprecated(reason = "superseded by MaybeUninit, removal planned", since = "1.38.0")]
-    pub fn uninit<T>() -> T;
-
     /// Moves a value out of scope without running drop glue.
+    /// This exists solely for `mem::forget_unsized`; normal `forget` uses `ManuallyDrop` instead.
     pub fn forget<T: ?Sized>(_: T);
 
     /// Reinterprets the bits of a value of one type as another type.
     /// byte past the end of an allocated object. If either pointer is out of
     /// bounds or arithmetic overflow occurs then any further use of the
     /// returned value will result in undefined behavior.
+    ///
+    /// The stabilized version of this intrinsic is
+    /// [`std::pointer::offset`](../../std/primitive.pointer.html#method.offset).
     pub fn offset<T>(dst: *const T, offset: isize) -> *const T;
 
     /// Calculates the offset from a pointer, potentially wrapping.
     /// resulting pointer to point into or one byte past the end of an allocated
     /// object, and it wraps with two's complement arithmetic. The resulting
     /// value is not necessarily valid to be used to actually access memory.
+    ///
+    /// The stabilized version of this intrinsic is
+    /// [`std::pointer::wrapping_offset`](../../std/primitive.pointer.html#method.wrapping_offset).
     pub fn arith_offset<T>(dst: *const T, offset: isize) -> *const T;
 
     /// Equivalent to the appropriate `llvm.memcpy.p0i8.0i8.*` intrinsic, with
     pub fn volatile_set_memory<T>(dst: *mut T, val: u8, count: usize);
 
     /// Performs a volatile load from the `src` pointer.
+    ///
     /// The stabilized version of this intrinsic is
     /// [`std::ptr::read_volatile`](../../std/ptr/fn.read_volatile.html).
     pub fn volatile_load<T>(src: *const T) -> T;
     /// Performs a volatile store to the `dst` pointer.
+    ///
     /// The stabilized version of this intrinsic is
     /// [`std::ptr::write_volatile`](../../std/ptr/fn.write_volatile.html).
     pub fn volatile_store<T>(dst: *mut T, val: T);
     pub fn unaligned_volatile_store<T>(dst: *mut T, val: T);
 
     /// Returns the square root of an `f32`
+    ///
+    /// The stabilized version of this intrinsic is
+    /// [`std::f32::sqrt`](../../std/primitive.f32.html#method.sqrt)
     pub fn sqrtf32(x: f32) -> f32;
     /// Returns the square root of an `f64`
+    ///
+    /// The stabilized version of this intrinsic is
+    /// [`std::f64::sqrt`](../../std/primitive.f64.html#method.sqrt)
     pub fn sqrtf64(x: f64) -> f64;
 
     /// Raises an `f32` to an integer power.
+    ///
+    /// The stabilized version of this intrinsic is
+    /// [`std::f32::powi`](../../std/primitive.f32.html#method.powi)
     pub fn powif32(a: f32, x: i32) -> f32;
     /// Raises an `f64` to an integer power.
+    ///
+    /// The stabilized version of this intrinsic is
+    /// [`std::f64::powi`](../../std/primitive.f64.html#method.powi)
     pub fn powif64(a: f64, x: i32) -> f64;
 
     /// Returns the sine of an `f32`.
+    ///
+    /// The stabilized version of this intrinsic is
+    /// [`std::f32::sin`](../../std/primitive.f32.html#method.sin)
     pub fn sinf32(x: f32) -> f32;
     /// Returns the sine of an `f64`.
+    ///
+    /// The stabilized version of this intrinsic is
+    /// [`std::f64::sin`](../../std/primitive.f64.html#method.sin)
     pub fn sinf64(x: f64) -> f64;
 
     /// Returns the cosine of an `f32`.
+    ///
+    /// The stabilized version of this intrinsic is
+    /// [`std::f32::cos`](../../std/primitive.f32.html#method.cos)
     pub fn cosf32(x: f32) -> f32;
     /// Returns the cosine of an `f64`.
+    ///
+    /// The stabilized version of this intrinsic is
+    /// [`std::f64::cos`](../../std/primitive.f64.html#method.cos)
     pub fn cosf64(x: f64) -> f64;
 
     /// Raises an `f32` to an `f32` power.
+    ///
+    /// The stabilized version of this intrinsic is
+    /// [`std::f32::powf`](../../std/primitive.f32.html#method.powf)
     pub fn powf32(a: f32, x: f32) -> f32;
     /// Raises an `f64` to an `f64` power.
+    ///
+    /// The stabilized version of this intrinsic is
+    /// [`std::f64::powf`](../../std/primitive.f64.html#method.powf)
     pub fn powf64(a: f64, x: f64) -> f64;
 
     /// Returns the exponential of an `f32`.
+    ///
+    /// The stabilized version of this intrinsic is
+    /// [`std::f32::exp`](../../std/primitive.f32.html#method.exp)
     pub fn expf32(x: f32) -> f32;
     /// Returns the exponential of an `f64`.
+    ///
+    /// The stabilized version of this intrinsic is
+    /// [`std::f64::exp`](../../std/primitive.f64.html#method.exp)
     pub fn expf64(x: f64) -> f64;
 
     /// Returns 2 raised to the power of an `f32`.
+    ///
+    /// The stabilized version of this intrinsic is
+    /// [`std::f32::exp2`](../../std/primitive.f32.html#method.exp2)
     pub fn exp2f32(x: f32) -> f32;
     /// Returns 2 raised to the power of an `f64`.
+    ///
+    /// The stabilized version of this intrinsic is
+    /// [`std::f64::exp2`](../../std/primitive.f64.html#method.exp2)
     pub fn exp2f64(x: f64) -> f64;
 
     /// Returns the natural logarithm of an `f32`.
+    ///
+    /// The stabilized version of this intrinsic is
+    /// [`std::f32::ln`](../../std/primitive.f32.html#method.ln)
     pub fn logf32(x: f32) -> f32;
     /// Returns the natural logarithm of an `f64`.
+    ///
+    /// The stabilized version of this intrinsic is
+    /// [`std::f64::ln`](../../std/primitive.f64.html#method.ln)
     pub fn logf64(x: f64) -> f64;
 
     /// Returns the base 10 logarithm of an `f32`.
+    ///
+    /// The stabilized version of this intrinsic is
+    /// [`std::f32::log10`](../../std/primitive.f32.html#method.log10)
     pub fn log10f32(x: f32) -> f32;
     /// Returns the base 10 logarithm of an `f64`.
+    ///
+    /// The stabilized version of this intrinsic is
+    /// [`std::f64::log10`](../../std/primitive.f64.html#method.log10)
     pub fn log10f64(x: f64) -> f64;
 
     /// Returns the base 2 logarithm of an `f32`.
+    ///
+    /// The stabilized version of this intrinsic is
+    /// [`std::f32::log2`](../../std/primitive.f32.html#method.log2)
     pub fn log2f32(x: f32) -> f32;
     /// Returns the base 2 logarithm of an `f64`.
+    ///
+    /// The stabilized version of this intrinsic is
+    /// [`std::f64::log2`](../../std/primitive.f64.html#method.log2)
     pub fn log2f64(x: f64) -> f64;
 
     /// Returns `a * b + c` for `f32` values.
+    ///
+    /// The stabilized version of this intrinsic is
+    /// [`std::f32::mul_add`](../../std/primitive.f32.html#method.mul_add)
     pub fn fmaf32(a: f32, b: f32, c: f32) -> f32;
     /// Returns `a * b + c` for `f64` values.
+    ///
+    /// The stabilized version of this intrinsic is
+    /// [`std::f64::mul_add`](../../std/primitive.f64.html#method.mul_add)
     pub fn fmaf64(a: f64, b: f64, c: f64) -> f64;
 
     /// Returns the absolute value of an `f32`.
+    ///
+    /// The stabilized version of this intrinsic is
+    /// [`std::f32::abs`](../../std/primitive.f32.html#method.abs)
     pub fn fabsf32(x: f32) -> f32;
     /// Returns the absolute value of an `f64`.
+    ///
+    /// The stabilized version of this intrinsic is
+    /// [`std::f64::abs`](../../std/primitive.f64.html#method.abs)
     pub fn fabsf64(x: f64) -> f64;
 
     /// Returns the minimum of two `f32` values.
+    ///
+    /// The stabilized version of this intrinsic is
+    /// [`std::f32::min`](../../std/primitive.f32.html#method.min)
     pub fn minnumf32(x: f32, y: f32) -> f32;
     /// Returns the minimum of two `f64` values.
+    ///
+    /// The stabilized version of this intrinsic is
+    /// [`std::f64::min`](../../std/primitive.f64.html#method.min)
     pub fn minnumf64(x: f64, y: f64) -> f64;
     /// Returns the maximum of two `f32` values.
+    ///
+    /// The stabilized version of this intrinsic is
+    /// [`std::f32::max`](../../std/primitive.f32.html#method.max)
     pub fn maxnumf32(x: f32, y: f32) -> f32;
     /// Returns the maximum of two `f64` values.
+    ///
+    /// The stabilized version of this intrinsic is
+    /// [`std::f64::max`](../../std/primitive.f64.html#method.max)
     pub fn maxnumf64(x: f64, y: f64) -> f64;
 
     /// Copies the sign from `y` to `x` for `f32` values.
+    ///
+    /// The stabilized version of this intrinsic is
+    /// [`std::f32::copysign`](../../std/primitive.f32.html#method.copysign)
     pub fn copysignf32(x: f32, y: f32) -> f32;
     /// Copies the sign from `y` to `x` for `f64` values.
+    ///
+    /// The stabilized version of this intrinsic is
+    /// [`std::f64::copysign`](../../std/primitive.f64.html#method.copysign)
     pub fn copysignf64(x: f64, y: f64) -> f64;
 
     /// Returns the largest integer less than or equal to an `f32`.
+    ///
+    /// The stabilized version of this intrinsic is
+    /// [`std::f32::floor`](../../std/primitive.f32.html#method.floor)
     pub fn floorf32(x: f32) -> f32;
     /// Returns the largest integer less than or equal to an `f64`.
+    ///
+    /// The stabilized version of this intrinsic is
+    /// [`std::f64::floor`](../../std/primitive.f64.html#method.floor)
     pub fn floorf64(x: f64) -> f64;
 
     /// Returns the smallest integer greater than or equal to an `f32`.
+    ///
+    /// The stabilized version of this intrinsic is
+    /// [`std::f32::ceil`](../../std/primitive.f32.html#method.ceil)
     pub fn ceilf32(x: f32) -> f32;
     /// Returns the smallest integer greater than or equal to an `f64`.
+    ///
+    /// The stabilized version of this intrinsic is
+    /// [`std::f64::ceil`](../../std/primitive.f64.html#method.ceil)
     pub fn ceilf64(x: f64) -> f64;
 
     /// Returns the integer part of an `f32`.
+    ///
+    /// The stabilized version of this intrinsic is
+    /// [`std::f32::trunc`](../../std/primitive.f32.html#method.trunc)
     pub fn truncf32(x: f32) -> f32;
     /// Returns the integer part of an `f64`.
+    ///
+    /// The stabilized version of this intrinsic is
+    /// [`std::f64::trunc`](../../std/primitive.f64.html#method.trunc)
     pub fn truncf64(x: f64) -> f64;
 
     /// Returns the nearest integer to an `f32`. May raise an inexact floating-point exception
     pub fn nearbyintf64(x: f64) -> f64;
 
     /// Returns the nearest integer to an `f32`. Rounds half-way cases away from zero.
+    ///
+    /// The stabilized version of this intrinsic is
+    /// [`std::f32::round`](../../std/primitive.f32.html#method.round)
     pub fn roundf32(x: f32) -> f32;
     /// Returns the nearest integer to an `f64`. Rounds half-way cases away from zero.
+    ///
+    /// The stabilized version of this intrinsic is
+    /// [`std::f64::round`](../../std/primitive.f64.html#method.round)
     pub fn roundf64(x: f64) -> f64;
 
     /// Float addition that allows optimizations based on algebraic rules.
     pub fn frem_fast<T>(a: T, b: T) -> T;
 
     /// Convert with LLVM’s fptoui/fptosi, which may return undef for values out of range
-    /// https://github.com/rust-lang/rust/issues/10184
+    /// (<https://github.com/rust-lang/rust/issues/10184>)
+    /// This is under stabilization at <https://github.com/rust-lang/rust/issues/67058>
     pub fn float_to_int_approx_unchecked<Float, Int>(value: Float) -> Int;
 
     /// Returns the number of bits set in an integer type `T`
+    ///
+    /// The stabilized versions of this intrinsic are available on the integer
+    /// primitives via the `count_ones` method. For example,
+    /// [`std::u32::count_ones`](../../std/primitive.u32.html#method.count_ones)
     #[rustc_const_stable(feature = "const_ctpop", since = "1.40.0")]
     pub fn ctpop<T>(x: T) -> T;
 
     /// Returns the number of leading unset bits (zeroes) in an integer type `T`.
     ///
+    /// The stabilized versions of this intrinsic are available on the integer
+    /// primitives via the `leading_zeros` method. For example,
+    /// [`std::u32::leading_zeros`](../../std/primitive.u32.html#method.leading_zeros)
+    ///
     /// # Examples
     ///
     /// ```
 
     /// Returns the number of trailing unset bits (zeroes) in an integer type `T`.
     ///
+    /// The stabilized versions of this intrinsic are available on the integer
+    /// primitives via the `trailing_zeros` method. For example,
+    /// [`std::u32::trailing_zeros`](../../std/primitive.u32.html#method.trailing_zeros)
+    ///
     /// # Examples
     ///
     /// ```
     pub fn cttz_nonzero<T>(x: T) -> T;
 
     /// Reverses the bytes in an integer type `T`.
+    ///
+    /// The stabilized versions of this intrinsic are available on the integer
+    /// primitives via the `swap_bytes` method. For example,
+    /// [`std::u32::swap_bytes`](../../std/primitive.u32.html#method.swap_bytes)
     #[rustc_const_stable(feature = "const_bswap", since = "1.40.0")]
     pub fn bswap<T>(x: T) -> T;
 
     /// Reverses the bits in an integer type `T`.
+    ///
+    /// The stabilized versions of this intrinsic are available on the integer
+    /// primitives via the `reverse_bits` method. For example,
+    /// [`std::u32::reverse_bits`](../../std/primitive.u32.html#method.reverse_bits)
     #[rustc_const_stable(feature = "const_bitreverse", since = "1.40.0")]
     pub fn bitreverse<T>(x: T) -> T;
 
     /// Performs checked integer addition.
+    ///
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `overflowing_add` method. For example,
     /// [`std::u32::overflowing_add`](../../std/primitive.u32.html#method.overflowing_add)
     pub fn add_with_overflow<T>(x: T, y: T) -> (T, bool);
 
     /// Performs checked integer subtraction
+    ///
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `overflowing_sub` method. For example,
     /// [`std::u32::overflowing_sub`](../../std/primitive.u32.html#method.overflowing_sub)
     pub fn sub_with_overflow<T>(x: T, y: T) -> (T, bool);
 
     /// Performs checked integer multiplication
+    ///
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `overflowing_mul` method. For example,
     /// [`std::u32::overflowing_mul`](../../std/primitive.u32.html#method.overflowing_mul)
 
     /// Performs an unchecked division, resulting in undefined behavior
     /// where y = 0 or x = `T::min_value()` and y = -1
+    ///
+    /// The stabilized versions of this intrinsic are available on the integer
+    /// primitives via the `checked_div` method. For example,
+    /// [`std::u32::checked_div`](../../std/primitive.u32.html#method.checked_div)
     #[rustc_const_unstable(feature = "const_int_unchecked_arith", issue = "none")]
     pub fn unchecked_div<T>(x: T, y: T) -> T;
     /// Returns the remainder of an unchecked division, resulting in
     /// undefined behavior where y = 0 or x = `T::min_value()` and y = -1
+    ///
+    /// The stabilized versions of this intrinsic are available on the integer
+    /// primitives via the `checked_rem` method. For example,
+    /// [`std::u32::checked_rem`](../../std/primitive.u32.html#method.checked_rem)
     #[rustc_const_unstable(feature = "const_int_unchecked_arith", issue = "none")]
     pub fn unchecked_rem<T>(x: T, y: T) -> T;
 
     /// Performs an unchecked left shift, resulting in undefined behavior when
     /// y < 0 or y >= N, where N is the width of T in bits.
+    ///
+    /// The stabilized versions of this intrinsic are available on the integer
+    /// primitives via the `checked_shl` method. For example,
+    /// [`std::u32::checked_shl`](../../std/primitive.u32.html#method.checked_shl)
     #[rustc_const_stable(feature = "const_int_unchecked", since = "1.40.0")]
     pub fn unchecked_shl<T>(x: T, y: T) -> T;
     /// Performs an unchecked right shift, resulting in undefined behavior when
     /// y < 0 or y >= N, where N is the width of T in bits.
+    ///
+    /// The stabilized versions of this intrinsic are available on the integer
+    /// primitives via the `checked_shr` method. For example,
+    /// [`std::u32::checked_shr`](../../std/primitive.u32.html#method.checked_shr)
     #[rustc_const_stable(feature = "const_int_unchecked", since = "1.40.0")]
     pub fn unchecked_shr<T>(x: T, y: T) -> T;
 
     pub fn unchecked_mul<T>(x: T, y: T) -> T;
 
     /// Performs rotate left.
+    ///
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `rotate_left` method. For example,
     /// [`std::u32::rotate_left`](../../std/primitive.u32.html#method.rotate_left)
     pub fn rotate_left<T>(x: T, y: T) -> T;
 
     /// Performs rotate right.
+    ///
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `rotate_right` method. For example,
     /// [`std::u32::rotate_right`](../../std/primitive.u32.html#method.rotate_right)
     pub fn rotate_right<T>(x: T, y: T) -> T;
 
     /// Returns (a + b) mod 2<sup>N</sup>, where N is the width of T in bits.
+    ///
     /// The stabilized versions of this intrinsic are available on the integer
-    /// primitives via the `wrapping_add` method. For example,
-    /// [`std::u32::wrapping_add`](../../std/primitive.u32.html#method.wrapping_add)
+    /// primitives via the `checked_add` method. For example,
+    /// [`std::u32::checked_add`](../../std/primitive.u32.html#method.checked_add)
     #[rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0")]
     pub fn wrapping_add<T>(a: T, b: T) -> T;
     /// Returns (a - b) mod 2<sup>N</sup>, where N is the width of T in bits.
+    ///
     /// The stabilized versions of this intrinsic are available on the integer
-    /// primitives via the `wrapping_sub` method. For example,
-    /// [`std::u32::wrapping_sub`](../../std/primitive.u32.html#method.wrapping_sub)
+    /// primitives via the `checked_sub` method. For example,
+    /// [`std::u32::checked_sub`](../../std/primitive.u32.html#method.checked_sub)
     #[rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0")]
     pub fn wrapping_sub<T>(a: T, b: T) -> T;
     /// Returns (a * b) mod 2<sup>N</sup>, where N is the width of T in bits.
+    ///
     /// The stabilized versions of this intrinsic are available on the integer
-    /// primitives via the `wrapping_mul` method. For example,
-    /// [`std::u32::wrapping_mul`](../../std/primitive.u32.html#method.wrapping_mul)
+    /// primitives via the `checked_mul` method. For example,
+    /// [`std::u32::checked_mul`](../../std/primitive.u32.html#method.checked_mul)
     #[rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0")]
     pub fn wrapping_mul<T>(a: T, b: T) -> T;
 
     /// Computes `a + b`, while saturating at numeric bounds.
+    ///
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `saturating_add` method. For example,
     /// [`std::u32::saturating_add`](../../std/primitive.u32.html#method.saturating_add)
     #[rustc_const_stable(feature = "const_int_saturating", since = "1.40.0")]
     pub fn saturating_add<T>(a: T, b: T) -> T;
     /// Computes `a - b`, while saturating at numeric bounds.
+    ///
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `saturating_sub` method. For example,
     /// [`std::u32::saturating_sub`](../../std/primitive.u32.html#method.saturating_sub)
 
     /// Returns the value of the discriminant for the variant in 'v',
     /// cast to a `u64`; if `T` has no discriminant, returns 0.
+    ///
+    /// The stabilized version of this intrinsic is
+    /// [`std::mem::discriminant`](../../std/mem/fn.discriminant.html)
+    #[rustc_const_unstable(feature = "const_discriminant", issue = "69821")]
     pub fn discriminant_value<T>(v: &T) -> u64;
 
-    /// Rust's "try catch" construct which invokes the function pointer `f` with
-    /// the data pointer `data`.
+    /// Rust's "try catch" construct which invokes the function pointer `try_fn`
+    /// with the data pointer `data`.
     ///
-    /// The third pointer is a target-specific data pointer which is filled in
-    /// with the specifics of the exception that occurred. For examples on Unix
-    /// platforms this is a `*mut *mut T` which is filled in by the compiler and
-    /// on MSVC it's `*mut [usize; 2]`. For more information see the compiler's
+    /// The third argument is a function called if a panic occurs. This function
+    /// takes the data pointer and a pointer to the target-specific exception
+    /// object that was caught. For more information see the compiler's
     /// source as well as std's catch implementation.
+    #[cfg(not(bootstrap))]
+    pub fn r#try(try_fn: fn(*mut u8), data: *mut u8, catch_fn: fn(*mut u8, *mut u8)) -> i32;
+    #[cfg(bootstrap)]
     pub fn r#try(f: fn(*mut u8), data: *mut u8, local_ptr: *mut u8) -> i32;
 
     /// Emits a `!nontemporal` store according to LLVM (see their docs).
     pub fn ptr_offset_from<T>(ptr: *const T, base: *const T) -> isize;
 
     /// Internal hook used by Miri to implement unwinding.
-    /// Compiles to a NOP during non-Miri codegen.
+    /// ICEs when encountered during non-Miri codegen.
+    ///
+    /// The `payload` ptr here will be exactly the one `do_catch` gets passed by `try`.
     ///
-    /// Perma-unstable: do not use
-    pub fn miri_start_panic(data: *mut (dyn crate::any::Any + crate::marker::Send)) -> ();
+    /// Perma-unstable: do not use.
+    pub fn miri_start_panic(payload: *mut u8) -> !;
 }
 
 // Some functions are defined here because they accidentally got made
index 0a7a9f26f891257211a68aff95006aed783eb152..4202e52448dcfc358a865fb4cb9fe58d404a870e 100644 (file)
@@ -1,7 +1,7 @@
 use crate::fmt;
 use crate::ops::Try;
 
-use super::super::{DoubleEndedIterator, FusedIterator, Iterator};
+use super::super::{DoubleEndedIterator, Fuse, FusedIterator, Iterator};
 use super::Map;
 
 /// An iterator that maps each element to an iterator, and yields the elements
@@ -239,14 +239,17 @@ impl<I, U> FusedIterator for Flatten<I>
 /// this type.
 #[derive(Clone, Debug)]
 struct FlattenCompat<I, U> {
-    iter: I,
+    iter: Fuse<I>,
     frontiter: Option<U>,
     backiter: Option<U>,
 }
-impl<I, U> FlattenCompat<I, U> {
+impl<I, U> FlattenCompat<I, U>
+where
+    I: Iterator,
+{
     /// Adapts an iterator by flattening it, for use in `flatten()` and `flat_map()`.
     fn new(iter: I) -> FlattenCompat<I, U> {
-        FlattenCompat { iter, frontiter: None, backiter: None }
+        FlattenCompat { iter: iter.fuse(), frontiter: None, backiter: None }
     }
 }
 
@@ -261,8 +264,9 @@ impl<I, U> Iterator for FlattenCompat<I, U>
     fn next(&mut self) -> Option<U::Item> {
         loop {
             if let Some(ref mut inner) = self.frontiter {
-                if let elt @ Some(_) = inner.next() {
-                    return elt;
+                match inner.next() {
+                    None => self.frontiter = None,
+                    elt @ Some(_) => return elt,
                 }
             }
             match self.iter.next() {
@@ -348,8 +352,9 @@ impl<I, U> DoubleEndedIterator for FlattenCompat<I, U>
     fn next_back(&mut self) -> Option<U::Item> {
         loop {
             if let Some(ref mut inner) = self.backiter {
-                if let elt @ Some(_) = inner.next_back() {
-                    return elt;
+                match inner.next_back() {
+                    None => self.backiter = None,
+                    elt @ Some(_) => return elt,
                 }
             }
             match self.iter.next_back() {
index 58606531a1acee91d4a98f07ee89bc56d51b63d7..3c0ddcb2bc871022d9a7bd1d2372d3ece86bbdc8 100644 (file)
@@ -200,6 +200,18 @@ fn fold<Acc, F>(self, init: Acc, f: F) -> Acc
     {
         self.it.fold(init, copy_fold(f))
     }
+
+    fn nth(&mut self, n: usize) -> Option<T> {
+        self.it.nth(n).copied()
+    }
+
+    fn last(self) -> Option<T> {
+        self.it.last().copied()
+    }
+
+    fn count(self) -> usize {
+        self.it.count()
+    }
 }
 
 #[stable(feature = "iter_copied", since = "1.36.0")]
@@ -1468,7 +1480,11 @@ impl<I> DoubleEndedIterator for Peekable<I>
 {
     #[inline]
     fn next_back(&mut self) -> Option<Self::Item> {
-        self.iter.next_back().or_else(|| self.peeked.take().and_then(|x| x))
+        match self.peeked.as_mut() {
+            Some(v @ Some(_)) => self.iter.next_back().or_else(|| v.take()),
+            Some(None) => None,
+            None => self.iter.next_back(),
+        }
     }
 
     #[inline]
@@ -1894,9 +1910,7 @@ fn nth(&mut self, n: usize) -> Option<I::Item> {
             let to_skip = self.n;
             self.n = 0;
             // nth(n) skips n+1
-            if self.iter.nth(to_skip - 1).is_none() {
-                return None;
-            }
+            self.iter.nth(to_skip - 1)?;
         }
         self.iter.nth(n)
     }
@@ -1916,9 +1930,7 @@ fn count(mut self) -> usize {
     fn last(mut self) -> Option<I::Item> {
         if self.n > 0 {
             // nth(n) skips n+1
-            if self.iter.nth(self.n - 1).is_none() {
-                return None;
-            }
+            self.iter.nth(self.n - 1)?;
         }
         self.iter.last()
     }
index 5fa9962f811c532eb7a39ffd5fd2ed1d7ddc3421..080b70c6368b286bf80f5636300001df18c2b4d0 100644 (file)
@@ -43,7 +43,7 @@
 //! are elements, and once they've all been exhausted, will return `None` to
 //! indicate that iteration is finished. Individual iterators may choose to
 //! resume iteration, and so calling [`next`] again may or may not eventually
-//! start returning `Some(Item)` again at some point.
+//! start returning `Some(Item)` again at some point (for example, see [`TryIter`]).
 //!
 //! [`Iterator`]'s full definition includes a number of other methods as well,
 //! but they are default methods, built on top of [`next`], and so you get
@@ -56,6 +56,7 @@
 //! [`Iterator`]: trait.Iterator.html
 //! [`next`]: trait.Iterator.html#tymethod.next
 //! [`Option`]: ../../std/option/enum.Option.html
+//! [`TryIter`]: ../../std/sync/mpsc/struct.TryIter.html
 //!
 //! # The three forms of iteration
 //!
index 4a7db348b18516c51c51f64fd091e41da85ce35f..ad87d09588e3a217fbda625eced1c2493a9b3667 100644 (file)
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait ExactSizeIterator: Iterator {
-    /// Returns the exact number of times the iterator will iterate.
+    /// Returns the exact length of the iterator.
     ///
+    /// The implementation ensures that the iterator will return exactly `len()`
+    /// more times a `Some(T)` value, before returning `None`.
     /// This method has a default implementation, so you usually should not
     /// implement it directly. However, if you can provide a more efficient
     /// implementation, you can do so. See the [trait-level] docs for an
index 6a529bfc8df97f8ad4644bb1e622e252927133e0..e2ebef9c6ce2f0dda4ab7fed0e06d1a8719b7af1 100644 (file)
@@ -92,7 +92,6 @@ fn _assert_is_object_safe(_: &dyn Iterator<Item = ()>) {}
     label = "`{Self}` is not an iterator",
     message = "`{Self}` is not an iterator"
 )]
-#[doc(spotlight)]
 #[must_use = "iterators are lazy and do nothing unless consumed"]
 pub trait Iterator {
     /// The type of the elements being iterated over.
index 7bd1d00e84ca1e184339949ecbdea7c120e31b44..94fc2fd357a06d424679e424d9264ca421752fde 100644 (file)
@@ -72,6 +72,7 @@
 #![feature(concat_idents)]
 #![feature(const_ascii_ctype_on_intrinsics)]
 #![feature(const_alloc_layout)]
+#![feature(const_discriminant)]
 #![feature(const_if_match)]
 #![feature(const_loop)]
 #![feature(const_checked_int_methods)]
@@ -90,7 +91,6 @@
 #![feature(custom_inner_attributes)]
 #![feature(decl_macro)]
 #![feature(doc_cfg)]
-#![feature(doc_spotlight)]
 #![feature(extern_types)]
 #![feature(fundamental)]
 #![feature(intrinsics)]
 #![feature(rtm_target_feature)]
 #![feature(f16c_target_feature)]
 #![feature(hexagon_target_feature)]
-#![feature(const_int_conversion)]
 #![feature(const_transmute)]
 #![feature(structural_match)]
 #![feature(abi_unadjusted)]
 #![feature(associated_type_bounds)]
 #![feature(const_type_id)]
 #![feature(const_caller_location)]
-#![feature(assoc_int_consts)]
-#![cfg_attr(not(bootstrap), feature(no_niche))] // rust-lang/rust#68303
+#![feature(option_zip)]
+#![feature(no_niche)] // rust-lang/rust#68303
 
 #[prelude_import]
 #[allow(unused)]
 #[macro_use]
 mod int_macros;
 
-#[path = "num/uint_macros.rs"]
-#[macro_use]
-mod uint_macros;
-
 #[path = "num/i128.rs"]
 pub mod i128;
 #[path = "num/i16.rs"]
index 76e58f0cc62bcdab060c396ee46cf45bffce3e3a..a0873fe6b625d2158457805239dabeea915ad5e8 100644 (file)
@@ -1,3 +1,4 @@
+#[cfg(bootstrap)]
 #[doc(include = "panic.md")]
 #[macro_export]
 #[allow_internal_unstable(core_panic, track_caller)]
@@ -20,6 +21,26 @@ macro_rules! panic {
     );
 }
 
+#[cfg(not(bootstrap))]
+#[doc(include = "panic.md")]
+#[macro_export]
+#[allow_internal_unstable(core_panic, track_caller)]
+#[stable(feature = "core", since = "1.6.0")]
+macro_rules! panic {
+    () => (
+        $crate::panic!("explicit panic")
+    );
+    ($msg:expr) => (
+        $crate::panicking::panic($msg)
+    );
+    ($msg:expr,) => (
+        $crate::panic!($msg)
+    );
+    ($fmt:expr, $($arg:tt)+) => (
+        $crate::panicking::panic_fmt($crate::format_args!($fmt, $($arg)+))
+    );
+}
+
 /// Asserts that two expressions are equal to each other (using [`PartialEq`]).
 ///
 /// On panic, this macro will print the values of the expressions with their
@@ -1383,6 +1404,18 @@ macro_rules! trace_macros {
         /* compiler built-in */
     }
 
+    /// Keeps the item it's applied to if the passed path is accessible, and removes it otherwise.
+    #[cfg(not(bootstrap))]
+    #[unstable(
+        feature = "cfg_accessible",
+        issue = "64797",
+        reason = "`cfg_accessible` is not fully implemented"
+    )]
+    #[rustc_builtin_macro]
+    pub macro cfg_accessible($item:item) {
+        /* compiler built-in */
+    }
+
     /// Unstable implementation detail of the `rustc` compiler, do not use.
     #[rustc_builtin_macro]
     #[stable(feature = "rust1", since = "1.0.0")]
index 2800f11cc01b1ae43600b4e82df2ceac154050e8..2b908f07af8da585f6cdbe7f9ff2590709662d05 100644 (file)
@@ -90,6 +90,7 @@ impl<T: ?Sized> !Send for *mut T {}
           ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>"
 )]
 #[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable
+#[cfg_attr(not(bootstrap), rustc_specialization_trait)]
 pub trait Sized {
     // Empty.
 }
index 4c3b81ea5eca5506d1dc9413f9fb6811fb46b9e2..9e5c2b10d0d9ece6d2938be31a0cb278a1dfd4ef 100644 (file)
@@ -93,7 +93,7 @@ pub const fn into_inner(slot: ManuallyDrop<T>) -> T {
     /// Instead of using [`ManuallyDrop::drop`] to manually drop the value,
     /// you can use this method to take the value and use it however desired.
     ///
-    /// Whenever possible, it is preferrable to use [`into_inner`][`ManuallyDrop::into_inner`]
+    /// Whenever possible, it is preferable to use [`into_inner`][`ManuallyDrop::into_inner`]
     /// instead, which prevents duplicating the content of the `ManuallyDrop<T>`.
     ///
     /// # Safety
index 58aaac21ad751fcc2a9f5f80cb3cf3c5ad172c82..bf39d56fc115c6e8bea5760a28a877e0a3d1a25f 100644 (file)
@@ -495,7 +495,10 @@ pub fn as_mut_ptr(&mut self) -> *mut T {
     #[inline(always)]
     #[rustc_diagnostic_item = "assume_init"]
     pub unsafe fn assume_init(self) -> T {
+        #[cfg(bootstrap)]
         intrinsics::panic_if_uninhabited::<T>();
+        #[cfg(not(bootstrap))]
+        intrinsics::assert_inhabited::<T>();
         ManuallyDrop::into_inner(self.value)
     }
 
@@ -559,7 +562,10 @@ pub unsafe fn assume_init(self) -> T {
     #[unstable(feature = "maybe_uninit_extra", issue = "63567")]
     #[inline(always)]
     pub unsafe fn read(&self) -> T {
+        #[cfg(bootstrap)]
         intrinsics::panic_if_uninhabited::<T>();
+        #[cfg(not(bootstrap))]
+        intrinsics::assert_inhabited::<T>();
         self.as_ptr().read()
     }
 
@@ -621,7 +627,10 @@ pub unsafe fn read(&self) -> T {
     #[unstable(feature = "maybe_uninit_ref", issue = "63568")]
     #[inline(always)]
     pub unsafe fn get_ref(&self) -> &T {
+        #[cfg(bootstrap)]
         intrinsics::panic_if_uninhabited::<T>();
+        #[cfg(not(bootstrap))]
+        intrinsics::assert_inhabited::<T>();
         &*self.value
     }
 
@@ -739,7 +748,10 @@ pub unsafe fn get_ref(&self) -> &T {
     #[unstable(feature = "maybe_uninit_ref", issue = "63568")]
     #[inline(always)]
     pub unsafe fn get_mut(&mut self) -> &mut T {
+        #[cfg(bootstrap)]
         intrinsics::panic_if_uninhabited::<T>();
+        #[cfg(not(bootstrap))]
+        intrinsics::assert_inhabited::<T>();
         &mut *self.value
     }
 
index 1120d6d4bc50eac3675de6734c060d11b85c25d6..dac9ee6a5d91e62342468065861a925c72cd8780 100644 (file)
@@ -58,7 +58,9 @@
 ///
 /// # Examples
 ///
-/// Leak an I/O object, never closing the file:
+/// The canonical safe use of `mem::forget` is to circumvent a value's destructor
+/// implemented by the `Drop` trait. For example, this will leak a `File`, i.e. reclaim
+/// the space taken by the variable but never close the underlying system resource:
 ///
 /// ```no_run
 /// use std::mem;
 /// mem::forget(file);
 /// ```
 ///
-/// The practical use cases for `forget` are rather specialized and mainly come
-/// up in unsafe or FFI code. However, [`ManuallyDrop`] is usually preferred
-/// for such cases, e.g.:
+/// This is useful when the ownership of the underlying resource was previously
+/// transferred to code outside of Rust, for example by transmitting the raw
+/// file descriptor to C code.
+///
+/// # Relationship with `ManuallyDrop`
+///
+/// While `mem::forget` can also be used to transfer *memory* ownership, doing so is error-prone.
+/// [`ManuallyDrop`] should be used instead. Consider, for example, this code:
+///
+/// ```
+/// use std::mem;
+///
+/// let mut v = vec![65, 122];
+/// // Build a `String` using the contents of `v`
+/// let s = unsafe { String::from_raw_parts(v.as_mut_ptr(), v.len(), v.capacity()) };
+/// // leak `v` because its memory is now managed by `s`
+/// mem::forget(v);  // ERROR - v is invalid and must not be passed to a function
+/// assert_eq!(s, "Az");
+/// // `s` is implicitly dropped and its memory deallocated.
+/// ```
+///
+/// There are two issues with the above example:
+///
+/// * If more code were added between the construction of `String` and the invocation of
+///   `mem::forget()`, a panic within it would cause a double free because the same memory
+///   is handled by both `v` and `s`.
+/// * After calling `v.as_mut_ptr()` and transmitting the ownership of the data to `s`,
+///   the `v` value is invalid. Even when a value is just moved to `mem::forget` (which won't
+///   inspect it), some types have strict requirements on their values that
+///   make them invalid when dangling or no longer owned. Using invalid values in any
+///   way, including passing them to or returning them from functions, constitutes
+///   undefined behavior and may break the assumptions made by the compiler.
+///
+/// Switching to `ManuallyDrop` avoids both issues:
 ///
 /// ```
 /// use std::mem::ManuallyDrop;
 /// // does not get dropped!
 /// let mut v = ManuallyDrop::new(v);
 /// // Now disassemble `v`. These operations cannot panic, so there cannot be a leak.
-/// let ptr = v.as_mut_ptr();
-/// let cap = v.capacity();
+/// let (ptr, len, cap) = (v.as_mut_ptr(), v.len(), v.capacity());
 /// // Finally, build a `String`.
-/// let s = unsafe { String::from_raw_parts(ptr, 2, cap) };
+/// let s = unsafe { String::from_raw_parts(ptr, len, cap) };
 /// assert_eq!(s, "Az");
 /// // `s` is implicitly dropped and its memory deallocated.
 /// ```
 ///
-/// Using `ManuallyDrop` here has two advantages:
+/// `ManuallyDrop` robustly prevents double-free because we disable `v`'s destructor
+/// before doing anything else. `mem::forget()` doesn't allow this because it consumes its
+/// argument, forcing us to call it only after extracting anything we need from `v`. Even
+/// if a panic were introduced between construction of `ManuallyDrop` and building the
+/// string (which cannot happen in the code as shown), it would result in a leak and not a
+/// double free. In other words, `ManuallyDrop` errs on the side of leaking instead of
+/// erring on the side of (double-)dropping.
 ///
-/// * We do not "touch" `v` after disassembling it. For some types, operations
-///   such as passing ownership (to a funcion like `mem::forget`) requires them to actually
-///   be fully owned right now; that is a promise we do not want to make here as we are
-///   in the process of transferring ownership to the new `String` we are building.
-/// * In case of an unexpected panic, `ManuallyDrop` is not dropped, but if the panic
-///   occurs before `mem::forget` was called we might end up dropping invalid data,
-///   or double-dropping. In other words, `ManuallyDrop` errs on the side of leaking
-///   instead of erring on the side of dropping.
+/// Also, `ManuallyDrop` prevents us from having to "touch" `v` after transferring the
+/// ownership to `s` - the final step of interacting with `v` to dispoe of it without
+/// running its destructor is entirely avoided.
 ///
 /// [drop]: fn.drop.html
 /// [uninit]: fn.uninitialized.html
@@ -490,14 +523,17 @@ pub const fn needs_drop<T>() -> bool {
 ///
 /// let _x: &i32 = unsafe { mem::zeroed() }; // Undefined behavior!
 /// ```
-#[inline]
+#[inline(always)]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[allow(deprecated_in_future)]
 #[allow(deprecated)]
 #[rustc_diagnostic_item = "mem_zeroed"]
 pub unsafe fn zeroed<T>() -> T {
+    #[cfg(not(bootstrap))]
+    intrinsics::assert_zero_valid::<T>();
+    #[cfg(bootstrap)]
     intrinsics::panic_if_uninhabited::<T>();
-    intrinsics::init()
+    MaybeUninit::zeroed().assume_init()
 }
 
 /// Bypasses Rust's normal memory-initialization checks by pretending to
@@ -522,15 +558,18 @@ pub unsafe fn zeroed<T>() -> T {
 /// [uninit]: union.MaybeUninit.html#method.uninit
 /// [assume_init]: union.MaybeUninit.html#method.assume_init
 /// [inv]: union.MaybeUninit.html#initialization-invariant
-#[inline]
+#[inline(always)]
 #[rustc_deprecated(since = "1.39.0", reason = "use `mem::MaybeUninit` instead")]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[allow(deprecated_in_future)]
 #[allow(deprecated)]
 #[rustc_diagnostic_item = "mem_uninitialized"]
 pub unsafe fn uninitialized<T>() -> T {
+    #[cfg(not(bootstrap))]
+    intrinsics::assert_uninit_valid::<T>();
+    #[cfg(bootstrap)]
     intrinsics::panic_if_uninhabited::<T>();
-    intrinsics::uninit()
+    MaybeUninit::uninit().assume_init()
 }
 
 /// Swaps the values at two mutable locations, without deinitializing either one.
@@ -864,6 +903,7 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
 /// assert_ne!(mem::discriminant(&Foo::B(3)), mem::discriminant(&Foo::C(3)));
 /// ```
 #[stable(feature = "discriminant_value", since = "1.21.0")]
-pub fn discriminant<T>(v: &T) -> Discriminant<T> {
+#[rustc_const_unstable(feature = "const_discriminant", issue = "69821")]
+pub const fn discriminant<T>(v: &T) -> Discriminant<T> {
     Discriminant(intrinsics::discriminant_value(v), PhantomData)
 }
index 0a4fc6464ca977f0dc99e0f8eed30317c5876962..3fdc2bae33876314a0ac0b100df23933d174adfe 100644 (file)
@@ -4,6 +4,9 @@
 //! *[See also the `f32` primitive type](../../std/primitive.f32.html).*
 //!
 //! Mathematically significant numbers are provided in the `consts` sub-module.
+//!
+//! Although using these constants won’t cause compilation warnings,
+//! new code should use the associated constants directly on the primitive type.
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
 use crate::num::FpCategory;
 
 /// The radix or base of the internal representation of `f32`.
+/// Use [`f32::RADIX`](../../std/primitive.f32.html#associatedconstant.RADIX) instead.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub const RADIX: u32 = f32::RADIX;
 
 /// Number of significant digits in base 2.
+/// Use [`f32::MANTISSA_DIGITS`](../../std/primitive.f32.html#associatedconstant.MANTISSA_DIGITS) instead.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub const MANTISSA_DIGITS: u32 = f32::MANTISSA_DIGITS;
 /// Approximate number of significant digits in base 10.
+/// Use [`f32::DIGITS`](../../std/primitive.f32.html#associatedconstant.DIGITS) instead.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub const DIGITS: u32 = f32::DIGITS;
 
 /// [Machine epsilon] value for `f32`.
+/// Use [`f32::EPSILON`](../../std/primitive.f32.html#associatedconstant.EPSILON) instead.
 ///
 /// This is the difference between `1.0` and the next larger representable number.
 ///
 pub const EPSILON: f32 = f32::EPSILON;
 
 /// Smallest finite `f32` value.
+/// Use [`f32::MIN`](../../std/primitive.f32.html#associatedconstant.MIN) instead.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub const MIN: f32 = f32::MIN;
 /// Smallest positive normal `f32` value.
+/// Use [`f32::MIN_POSITIVE`](../../std/primitive.f32.html#associatedconstant.MIN_POSITIVE) instead.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub const MIN_POSITIVE: f32 = f32::MIN_POSITIVE;
 /// Largest finite `f32` value.
+/// Use [`f32::MAX`](../../std/primitive.f32.html#associatedconstant.MAX) instead.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub const MAX: f32 = f32::MAX;
 
 /// One greater than the minimum possible normal power of 2 exponent.
+/// Use [`f32::MIN_EXP`](../../std/primitive.f32.html#associatedconstant.MIN_EXP) instead.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub const MIN_EXP: i32 = f32::MIN_EXP;
 /// Maximum possible power of 2 exponent.
+/// Use [`f32::MAX_EXP`](../../std/primitive.f32.html#associatedconstant.MAX_EXP) instead.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub const MAX_EXP: i32 = f32::MAX_EXP;
 
 /// Minimum possible normal power of 10 exponent.
+/// Use [`f32::MIN_10_EXP`](../../std/primitive.f32.html#associatedconstant.MIN_10_EXP) instead.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub const MIN_10_EXP: i32 = f32::MIN_10_EXP;
 /// Maximum possible power of 10 exponent.
+/// Use [`f32::MAX_10_EXP`](../../std/primitive.f32.html#associatedconstant.MAX_10_EXP) instead.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub const MAX_10_EXP: i32 = f32::MAX_10_EXP;
 
 /// Not a Number (NaN).
+/// Use [`f32::NAN`](../../std/primitive.f32.html#associatedconstant.NAN) instead.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub const NAN: f32 = f32::NAN;
 /// Infinity (∞).
+/// Use [`f32::INFINITY`](../../std/primitive.f32.html#associatedconstant.INFINITY) instead.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub const INFINITY: f32 = f32::INFINITY;
 /// Negative infinity (−∞).
+/// Use [`f32::NEG_INFINITY`](../../std/primitive.f32.html#associatedconstant.NEG_INFINITY) instead.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub const NEG_INFINITY: f32 = f32::NEG_INFINITY;
 
@@ -154,15 +171,15 @@ pub mod consts {
 #[cfg(not(test))]
 impl f32 {
     /// The radix or base of the internal representation of `f32`.
-    #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")]
+    #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const RADIX: u32 = 2;
 
     /// Number of significant digits in base 2.
-    #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")]
+    #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const MANTISSA_DIGITS: u32 = 24;
 
     /// Approximate number of significant digits in base 10.
-    #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")]
+    #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const DIGITS: u32 = 6;
 
     /// [Machine epsilon] value for `f32`.
@@ -170,48 +187,46 @@ impl f32 {
     /// This is the difference between `1.0` and the next larger representable number.
     ///
     /// [Machine epsilon]: https://en.wikipedia.org/wiki/Machine_epsilon
-    #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")]
+    #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const EPSILON: f32 = 1.19209290e-07_f32;
 
     /// Smallest finite `f32` value.
-    #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")]
+    #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const MIN: f32 = -3.40282347e+38_f32;
     /// Smallest positive normal `f32` value.
-    #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")]
+    #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const MIN_POSITIVE: f32 = 1.17549435e-38_f32;
     /// Largest finite `f32` value.
-    #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")]
+    #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const MAX: f32 = 3.40282347e+38_f32;
 
     /// One greater than the minimum possible normal power of 2 exponent.
-    #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")]
+    #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const MIN_EXP: i32 = -125;
     /// Maximum possible power of 2 exponent.
-    #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")]
+    #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const MAX_EXP: i32 = 128;
 
     /// Minimum possible normal power of 10 exponent.
-    #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")]
+    #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const MIN_10_EXP: i32 = -37;
     /// Maximum possible power of 10 exponent.
-    #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")]
+    #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const MAX_10_EXP: i32 = 38;
 
     /// Not a Number (NaN).
-    #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")]
+    #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const NAN: f32 = 0.0_f32 / 0.0_f32;
     /// Infinity (∞).
-    #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")]
+    #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const INFINITY: f32 = 1.0_f32 / 0.0_f32;
     /// Negative infinity (-∞).
-    #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")]
+    #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const NEG_INFINITY: f32 = -1.0_f32 / 0.0_f32;
 
     /// Returns `true` if this value is `NaN`.
     ///
     /// ```
-    /// use std::f32;
-    ///
     /// let nan = f32::NAN;
     /// let f = 7.0_f32;
     ///
@@ -236,8 +251,6 @@ fn abs_private(self) -> f32 {
     /// `false` otherwise.
     ///
     /// ```
-    /// use std::f32;
-    ///
     /// let f = 7.0f32;
     /// let inf = f32::INFINITY;
     /// let neg_inf = f32::NEG_INFINITY;
@@ -258,8 +271,6 @@ pub fn is_infinite(self) -> bool {
     /// Returns `true` if this number is neither infinite nor `NaN`.
     ///
     /// ```
-    /// use std::f32;
-    ///
     /// let f = 7.0f32;
     /// let inf = f32::INFINITY;
     /// let neg_inf = f32::NEG_INFINITY;
@@ -283,8 +294,6 @@ pub fn is_finite(self) -> bool {
     /// [subnormal], or `NaN`.
     ///
     /// ```
-    /// use std::f32;
-    ///
     /// let min = f32::MIN_POSITIVE; // 1.17549435e-38f32
     /// let max = f32::MAX;
     /// let lower_than_min = 1.0e-40_f32;
@@ -312,7 +321,6 @@ pub fn is_normal(self) -> bool {
     ///
     /// ```
     /// use std::num::FpCategory;
-    /// use std::f32;
     ///
     /// let num = 12.4_f32;
     /// let inf = f32::INFINITY;
@@ -372,8 +380,6 @@ pub fn is_sign_negative(self) -> bool {
     /// Takes the reciprocal (inverse) of a number, `1/x`.
     ///
     /// ```
-    /// use std::f32;
-    ///
     /// let x = 2.0_f32;
     /// let abs_difference = (x.recip() - (1.0 / x)).abs();
     ///
@@ -388,7 +394,7 @@ pub fn recip(self) -> f32 {
     /// Converts radians to degrees.
     ///
     /// ```
-    /// use std::f32::{self, consts};
+    /// use std::f32::consts;
     ///
     /// let angle = consts::PI;
     ///
@@ -407,7 +413,7 @@ pub fn to_degrees(self) -> f32 {
     /// Converts degrees to radians.
     ///
     /// ```
-    /// use std::f32::{self, consts};
+    /// use std::f32::consts;
     ///
     /// let angle = 180.0f32;
     ///
index a3acf0f23c4e2076abad096491768bbeb32ea80b..129df937c0bb887c8eafc5001b1a5605d41c93f2 100644 (file)
@@ -4,6 +4,9 @@
 //! *[See also the `f64` primitive type](../../std/primitive.f64.html).*
 //!
 //! Mathematically significant numbers are provided in the `consts` sub-module.
+//!
+//! Although using these constants won’t cause compilation warnings,
+//! new code should use the associated constants directly on the primitive type.
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
 use crate::num::FpCategory;
 
 /// The radix or base of the internal representation of `f64`.
+/// Use [`f64::RADIX`](../../std/primitive.f64.html#associatedconstant.RADIX) instead.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub const RADIX: u32 = f64::RADIX;
 
 /// Number of significant digits in base 2.
+/// Use [`f64::MANTISSA_DIGITS`](../../std/primitive.f64.html#associatedconstant.MANTISSA_DIGITS) instead.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub const MANTISSA_DIGITS: u32 = f64::MANTISSA_DIGITS;
 /// Approximate number of significant digits in base 10.
+/// Use [`f64::DIGITS`](../../std/primitive.f64.html#associatedconstant.DIGITS) instead.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub const DIGITS: u32 = f64::DIGITS;
 
 /// [Machine epsilon] value for `f64`.
+/// Use [`f64::EPSILON`](../../std/primitive.f64.html#associatedconstant.EPSILON) instead.
 ///
 /// This is the difference between `1.0` and the next larger representable number.
 ///
 pub const EPSILON: f64 = f64::EPSILON;
 
 /// Smallest finite `f64` value.
+/// Use [`f64::MIN`](../../std/primitive.f64.html#associatedconstant.MIN) instead.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub const MIN: f64 = f64::MIN;
 /// Smallest positive normal `f64` value.
+/// Use [`f64::MIN_POSITIVE`](../../std/primitive.f64.html#associatedconstant.MIN_POSITIVE) instead.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub const MIN_POSITIVE: f64 = f64::MIN_POSITIVE;
 /// Largest finite `f64` value.
+/// Use [`f64::MAX`](../../std/primitive.f64.html#associatedconstant.MAX) instead.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub const MAX: f64 = f64::MAX;
 
 /// One greater than the minimum possible normal power of 2 exponent.
+/// Use [`f64::MIN_EXP`](../../std/primitive.f64.html#associatedconstant.MIN_EXP) instead.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub const MIN_EXP: i32 = f64::MIN_EXP;
 /// Maximum possible power of 2 exponent.
+/// Use [`f64::MAX_EXP`](../../std/primitive.f64.html#associatedconstant.MAX_EXP) instead.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub const MAX_EXP: i32 = f64::MAX_EXP;
 
 /// Minimum possible normal power of 10 exponent.
+/// Use [`f64::MIN_10_EXP`](../../std/primitive.f64.html#associatedconstant.MIN_10_EXP) instead.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub const MIN_10_EXP: i32 = f64::MIN_10_EXP;
 /// Maximum possible power of 10 exponent.
+/// Use [`f64::MAX_10_EXP`](../../std/primitive.f64.html#associatedconstant.MAX_10_EXP) instead.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub const MAX_10_EXP: i32 = f64::MAX_10_EXP;
 
 /// Not a Number (NaN).
+/// Use [`f64::NAN`](../../std/primitive.f64.html#associatedconstant.NAN) instead.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub const NAN: f64 = f64::NAN;
 /// Infinity (∞).
+/// Use [`f64::INFINITY`](../../std/primitive.f64.html#associatedconstant.INFINITY) instead.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub const INFINITY: f64 = f64::INFINITY;
 /// Negative infinity (−∞).
+/// Use [`f64::NEG_INFINITY`](../../std/primitive.f64.html#associatedconstant.NEG_INFINITY) instead.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub const NEG_INFINITY: f64 = f64::NEG_INFINITY;
 
@@ -154,14 +171,14 @@ pub mod consts {
 #[cfg(not(test))]
 impl f64 {
     /// The radix or base of the internal representation of `f64`.
-    #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")]
+    #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const RADIX: u32 = 2;
 
     /// Number of significant digits in base 2.
-    #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")]
+    #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const MANTISSA_DIGITS: u32 = 53;
     /// Approximate number of significant digits in base 10.
-    #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")]
+    #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const DIGITS: u32 = 15;
 
     /// [Machine epsilon] value for `f64`.
@@ -169,48 +186,46 @@ impl f64 {
     /// This is the difference between `1.0` and the next larger representable number.
     ///
     /// [Machine epsilon]: https://en.wikipedia.org/wiki/Machine_epsilon
-    #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")]
+    #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const EPSILON: f64 = 2.2204460492503131e-16_f64;
 
     /// Smallest finite `f64` value.
-    #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")]
+    #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const MIN: f64 = -1.7976931348623157e+308_f64;
     /// Smallest positive normal `f64` value.
-    #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")]
+    #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const MIN_POSITIVE: f64 = 2.2250738585072014e-308_f64;
     /// Largest finite `f64` value.
-    #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")]
+    #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const MAX: f64 = 1.7976931348623157e+308_f64;
 
     /// One greater than the minimum possible normal power of 2 exponent.
-    #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")]
+    #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const MIN_EXP: i32 = -1021;
     /// Maximum possible power of 2 exponent.
-    #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")]
+    #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const MAX_EXP: i32 = 1024;
 
     /// Minimum possible normal power of 10 exponent.
-    #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")]
+    #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const MIN_10_EXP: i32 = -307;
     /// Maximum possible power of 10 exponent.
-    #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")]
+    #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const MAX_10_EXP: i32 = 308;
 
     /// Not a Number (NaN).
-    #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")]
+    #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const NAN: f64 = 0.0_f64 / 0.0_f64;
     /// Infinity (∞).
-    #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")]
+    #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const INFINITY: f64 = 1.0_f64 / 0.0_f64;
     /// Negative infinity (-∞).
-    #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")]
+    #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const NEG_INFINITY: f64 = -1.0_f64 / 0.0_f64;
 
     /// Returns `true` if this value is `NaN`.
     ///
     /// ```
-    /// use std::f64;
-    ///
     /// let nan = f64::NAN;
     /// let f = 7.0_f64;
     ///
@@ -235,8 +250,6 @@ fn abs_private(self) -> f64 {
     /// `false` otherwise.
     ///
     /// ```
-    /// use std::f64;
-    ///
     /// let f = 7.0f64;
     /// let inf = f64::INFINITY;
     /// let neg_inf = f64::NEG_INFINITY;
@@ -257,8 +270,6 @@ pub fn is_infinite(self) -> bool {
     /// Returns `true` if this number is neither infinite nor `NaN`.
     ///
     /// ```
-    /// use std::f64;
-    ///
     /// let f = 7.0f64;
     /// let inf: f64 = f64::INFINITY;
     /// let neg_inf: f64 = f64::NEG_INFINITY;
@@ -282,8 +293,6 @@ pub fn is_finite(self) -> bool {
     /// [subnormal], or `NaN`.
     ///
     /// ```
-    /// use std::f64;
-    ///
     /// let min = f64::MIN_POSITIVE; // 2.2250738585072014e-308f64
     /// let max = f64::MAX;
     /// let lower_than_min = 1.0e-308_f64;
@@ -311,7 +320,6 @@ pub fn is_normal(self) -> bool {
     ///
     /// ```
     /// use std::num::FpCategory;
-    /// use std::f64;
     ///
     /// let num = 12.4_f64;
     /// let inf = f64::INFINITY;
index 564ed598a882c700dbbf10a09842d0ba5aea26f5..08cb7959468689ceb44d7a633e2a9b6d26ebaf50 100644 (file)
@@ -1,6 +1,9 @@
 //! The 128-bit signed integer type.
 //!
 //! *[See also the `i128` primitive type](../../std/primitive.i128.html).*
+//!
+//! Although using these constants won’t cause compilation warnings,
+//! new code should use the associated constants directly on the primitive type.
 
 #![stable(feature = "i128", since = "1.26.0")]
 
index 44d6aaef25ba03b074a82204eb42667ad9b62b5e..288eaceba59d6babd5f53187e2e73909eb195eb3 100644 (file)
@@ -1,6 +1,9 @@
 //! The 16-bit signed integer type.
 //!
 //! *[See also the `i16` primitive type](../../std/primitive.i16.html).*
+//!
+//! Although using these constants won’t cause compilation warnings,
+//! new code should use the associated constants directly on the primitive type.
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
index 90a5f89195e3130dc4922fc7701de187ed2b84d5..0e1a2ec56ccb2419b003425d87c94c815b4f24e7 100644 (file)
@@ -1,6 +1,9 @@
 //! The 32-bit signed integer type.
 //!
 //! *[See also the `i32` primitive type](../../std/primitive.i32.html).*
+//!
+//! Although using these constants won’t cause compilation warnings,
+//! new code should use the associated constants directly on the primitive type.
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
index 04a8a9d757915c6f32f21601018162d202837379..27f7092710b347872842c2016b556cd122e42f27 100644 (file)
@@ -1,6 +1,9 @@
 //! The 64-bit signed integer type.
 //!
 //! *[See also the `i64` primitive type](../../std/primitive.i64.html).*
+//!
+//! Although using these constants won’t cause compilation warnings,
+//! new code should use the associated constants directly on the primitive type.
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
index 5a52a967cf96d61fe73ddc5915ed4d57ae35c8f8..e84b421e1a4447c9785f3b751b8d0bbe7e993831 100644 (file)
@@ -1,6 +1,9 @@
 //! The 8-bit signed integer type.
 //!
 //! *[See also the `i8` primitive type](../../std/primitive.i8.html).*
+//!
+//! Although using these constants won’t cause compilation warnings,
+//! new code should use the associated constants directly on the primitive type.
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
index 5c59fe25f6483da175d57676c736bb23b010b47c..b68a09e1131809230509fa3e6f9c9827809924cc 100644 (file)
@@ -1,13 +1,27 @@
 #![doc(hidden)]
 
+macro_rules! doc_comment {
+    ($x:expr, $($tt:tt)*) => {
+        #[doc = $x]
+        $($tt)*
+    };
+}
+
 macro_rules! int_module {
     ($T:ident) => (int_module!($T, #[stable(feature = "rust1", since = "1.0.0")]););
     ($T:ident, #[$attr:meta]) => (
-        /// The smallest value that can be represented by this integer type.
-        #[$attr]
-        pub const MIN: $T = $T::min_value();
-        /// The largest value that can be represented by this integer type.
-        #[$attr]
-        pub const MAX: $T = $T::max_value();
+        doc_comment! {
+            concat!("The smallest value that can be represented by this integer type.
+Use [`", stringify!($T), "::MIN", "`](../../std/primitive.", stringify!($T), ".html#associatedconstant.MIN) instead."),
+            #[$attr]
+            pub const MIN: $T = $T::min_value();
+        }
+
+        doc_comment! {
+            concat!("The largest value that can be represented by this integer type.
+Use [`", stringify!($T), "::MAX", "`](../../std/primitive.", stringify!($T), ".html#associatedconstant.MAX) instead."),
+            #[$attr]
+            pub const MAX: $T = $T::max_value();
+        }
     )
 }
index 143f8b3b272d6189dc69c1571af9b78dd36aca9e..0dcfa4a2bd134509a29179cf6b001725c14c5a80 100644 (file)
@@ -1,6 +1,9 @@
 //! The pointer-sized signed integer type.
 //!
 //! *[See also the `isize` primitive type](../../std/primitive.isize.html).*
+//!
+//! Although using these constants won’t cause compilation warnings,
+//! new code should use the associated constants directly on the primitive type.
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
index 43c5f7cf6b939c4a418400c464f5292425ffdf8d..853092dd85ee94436fb3433c35ce4b4b181aa71b 100644 (file)
@@ -266,11 +266,10 @@ macro_rules! int_impl {
 Basic usage:
 
 ```
-#![feature(assoc_int_consts)]
 ", $Feature, "assert_eq!(", stringify!($SelfT), "::MIN, ", stringify!($Min), ");",
 $EndFeature, "
 ```"),
-            #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")]
+            #[stable(feature = "assoc_int_consts", since = "1.43.0")]
             pub const MIN: Self = !0 ^ ((!0 as $UnsignedT) >> 1) as Self;
         }
 
@@ -282,36 +281,13 @@ macro_rules! int_impl {
 Basic usage:
 
 ```
-#![feature(assoc_int_consts)]
 ", $Feature, "assert_eq!(", stringify!($SelfT), "::MAX, ", stringify!($Max), ");",
 $EndFeature, "
 ```"),
-            #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")]
+            #[stable(feature = "assoc_int_consts", since = "1.43.0")]
             pub const MAX: Self = !Self::MIN;
         }
 
-        doc_comment! {
-            "Returns the smallest value that can be represented by this integer type.",
-            #[stable(feature = "rust1", since = "1.0.0")]
-            #[inline(always)]
-            #[rustc_promotable]
-            #[rustc_const_stable(feature = "const_min_value", since = "1.32.0")]
-            pub const fn min_value() -> Self {
-                Self::MIN
-            }
-        }
-
-        doc_comment! {
-            "Returns the largest value that can be represented by this integer type.",
-            #[stable(feature = "rust1", since = "1.0.0")]
-            #[inline(always)]
-            #[rustc_promotable]
-            #[rustc_const_stable(feature = "const_max_value", since = "1.32.0")]
-            pub const fn max_value() -> Self {
-                Self::MAX
-            }
-        }
-
         doc_comment! {
             concat!("Converts a string slice in a given base to an integer.
 
@@ -369,7 +345,7 @@ pub const fn count_ones(self) -> u32 { (self as $UnsignedT).count_ones() }
 Basic usage:
 
 ```
-", $Feature, "assert_eq!(", stringify!($SelfT), "::max_value().count_zeros(), 1);", $EndFeature, "
+", $Feature, "assert_eq!(", stringify!($SelfT), "::MAX.count_zeros(), 1);", $EndFeature, "
 ```"),
             #[stable(feature = "rust1", since = "1.0.0")]
             #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
@@ -706,8 +682,8 @@ pub const fn to_le(self) -> Self {
 
 ```
 ", $Feature, "assert_eq!((", stringify!($SelfT),
-"::max_value() - 2).checked_add(1), Some(", stringify!($SelfT), "::max_value() - 1));
-assert_eq!((", stringify!($SelfT), "::max_value() - 2).checked_add(3), None);",
+"::MAX - 2).checked_add(1), Some(", stringify!($SelfT), "::MAX - 1));
+assert_eq!((", stringify!($SelfT), "::MAX - 2).checked_add(3), None);",
 $EndFeature, "
 ```"),
             #[stable(feature = "rust1", since = "1.0.0")]
@@ -731,8 +707,8 @@ pub const fn checked_add(self, rhs: Self) -> Option<Self> {
 
 ```
 ", $Feature, "assert_eq!((", stringify!($SelfT),
-"::min_value() + 2).checked_sub(1), Some(", stringify!($SelfT), "::min_value() + 1));
-assert_eq!((", stringify!($SelfT), "::min_value() + 2).checked_sub(3), None);",
+"::MIN + 2).checked_sub(1), Some(", stringify!($SelfT), "::MIN + 1));
+assert_eq!((", stringify!($SelfT), "::MIN + 2).checked_sub(3), None);",
 $EndFeature, "
 ```"),
             #[stable(feature = "rust1", since = "1.0.0")]
@@ -756,8 +732,8 @@ pub const fn checked_sub(self, rhs: Self) -> Option<Self> {
 
 ```
 ", $Feature, "assert_eq!(", stringify!($SelfT),
-"::max_value().checked_mul(1), Some(", stringify!($SelfT), "::max_value()));
-assert_eq!(", stringify!($SelfT), "::max_value().checked_mul(2), None);",
+"::MAX.checked_mul(1), Some(", stringify!($SelfT), "::MAX));
+assert_eq!(", stringify!($SelfT), "::MAX.checked_mul(2), None);",
 $EndFeature, "
 ```"),
             #[stable(feature = "rust1", since = "1.0.0")]
@@ -781,8 +757,8 @@ pub const fn checked_mul(self, rhs: Self) -> Option<Self> {
 
 ```
 ", $Feature, "assert_eq!((", stringify!($SelfT),
-"::min_value() + 1).checked_div(-1), Some(", stringify!($Max), "));
-assert_eq!(", stringify!($SelfT), "::min_value().checked_div(-1), None);
+"::MIN + 1).checked_div(-1), Some(", stringify!($Max), "));
+assert_eq!(", stringify!($SelfT), "::MIN.checked_div(-1), None);
 assert_eq!((1", stringify!($SelfT), ").checked_div(0), None);",
 $EndFeature, "
 ```"),
@@ -811,8 +787,8 @@ pub const fn checked_div(self, rhs: Self) -> Option<Self> {
 
 ```
 assert_eq!((", stringify!($SelfT),
-"::min_value() + 1).checked_div_euclid(-1), Some(", stringify!($Max), "));
-assert_eq!(", stringify!($SelfT), "::min_value().checked_div_euclid(-1), None);
+"::MIN + 1).checked_div_euclid(-1), Some(", stringify!($Max), "));
+assert_eq!(", stringify!($SelfT), "::MIN.checked_div_euclid(-1), None);
 assert_eq!((1", stringify!($SelfT), ").checked_div_euclid(0), None);
 ```"),
             #[stable(feature = "euclidean_division", since = "1.38.0")]
@@ -838,8 +814,7 @@ pub const fn checked_div_euclid(self, rhs: Self) -> Option<Self> {
 Basic usage:
 
 ```
-", $Feature, "use std::", stringify!($SelfT), ";
-
+", $Feature, "
 assert_eq!(5", stringify!($SelfT), ".checked_rem(2), Some(1));
 assert_eq!(5", stringify!($SelfT), ".checked_rem(0), None);
 assert_eq!(", stringify!($SelfT), "::MIN.checked_rem(-1), None);",
@@ -869,8 +844,6 @@ pub const fn checked_rem(self, rhs: Self) -> Option<Self> {
 Basic usage:
 
 ```
-use std::", stringify!($SelfT), ";
-
 assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(2), Some(1));
 assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(0), None);
 assert_eq!(", stringify!($SelfT), "::MIN.checked_rem_euclid(-1), None);
@@ -897,8 +870,7 @@ pub const fn checked_rem_euclid(self, rhs: Self) -> Option<Self> {
 Basic usage:
 
 ```
-", $Feature, "use std::", stringify!($SelfT), ";
-
+", $Feature, "
 assert_eq!(5", stringify!($SelfT), ".checked_neg(), Some(-5));
 assert_eq!(", stringify!($SelfT), "::MIN.checked_neg(), None);",
 $EndFeature, "
@@ -969,8 +941,7 @@ pub const fn checked_shr(self, rhs: u32) -> Option<Self> {
 Basic usage:
 
 ```
-", $Feature, "use std::", stringify!($SelfT), ";
-
+", $Feature, "
 assert_eq!((-5", stringify!($SelfT), ").checked_abs(), Some(5));
 assert_eq!(", stringify!($SelfT), "::MIN.checked_abs(), None);",
 $EndFeature, "
@@ -997,7 +968,7 @@ pub const fn checked_abs(self) -> Option<Self> {
 
 ```
 ", $Feature, "assert_eq!(8", stringify!($SelfT), ".checked_pow(2), Some(64));
-assert_eq!(", stringify!($SelfT), "::max_value().checked_pow(2), None);",
+assert_eq!(", stringify!($SelfT), "::MAX.checked_pow(2), None);",
 $EndFeature, "
 ```"),
 
@@ -1039,10 +1010,10 @@ pub const fn checked_pow(self, mut exp: u32) -> Option<Self> {
 
 ```
 ", $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());",
+assert_eq!(", stringify!($SelfT), "::MAX.saturating_add(100), ", stringify!($SelfT),
+"::MAX);
+assert_eq!(", stringify!($SelfT), "::MIN.saturating_add(-1), ", stringify!($SelfT),
+"::MIN);",
 $EndFeature, "
 ```"),
 
@@ -1066,10 +1037,10 @@ pub const fn saturating_add(self, rhs: Self) -> Self {
 
 ```
 ", $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());",
+assert_eq!(", stringify!($SelfT), "::MIN.saturating_sub(100), ", stringify!($SelfT),
+"::MIN);
+assert_eq!(", stringify!($SelfT), "::MAX.saturating_sub(-1), ", stringify!($SelfT),
+"::MAX);",
 $EndFeature, "
 ```"),
             #[stable(feature = "rust1", since = "1.0.0")]
@@ -1094,10 +1065,10 @@ pub const fn saturating_sub(self, rhs: Self) -> Self {
 ", $Feature, "#![feature(saturating_neg)]
 assert_eq!(100", stringify!($SelfT), ".saturating_neg(), -100);
 assert_eq!((-100", stringify!($SelfT), ").saturating_neg(), 100);
-assert_eq!(", stringify!($SelfT), "::min_value().saturating_neg(), ", stringify!($SelfT),
-"::max_value());
-assert_eq!(", stringify!($SelfT), "::max_value().saturating_neg(), ", stringify!($SelfT),
-"::min_value() + 1);",
+assert_eq!(", stringify!($SelfT), "::MIN.saturating_neg(), ", stringify!($SelfT),
+"::MAX);
+assert_eq!(", stringify!($SelfT), "::MAX.saturating_neg(), ", stringify!($SelfT),
+"::MIN + 1);",
 $EndFeature, "
 ```"),
 
@@ -1121,10 +1092,10 @@ pub const fn saturating_neg(self) -> Self {
 ", $Feature, "#![feature(saturating_neg)]
 assert_eq!(100", stringify!($SelfT), ".saturating_abs(), 100);
 assert_eq!((-100", stringify!($SelfT), ").saturating_abs(), 100);
-assert_eq!(", stringify!($SelfT), "::min_value().saturating_abs(), ", stringify!($SelfT),
-"::max_value());
-assert_eq!((", stringify!($SelfT), "::min_value() + 1).saturating_abs(), ", stringify!($SelfT),
-"::max_value());",
+assert_eq!(", stringify!($SelfT), "::MIN.saturating_abs(), ", stringify!($SelfT),
+"::MAX);
+assert_eq!((", stringify!($SelfT), "::MIN + 1).saturating_abs(), ", stringify!($SelfT),
+"::MAX);",
 $EndFeature, "
 ```"),
 
@@ -1149,8 +1120,7 @@ pub const fn saturating_abs(self) -> Self {
 Basic usage:
 
 ```
-", $Feature, "use std::", stringify!($SelfT), ";
-
+", $Feature, "
 assert_eq!(10", stringify!($SelfT), ".saturating_mul(12), 120);
 assert_eq!(", stringify!($SelfT), "::MAX.saturating_mul(10), ", stringify!($SelfT), "::MAX);
 assert_eq!(", stringify!($SelfT), "::MIN.saturating_mul(10), ", stringify!($SelfT), "::MIN);",
@@ -1182,8 +1152,7 @@ pub const fn saturating_mul(self, rhs: Self) -> Self {
 Basic usage:
 
 ```
-", $Feature, "use std::", stringify!($SelfT), ";
-
+", $Feature, "
 assert_eq!((-4", stringify!($SelfT), ").saturating_pow(3), -64);
 assert_eq!(", stringify!($SelfT), "::MIN.saturating_pow(2), ", stringify!($SelfT), "::MAX);
 assert_eq!(", stringify!($SelfT), "::MIN.saturating_pow(3), ", stringify!($SelfT), "::MIN);",
@@ -1213,8 +1182,8 @@ pub const fn saturating_pow(self, exp: u32) -> Self {
 
 ```
 ", $Feature, "assert_eq!(100", stringify!($SelfT), ".wrapping_add(27), 127);
-assert_eq!(", stringify!($SelfT), "::max_value().wrapping_add(2), ", stringify!($SelfT),
-"::min_value() + 1);",
+assert_eq!(", stringify!($SelfT), "::MAX.wrapping_add(2), ", stringify!($SelfT),
+"::MIN + 1);",
 $EndFeature, "
 ```"),
             #[stable(feature = "rust1", since = "1.0.0")]
@@ -1237,8 +1206,8 @@ pub const fn wrapping_add(self, rhs: Self) -> Self {
 
 ```
 ", $Feature, "assert_eq!(0", stringify!($SelfT), ".wrapping_sub(127), -127);
-assert_eq!((-2", stringify!($SelfT), ").wrapping_sub(", stringify!($SelfT), "::max_value()), ",
-stringify!($SelfT), "::max_value());",
+assert_eq!((-2", stringify!($SelfT), ").wrapping_sub(", stringify!($SelfT), "::MAX), ",
+stringify!($SelfT), "::MAX);",
 $EndFeature, "
 ```"),
             #[stable(feature = "rust1", since = "1.0.0")]
@@ -1409,8 +1378,8 @@ pub const fn wrapping_rem_euclid(self, rhs: Self) -> Self {
 
 ```
 ", $Feature, "assert_eq!(100", stringify!($SelfT), ".wrapping_neg(), -100);
-assert_eq!(", stringify!($SelfT), "::min_value().wrapping_neg(), ", stringify!($SelfT),
-"::min_value());",
+assert_eq!(", stringify!($SelfT), "::MIN.wrapping_neg(), ", stringify!($SelfT),
+"::MIN);",
 $EndFeature, "
 ```"),
             #[stable(feature = "num_wrapping", since = "1.2.0")]
@@ -1500,8 +1469,8 @@ pub const fn wrapping_shr(self, rhs: u32) -> Self {
 ```
 ", $Feature, "assert_eq!(100", stringify!($SelfT), ".wrapping_abs(), 100);
 assert_eq!((-100", stringify!($SelfT), ").wrapping_abs(), 100);
-assert_eq!(", stringify!($SelfT), "::min_value().wrapping_abs(), ", stringify!($SelfT),
-"::min_value());
+assert_eq!(", stringify!($SelfT), "::MIN.wrapping_abs(), ", stringify!($SelfT),
+"::MIN);
 assert_eq!((-128i8).wrapping_abs() as u8, 128);",
 $EndFeature, "
 ```"),
@@ -1572,8 +1541,7 @@ pub const fn wrapping_pow(self, mut exp: u32) -> Self {
 Basic usage:
 
 ```
-", $Feature, "use std::", stringify!($SelfT), ";
-
+", $Feature, "
 assert_eq!(5", stringify!($SelfT), ".overflowing_add(2), (7, false));
 assert_eq!(", stringify!($SelfT), "::MAX.overflowing_add(1), (", stringify!($SelfT),
 "::MIN, true));", $EndFeature, "
@@ -1600,8 +1568,7 @@ pub const fn overflowing_add(self, rhs: Self) -> (Self, bool) {
 Basic usage:
 
 ```
-", $Feature, "use std::", stringify!($SelfT), ";
-
+", $Feature, "
 assert_eq!(5", stringify!($SelfT), ".overflowing_sub(2), (3, false));
 assert_eq!(", stringify!($SelfT), "::MIN.overflowing_sub(1), (", stringify!($SelfT),
 "::MAX, true));", $EndFeature, "
@@ -1658,8 +1625,7 @@ pub const fn overflowing_mul(self, rhs: Self) -> (Self, bool) {
 Basic usage:
 
 ```
-", $Feature, "use std::", stringify!($SelfT), ";
-
+", $Feature, "
 assert_eq!(5", stringify!($SelfT), ".overflowing_div(2), (2, false));
 assert_eq!(", stringify!($SelfT), "::MIN.overflowing_div(-1), (", stringify!($SelfT),
 "::MIN, true));",
@@ -1694,8 +1660,6 @@ pub const fn overflowing_div(self, rhs: Self) -> (Self, bool) {
 Basic usage:
 
 ```
-use std::", stringify!($SelfT), ";
-
 assert_eq!(5", stringify!($SelfT), ".overflowing_div_euclid(2), (2, false));
 assert_eq!(", stringify!($SelfT), "::MIN.overflowing_div_euclid(-1), (", stringify!($SelfT),
 "::MIN, true));
@@ -1729,8 +1693,7 @@ pub const fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) {
 Basic usage:
 
 ```
-", $Feature, "use std::", stringify!($SelfT), ";
-
+", $Feature, "
 assert_eq!(5", stringify!($SelfT), ".overflowing_rem(2), (1, false));
 assert_eq!(", stringify!($SelfT), "::MIN.overflowing_rem(-1), (0, true));",
 $EndFeature, "
@@ -1765,8 +1728,6 @@ pub const fn overflowing_rem(self, rhs: Self) -> (Self, bool) {
 Basic usage:
 
 ```
-use std::", stringify!($SelfT), ";
-
 assert_eq!(5", stringify!($SelfT), ".overflowing_rem_euclid(2), (1, false));
 assert_eq!(", stringify!($SelfT), "::MIN.overflowing_rem_euclid(-1), (0, true));
 ```"),
@@ -1797,8 +1758,6 @@ pub const fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) {
 Basic usage:
 
 ```
-", $Feature, "use std::", stringify!($SelfT), ";
-
 assert_eq!(2", stringify!($SelfT), ".overflowing_neg(), (-2, false));
 assert_eq!(", stringify!($SelfT), "::MIN.overflowing_neg(), (", stringify!($SelfT),
 "::MIN, true));", $EndFeature, "
@@ -1884,8 +1843,8 @@ pub const fn overflowing_shr(self, rhs: u32) -> (Self, bool) {
 ```
 ", $Feature, "assert_eq!(10", stringify!($SelfT), ".overflowing_abs(), (10, false));
 assert_eq!((-10", stringify!($SelfT), ").overflowing_abs(), (10, false));
-assert_eq!((", stringify!($SelfT), "::min_value()).overflowing_abs(), (", stringify!($SelfT),
-"::min_value(), true));",
+assert_eq!((", stringify!($SelfT), "::MIN).overflowing_abs(), (", stringify!($SelfT),
+"::MIN, true));",
 $EndFeature, "
 ```"),
             #[stable(feature = "no_panic_abs", since = "1.13.0")]
@@ -2083,10 +2042,10 @@ pub const fn rem_euclid(self, rhs: Self) -> Self {
 
 # Overflow behavior
 
-The absolute value of `", stringify!($SelfT), "::min_value()` cannot be represented as an
+The absolute value of `", stringify!($SelfT), "::MIN` cannot be represented as an
 `", stringify!($SelfT), "`, and attempting to calculate it will cause an overflow. This means that
 code in debug mode will trigger a panic on this case and optimized code will return `",
-stringify!($SelfT), "::min_value()` without a panic.
+stringify!($SelfT), "::MIN` without a panic.
 
 # Examples
 
@@ -2195,7 +2154,7 @@ pub const fn is_negative(self) -> bool { self < 0 }
 assert_eq!(bytes, ", $be_bytes, ");
 ```"),
             #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
-            #[rustc_const_unstable(feature = "const_int_conversion", issue = "53718")]
+            #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
             #[inline]
             pub const fn to_be_bytes(self) -> [u8; mem::size_of::<Self>()] {
                 self.to_be().to_ne_bytes()
@@ -2215,7 +2174,7 @@ pub const fn is_negative(self) -> bool { self < 0 }
 assert_eq!(bytes, ", $le_bytes, ");
 ```"),
             #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
-            #[rustc_const_unstable(feature = "const_int_conversion", issue = "53718")]
+            #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
             #[inline]
             pub const fn to_le_bytes(self) -> [u8; mem::size_of::<Self>()] {
                 self.to_le().to_ne_bytes()
@@ -2250,12 +2209,20 @@ pub const fn is_negative(self) -> bool { self < 0 }
 );
 ```"),
             #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
-            #[rustc_const_unstable(feature = "const_int_conversion", issue = "53718")]
+            #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
+            // SAFETY: const sound because integers are plain old datatypes so we can always
+            // transmute them to arrays of bytes
+            #[allow_internal_unstable(const_fn_union)]
             #[inline]
             pub const fn to_ne_bytes(self) -> [u8; mem::size_of::<Self>()] {
+                #[repr(C)]
+                union Bytes {
+                    val: $SelfT,
+                    bytes: [u8; mem::size_of::<$SelfT>()],
+                }
                 // SAFETY: integers are plain old datatypes so we can always transmute them to
                 // arrays of bytes
-                unsafe { mem::transmute(self) }
+                unsafe { Bytes { val: self }.bytes }
             }
         }
 
@@ -2284,7 +2251,7 @@ fn read_be_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT),
 }
 ```"),
             #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
-            #[rustc_const_unstable(feature = "const_int_conversion", issue = "53718")]
+            #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
             #[inline]
             pub const fn from_be_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
                 Self::from_be(Self::from_ne_bytes(bytes))
@@ -2317,7 +2284,7 @@ fn read_le_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT),
 }
 ```"),
             #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
-            #[rustc_const_unstable(feature = "const_int_conversion", issue = "53718")]
+            #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
             #[inline]
             pub const fn from_le_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
                 Self::from_le(Self::from_ne_bytes(bytes))
@@ -2360,11 +2327,51 @@ fn read_ne_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT),
 }
 ```"),
             #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
-            #[rustc_const_unstable(feature = "const_int_conversion", issue = "53718")]
+            #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
+            // SAFETY: const sound because integers are plain old datatypes so we can always
+            // transmute to them
+            #[allow_internal_unstable(const_fn_union)]
             #[inline]
             pub const fn from_ne_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
+                #[repr(C)]
+                union Bytes {
+                    val: $SelfT,
+                    bytes: [u8; mem::size_of::<$SelfT>()],
+                }
                 // SAFETY: integers are plain old datatypes so we can always transmute to them
-                unsafe { mem::transmute(bytes) }
+                unsafe { Bytes { bytes }.val }
+            }
+        }
+
+        doc_comment! {
+            concat!("**This method is soft-deprecated.**
+
+Although using it won’t cause compilation warning,
+new code should use [`", stringify!($SelfT), "::MIN", "`](#associatedconstant.MIN) instead.
+
+Returns the smallest value that can be represented by this integer type."),
+            #[stable(feature = "rust1", since = "1.0.0")]
+            #[inline(always)]
+            #[rustc_promotable]
+            #[rustc_const_stable(feature = "const_min_value", since = "1.32.0")]
+            pub const fn min_value() -> Self {
+                Self::MIN
+            }
+        }
+
+        doc_comment! {
+            concat!("**This method is soft-deprecated.**
+
+Although using it won’t cause compilation warning,
+new code should use [`", stringify!($SelfT), "::MAX", "`](#associatedconstant.MAX) instead.
+
+Returns the largest value that can be represented by this integer type."),
+            #[stable(feature = "rust1", since = "1.0.0")]
+            #[inline(always)]
+            #[rustc_promotable]
+            #[rustc_const_stable(feature = "const_max_value", since = "1.32.0")]
+            pub const fn max_value() -> Self {
+                Self::MAX
             }
         }
     }
@@ -2449,10 +2456,9 @@ macro_rules! uint_impl {
 Basic usage:
 
 ```
-#![feature(assoc_int_consts)]
 ", $Feature, "assert_eq!(", stringify!($SelfT), "::MIN, 0);", $EndFeature, "
 ```"),
-            #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")]
+            #[stable(feature = "assoc_int_consts", since = "1.43.0")]
             pub const MIN: Self = 0;
         }
 
@@ -2464,32 +2470,13 @@ macro_rules! uint_impl {
 Basic usage:
 
 ```
-#![feature(assoc_int_consts)]
 ", $Feature, "assert_eq!(", stringify!($SelfT), "::MAX, ", stringify!($MaxV), ");",
 $EndFeature, "
 ```"),
-            #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")]
+            #[stable(feature = "assoc_int_consts", since = "1.43.0")]
             pub const MAX: Self = !0;
         }
 
-        doc_comment! {
-            "Returns the smallest value that can be represented by this integer type.",
-            #[stable(feature = "rust1", since = "1.0.0")]
-            #[rustc_promotable]
-            #[inline(always)]
-            #[rustc_const_stable(feature = "const_max_value", since = "1.32.0")]
-            pub const fn min_value() -> Self { Self::MIN }
-        }
-
-        doc_comment! {
-            "Returns the largest value that can be represented by this integer type.",
-            #[stable(feature = "rust1", since = "1.0.0")]
-            #[rustc_promotable]
-            #[inline(always)]
-            #[rustc_const_stable(feature = "const_max_value", since = "1.32.0")]
-            pub const fn max_value() -> Self { Self::MAX }
-        }
-
         doc_comment! {
             concat!("Converts a string slice in a given base to an integer.
 
@@ -2548,7 +2535,7 @@ pub const fn count_ones(self) -> u32 {
 Basic usage:
 
 ```
-", $Feature, "assert_eq!(", stringify!($SelfT), "::max_value().count_zeros(), 0);", $EndFeature, "
+", $Feature, "assert_eq!(", stringify!($SelfT), "::MAX.count_zeros(), 0);", $EndFeature, "
 ```"),
             #[stable(feature = "rust1", since = "1.0.0")]
             #[rustc_const_stable(feature = "const_math", since = "1.32.0")]
@@ -2566,7 +2553,7 @@ pub const fn count_zeros(self) -> u32 {
 Basic usage:
 
 ```
-", $Feature, "let n = ", stringify!($SelfT), "::max_value() >> 2;
+", $Feature, "let n = ", stringify!($SelfT), "::MAX >> 2;
 
 assert_eq!(n.leading_zeros(), 2);", $EndFeature, "
 ```"),
@@ -2608,7 +2595,7 @@ pub const fn trailing_zeros(self) -> u32 {
 
 ```
 ", $Feature, "#![feature(leading_trailing_ones)]
-let n = !(", stringify!($SelfT), "::max_value() >> 2);
+let n = !(", stringify!($SelfT), "::MAX >> 2);
 
 assert_eq!(n.leading_ones(), 2);", $EndFeature, "
 ```"),
@@ -2882,9 +2869,9 @@ pub const fn to_le(self) -> Self {
 Basic usage:
 
 ```
-", $Feature, "assert_eq!((", stringify!($SelfT), "::max_value() - 2).checked_add(1), ",
-"Some(", stringify!($SelfT), "::max_value() - 1));
-assert_eq!((", stringify!($SelfT), "::max_value() - 2).checked_add(3), None);", $EndFeature, "
+", $Feature, "assert_eq!((", stringify!($SelfT), "::MAX - 2).checked_add(1), ",
+"Some(", stringify!($SelfT), "::MAX - 1));
+assert_eq!((", stringify!($SelfT), "::MAX - 2).checked_add(3), None);", $EndFeature, "
 ```"),
             #[stable(feature = "rust1", since = "1.0.0")]
             #[rustc_const_unstable(feature = "const_checked_int_methods", issue = "53718")]
@@ -2930,7 +2917,7 @@ pub const fn checked_sub(self, rhs: Self) -> Option<Self> {
 
 ```
 ", $Feature, "assert_eq!(5", stringify!($SelfT), ".checked_mul(1), Some(5));
-assert_eq!(", stringify!($SelfT), "::max_value().checked_mul(2), None);", $EndFeature, "
+assert_eq!(", stringify!($SelfT), "::MAX.checked_mul(2), None);", $EndFeature, "
 ```"),
             #[stable(feature = "rust1", since = "1.0.0")]
             #[rustc_const_unstable(feature = "const_checked_int_methods", issue = "53718")]
@@ -3130,7 +3117,7 @@ pub const fn checked_shr(self, rhs: u32) -> Option<Self> {
 
 ```
 ", $Feature, "assert_eq!(2", stringify!($SelfT), ".checked_pow(5), Some(32));
-assert_eq!(", stringify!($SelfT), "::max_value().checked_pow(2), None);", $EndFeature, "
+assert_eq!(", stringify!($SelfT), "::MAX.checked_pow(2), None);", $EndFeature, "
 ```"),
             #[stable(feature = "no_panic_pow", since = "1.34.0")]
             #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
@@ -3214,8 +3201,7 @@ pub const fn saturating_sub(self, rhs: Self) -> Self {
 Basic usage:
 
 ```
-", $Feature, "use std::", stringify!($SelfT), ";
-
+", $Feature, "
 assert_eq!(2", stringify!($SelfT), ".saturating_mul(10), 20);
 assert_eq!((", stringify!($SelfT), "::MAX).saturating_mul(10), ", stringify!($SelfT),
 "::MAX);", $EndFeature, "
@@ -3242,8 +3228,7 @@ pub const fn saturating_mul(self, rhs: Self) -> Self {
 Basic usage:
 
 ```
-", $Feature, "use std::", stringify!($SelfT), ";
-
+", $Feature, "
 assert_eq!(4", stringify!($SelfT), ".saturating_pow(3), 64);
 assert_eq!(", stringify!($SelfT), "::MAX.saturating_pow(2), ", stringify!($SelfT), "::MAX);",
 $EndFeature, "
@@ -3271,7 +3256,7 @@ pub const fn saturating_pow(self, exp: u32) -> Self {
 
 ```
 ", $Feature, "assert_eq!(200", stringify!($SelfT), ".wrapping_add(55), 255);
-assert_eq!(200", stringify!($SelfT), ".wrapping_add(", stringify!($SelfT), "::max_value()), 199);",
+assert_eq!(200", stringify!($SelfT), ".wrapping_add(", stringify!($SelfT), "::MAX), 199);",
 $EndFeature, "
 ```"),
             #[stable(feature = "rust1", since = "1.0.0")]
@@ -3294,7 +3279,7 @@ pub const fn wrapping_add(self, rhs: Self) -> Self {
 
 ```
 ", $Feature, "assert_eq!(100", stringify!($SelfT), ".wrapping_sub(100), 0);
-assert_eq!(100", stringify!($SelfT), ".wrapping_sub(", stringify!($SelfT), "::max_value()), 101);",
+assert_eq!(100", stringify!($SelfT), ".wrapping_sub(", stringify!($SelfT), "::MAX), 101);",
 $EndFeature, "
 ```"),
             #[stable(feature = "rust1", since = "1.0.0")]
@@ -3582,8 +3567,7 @@ pub const fn wrapping_pow(self, mut exp: u32) -> Self {
 Basic usage
 
 ```
-", $Feature, "use std::", stringify!($SelfT), ";
-
+", $Feature, "
 assert_eq!(5", stringify!($SelfT), ".overflowing_add(2), (7, false));
 assert_eq!(", stringify!($SelfT), "::MAX.overflowing_add(1), (0, true));", $EndFeature, "
 ```"),
@@ -3610,8 +3594,7 @@ pub const fn overflowing_add(self, rhs: Self) -> (Self, bool) {
 Basic usage
 
 ```
-", $Feature, "use std::", stringify!($SelfT), ";
-
+", $Feature, "
 assert_eq!(5", stringify!($SelfT), ".overflowing_sub(2), (3, false));
 assert_eq!(0", stringify!($SelfT), ".overflowing_sub(1), (", stringify!($SelfT), "::MAX, true));",
 $EndFeature, "
@@ -4083,7 +4066,7 @@ pub const fn next_power_of_two(self) -> Self {
 ", $Feature, "assert_eq!(2", stringify!($SelfT),
 ".checked_next_power_of_two(), Some(2));
 assert_eq!(3", stringify!($SelfT), ".checked_next_power_of_two(), Some(4));
-assert_eq!(", stringify!($SelfT), "::max_value().checked_next_power_of_two(), None);",
+assert_eq!(", stringify!($SelfT), "::MAX.checked_next_power_of_two(), None);",
 $EndFeature, "
 ```"),
             #[inline]
@@ -4108,7 +4091,7 @@ pub const fn checked_next_power_of_two(self) -> Option<Self> {
 ", $Feature, "
 assert_eq!(2", stringify!($SelfT), ".wrapping_next_power_of_two(), 2);
 assert_eq!(3", stringify!($SelfT), ".wrapping_next_power_of_two(), 4);
-assert_eq!(", stringify!($SelfT), "::max_value().wrapping_next_power_of_two(), 0);",
+assert_eq!(", stringify!($SelfT), "::MAX.wrapping_next_power_of_two(), 0);",
 $EndFeature, "
 ```"),
             #[unstable(feature = "wrapping_next_power_of_two", issue = "32463",
@@ -4132,7 +4115,7 @@ pub const fn wrapping_next_power_of_two(self) -> Self {
 assert_eq!(bytes, ", $be_bytes, ");
 ```"),
             #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
-            #[rustc_const_unstable(feature = "const_int_conversion", issue = "53718")]
+            #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
             #[inline]
             pub const fn to_be_bytes(self) -> [u8; mem::size_of::<Self>()] {
                 self.to_be().to_ne_bytes()
@@ -4152,7 +4135,7 @@ pub const fn wrapping_next_power_of_two(self) -> Self {
 assert_eq!(bytes, ", $le_bytes, ");
 ```"),
             #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
-            #[rustc_const_unstable(feature = "const_int_conversion", issue = "53718")]
+            #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
             #[inline]
             pub const fn to_le_bytes(self) -> [u8; mem::size_of::<Self>()] {
                 self.to_le().to_ne_bytes()
@@ -4187,12 +4170,20 @@ pub const fn wrapping_next_power_of_two(self) -> Self {
 );
 ```"),
             #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
-            #[rustc_const_unstable(feature = "const_int_conversion", issue = "53718")]
+            #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
+            // SAFETY: const sound because integers are plain old datatypes so we can always
+            // transmute them to arrays of bytes
+            #[allow_internal_unstable(const_fn_union)]
             #[inline]
             pub const fn to_ne_bytes(self) -> [u8; mem::size_of::<Self>()] {
+                #[repr(C)]
+                union Bytes {
+                    val: $SelfT,
+                    bytes: [u8; mem::size_of::<$SelfT>()],
+                }
                 // SAFETY: integers are plain old datatypes so we can always transmute them to
                 // arrays of bytes
-                unsafe { mem::transmute(self) }
+                unsafe { Bytes { val: self }.bytes }
             }
         }
 
@@ -4221,7 +4212,7 @@ fn read_be_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT),
 }
 ```"),
             #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
-            #[rustc_const_unstable(feature = "const_int_conversion", issue = "53718")]
+            #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
             #[inline]
             pub const fn from_be_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
                 Self::from_be(Self::from_ne_bytes(bytes))
@@ -4254,7 +4245,7 @@ fn read_le_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT),
 }
 ```"),
             #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
-            #[rustc_const_unstable(feature = "const_int_conversion", issue = "53718")]
+            #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
             #[inline]
             pub const fn from_le_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
                 Self::from_le(Self::from_ne_bytes(bytes))
@@ -4297,13 +4288,49 @@ fn read_ne_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT),
 }
 ```"),
             #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
-            #[rustc_const_unstable(feature = "const_int_conversion", issue = "53718")]
+            #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
+            // SAFETY: const sound because integers are plain old datatypes so we can always
+            // transmute to them
+            #[allow_internal_unstable(const_fn_union)]
             #[inline]
             pub const fn from_ne_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
+                #[repr(C)]
+                union Bytes {
+                    val: $SelfT,
+                    bytes: [u8; mem::size_of::<$SelfT>()],
+                }
                 // SAFETY: integers are plain old datatypes so we can always transmute to them
-                unsafe { mem::transmute(bytes) }
+                unsafe { Bytes { bytes }.val }
             }
         }
+
+        doc_comment! {
+            concat!("**This method is soft-deprecated.**
+
+Although using it won’t cause compilation warning,
+new code should use [`", stringify!($SelfT), "::MIN", "`](#associatedconstant.MIN) instead.
+
+Returns the smallest value that can be represented by this integer type."),
+            #[stable(feature = "rust1", since = "1.0.0")]
+            #[rustc_promotable]
+            #[inline(always)]
+            #[rustc_const_stable(feature = "const_max_value", since = "1.32.0")]
+            pub const fn min_value() -> Self { Self::MIN }
+        }
+
+        doc_comment! {
+            concat!("**This method is soft-deprecated.**
+
+Although using it won’t cause compilation warning,
+new code should use [`", stringify!($SelfT), "::MAX", "`](#associatedconstant.MAX) instead.
+
+Returns the largest value that can be represented by this integer type."),
+            #[stable(feature = "rust1", since = "1.0.0")]
+            #[rustc_promotable]
+            #[inline(always)]
+            #[rustc_const_stable(feature = "const_max_value", since = "1.32.0")]
+            pub const fn max_value() -> Self { Self::MAX }
+        }
     }
 }
 
@@ -4876,7 +4903,6 @@ impl usize {
 ///
 /// ```
 /// use std::num::FpCategory;
-/// use std::f32;
 ///
 /// let num = 12.4_f32;
 /// let inf = f32::INFINITY;
index 7d1aa664de30c52adfd54cc14b47555c7e3f2258..dd45ff141539fcd4c7d8b58e51bc3eddbf3b64c5 100644 (file)
@@ -1,6 +1,9 @@
 //! The 128-bit unsigned integer type.
 //!
 //! *[See also the `u128` primitive type](../../std/primitive.u128.html).*
+//!
+//! Although using these constants won’t cause compilation warnings,
+//! new code should use the associated constants directly on the primitive type.
 
 #![stable(feature = "i128", since = "1.26.0")]
-uint_module! { u128, #[stable(feature = "i128", since="1.26.0")] }
+int_module! { u128, #[stable(feature = "i128", since="1.26.0")] }
index 34f80abaecc0580df9aae5866933ed5ebceff1e6..738071643b63963d1884914c1ed833c5c314d93c 100644 (file)
@@ -1,7 +1,10 @@
 //! The 16-bit unsigned integer type.
 //!
 //! *[See also the `u16` primitive type](../../std/primitive.u16.html).*
+//!
+//! Although using these constants won’t cause compilation warnings,
+//! new code should use the associated constants directly on the primitive type.
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-uint_module! { u16 }
+int_module! { u16 }
index 5fd486f5466085c0a2183f410641d4713c225216..9800c9099748fece634361a65ec82b83b0587e72 100644 (file)
@@ -1,7 +1,10 @@
 //! The 32-bit unsigned integer type.
 //!
 //! *[See also the `u32` primitive type](../../std/primitive.u32.html).*
+//!
+//! Although using these constants won’t cause compilation warnings,
+//! new code should use the associated constants directly on the primitive type.
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-uint_module! { u32 }
+int_module! { u32 }
index 044d238aea9be377cd57c8e2fb59605daed2f1fb..fb686c396f033e4075b02816f870624a3fa88a36 100644 (file)
@@ -1,7 +1,10 @@
 //! The 64-bit unsigned integer type.
 //!
 //! *[See also the `u64` primitive type](../../std/primitive.u64.html).*
+//!
+//! Although using these constants won’t cause compilation warnings,
+//! new code should use the associated constants directly on the primitive type.
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-uint_module! { u64 }
+int_module! { u64 }
index 6747e6a0f6c24f1968d273bcec247e8159568e6f..c03cbdda25dbbbcd41b34595d4ba980c7ba894b7 100644 (file)
@@ -1,7 +1,10 @@
 //! The 8-bit unsigned integer type.
 //!
 //! *[See also the `u8` primitive type](../../std/primitive.u8.html).*
+//!
+//! Although using these constants won’t cause compilation warnings,
+//! new code should use the associated constants directly on the primitive type.
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-uint_module! { u8 }
+int_module! { u8 }
diff --git a/src/libcore/num/uint_macros.rs b/src/libcore/num/uint_macros.rs
deleted file mode 100644 (file)
index a94b541..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-#![doc(hidden)]
-
-macro_rules! uint_module {
-    ($T:ident) => (uint_module!($T, #[stable(feature = "rust1", since = "1.0.0")]););
-    ($T:ident, #[$attr:meta]) => (
-        /// The smallest value that can be represented by this integer type.
-        #[$attr]
-        pub const MIN: $T = $T::min_value();
-        /// The largest value that can be represented by this integer type.
-        #[$attr]
-        pub const MAX: $T = $T::max_value();
-    )
-}
index e3a5239d908dc01bce3acaf6586e00f9053f28ca..a89304161524463aeb55f15b97784fc4d69fa45e 100644 (file)
@@ -1,7 +1,10 @@
 //! The pointer-sized unsigned integer type.
 //!
 //! *[See also the `usize` primitive type](../../std/primitive.usize.html).*
+//!
+//! Although using these constants won’t cause compilation warnings,
+//! new code should use the associated constants directly on the primitive type.
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-uint_module! { usize }
+int_module! { usize }
index 59a72799e256726e20dbf7728f4c94298269d7d9..e9ec81394e32d8c528cc41c1864f992014f9bd11 100644 (file)
@@ -13,7 +13,7 @@
 /// ```
 /// use std::ops::Add;
 ///
-/// #[derive(Debug, PartialEq)]
+/// #[derive(Debug, Copy, Clone, PartialEq)]
 /// struct Point {
 ///     x: i32,
 ///     y: i32,
@@ -42,7 +42,7 @@
 /// ```
 /// use std::ops::Add;
 ///
-/// #[derive(Debug, PartialEq)]
+/// #[derive(Debug, Copy, Clone, PartialEq)]
 /// struct Point<T> {
 ///     x: T,
 ///     y: T,
@@ -115,7 +115,7 @@ fn add(self, other: $t) -> $t { self + other }
 /// ```
 /// use std::ops::Sub;
 ///
-/// #[derive(Debug, PartialEq)]
+/// #[derive(Debug, Copy, Clone, PartialEq)]
 /// struct Point {
 ///     x: i32,
 ///     y: i32,
@@ -657,7 +657,7 @@ macro_rules! neg_impl_unsigned {
 /// ```
 /// use std::ops::AddAssign;
 ///
-/// #[derive(Debug, PartialEq)]
+/// #[derive(Debug, Copy, Clone, PartialEq)]
 /// struct Point {
 ///     x: i32,
 ///     y: i32,
@@ -715,7 +715,7 @@ fn add_assign(&mut self, other: $t) { *self += other }
 /// ```
 /// use std::ops::SubAssign;
 ///
-/// #[derive(Debug, PartialEq)]
+/// #[derive(Debug, Copy, Clone, PartialEq)]
 /// struct Point {
 ///     x: i32,
 ///     y: i32,
index 4e43561996c370ee7c151ef6f632925c7ac35d1a..4f23620b92b806067b336ac4fa76a5f3a7c96459 100644 (file)
@@ -67,7 +67,7 @@ pub enum GeneratorState<Y, R> {
 #[lang = "generator"]
 #[unstable(feature = "generator_trait", issue = "43122")]
 #[fundamental]
-pub trait Generator<#[cfg(not(bootstrap))] R = ()> {
+pub trait Generator<R = ()> {
     /// The type of value this generator yields.
     ///
     /// This associated type corresponds to the `yield` expression and the
@@ -110,35 +110,9 @@ pub trait Generator<#[cfg(not(bootstrap))] R = ()> {
     /// been returned previously. While generator literals in the language are
     /// guaranteed to panic on resuming after `Complete`, this is not guaranteed
     /// for all implementations of the `Generator` trait.
-    fn resume(
-        self: Pin<&mut Self>,
-        #[cfg(not(bootstrap))] arg: R,
-    ) -> GeneratorState<Self::Yield, Self::Return>;
+    fn resume(self: Pin<&mut Self>, arg: R) -> GeneratorState<Self::Yield, Self::Return>;
 }
 
-#[cfg(bootstrap)]
-#[unstable(feature = "generator_trait", issue = "43122")]
-impl<G: ?Sized + Generator> Generator for Pin<&mut G> {
-    type Yield = G::Yield;
-    type Return = G::Return;
-
-    fn resume(mut self: Pin<&mut Self>) -> GeneratorState<Self::Yield, Self::Return> {
-        G::resume((*self).as_mut())
-    }
-}
-
-#[cfg(bootstrap)]
-#[unstable(feature = "generator_trait", issue = "43122")]
-impl<G: ?Sized + Generator + Unpin> Generator for &mut G {
-    type Yield = G::Yield;
-    type Return = G::Return;
-
-    fn resume(mut self: Pin<&mut Self>) -> GeneratorState<Self::Yield, Self::Return> {
-        G::resume(Pin::new(&mut *self))
-    }
-}
-
-#[cfg(not(bootstrap))]
 #[unstable(feature = "generator_trait", issue = "43122")]
 impl<G: ?Sized + Generator<R>, R> Generator<R> for Pin<&mut G> {
     type Yield = G::Yield;
@@ -149,7 +123,6 @@ fn resume(mut self: Pin<&mut Self>, arg: R) -> GeneratorState<Self::Yield, Self:
     }
 }
 
-#[cfg(not(bootstrap))]
 #[unstable(feature = "generator_trait", issue = "43122")]
 impl<G: ?Sized + Generator<R> + Unpin, R> Generator<R> for &mut G {
     type Yield = G::Yield;
index 77b92b6ccbdaa5bbdc8f8888112c6487733b2b47..e3e5934b44be1f0732913ce89568a556dc3d4e19 100644 (file)
@@ -42,7 +42,7 @@
 //! ```rust
 //! use std::ops::{Add, Sub};
 //!
-//! #[derive(Debug, PartialEq)]
+//! #[derive(Debug, Copy, Clone, PartialEq)]
 //! struct Point {
 //!     x: i32,
 //!     y: i32,
index 9b32442371c37a32c77577b8e66e2f6551972911..3aab8b1b3337cc4ff39619782564eb328f9616ea 100644 (file)
@@ -913,6 +913,63 @@ pub fn take(&mut self) -> Option<T> {
     pub fn replace(&mut self, value: T) -> Option<T> {
         mem::replace(self, Some(value))
     }
+
+    /// Zips `self` with another `Option`.
+    ///
+    /// If `self` is `Some(s)` and `other` is `Some(o)`, this method returns `Some((s, o))`.
+    /// Otherwise, `None` is returned.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(option_zip)]
+    /// let x = Some(1);
+    /// let y = Some("hi");
+    /// let z = None::<u8>;
+    ///
+    /// assert_eq!(x.zip(y), Some((1, "hi")));
+    /// assert_eq!(x.zip(z), None);
+    /// ```
+    #[unstable(feature = "option_zip", issue = "70086")]
+    pub fn zip<U>(self, other: Option<U>) -> Option<(T, U)> {
+        self.zip_with(other, |a, b| (a, b))
+    }
+
+    /// Zips `self` and another `Option` with function `f`.
+    ///
+    /// If `self` is `Some(s)` and `other` is `Some(o)`, this method returns `Some(f(s, o))`.
+    /// Otherwise, `None` is returned.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(option_zip)]
+    ///
+    /// #[derive(Debug, PartialEq)]
+    /// struct Point {
+    ///     x: f64,
+    ///     y: f64,
+    /// }
+    ///
+    /// impl Point {
+    ///     fn new(x: f64, y: f64) -> Self {
+    ///         Self { x, y }
+    ///     }
+    /// }
+    ///
+    /// let x = Some(17.5);
+    /// let y = Some(42.7);
+    ///
+    /// assert_eq!(x.zip_with(y, Point::new), Some(Point { x: 17.5, y: 42.7 }));
+    /// assert_eq!(x.zip_with(None, Point::new), None);
+    /// ```
+    #[unstable(feature = "option_zip", issue = "70086")]
+    pub fn zip_with<U, F, R>(self, other: Option<U>, f: F) -> Option<R>
+    where
+        F: FnOnce(T, U) -> R,
+    {
+        Some(f(self?, other?))
+    }
 }
 
 impl<T: Copy> Option<&T> {
index 61b764f2d6206ad7773ede553601ea130ce968d1..3587f3f0ebf56c738feb4be9a8db8327052a6424 100644 (file)
@@ -32,6 +32,7 @@
 use crate::fmt;
 use crate::panic::{Location, PanicInfo};
 
+/// The underlying implementation of libcore's `panic!` macro when no formatting is used.
 #[cold]
 // never inline unless panic_immediate_abort to avoid code
 // bloat at the call sites as much as possible
@@ -49,9 +50,28 @@ pub fn panic(expr: &str) -> ! {
     // truncation and padding (even though none is used here). Using
     // Arguments::new_v1 may allow the compiler to omit Formatter::pad from the
     // output binary, saving up to a few kilobytes.
-    panic_fmt(fmt::Arguments::new_v1(&[expr], &[]), Location::caller())
+    #[cfg(not(bootstrap))]
+    panic_fmt(fmt::Arguments::new_v1(&[expr], &[]));
+    #[cfg(bootstrap)]
+    panic_fmt(fmt::Arguments::new_v1(&[expr], &[]), Location::caller());
 }
 
+#[cfg(not(bootstrap))]
+#[cold]
+#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
+#[track_caller]
+#[lang = "panic_bounds_check"] // needed by codegen for panic on OOB array/slice access
+fn panic_bounds_check(index: usize, len: usize) -> ! {
+    if cfg!(feature = "panic_immediate_abort") {
+        unsafe { super::intrinsics::abort() }
+    }
+
+    panic!("index out of bounds: the len is {} but the index is {}", len, index)
+}
+
+// For bootstrap, we need a variant with the old argument order, and a corresponding
+// `panic_fmt`.
+#[cfg(bootstrap)]
 #[cold]
 #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
 #[lang = "panic_bounds_check"] // needed by codegen for panic on OOB array/slice access
@@ -66,10 +86,12 @@ fn panic_bounds_check(location: &Location<'_>, index: usize, len: usize) -> ! {
     )
 }
 
+/// The underlying implementation of libcore's `panic!` macro when formatting is used.
 #[cold]
 #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
 #[cfg_attr(feature = "panic_immediate_abort", inline)]
-pub fn panic_fmt(fmt: fmt::Arguments<'_>, location: &Location<'_>) -> ! {
+#[cfg_attr(not(bootstrap), track_caller)]
+pub fn panic_fmt(fmt: fmt::Arguments<'_>, #[cfg(bootstrap)] location: &Location<'_>) -> ! {
     if cfg!(feature = "panic_immediate_abort") {
         unsafe { super::intrinsics::abort() }
     }
@@ -81,6 +103,10 @@ pub fn panic_fmt(fmt: fmt::Arguments<'_>, location: &Location<'_>) -> ! {
         fn panic_impl(pi: &PanicInfo<'_>) -> !;
     }
 
+    #[cfg(bootstrap)]
     let pi = PanicInfo::internal_constructor(Some(&fmt), location);
+    #[cfg(not(bootstrap))]
+    let pi = PanicInfo::internal_constructor(Some(&fmt), Location::caller());
+
     unsafe { panic_impl(&pi) }
 }
index 676d2c784acee2143bf2b72efd441193fac2fffd..774ecd997c201d56630ebef9463a7d7a7a49b3f9 100644 (file)
 //!
 //! ## Examples
 //!
-//! For a type like [`Vec<T>`], both possibilites (structural pinning or not) make sense.
+//! For a type like [`Vec<T>`], both possibilities (structural pinning or not) make sense.
 //! A [`Vec<T>`] with structural pinning could have `get_pin`/`get_pin_mut` methods to get
 //! pinned references to elements. However, it could *not* allow calling
 //! [`pop`][Vec::pop] on a pinned [`Vec<T>`] because that would move the (structurally pinned)
@@ -539,7 +539,7 @@ impl<P: Deref> Pin<P> {
     /// ```
     /// A value, once pinned, must remain pinned forever (unless its type implements `Unpin`).
     ///
-    /// Similarily, calling `Pin::new_unchecked` on an `Rc<T>` is unsafe because there could be
+    /// Similarly, calling `Pin::new_unchecked` on an `Rc<T>` is unsafe because there could be
     /// aliases to the same data that are not subject to the pinning restrictions:
     /// ```
     /// use std::rc::Rc;
index 66b5a90b77b919f6f6a1c894e3f185e2a64a5de2..c91370b2719929bef21884c043872fd08623fd9e 100644 (file)
 pub use crate::macros::builtin::{
     bench, global_allocator, test, test_case, RustcDecodable, RustcEncodable,
 };
+
+#[cfg(not(bootstrap))]
+#[unstable(
+    feature = "cfg_accessible",
+    issue = "64797",
+    reason = "`cfg_accessible` is not fully implemented"
+)]
+#[doc(no_inline)]
+pub use crate::macros::builtin::cfg_accessible;
index fc3c02e1f066df2573de4a3bdd8385b5cc4d9cff..a540016854df3b7b5d127558dc856e9d75313665 100644 (file)
@@ -53,7 +53,7 @@ pub const fn cast<U>(self) -> *const U {
     /// all of the following is true:
     /// - it is properly aligned
     /// - it must point to an initialized instance of T; in particular, the pointer must be
-    ///   "dereferencable" in the sense defined [here].
+    ///   "dereferenceable" in the sense defined [here].
     ///
     /// This applies even if the result of this method is unused!
     /// (The part about being initialized is not yet fully decided, but until
@@ -183,7 +183,7 @@ pub unsafe fn offset(self, count: isize) -> *const T
     /// within the same allocated object: [`offset`] is immediate Undefined Behavior when
     /// crossing object boundaries; `wrapping_offset` produces a pointer but still leads
     /// to Undefined Behavior if that pointer is dereferenced. [`offset`] can be optimized
-    /// better and is thus preferrable in performance-sensitive code.
+    /// better and is thus preferable in performance-sensitive code.
     ///
     /// If you need to cross object boundaries, cast the pointer to an integer and
     /// do the arithmetic there.
@@ -480,7 +480,7 @@ pub unsafe fn sub(self, count: usize) -> Self
     /// within the same allocated object: [`add`] is immediate Undefined Behavior when
     /// crossing object boundaries; `wrapping_add` produces a pointer but still leads
     /// to Undefined Behavior if that pointer is dereferenced. [`add`] can be optimized
-    /// better and is thus preferrable in performance-sensitive code.
+    /// better and is thus preferable in performance-sensitive code.
     ///
     /// If you need to cross object boundaries, cast the pointer to an integer and
     /// do the arithmetic there.
@@ -535,7 +535,7 @@ pub fn wrapping_add(self, count: usize) -> Self
     /// within the same allocated object: [`sub`] is immediate Undefined Behavior when
     /// crossing object boundaries; `wrapping_sub` produces a pointer but still leads
     /// to Undefined Behavior if that pointer is dereferenced. [`sub`] can be optimized
-    /// better and is thus preferrable in performance-sensitive code.
+    /// better and is thus preferable in performance-sensitive code.
     ///
     /// If you need to cross object boundaries, cast the pointer to an integer and
     /// do the arithmetic there.
index fcfa98d8507213f74c351249946524d802cc9554..4913cd73a2a9a373edb03badb983f8e640cb11b8 100644 (file)
@@ -19,7 +19,7 @@
 //! * All pointers (except for the null pointer) are valid for all operations of
 //!   [size zero][zst].
 //! * For a pointer to be valid, it is necessary, but not always sufficient, that the pointer
-//!   be *dereferencable*: the memory range of the given size starting at the pointer must all be
+//!   be *dereferenceable*: the memory range of the given size starting at the pointer must all be
 //!   within the bounds of a single allocated object. Note that in Rust,
 //!   every (stack-allocated) variable is considered a separate allocated object.
 //! * All accesses performed by functions in this module are *non-atomic* in the sense
@@ -810,9 +810,7 @@ pub unsafe fn read_unaligned<T>(src: *const T) -> T {
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub unsafe fn write<T>(dst: *mut T, src: T) {
-    // FIXME: the debug assertion here causes codegen test failures on some architectures.
-    // See <https://github.com/rust-lang/rust/pull/69208#issuecomment-591326757>.
-    // debug_assert!(is_aligned_and_not_null(dst), "attempt to write to unaligned or null pointer");
+    debug_assert!(is_aligned_and_not_null(dst), "attempt to write to unaligned or null pointer");
     intrinsics::move_val_init(&mut *dst, src)
 }
 
index 4bc0a3e9faa607dd93efe45742f92a040a3a5ecb..01d830ca186024aef22f5d81278469ab83bc3a63 100644 (file)
@@ -49,7 +49,7 @@ pub const fn cast<U>(self) -> *mut U {
     /// memory.
     ///
     /// When calling this method, you have to ensure that if the pointer is
-    /// non-NULL, then it is properly aligned, dereferencable (for the whole
+    /// non-NULL, then it is properly aligned, dereferenceable (for the whole
     /// size of `T`) and points to an initialized instance of `T`. This applies
     /// even if the result of this method is unused!
     /// (The part about being initialized is not yet fully decided, but until
@@ -176,7 +176,7 @@ pub unsafe fn offset(self, count: isize) -> *mut T
     /// within the same allocated object: [`offset`] is immediate Undefined Behavior when
     /// crossing object boundaries; `wrapping_offset` produces a pointer but still leads
     /// to Undefined Behavior if that pointer is dereferenced. [`offset`] can be optimized
-    /// better and is thus preferrable in performance-sensitive code.
+    /// better and is thus preferable in performance-sensitive code.
     ///
     /// If you need to cross object boundaries, cast the pointer to an integer and
     /// do the arithmetic there.
@@ -224,7 +224,7 @@ pub fn wrapping_offset(self, count: isize) -> *mut T
     /// all of the following is true:
     /// - it is properly aligned
     /// - it must point to an initialized instance of T; in particular, the pointer must be
-    ///   "dereferencable" in the sense defined [here].
+    ///   "dereferenceable" in the sense defined [here].
     ///
     /// This applies even if the result of this method is unused!
     /// (The part about being initialized is not yet fully decided, but until
@@ -526,7 +526,7 @@ pub unsafe fn sub(self, count: usize) -> Self
     /// within the same allocated object: [`add`] is immediate Undefined Behavior when
     /// crossing object boundaries; `wrapping_add` produces a pointer but still leads
     /// to Undefined Behavior if that pointer is dereferenced. [`add`] can be optimized
-    /// better and is thus preferrable in performance-sensitive code.
+    /// better and is thus preferable in performance-sensitive code.
     ///
     /// If you need to cross object boundaries, cast the pointer to an integer and
     /// do the arithmetic there.
@@ -581,7 +581,7 @@ pub fn wrapping_add(self, count: usize) -> Self
     /// within the same allocated object: [`sub`] is immediate Undefined Behavior when
     /// crossing object boundaries; `wrapping_sub` produces a pointer but still leads
     /// to Undefined Behavior if that pointer is dereferenced. [`sub`] can be optimized
-    /// better and is thus preferrable in performance-sensitive code.
+    /// better and is thus preferable in performance-sensitive code.
     ///
     /// If you need to cross object boundaries, cast the pointer to an integer and
     /// do the arithmetic there.
index 1670c8418421f62f3120a584ade7603490707f13..0e12e6360da9512363d87f7631939a89161e1024 100644 (file)
@@ -103,7 +103,7 @@ pub const fn is_empty(&self) -> bool {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn first(&self) -> Option<&T> {
-        self.get(0)
+        if let [first, ..] = self { Some(first) } else { None }
     }
 
     /// Returns a mutable pointer to the first element of the slice, or `None` if it is empty.
@@ -121,7 +121,7 @@ pub fn first(&self) -> Option<&T> {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn first_mut(&mut self) -> Option<&mut T> {
-        self.get_mut(0)
+        if let [first, ..] = self { Some(first) } else { None }
     }
 
     /// Returns the first and all the rest of the elements of the slice, or `None` if it is empty.
@@ -139,7 +139,7 @@ pub fn first_mut(&mut self) -> Option<&mut T> {
     #[stable(feature = "slice_splits", since = "1.5.0")]
     #[inline]
     pub fn split_first(&self) -> Option<(&T, &[T])> {
-        if self.is_empty() { None } else { Some((&self[0], &self[1..])) }
+        if let [first, tail @ ..] = self { Some((first, tail)) } else { None }
     }
 
     /// Returns the first and all the rest of the elements of the slice, or `None` if it is empty.
@@ -159,12 +159,7 @@ pub fn split_first(&self) -> Option<(&T, &[T])> {
     #[stable(feature = "slice_splits", since = "1.5.0")]
     #[inline]
     pub fn split_first_mut(&mut self) -> Option<(&mut T, &mut [T])> {
-        if self.is_empty() {
-            None
-        } else {
-            let split = self.split_at_mut(1);
-            Some((&mut split.0[0], split.1))
-        }
+        if let [first, tail @ ..] = self { Some((first, tail)) } else { None }
     }
 
     /// Returns the last and all the rest of the elements of the slice, or `None` if it is empty.
@@ -182,8 +177,7 @@ pub fn split_first_mut(&mut self) -> Option<(&mut T, &mut [T])> {
     #[stable(feature = "slice_splits", since = "1.5.0")]
     #[inline]
     pub fn split_last(&self) -> Option<(&T, &[T])> {
-        let len = self.len();
-        if len == 0 { None } else { Some((&self[len - 1], &self[..(len - 1)])) }
+        if let [init @ .., last] = self { Some((last, init)) } else { None }
     }
 
     /// Returns the last and all the rest of the elements of the slice, or `None` if it is empty.
@@ -203,13 +197,7 @@ pub fn split_last(&self) -> Option<(&T, &[T])> {
     #[stable(feature = "slice_splits", since = "1.5.0")]
     #[inline]
     pub fn split_last_mut(&mut self) -> Option<(&mut T, &mut [T])> {
-        let len = self.len();
-        if len == 0 {
-            None
-        } else {
-            let split = self.split_at_mut(len - 1);
-            Some((&mut split.1[0], split.0))
-        }
+        if let [init @ .., last] = self { Some((last, init)) } else { None }
     }
 
     /// Returns the last element of the slice, or `None` if it is empty.
@@ -226,8 +214,7 @@ pub fn split_last_mut(&mut self) -> Option<(&mut T, &mut [T])> {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn last(&self) -> Option<&T> {
-        let last_idx = self.len().checked_sub(1)?;
-        self.get(last_idx)
+        if let [.., last] = self { Some(last) } else { None }
     }
 
     /// Returns a mutable pointer to the last item in the slice.
@@ -245,8 +232,7 @@ pub fn last(&self) -> Option<&T> {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn last_mut(&mut self) -> Option<&mut T> {
-        let last_idx = self.len().checked_sub(1)?;
-        self.get_mut(last_idx)
+        if let [.., last] = self { Some(last) } else { None }
     }
 
     /// Returns a reference to an element or subslice depending on the type of
index 9c0db5d98725dfe779a723303e4abee6d7d7a39a..6ad0e68a88f3bfe2a914295827633c4a896d7ffc 100644 (file)
@@ -2,7 +2,9 @@
 
 //! String manipulation.
 //!
-//! For more details, see the `std::str` module.
+//! For more details, see the [`std::str`] module.
+//!
+//! [`std::str`]: ../../std/str/index.html
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
index 6c826e5dcdec01c8aa2f7e95eae1a8a5873d12ec..ffa418cba6c99346b91892adabbcfba74f25a2df 100644 (file)
@@ -365,11 +365,7 @@ fn next_match_back(&mut self) -> Option<(usize, usize)> {
         let haystack = self.haystack.as_bytes();
         loop {
             // get the haystack up to but not including the last character searched
-            let bytes = if let Some(slice) = haystack.get(self.finger..self.finger_back) {
-                slice
-            } else {
-                return None;
-            };
+            let bytes = haystack.get(self.finger..self.finger_back)?;
             // the last byte of the utf8 encoded needle
             // SAFETY: we have an invariant that `utf8_size < 5`
             let last_byte = unsafe { *self.utf8_encoded.get_unchecked(self.utf8_size - 1) };
@@ -575,11 +571,12 @@ fn is_prefix_of(self, haystack: &'a str) -> bool {
 
         #[inline]
         fn is_suffix_of(self, haystack: &'a str) -> bool
-            where $t: ReverseSearcher<'a>
+        where
+            $t: ReverseSearcher<'a>,
         {
             ($pmap)(self).is_suffix_of(haystack)
         }
-    }
+    };
 }
 
 macro_rules! searcher_methods {
@@ -614,7 +611,7 @@ fn next_match_back(&mut self) -> Option<(usize, usize)> {
         fn next_reject_back(&mut self) -> Option<(usize, usize)> {
             self.0.next_reject_back()
         }
-    }
+    };
 }
 
 /////////////////////////////////////////////////////////////////////////////
index 9d449bb9915071e3453af165045684d205cbacc9..220f221cdd36dc2713fb836392d44d706b2cefae 100644 (file)
@@ -2259,7 +2259,7 @@ fn strongest_failure_ordering(order: Ordering) -> Ordering {
 }
 
 #[inline]
-unsafe fn atomic_store<T>(dst: *mut T, val: T, order: Ordering) {
+unsafe fn atomic_store<T: Copy>(dst: *mut T, val: T, order: Ordering) {
     match order {
         Release => intrinsics::atomic_store_rel(dst, val),
         Relaxed => intrinsics::atomic_store_relaxed(dst, val),
@@ -2270,7 +2270,7 @@ unsafe fn atomic_store<T>(dst: *mut T, val: T, order: Ordering) {
 }
 
 #[inline]
-unsafe fn atomic_load<T>(dst: *const T, order: Ordering) -> T {
+unsafe fn atomic_load<T: Copy>(dst: *const T, order: Ordering) -> T {
     match order {
         Acquire => intrinsics::atomic_load_acq(dst),
         Relaxed => intrinsics::atomic_load_relaxed(dst),
@@ -2282,7 +2282,7 @@ unsafe fn atomic_load<T>(dst: *const T, order: Ordering) -> T {
 
 #[inline]
 #[cfg(target_has_atomic = "8")]
-unsafe fn atomic_swap<T>(dst: *mut T, val: T, order: Ordering) -> T {
+unsafe fn atomic_swap<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
     match order {
         Acquire => intrinsics::atomic_xchg_acq(dst, val),
         Release => intrinsics::atomic_xchg_rel(dst, val),
@@ -2295,7 +2295,7 @@ unsafe fn atomic_swap<T>(dst: *mut T, val: T, order: Ordering) -> T {
 /// Returns the previous value (like __sync_fetch_and_add).
 #[inline]
 #[cfg(target_has_atomic = "8")]
-unsafe fn atomic_add<T>(dst: *mut T, val: T, order: Ordering) -> T {
+unsafe fn atomic_add<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
     match order {
         Acquire => intrinsics::atomic_xadd_acq(dst, val),
         Release => intrinsics::atomic_xadd_rel(dst, val),
@@ -2308,7 +2308,7 @@ unsafe fn atomic_add<T>(dst: *mut T, val: T, order: Ordering) -> T {
 /// Returns the previous value (like __sync_fetch_and_sub).
 #[inline]
 #[cfg(target_has_atomic = "8")]
-unsafe fn atomic_sub<T>(dst: *mut T, val: T, order: Ordering) -> T {
+unsafe fn atomic_sub<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
     match order {
         Acquire => intrinsics::atomic_xsub_acq(dst, val),
         Release => intrinsics::atomic_xsub_rel(dst, val),
@@ -2320,7 +2320,7 @@ unsafe fn atomic_sub<T>(dst: *mut T, val: T, order: Ordering) -> T {
 
 #[inline]
 #[cfg(target_has_atomic = "8")]
-unsafe fn atomic_compare_exchange<T>(
+unsafe fn atomic_compare_exchange<T: Copy>(
     dst: *mut T,
     old: T,
     new: T,
@@ -2346,7 +2346,7 @@ unsafe fn atomic_compare_exchange<T>(
 
 #[inline]
 #[cfg(target_has_atomic = "8")]
-unsafe fn atomic_compare_exchange_weak<T>(
+unsafe fn atomic_compare_exchange_weak<T: Copy>(
     dst: *mut T,
     old: T,
     new: T,
@@ -2372,7 +2372,7 @@ unsafe fn atomic_compare_exchange_weak<T>(
 
 #[inline]
 #[cfg(target_has_atomic = "8")]
-unsafe fn atomic_and<T>(dst: *mut T, val: T, order: Ordering) -> T {
+unsafe fn atomic_and<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
     match order {
         Acquire => intrinsics::atomic_and_acq(dst, val),
         Release => intrinsics::atomic_and_rel(dst, val),
@@ -2384,7 +2384,7 @@ unsafe fn atomic_and<T>(dst: *mut T, val: T, order: Ordering) -> T {
 
 #[inline]
 #[cfg(target_has_atomic = "8")]
-unsafe fn atomic_nand<T>(dst: *mut T, val: T, order: Ordering) -> T {
+unsafe fn atomic_nand<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
     match order {
         Acquire => intrinsics::atomic_nand_acq(dst, val),
         Release => intrinsics::atomic_nand_rel(dst, val),
@@ -2396,7 +2396,7 @@ unsafe fn atomic_nand<T>(dst: *mut T, val: T, order: Ordering) -> T {
 
 #[inline]
 #[cfg(target_has_atomic = "8")]
-unsafe fn atomic_or<T>(dst: *mut T, val: T, order: Ordering) -> T {
+unsafe fn atomic_or<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
     match order {
         Acquire => intrinsics::atomic_or_acq(dst, val),
         Release => intrinsics::atomic_or_rel(dst, val),
@@ -2408,7 +2408,7 @@ unsafe fn atomic_or<T>(dst: *mut T, val: T, order: Ordering) -> T {
 
 #[inline]
 #[cfg(target_has_atomic = "8")]
-unsafe fn atomic_xor<T>(dst: *mut T, val: T, order: Ordering) -> T {
+unsafe fn atomic_xor<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
     match order {
         Acquire => intrinsics::atomic_xor_acq(dst, val),
         Release => intrinsics::atomic_xor_rel(dst, val),
@@ -2421,7 +2421,7 @@ unsafe fn atomic_xor<T>(dst: *mut T, val: T, order: Ordering) -> T {
 /// returns the max value (signed comparison)
 #[inline]
 #[cfg(target_has_atomic = "8")]
-unsafe fn atomic_max<T>(dst: *mut T, val: T, order: Ordering) -> T {
+unsafe fn atomic_max<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
     match order {
         Acquire => intrinsics::atomic_max_acq(dst, val),
         Release => intrinsics::atomic_max_rel(dst, val),
@@ -2434,7 +2434,7 @@ unsafe fn atomic_max<T>(dst: *mut T, val: T, order: Ordering) -> T {
 /// returns the min value (signed comparison)
 #[inline]
 #[cfg(target_has_atomic = "8")]
-unsafe fn atomic_min<T>(dst: *mut T, val: T, order: Ordering) -> T {
+unsafe fn atomic_min<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
     match order {
         Acquire => intrinsics::atomic_min_acq(dst, val),
         Release => intrinsics::atomic_min_rel(dst, val),
@@ -2444,10 +2444,10 @@ unsafe fn atomic_min<T>(dst: *mut T, val: T, order: Ordering) -> T {
     }
 }
 
-/// returns the max value (signed comparison)
+/// returns the max value (unsigned comparison)
 #[inline]
 #[cfg(target_has_atomic = "8")]
-unsafe fn atomic_umax<T>(dst: *mut T, val: T, order: Ordering) -> T {
+unsafe fn atomic_umax<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
     match order {
         Acquire => intrinsics::atomic_umax_acq(dst, val),
         Release => intrinsics::atomic_umax_rel(dst, val),
@@ -2457,10 +2457,10 @@ unsafe fn atomic_umax<T>(dst: *mut T, val: T, order: Ordering) -> T {
     }
 }
 
-/// returns the min value (signed comparison)
+/// returns the min value (unsigned comparison)
 #[inline]
 #[cfg(target_has_atomic = "8")]
-unsafe fn atomic_umin<T>(dst: *mut T, val: T, order: Ordering) -> T {
+unsafe fn atomic_umin<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
     match order {
         Acquire => intrinsics::atomic_umin_acq(dst, val),
         Release => intrinsics::atomic_umin_rel(dst, val),
index 63537ba23d84dc0edfabc9384a45e7a7a2249b7b..c8592e40a69a0168016db92542748a8efded529b 100644 (file)
@@ -1,10 +1,13 @@
 use core::alloc::Layout;
+use core::ptr::NonNull;
 
 #[test]
 fn const_unchecked_layout() {
     const SIZE: usize = 0x2000;
     const ALIGN: usize = 0x1000;
     const LAYOUT: Layout = unsafe { Layout::from_size_align_unchecked(SIZE, ALIGN) };
+    const DANGLING: NonNull<u8> = LAYOUT.dangling();
     assert_eq!(LAYOUT.size(), SIZE);
     assert_eq!(LAYOUT.align(), ALIGN);
+    assert_eq!(Some(DANGLING), NonNull::new(ALIGN as *mut u8));
 }
index 12aa20a0bbd87ab60d78ac309b36b14036895ce2..5c0e114e93c158098ea579352ab50fc9c208fa82 100644 (file)
@@ -298,7 +298,6 @@ fn test_hash_no_concat_alias() {
     let t = ("aabb", "");
     let u = ("a", "abb");
 
-    assert!(s != t && t != u);
     assert_ne!(s, t);
     assert_ne!(t, u);
     assert_ne!(hash(&s), hash(&t));
index 5b41ef350657fe491dd7b6cbd34edb48ee3544b1..98e3eeb982bde665ec826959a60db1ac6580e064 100644 (file)
@@ -1,3 +1,5 @@
+// ignore-tidy-filelength
+
 use core::cell::Cell;
 use core::convert::TryFrom;
 use core::iter::*;
@@ -2940,3 +2942,73 @@ fn check(xs: &mut [i32], ref p: impl Fn(&i32) -> bool, expected: usize) {
     check(xs, |&x| x < 3, 3); // small
     check(xs, |&x| x > 6, 3); // large
 }
+
+/// An iterator that panics whenever `next` or next_back` is called
+/// after `None` has already been returned. This does not violate
+/// `Iterator`'s contract. Used to test that iterator adaptors don't
+/// poll their inner iterators after exhausting them.
+struct NonFused<I> {
+    iter: I,
+    done: bool,
+}
+
+impl<I> NonFused<I> {
+    fn new(iter: I) -> Self {
+        Self { iter, done: false }
+    }
+}
+
+impl<I> Iterator for NonFused<I>
+where
+    I: Iterator,
+{
+    type Item = I::Item;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        assert!(!self.done, "this iterator has already returned None");
+        self.iter.next().or_else(|| {
+            self.done = true;
+            None
+        })
+    }
+}
+
+impl<I> DoubleEndedIterator for NonFused<I>
+where
+    I: DoubleEndedIterator,
+{
+    fn next_back(&mut self) -> Option<Self::Item> {
+        assert!(!self.done, "this iterator has already returned None");
+        self.iter.next_back().or_else(|| {
+            self.done = true;
+            None
+        })
+    }
+}
+
+#[test]
+fn test_peekable_non_fused() {
+    let mut iter = NonFused::new(empty::<i32>()).peekable();
+
+    assert_eq!(iter.peek(), None);
+    assert_eq!(iter.next_back(), None);
+}
+
+#[test]
+fn test_flatten_non_fused_outer() {
+    let mut iter = NonFused::new(once(0..2)).flatten();
+
+    assert_eq!(iter.next_back(), Some(1));
+    assert_eq!(iter.next(), Some(0));
+    assert_eq!(iter.next(), None);
+}
+
+#[test]
+fn test_flatten_non_fused_inner() {
+    let mut iter = once(0..1).chain(once(1..3)).flat_map(NonFused::new);
+
+    assert_eq!(iter.next_back(), Some(2));
+    assert_eq!(iter.next(), Some(0));
+    assert_eq!(iter.next(), Some(1));
+    assert_eq!(iter.next(), None);
+}
index cc341c939803e7af13ca3f92adb5fcf7cb7e0c94..05f958cbe81fe09e4e2d707ec6395c88ef2ab542 100644 (file)
@@ -1,3 +1,4 @@
+#![feature(alloc_layout_extra)]
 #![feature(bool_to_option)]
 #![feature(bound_cloned)]
 #![feature(box_syntax)]
index eee9ea52ef0d2e2387c8d6ef43c0682e6f2b8454..9680aa14d3b54568c0816b33469a5df9bcda6c79 100644 (file)
@@ -44,7 +44,7 @@ pub(crate) fn is_printable(x: char) -> bool {
     } else if x < 0x20000 {
         check(lower, SINGLETONS1U, SINGLETONS1L, NORMAL1)
     } else {
-        if 0x2a6d7 <= x && x < 0x2a700 {
+        if 0x2a6de <= x && x < 0x2a700 {
             return false;
         }
         if 0x2b735 <= x && x < 0x2b740 {
@@ -59,7 +59,10 @@ pub(crate) fn is_printable(x: char) -> bool {
         if 0x2ebe1 <= x && x < 0x2f800 {
             return false;
         }
-        if 0x2fa1e <= x && x < 0xe0100 {
+        if 0x2fa1e <= x && x < 0x30000 {
+            return false;
+        }
+        if 0x3134b <= x && x < 0xe0100 {
             return false;
         }
         if 0xe01f0 <= x && x < 0x110000 {
@@ -81,7 +84,7 @@ pub(crate) fn is_printable(x: char) -> bool {
     (0x0a, 28),
     (0x0b, 25),
     (0x0c, 20),
-    (0x0d, 18),
+    (0x0d, 16),
     (0x0e, 13),
     (0x0f, 4),
     (0x10, 3),
@@ -96,7 +99,7 @@ pub(crate) fn is_printable(x: char) -> bool {
     (0x1d, 1),
     (0x1f, 22),
     (0x20, 3),
-    (0x2b, 4),
+    (0x2b, 3),
     (0x2c, 2),
     (0x2d, 11),
     (0x2e, 1),
@@ -129,29 +132,29 @@ pub(crate) fn is_printable(x: char) -> bool {
     0x4a, 0x5e, 0x64, 0x65, 0x84, 0x91, 0x9b, 0x9d,
     0xc9, 0xce, 0xcf, 0x0d, 0x11, 0x29, 0x45, 0x49,
     0x57, 0x64, 0x65, 0x8d, 0x91, 0xa9, 0xb4, 0xba,
-    0xbb, 0xc5, 0xc9, 0xdf, 0xe4, 0xe5, 0xf0, 0x04,
-    0x0d, 0x11, 0x45, 0x49, 0x64, 0x65, 0x80, 0x81,
-    0x84, 0xb2, 0xbc, 0xbe, 0xbf, 0xd5, 0xd7, 0xf0,
-    0xf1, 0x83, 0x85, 0x8b, 0xa4, 0xa6, 0xbe, 0xbf,
-    0xc5, 0xc7, 0xce, 0xcf, 0xda, 0xdb, 0x48, 0x98,
-    0xbd, 0xcd, 0xc6, 0xce, 0xcf, 0x49, 0x4e, 0x4f,
-    0x57, 0x59, 0x5e, 0x5f, 0x89, 0x8e, 0x8f, 0xb1,
-    0xb6, 0xb7, 0xbf, 0xc1, 0xc6, 0xc7, 0xd7, 0x11,
-    0x16, 0x17, 0x5b, 0x5c, 0xf6, 0xf7, 0xfe, 0xff,
-    0x80, 0x0d, 0x6d, 0x71, 0xde, 0xdf, 0x0e, 0x0f,
-    0x1f, 0x6e, 0x6f, 0x1c, 0x1d, 0x5f, 0x7d, 0x7e,
-    0xae, 0xaf, 0xbb, 0xbc, 0xfa, 0x16, 0x17, 0x1e,
-    0x1f, 0x46, 0x47, 0x4e, 0x4f, 0x58, 0x5a, 0x5c,
-    0x5e, 0x7e, 0x7f, 0xb5, 0xc5, 0xd4, 0xd5, 0xdc,
-    0xf0, 0xf1, 0xf5, 0x72, 0x73, 0x8f, 0x74, 0x75,
-    0x96, 0x97, 0x2f, 0x5f, 0x26, 0x2e, 0x2f, 0xa7,
-    0xaf, 0xb7, 0xbf, 0xc7, 0xcf, 0xd7, 0xdf, 0x9a,
-    0x40, 0x97, 0x98, 0x30, 0x8f, 0x1f, 0xc0, 0xc1,
-    0xce, 0xff, 0x4e, 0x4f, 0x5a, 0x5b, 0x07, 0x08,
-    0x0f, 0x10, 0x27, 0x2f, 0xee, 0xef, 0x6e, 0x6f,
-    0x37, 0x3d, 0x3f, 0x42, 0x45, 0x90, 0x91, 0xfe,
-    0xff, 0x53, 0x67, 0x75, 0xc8, 0xc9, 0xd0, 0xd1,
-    0xd8, 0xd9, 0xe7, 0xfe, 0xff,
+    0xbb, 0xc5, 0xc9, 0xdf, 0xe4, 0xe5, 0xf0, 0x0d,
+    0x11, 0x45, 0x49, 0x64, 0x65, 0x80, 0x84, 0xb2,
+    0xbc, 0xbe, 0xbf, 0xd5, 0xd7, 0xf0, 0xf1, 0x83,
+    0x85, 0x8b, 0xa4, 0xa6, 0xbe, 0xbf, 0xc5, 0xc7,
+    0xce, 0xcf, 0xda, 0xdb, 0x48, 0x98, 0xbd, 0xcd,
+    0xc6, 0xce, 0xcf, 0x49, 0x4e, 0x4f, 0x57, 0x59,
+    0x5e, 0x5f, 0x89, 0x8e, 0x8f, 0xb1, 0xb6, 0xb7,
+    0xbf, 0xc1, 0xc6, 0xc7, 0xd7, 0x11, 0x16, 0x17,
+    0x5b, 0x5c, 0xf6, 0xf7, 0xfe, 0xff, 0x80, 0x0d,
+    0x6d, 0x71, 0xde, 0xdf, 0x0e, 0x0f, 0x1f, 0x6e,
+    0x6f, 0x1c, 0x1d, 0x5f, 0x7d, 0x7e, 0xae, 0xaf,
+    0xbb, 0xbc, 0xfa, 0x16, 0x17, 0x1e, 0x1f, 0x46,
+    0x47, 0x4e, 0x4f, 0x58, 0x5a, 0x5c, 0x5e, 0x7e,
+    0x7f, 0xb5, 0xc5, 0xd4, 0xd5, 0xdc, 0xf0, 0xf1,
+    0xf5, 0x72, 0x73, 0x8f, 0x74, 0x75, 0x96, 0x2f,
+    0x5f, 0x26, 0x2e, 0x2f, 0xa7, 0xaf, 0xb7, 0xbf,
+    0xc7, 0xcf, 0xd7, 0xdf, 0x9a, 0x40, 0x97, 0x98,
+    0x30, 0x8f, 0x1f, 0xc0, 0xc1, 0xce, 0xff, 0x4e,
+    0x4f, 0x5a, 0x5b, 0x07, 0x08, 0x0f, 0x10, 0x27,
+    0x2f, 0xee, 0xef, 0x6e, 0x6f, 0x37, 0x3d, 0x3f,
+    0x42, 0x45, 0x90, 0x91, 0xfe, 0xff, 0x53, 0x67,
+    0x75, 0xc8, 0xc9, 0xd0, 0xd1, 0xd8, 0xd9, 0xe7,
+    0xfe, 0xff,
 ];
 #[rustfmt::skip]
 const SINGLETONS1U: &[(u8, u8)] = &[
@@ -163,14 +166,15 @@ pub(crate) fn is_printable(x: char) -> bool {
     (0x09, 2),
     (0x0a, 5),
     (0x0b, 2),
+    (0x0e, 4),
     (0x10, 1),
-    (0x11, 4),
+    (0x11, 2),
     (0x12, 5),
     (0x13, 17),
-    (0x14, 2),
+    (0x14, 1),
     (0x15, 2),
     (0x17, 2),
-    (0x19, 4),
+    (0x19, 13),
     (0x1c, 5),
     (0x1d, 8),
     (0x24, 1),
@@ -188,32 +192,35 @@ pub(crate) fn is_printable(x: char) -> bool {
     (0xe8, 2),
     (0xee, 32),
     (0xf0, 4),
-    (0xf9, 6),
+    (0xf8, 2),
+    (0xf9, 2),
     (0xfa, 2),
+    (0xfb, 1),
 ];
 #[rustfmt::skip]
 const SINGLETONS1L: &[u8] = &[
     0x0c, 0x27, 0x3b, 0x3e, 0x4e, 0x4f, 0x8f, 0x9e,
     0x9e, 0x9f, 0x06, 0x07, 0x09, 0x36, 0x3d, 0x3e,
     0x56, 0xf3, 0xd0, 0xd1, 0x04, 0x14, 0x18, 0x36,
-    0x37, 0x56, 0x57, 0xbd, 0x35, 0xce, 0xcf, 0xe0,
-    0x12, 0x87, 0x89, 0x8e, 0x9e, 0x04, 0x0d, 0x0e,
-    0x11, 0x12, 0x29, 0x31, 0x34, 0x3a, 0x45, 0x46,
-    0x49, 0x4a, 0x4e, 0x4f, 0x64, 0x65, 0x5a, 0x5c,
-    0xb6, 0xb7, 0x1b, 0x1c, 0xa8, 0xa9, 0xd8, 0xd9,
-    0x09, 0x37, 0x90, 0x91, 0xa8, 0x07, 0x0a, 0x3b,
-    0x3e, 0x66, 0x69, 0x8f, 0x92, 0x6f, 0x5f, 0xee,
-    0xef, 0x5a, 0x62, 0x9a, 0x9b, 0x27, 0x28, 0x55,
-    0x9d, 0xa0, 0xa1, 0xa3, 0xa4, 0xa7, 0xa8, 0xad,
-    0xba, 0xbc, 0xc4, 0x06, 0x0b, 0x0c, 0x15, 0x1d,
-    0x3a, 0x3f, 0x45, 0x51, 0xa6, 0xa7, 0xcc, 0xcd,
-    0xa0, 0x07, 0x19, 0x1a, 0x22, 0x25, 0x3e, 0x3f,
-    0xc5, 0xc6, 0x04, 0x20, 0x23, 0x25, 0x26, 0x28,
-    0x33, 0x38, 0x3a, 0x48, 0x4a, 0x4c, 0x50, 0x53,
-    0x55, 0x56, 0x58, 0x5a, 0x5c, 0x5e, 0x60, 0x63,
-    0x65, 0x66, 0x6b, 0x73, 0x78, 0x7d, 0x7f, 0x8a,
-    0xa4, 0xaa, 0xaf, 0xb0, 0xc0, 0xd0, 0x0c, 0x72,
-    0xa3, 0xa4, 0xcb, 0xcc, 0x6e, 0x6f,
+    0x37, 0x56, 0x57, 0x7f, 0xaa, 0xae, 0xaf, 0xbd,
+    0x35, 0xe0, 0x12, 0x87, 0x89, 0x8e, 0x9e, 0x04,
+    0x0d, 0x0e, 0x11, 0x12, 0x29, 0x31, 0x34, 0x3a,
+    0x45, 0x46, 0x49, 0x4a, 0x4e, 0x4f, 0x64, 0x65,
+    0x5c, 0xb6, 0xb7, 0x1b, 0x1c, 0x07, 0x08, 0x0a,
+    0x0b, 0x14, 0x17, 0x36, 0x39, 0x3a, 0xa8, 0xa9,
+    0xd8, 0xd9, 0x09, 0x37, 0x90, 0x91, 0xa8, 0x07,
+    0x0a, 0x3b, 0x3e, 0x66, 0x69, 0x8f, 0x92, 0x6f,
+    0x5f, 0xee, 0xef, 0x5a, 0x62, 0x9a, 0x9b, 0x27,
+    0x28, 0x55, 0x9d, 0xa0, 0xa1, 0xa3, 0xa4, 0xa7,
+    0xa8, 0xad, 0xba, 0xbc, 0xc4, 0x06, 0x0b, 0x0c,
+    0x15, 0x1d, 0x3a, 0x3f, 0x45, 0x51, 0xa6, 0xa7,
+    0xcc, 0xcd, 0xa0, 0x07, 0x19, 0x1a, 0x22, 0x25,
+    0x3e, 0x3f, 0xc5, 0xc6, 0x04, 0x20, 0x23, 0x25,
+    0x26, 0x28, 0x33, 0x38, 0x3a, 0x48, 0x4a, 0x4c,
+    0x50, 0x53, 0x55, 0x56, 0x58, 0x5a, 0x5c, 0x5e,
+    0x60, 0x63, 0x65, 0x66, 0x6b, 0x73, 0x78, 0x7d,
+    0x7f, 0x8a, 0xa4, 0xaa, 0xaf, 0xb0, 0xc0, 0xd0,
+    0xae, 0xaf, 0x79, 0xcc, 0x6e, 0x6f, 0x93,
 ];
 #[rustfmt::skip]
 const NORMAL0: &[u8] = &[
@@ -225,7 +232,7 @@ pub(crate) fn is_printable(x: char) -> bool {
     0x06, 0x11,
     0x81, 0xac, 0x0e,
     0x80, 0xab, 0x35,
-    0x1e, 0x15,
+    0x28, 0x0b,
     0x80, 0xe0, 0x03,
     0x19, 0x08,
     0x01, 0x04,
@@ -237,8 +244,8 @@ pub(crate) fn is_printable(x: char) -> bool {
     0x11, 0x0a,
     0x50, 0x0f,
     0x12, 0x07,
-    0x55, 0x08,
-    0x02, 0x04,
+    0x55, 0x07,
+    0x03, 0x04,
     0x1c, 0x0a,
     0x09, 0x03,
     0x08, 0x03,
@@ -292,7 +299,7 @@ pub(crate) fn is_printable(x: char) -> bool {
     0x0b, 0x03,
     0x80, 0xac, 0x06,
     0x0a, 0x06,
-    0x1f, 0x41,
+    0x21, 0x3f,
     0x4c, 0x04,
     0x2d, 0x03,
     0x74, 0x08,
@@ -315,21 +322,19 @@ pub(crate) fn is_printable(x: char) -> bool {
     0x3b, 0x07,
     0x02, 0x0e,
     0x18, 0x09,
-    0x80, 0xb0, 0x30,
+    0x80, 0xb3, 0x2d,
     0x74, 0x0c,
     0x80, 0xd6, 0x1a,
     0x0c, 0x05,
     0x80, 0xff, 0x05,
-    0x80, 0xb6, 0x05,
-    0x24, 0x0c,
-    0x9b, 0xc6, 0x0a,
-    0xd2, 0x30, 0x10,
+    0x80, 0xdf, 0x0c,
+    0xee, 0x0d, 0x03,
     0x84, 0x8d, 0x03,
     0x37, 0x09,
     0x81, 0x5c, 0x14,
     0x80, 0xb8, 0x08,
-    0x80, 0xc7, 0x30,
-    0x35, 0x04,
+    0x80, 0xcb, 0x2a,
+    0x38, 0x03,
     0x0a, 0x06,
     0x38, 0x08,
     0x46, 0x08,
@@ -341,7 +346,7 @@ pub(crate) fn is_printable(x: char) -> bool {
     0x80, 0x83, 0x18,
     0x1c, 0x0a,
     0x16, 0x09,
-    0x48, 0x08,
+    0x4c, 0x04,
     0x80, 0x8a, 0x06,
     0xab, 0xa4, 0x0c,
     0x17, 0x04,
@@ -365,7 +370,7 @@ pub(crate) fn is_printable(x: char) -> bool {
     0x7b, 0x05,
     0x03, 0x04,
     0x2d, 0x03,
-    0x65, 0x04,
+    0x66, 0x03,
     0x01, 0x2f,
     0x2e, 0x80, 0x82,
     0x1d, 0x03,
@@ -410,16 +415,17 @@ pub(crate) fn is_printable(x: char) -> bool {
     0x33, 0x07,
     0x2e, 0x08,
     0x0a, 0x81, 0x26,
-    0x1f, 0x80, 0x81,
+    0x52, 0x4e,
     0x28, 0x08,
-    0x2a, 0x80, 0x86,
+    0x2a, 0x56,
+    0x1c, 0x14,
     0x17, 0x09,
     0x4e, 0x04,
     0x1e, 0x0f,
     0x43, 0x0e,
     0x19, 0x07,
     0x0a, 0x06,
-    0x47, 0x09,
+    0x48, 0x08,
     0x27, 0x09,
     0x75, 0x0b,
     0x3f, 0x41,
@@ -430,7 +436,7 @@ pub(crate) fn is_printable(x: char) -> bool {
     0x01, 0x05,
     0x10, 0x03,
     0x05, 0x80, 0x8b,
-    0x60, 0x20,
+    0x62, 0x1e,
     0x48, 0x08,
     0x0a, 0x80, 0xa6,
     0x5e, 0x22,
@@ -443,7 +449,8 @@ pub(crate) fn is_printable(x: char) -> bool {
     0x10, 0x80, 0xc0,
     0x3c, 0x64,
     0x53, 0x0c,
-    0x01, 0x80, 0xa0,
+    0x48, 0x09,
+    0x0a, 0x46,
     0x45, 0x1b,
     0x48, 0x08,
     0x53, 0x1d,
@@ -456,7 +463,8 @@ pub(crate) fn is_printable(x: char) -> bool {
     0x0a, 0x06,
     0x39, 0x07,
     0x0a, 0x81, 0x36,
-    0x19, 0x80, 0xc7,
+    0x19, 0x80, 0xb7,
+    0x01, 0x0f,
     0x32, 0x0d,
     0x83, 0x9b, 0x66,
     0x75, 0x0b,
@@ -474,9 +482,11 @@ pub(crate) fn is_printable(x: char) -> bool {
     0x4b, 0x04,
     0x39, 0x07,
     0x11, 0x40,
-    0x04, 0x1c,
+    0x05, 0x0b,
+    0x02, 0x0e,
     0x97, 0xf8, 0x08,
-    0x82, 0xf3, 0xa5, 0x0d,
+    0x84, 0xd6, 0x2a,
+    0x09, 0xa2, 0xf7,
     0x81, 0x1f, 0x31,
     0x03, 0x11,
     0x04, 0x08,
@@ -515,17 +525,15 @@ pub(crate) fn is_printable(x: char) -> bool {
     0x2c, 0x04,
     0x64, 0x0c,
     0x56, 0x0a,
-    0x0d, 0x03,
-    0x5d, 0x03,
-    0x3d, 0x39,
+    0x80, 0xae, 0x38,
     0x1d, 0x0d,
     0x2c, 0x04,
     0x09, 0x07,
     0x02, 0x0e,
     0x06, 0x80, 0x9a,
-    0x83, 0xd6, 0x0a,
+    0x83, 0xd8, 0x08,
+    0x0d, 0x03,
     0x0d, 0x03,
-    0x0b, 0x05,
     0x74, 0x0c,
     0x59, 0x07,
     0x0c, 0x14,
@@ -533,12 +541,15 @@ pub(crate) fn is_printable(x: char) -> bool {
     0x38, 0x08,
     0x0a, 0x06,
     0x28, 0x08,
-    0x1e, 0x52,
-    0x77, 0x03,
-    0x31, 0x03,
-    0x80, 0xa6, 0x0c,
-    0x14, 0x04,
+    0x22, 0x4e,
+    0x81, 0x54, 0x0c,
+    0x15, 0x03,
     0x03, 0x05,
+    0x07, 0x09,
+    0x19, 0x07,
+    0x07, 0x09,
     0x03, 0x0d,
-    0x06, 0x85, 0x6a,
+    0x07, 0x29,
+    0x80, 0xcb, 0x25,
+    0x0a, 0x84, 0x06,
 ];
index da4cd4e9b1da1900e5703b5a2cc7f3ad65a77d90..3e90028613ce1c3df30850b712c38b259a579e1d 100644 (file)
 ///! This file is generated by src/tools/unicode-table-generator; do not edit manually!
 use super::range_search;
 
-pub const UNICODE_VERSION: (u32, u32, u32) = (12, 1, 0);
+pub const UNICODE_VERSION: (u32, u32, u32) = (13, 0, 0);
 
 #[rustfmt::skip]
 pub mod alphabetic {
-    static BITSET_LAST_CHUNK_MAP: (u16, u8) = (190, 37);
-    static BITSET_CHUNKS_MAP: [u8; 187] = [
-        6, 32, 10, 18, 19, 23, 21, 12, 7, 5, 0, 20, 14, 49, 49, 49, 49, 49, 49, 36, 49, 49, 49, 49,
-        49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 47, 49, 30, 8, 49, 49, 49, 49,
-        49, 49, 49, 49, 49, 49, 45, 0, 0, 0, 0, 0, 0, 0, 0, 4, 35, 17, 31, 16, 25, 24, 26, 13, 15,
-        44, 27, 0, 0, 49, 11, 0, 0, 0, 39, 0, 0, 0, 0, 0, 0, 0, 0, 38, 1, 49, 49, 49, 49, 49, 48,
-        42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, 0, 28, 0, 0, 0, 0, 0, 29, 0, 0, 9, 0, 33, 2, 3, 0, 0,
-        0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
-        49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 41, 49, 49, 49,
-        43, 22, 49, 49, 49, 49, 40, 49, 49, 49, 49, 49, 49, 46,
+    static BITSET_LAST_CHUNK_MAP: (u16, u8) = (196, 44);
+    static BITSET_CHUNKS_MAP: [u8; 196] = [
+        6, 32, 10, 18, 19, 23, 21, 12, 7, 5, 0, 20, 14, 50, 50, 50, 50, 50, 50, 37, 50, 50, 50, 50,
+        50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 49, 50, 30, 8, 50, 50, 50, 50,
+        50, 50, 50, 50, 50, 50, 46, 0, 0, 0, 0, 0, 0, 0, 0, 4, 36, 17, 31, 16, 25, 24, 26, 13, 15,
+        45, 27, 0, 0, 50, 11, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 39, 1, 50, 50, 50, 50, 50, 48,
+        50, 34, 0, 0, 0, 0, 0, 0, 0, 0, 35, 0, 0, 28, 0, 0, 0, 0, 0, 29, 0, 0, 9, 0, 33, 2, 3, 0, 0,
+        0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+        50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 42, 50, 50, 50,
+        43, 22, 50, 50, 50, 50, 41, 50, 50, 50, 50, 50, 50, 47, 0, 0, 0, 38, 0, 50, 50, 50, 50,
     ];
-    static BITSET_INDEX_CHUNKS: [[u8; 16]; 50] = [
+    static BITSET_INDEX_CHUNKS: [[u8; 16]; 51] = [
         [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [0, 0, 0, 0, 0, 0, 0, 0, 0, 248, 0, 0, 248, 241, 38, 40],
-        [0, 0, 0, 0, 0, 0, 0, 0, 108, 133, 110, 0, 0, 0, 0, 0],
-        [0, 0, 0, 0, 190, 200, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [0, 0, 0, 0, 248, 248, 248, 248, 248, 205, 248, 23, 134, 245, 68, 237],
-        [0, 0, 179, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [0, 103, 99, 176, 248, 248, 248, 248, 248, 248, 248, 61, 0, 151, 217, 178],
-        [0, 145, 28, 0, 168, 221, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [48, 77, 248, 165, 201, 120, 184, 137, 91, 175, 143, 83, 206, 196, 248, 56],
-        [53, 0, 0, 0, 126, 15, 0, 0, 0, 0, 0, 58, 0, 0, 0, 0],
-        [59, 54, 127, 199, 167, 186, 157, 114, 154, 84, 160, 115, 158, 66, 155, 21],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 0, 0, 254, 247, 39, 68],
+        [0, 0, 0, 0, 0, 0, 0, 0, 111, 135, 113, 0, 0, 0, 0, 0],
+        [0, 0, 0, 0, 195, 205, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 0, 254, 254, 254, 254, 254, 210, 254, 25, 136, 251, 71, 243],
+        [0, 0, 182, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 107, 103, 180, 254, 254, 254, 254, 254, 254, 254, 61, 0, 155, 222, 181],
+        [0, 148, 30, 0, 172, 226, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [48, 80, 254, 169, 206, 123, 189, 139, 95, 179, 145, 86, 211, 204, 254, 56],
+        [53, 0, 0, 0, 129, 17, 0, 0, 0, 0, 0, 58, 0, 0, 0, 0],
+        [59, 54, 185, 203, 171, 191, 161, 117, 158, 87, 164, 118, 162, 67, 159, 23],
         [62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [91, 129, 164, 101, 248, 248, 248, 79, 248, 248, 248, 248, 230, 128, 135, 117],
-        [97, 0, 220, 144, 0, 0, 212, 44, 142, 240, 30, 97, 0, 0, 0, 0],
-        [116, 247, 219, 171, 188, 248, 104, 190, 0, 0, 0, 0, 0, 0, 0, 0],
-        [141, 185, 88, 0, 149, 213, 22, 0, 0, 0, 0, 89, 0, 0, 0, 0],
-        [147, 90, 35, 82, 98, 0, 153, 0, 85, 119, 29, 45, 86, 71, 18, 0],
-        [150, 32, 248, 107, 0, 81, 0, 0, 0, 0, 227, 17, 211, 105, 231, 19],
-        [162, 41, 161, 69, 163, 173, 123, 73, 106, 14, 124, 37, 1, 187, 121, 0],
-        [172, 240, 228, 170, 248, 248, 248, 248, 248, 229, 138, 235, 234, 24, 222, 125],
-        [208, 233, 248, 74, 204, 64, 140, 232, 63, 0, 0, 0, 0, 0, 0, 0],
-        [220, 97, 202, 86, 94, 78, 203, 9, 226, 80, 46, 0, 183, 11, 174, 67],
-        [231, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248],
-        [247, 248, 248, 248, 248, 248, 248, 248, 248, 209, 225, 95, 76, 75, 180, 25],
-        [248, 5, 96, 50, 72, 87, 248, 26, 132, 0, 198, 51, 159, 42, 0, 0],
-        [248, 8, 72, 72, 49, 0, 0, 0, 0, 0, 0, 0, 194, 5, 0, 89],
-        [248, 36, 248, 7, 0, 0, 139, 31, 143, 3, 93, 0, 55, 0, 0, 0],
-        [248, 62, 248, 248, 248, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [248, 118, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [248, 236, 166, 246, 136, 239, 248, 248, 248, 248, 215, 169, 182, 207, 214, 12],
-        [248, 248, 13, 130, 248, 248, 248, 248, 57, 146, 248, 65, 218, 248, 243, 177],
-        [248, 248, 191, 111, 197, 43, 0, 0, 248, 248, 248, 248, 91, 47, 0, 0],
-        [248, 248, 244, 248, 189, 223, 152, 70, 224, 210, 248, 148, 240, 242, 68, 100],
-        [248, 248, 248, 4, 248, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [248, 248, 248, 248, 35, 195, 248, 248, 248, 248, 248, 113, 0, 0, 0, 0],
-        [248, 248, 248, 248, 131, 240, 238, 109, 0, 181, 248, 122, 102, 216, 143, 27],
-        [248, 248, 248, 248, 248, 248, 86, 0, 248, 248, 248, 248, 248, 248, 248, 248],
-        [248, 248, 248, 248, 248, 248, 248, 248, 33, 0, 0, 0, 0, 0, 0, 0],
-        [248, 248, 248, 248, 248, 248, 248, 248, 97, 35, 0, 60, 65, 156, 16, 0],
-        [248, 248, 248, 248, 248, 248, 248, 248, 248, 6, 0, 0, 0, 0, 0, 0],
-        [248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 192, 248, 248, 248, 248, 248],
-        [248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 20, 248, 248, 248, 248],
-        [248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 72, 0, 0, 0, 0],
-        [248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 81, 248, 248, 248],
-        [248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 23, 0],
-        [248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 193, 112],
-        [248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 39],
-        [248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 65],
-        [248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 92],
-        [248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248],
+        [95, 131, 168, 105, 254, 254, 254, 82, 254, 254, 254, 254, 236, 130, 137, 120],
+        [101, 0, 225, 146, 151, 2, 217, 45, 144, 246, 32, 101, 0, 0, 0, 0],
+        [119, 253, 224, 175, 193, 254, 227, 195, 0, 0, 0, 0, 0, 0, 0, 0],
+        [143, 190, 91, 0, 153, 218, 24, 0, 0, 0, 0, 92, 0, 0, 66, 0],
+        [150, 94, 37, 85, 102, 0, 157, 0, 88, 122, 31, 46, 89, 74, 20, 0],
+        [154, 34, 254, 110, 0, 84, 0, 0, 0, 0, 233, 19, 216, 108, 237, 21],
+        [166, 42, 165, 72, 167, 177, 126, 76, 109, 16, 127, 38, 1, 192, 124, 0],
+        [176, 246, 234, 174, 254, 254, 254, 254, 254, 235, 140, 241, 240, 26, 228, 128],
+        [213, 239, 254, 77, 209, 64, 142, 238, 63, 0, 0, 0, 0, 0, 0, 0],
+        [225, 101, 207, 89, 98, 81, 208, 10, 232, 83, 147, 1, 188, 13, 178, 70],
+        [237, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254],
+        [253, 254, 254, 254, 254, 254, 254, 254, 254, 214, 231, 99, 79, 78, 183, 27],
+        [254, 6, 100, 50, 75, 90, 254, 28, 134, 0, 202, 51, 163, 43, 0, 0],
+        [254, 9, 75, 75, 49, 0, 0, 0, 0, 0, 69, 0, 199, 6, 195, 93],
+        [254, 41, 254, 8, 0, 0, 141, 33, 145, 4, 97, 0, 55, 0, 0, 0],
+        [254, 62, 254, 254, 254, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [254, 121, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [254, 242, 170, 252, 138, 245, 254, 254, 254, 254, 220, 173, 186, 212, 219, 14],
+        [254, 254, 15, 132, 254, 254, 254, 254, 57, 149, 254, 65, 223, 254, 249, 187],
+        [254, 254, 196, 114, 201, 44, 0, 0, 254, 254, 254, 254, 95, 47, 0, 0],
+        [254, 254, 250, 254, 194, 229, 156, 73, 230, 215, 254, 152, 246, 248, 71, 104],
+        [254, 254, 254, 5, 254, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [254, 254, 254, 22, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [254, 254, 254, 254, 37, 200, 254, 254, 254, 254, 254, 116, 0, 0, 0, 0],
+        [254, 254, 254, 254, 133, 246, 244, 112, 0, 184, 254, 125, 106, 221, 145, 29],
+        [254, 254, 254, 254, 254, 254, 254, 0, 254, 254, 254, 254, 254, 254, 254, 254],
+        [254, 254, 254, 254, 254, 254, 254, 254, 35, 0, 0, 0, 0, 0, 0, 0],
+        [254, 254, 254, 254, 254, 254, 254, 254, 101, 37, 0, 60, 65, 160, 18, 0],
+        [254, 254, 254, 254, 254, 254, 254, 254, 254, 7, 0, 0, 0, 0, 0, 0],
+        [254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 197, 254, 254, 254, 254, 254],
+        [254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 35, 254, 254, 254, 254],
+        [254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 84, 254, 254, 254],
+        [254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 11, 0, 0],
+        [254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 25, 0],
+        [254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 198, 115],
+        [254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 40],
+        [254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 96],
+        [254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 125],
+        [254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254],
     ];
-    static BITSET: [u64; 249] = [
-        0, 1, 15, 17, 31, 63, 127, 179, 511, 1023, 2191, 4079, 4087, 8191, 8319, 16384, 65535,
-        131071, 262143, 4128527, 8388607, 8461767, 24870911, 67108863, 134217727, 276824575,
-        335544350, 486341884, 536805376, 536870911, 553648127, 1056964608, 1073692671, 1073741823,
-        1140785663, 2147483647, 2147485627, 4026540127, 4294934783, 8589934591, 47244640256,
-        64548249055, 68191066527, 68719476735, 115913785343, 137438953215, 549755813888,
-        1095220854783, 1099511627711, 1099511627775, 2199023190016, 2199023255551, 4398046511103,
-        8641373536127, 8791831609343, 8795690369023, 8796093022207, 13198434443263, 17592186044415,
-        35184321757183, 70368744112128, 88094074470339, 140737488355327, 140737488355328,
-        141836999983103, 281474976710655, 563017343310239, 1125625028935679, 1125899906842623,
-        1688915364814303, 2119858418286774, 2251795522912255, 2251799813685247, 3377704004976767,
-        3509778554814463, 3905461007941631, 4503595333443583, 4503599627370495, 8796093022142464,
-        9006649498927104, 9007192812290047, 9007199254740991, 15762594400829440, 17169970223906821,
-        17732925109967239, 18014398491652207, 18014398509481983, 20266198323101808,
-        36027697507139583, 36028792723996672, 36028792728190975, 36028797018963967,
-        72057594037927935, 90071992547409919, 143851303137705983, 144053615424700415,
-        144115188075855868, 144115188075855871, 288230371860938751, 297241973452963840,
-        301749971126844416, 319718190147960832, 576460743713488896, 576460743847706622,
-        576460748008488959, 576460752303359999, 576460752303423486, 576460752303423487,
-        790380184120328175, 1152640029630136575, 1152917029519358975, 1152921504591118335,
-        1152921504606845055, 1152921504606846975, 1153765996922689951, 2161727885562420159,
-        2251241253188403424, 2295745090394464220, 2305570330330005503, 2305843004918726656,
-        2305843004919250943, 2305843009196916483, 2305843009213693951, 3457638613854978028,
-        4323455298678290390, 4557642822898941951, 4575692405780512767, 4602678814877679616,
-        4611686017001275199, 4611686018360336384, 4611686018427322368, 4611686018427387903,
-        4656722014700830719, 6843210385291930244, 6881498031078244479, 6908521828386340863,
-        8935141660164089791, 8935423131384840192, 9168765891372858879, 9169328841326329855,
-        9187201948305063935, 9187343239835811327, 9216616637413720063, 9223372036854775807,
-        9223372041149743103, 9223934986808197120, 10371930679322607615, 10502394331027995967,
-        11241233151490523135, 13006395723845991295, 13258596753222922239, 13609596598936928288,
-        13834776580305453567, 13907115649320091647, 14082190885810440174, 14123225865944680428,
-        16212958624174047247, 16412803692974677999, 16424062692043104238, 16424062692043104239,
-        16424062692043243502, 16424625641996804079, 16429129241624174575, 16717361816799141871,
-        16717361816799216127, 16788293510930366511, 17005555242810474495, 17293822569102704639,
-        17581979622616071300, 17870283321271910397, 17870283321406070975, 17870283321406128127,
-        17978369712463020031, 18158513764145585631, 18158781978395017215, 18194542490281852927,
-        18410715276682199039, 18410715276690587772, 18428729675200069631, 18428729675200069632,
-        18433233274827440127, 18437455399478099968, 18437736874452713471, 18442240474082181119,
+    static BITSET: [u64; 255] = [
+        0, 1, 7, 15, 17, 31, 63, 127, 179, 511, 1023, 2047, 2191, 4079, 4087, 8191, 8319, 16384,
+        65535, 131071, 262143, 4128527, 4194303, 8461767, 24870911, 67108863, 134217727, 276824575,
+        335593502, 486341884, 536805376, 536870911, 553648127, 1056964608, 1073692671, 1073741823,
+        1140785663, 2147483647, 4026540127, 4294934783, 8589934591, 15032387515, 64548249055,
+        68191066527, 68719476735, 115913785343, 137438953215, 1095220854783, 1099511627711,
+        1099511627775, 2199023190016, 2199023255551, 4398046511103, 8641373536127, 8791831609343,
+        8795690369023, 8796093022207, 13198434443263, 17592186044415, 35184321757183,
+        70368744112128, 88094074470339, 140737488355327, 140737488355328, 141836999983103,
+        281474976710655, 281474976710656, 563017343310239, 844472174772224, 875211255709695,
+        1125625028935679, 1125899906842623, 1688915364814303, 2119858418286774, 2251795522912255,
+        2251799813685247, 3377704004976767, 3509778554814463, 3905461007941631, 4503595333443583,
+        4503599627370495, 8796093022142464, 9006649498927104, 9007192812290047, 9007199254740991,
+        15762594400829440, 17169970223906821, 17732925109967239, 18014398491652207,
+        18014398509481983, 20266198323101936, 36027697507139583, 36028792723996672,
+        36028792723996703, 36028792728190975, 36028797018963967, 72057594037927935,
+        90071992547409919, 143851303137705983, 144053615424700415, 144115188075855868,
+        144115188075855871, 288230371860938751, 297241973452963840, 301749971126844416,
+        319718190147960832, 576460743713488896, 576460743847706622, 576460752303359999,
+        576460752303423486, 576460752303423487, 790380184120328175, 1152640029630136575,
+        1152917029519358975, 1152921504591118335, 1152921504606845055, 1152921504606846975,
+        1153765996922689951, 2161727885562420159, 2251241253188403424, 2295745090394464220,
+        2305570330330005503, 2305843004918726656, 2305843004919250943, 2305843009196916483,
+        2305843009213693951, 3457638613854978030, 4323455298678290390, 4557642822898941951,
+        4575692405780512767, 4611686017001275199, 4611686018360336384, 4611686018427322368,
+        4611686018427387903, 4656722014700830719, 6843210385291930244, 6881498031078244479,
+        6908521828386340863, 8935141660164089791, 8935423131384840192, 9168765891372858879,
+        9169328841326329855, 9187201948305063935, 9187343239835811327, 9216616637413720063,
+        9223372036854775807, 9223372041149743103, 9223372586610589696, 9223934986808197120,
+        10371930679322607615, 10502394331027995967, 11078855083321979519, 11241233151490523135,
+        13006395723845991295, 13258596753222922239, 13609596598936928288, 13834776580305453567,
+        13907115649320091647, 14082190885810440174, 14123225865944680428, 16212958624174047247,
+        16412803692974677999, 16424062692043104238, 16424062692043104239, 16424062692043243502,
+        16424625641996804079, 16429129241624174575, 16717361816799141887, 16717361816799216127,
+        16788293510930366511, 17005555242810474495, 17293822569102704639, 17581979622616071300,
+        17870283321271910397, 17870283321406070975, 17870283321406128127, 17978369712463020031,
+        18158513764145585631, 18158781978395017215, 18194542490281852927, 18410715276682199039,
+        18428729675200069631, 18428729675200069632, 18433233274827440127, 18437455399478099968,
+        18437736870159843328, 18437736874452713471, 18437736874454812668, 18442240474082181119,
         18444492273895866367, 18445618173802708993, 18446181192473632767, 18446216308128218879,
         18446462598732840928, 18446462598732840959, 18446462598732840960, 18446462599806582783,
         18446462615912710143, 18446462667452317695, 18446463149025525759, 18446463629525450752,
-        18446463698110251007, 18446463698244468735, 18446464796682337663, 18446466966713532416,
+        18446463698244468735, 18446464796682337663, 18446466966713532671, 18446466996645134335,
         18446466996779287551, 18446471394825862144, 18446471394825863167, 18446480190918885375,
         18446498607738650623, 18446532967477018623, 18446602782178705022, 18446603336221163519,
         18446603336221196287, 18446638520593285119, 18446673709243564031, 18446708893632430079,
         18446740770879700992, 18446741595513422027, 18446741874686295551, 18446743249075830783,
         18446743798965862398, 18446744056529672000, 18446744060816261120, 18446744068886102015,
-        18446744069414584320, 18446744069414601696, 18446744069414649855, 18446744069456527359,
-        18446744069548736512, 18446744069548802046, 18446744069683019775, 18446744069951455231,
-        18446744070421282815, 18446744070446333439, 18446744070475743231, 18446744070488326143,
-        18446744071553646463, 18446744071562067967, 18446744073696837631, 18446744073701162813,
-        18446744073707454463, 18446744073709027328, 18446744073709355007, 18446744073709419615,
-        18446744073709486080, 18446744073709520895, 18446744073709543424, 18446744073709550079,
-        18446744073709550595, 18446744073709551579, 18446744073709551599, 18446744073709551614,
-        18446744073709551615,
+        18446744069414584320, 18446744069414601696, 18446744069414617087, 18446744069414649855,
+        18446744069456527359, 18446744069548736512, 18446744069548802046, 18446744069683019775,
+        18446744069951455231, 18446744070421282815, 18446744070446333439, 18446744070475743231,
+        18446744070488326143, 18446744071553646463, 18446744071562067967, 18446744073696837631,
+        18446744073701162813, 18446744073707454463, 18446744073709027328, 18446744073709355007,
+        18446744073709419615, 18446744073709486080, 18446744073709520895, 18446744073709543424,
+        18446744073709550079, 18446744073709550595, 18446744073709551579, 18446744073709551599,
+        18446744073709551614, 18446744073709551615,
     ];
 
     pub fn lookup(c: char) -> bool {
@@ -141,82 +143,83 @@ pub mod case_ignorable {
     static BITSET_LAST_CHUNK_MAP: (u16, u8) = (896, 33);
     static BITSET_CHUNKS_MAP: [u8; 125] = [
         25, 14, 21, 30, 28, 4, 17, 23, 22, 0, 0, 16, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 13, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 13, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 3, 6, 9, 0, 7, 11, 32, 31, 26, 29, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 5, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0,
-        10, 0, 8, 0, 20, 0, 12, 0, 1,
+        10, 0, 8, 0, 19, 0, 12, 0, 1,
     ];
     static BITSET_INDEX_CHUNKS: [[u8; 16]; 34] = [
         [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 164],
-        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 47, 52],
-        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 171, 2],
-        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 88, 134, 38],
-        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 102, 6, 0, 0],
-        [0, 0, 0, 0, 0, 0, 0, 0, 76, 26, 0, 146, 136, 79, 43, 117],
-        [0, 0, 0, 0, 0, 0, 0, 0, 152, 0, 0, 58, 0, 0, 0, 0],
-        [0, 0, 0, 0, 0, 0, 0, 0, 165, 97, 75, 0, 0, 0, 0, 0],
-        [0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 48, 0, 114, 0, 0],
-        [0, 0, 0, 0, 0, 170, 68, 0, 0, 7, 0, 0, 0, 0, 0, 0],
-        [0, 0, 0, 0, 61, 0, 0, 0, 0, 0, 0, 0, 0, 23, 0, 0],
-        [0, 0, 0, 28, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [0, 0, 0, 133, 0, 0, 0, 0, 15, 160, 45, 84, 51, 78, 12, 109],
-        [0, 0, 11, 0, 0, 30, 161, 90, 35, 80, 0, 69, 173, 13, 81, 129],
-        [0, 0, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [0, 131, 0, 85, 0, 148, 0, 175, 73, 0, 0, 0, 0, 0, 0, 0],
-        [20, 4, 62, 0, 118, 0, 0, 0, 32, 154, 145, 0, 124, 89, 67, 86],
-        [25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [59, 0, 0, 150, 70, 24, 132, 60, 100, 122, 163, 99, 0, 46, 0, 66],
-        [63, 0, 0, 0, 135, 0, 0, 0, 0, 0, 0, 74, 0, 0, 0, 0],
-        [71, 33, 0, 178, 123, 83, 120, 137, 121, 98, 121, 167, 153, 55, 3, 18],
-        [72, 149, 36, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [104, 133, 0, 110, 174, 105, 177, 166, 0, 0, 0, 0, 0, 0, 155, 139],
-        [107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [111, 50, 106, 0, 0, 0, 0, 0, 0, 0, 172, 179, 179, 112, 9, 0],
-        [113, 0, 0, 0, 0, 0, 0, 49, 142, 34, 31, 0, 0, 0, 0, 0],
-        [116, 0, 42, 141, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [140, 93, 37, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 0, 0],
-        [159, 0, 101, 0, 158, 10, 29, 0, 0, 0, 0, 91, 0, 0, 0, 0],
-        [162, 56, 153, 54, 125, 53, 0, 27, 115, 21, 126, 19, 108, 144, 127, 8],
-        [168, 41, 151, 5, 0, 0, 157, 39, 156, 1, 103, 0, 65, 0, 0, 0],
-        [169, 147, 130, 17, 96, 87, 143, 16, 138, 0, 0, 64, 125, 95, 0, 0],
-        [176, 179, 0, 0, 179, 179, 179, 77, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 166],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 47, 57],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 173, 3],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 90, 136, 38],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 104, 7, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 78, 27, 0, 148, 138, 81, 44, 119],
+        [0, 0, 0, 0, 0, 0, 0, 0, 154, 0, 0, 58, 0, 0, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 167, 99, 77, 0, 0, 0, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 130, 0, 0, 0, 48, 0, 116, 0, 0],
+        [0, 0, 0, 0, 0, 172, 70, 0, 0, 8, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 67, 0, 0, 24, 0, 0],
+        [0, 0, 0, 29, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 135, 0, 0, 0, 0, 16, 162, 46, 86, 51, 80, 13, 111],
+        [0, 0, 12, 0, 0, 43, 163, 92, 35, 82, 0, 71, 175, 14, 83, 131],
+        [0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 133, 0, 87, 0, 150, 0, 178, 75, 0, 0, 0, 0, 0, 0, 0],
+        [20, 5, 61, 0, 120, 0, 0, 0, 32, 156, 176, 1, 126, 91, 69, 88],
+        [26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [62, 0, 0, 0, 137, 0, 0, 0, 0, 0, 0, 76, 0, 0, 0, 0],
+        [66, 0, 0, 152, 72, 25, 134, 59, 102, 124, 165, 101, 0, 64, 0, 68],
+        [73, 33, 0, 181, 125, 85, 122, 139, 123, 100, 123, 169, 155, 54, 4, 18],
+        [74, 151, 36, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [106, 135, 0, 112, 177, 107, 180, 168, 0, 0, 0, 0, 0, 0, 157, 142],
+        [109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [113, 50, 108, 0, 0, 0, 0, 0, 0, 0, 174, 182, 182, 114, 10, 0],
+        [115, 0, 0, 0, 141, 5, 0, 49, 145, 34, 31, 0, 0, 0, 0, 0],
+        [118, 0, 42, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [143, 95, 37, 121, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0],
+        [161, 0, 103, 0, 160, 11, 30, 0, 0, 0, 0, 93, 0, 0, 0, 0],
+        [164, 55, 155, 53, 127, 52, 2, 28, 117, 21, 128, 19, 110, 147, 129, 9],
+        [170, 41, 153, 6, 0, 0, 159, 39, 158, 1, 105, 0, 65, 0, 0, 0],
+        [171, 149, 132, 17, 98, 89, 146, 23, 140, 0, 0, 63, 127, 97, 0, 0],
+        [179, 182, 0, 0, 182, 182, 182, 79, 0, 0, 0, 0, 0, 0, 0, 0],
     ];
-    static BITSET: [u64; 180] = [
-        0, 1, 3, 4, 8, 13, 15, 28, 64, 176, 191, 1016, 1792, 2047, 4080, 4096, 7680, 8192, 8193,
-        16192, 30720, 32704, 32768, 131008, 262016, 2097152, 2359296, 6030336, 8323072, 10682368,
-        33554432, 58719232, 159383552, 234881024, 243138688, 402587711, 536805376, 536879204,
-        546307648, 805306369, 1073741824, 1073741916, 2113929216, 3221225472, 3758096384,
-        4026531840, 4160749568, 4294934528, 4294967296, 4512022528, 5368709120, 17179869183,
-        47244640256, 51539615774, 51539619904, 51543810078, 51545914817, 66035122176, 412316860416,
-        412316862532, 412316893184, 1030792151040, 2199023255648, 8641373536127, 8763880767488,
-        17303886364672, 36421322670080, 65128884076547, 65970697670631, 68168642985984,
-        70093866270720, 70368739983360, 136957967529984, 140737488355328, 263882790666240,
-        281470547525648, 281470682333183, 281474976710655, 281474976710656, 281474976710657,
-        281479271675905, 562675075514368, 562949953355776, 563001509683710, 844424930131968,
-        985162418487296, 1023920203366400, 2251799813685248, 3377699721314304, 4494803534348292,
-        4503599627370678, 6755399441055744, 7881299349733376, 8444256867844096, 8725724278030336,
-        8760633772212225, 8989057312882695, 9042383626829823, 9851624185018758, 24822575045541890,
-        28848986089586688, 30958948903026688, 35747322042253312, 53805701016846336,
-        58529202969772032, 72066390130950143, 112767012056334336, 143833713099145216,
-        189151184399892480, 216172782113783808, 220713756545974272, 288301294651703296,
-        302022650010533887, 504262420777140224, 558446353793941504, 572520102629474304,
-        593978171557150752, 1008806350890729472, 1009933895770046464, 1152921504606846976,
-        1152921504606846978, 1152921504606846982, 1153202979583561736, 1441151880758558727,
-        1715871458028158991, 1729382256910270467, 2301902359539744768, 2305843009196908767,
-        2305843009213693952, 2612078987781865472, 2771965570646540291, 3458764513820540928,
-        3731232291276455943, 4539628424389459968, 4589168020290535424, 4611404543450677248,
-        4611686018494513280, 4611686069967003678, 4671217976001691648, 6917775322003857411,
-        7421334051581067264, 8070450532247928832, 8788774672813524990, 9205357638345293827,
-        9222809086901354496, 9223091111633879040, 9223372036854775808, 9223372036854775935,
-        9223512774343131136, 9224216320050987008, 9224497932466651184, 9653465801268658176,
-        9727775195120332910, 10376293541461622786, 11526998316797657088, 11529215046068469760,
-        12103423998558208000, 12699025049277956096, 13005832773892571136, 13798747783286489088,
-        13832665517980123136, 13835058055282032640, 13835058055282163729, 13951307220663664640,
-        17870283321406128128, 17906312118425092095, 18158513697557839871, 18158513749097456062,
-        18374686479671623680, 18374686479671623682, 18444496122186563584, 18445618173802708992,
-        18446462598732840960, 18446462598733004800, 18446726481523507200, 18446744069414584320,
-        18446744069414584322, 18446744073575333888, 18446744073709027328, 18446744073709551615,
+    static BITSET: [u64; 183] = [
+        0, 1, 2, 3, 4, 8, 13, 15, 28, 64, 176, 191, 1016, 1792, 2047, 4080, 4096, 8192, 8193,
+        16192, 30720, 32704, 32768, 40448, 131008, 262016, 2097152, 2359296, 6030336, 8323072,
+        10682368, 58719232, 159383552, 234881024, 243138688, 402587711, 536805376, 536879204,
+        546307648, 805306369, 1073741824, 1073741916, 2113929216, 2181038080, 3221225472,
+        3758096384, 4026531840, 4294934528, 4294967296, 4512022528, 5368709120, 17179869183,
+        51539615774, 51539619904, 51545907230, 51545914817, 66035122176, 115964116992, 412316860416,
+        412316893184, 1030792151040, 2199023255648, 8641373536127, 8763880767488, 15397323538432,
+        17303886364672, 18004502906948, 26388279066624, 36421322670080, 65128884076547,
+        65970697670631, 68168642985984, 70093866270720, 70368739983360, 136957967529984,
+        140737488355328, 263882790666240, 281470547525648, 281470682333183, 281474976710655,
+        281474976710656, 281474976710657, 281479271675905, 562675075514368, 562949953355776,
+        563001509683710, 844424930131968, 985162418487296, 1023920203366400, 2251799813685248,
+        3377699721314304, 4494803534348292, 4503599627370678, 6755399441055744, 7881299349733376,
+        8444256867844096, 8725724278030336, 8760633772212225, 8989057312882695, 9042383626829823,
+        9851624185018758, 24822575045541890, 28848986089586688, 30958948903026688,
+        35747322042253312, 53805701016846336, 58529202969772032, 72066390130950143,
+        112767012056334336, 143833713099145216, 189151184399892480, 216172782113783808,
+        220713756545974272, 288301294651703296, 302022650010533887, 504262420777140224,
+        558446353793941504, 572520102629474304, 593978171557150752, 1008806350890729472,
+        1009933895770046464, 1152921504606846976, 1152921504606846978, 1152921504606846982,
+        1153202979583561736, 1441151880758558727, 1715871458028158991, 1729382256910270467,
+        2301902359539744768, 2305843009196908767, 2305843009213693952, 2612078987781865472,
+        2771965570646540291, 3458764513820540928, 3731232291276455943, 4539628424389459968,
+        4589168020290535424, 4611404543450677248, 4611686018494513280, 4611686069967003678,
+        4671217976001691648, 6341068275337658368, 6917775322003857411, 7421334051581067264,
+        8070450532247928832, 8788774672813524990, 9205357638345293827, 9222809086901354496,
+        9223372036854775808, 9223372036854775935, 9223512774343131136, 9224216320050987008,
+        9224497932466651184, 9653465801268658176, 9727775195120332910, 10376293541461622786,
+        11526998316797657088, 11529215046068469760, 12103423998558208000, 12699025049277956096,
+        13005832773892571136, 13798747783286489088, 13832665517980123136, 13835058055282032640,
+        13835058055282163729, 13951307220663664640, 17870283321406128128, 17906312118425092095,
+        18158513697557839871, 18158513749097456062, 18374686479671623680, 18374686479671623682,
+        18444496122186563584, 18445618173802708992, 18446462598732840960, 18446462598733004800,
+        18446463148488654848, 18446726481523507200, 18446744069414584320, 18446744069414584322,
+        18446744073575333888, 18446744073709027328, 18446744073709551615,
     ];
 
     pub fn lookup(c: char) -> bool {
@@ -264,13 +267,13 @@ pub mod cased {
     static BITSET: [u64; 63] = [
         0, 15, 24, 511, 1023, 4087, 65535, 16253055, 134217726, 536805376, 1073741823, 4294967295,
         133143986179, 4398046511103, 36009005809663, 70368744177663, 2251799813685247,
-        3509778554814463, 144115188074807295, 297241973452963840, 504403158265495676,
+        3509778554814463, 144115188074807295, 297241973452963840, 531424756029720572,
         576460743713488896, 576460743847706622, 1152921504591118335, 2295745090394464220,
         4557642822898941951, 4611686017001275199, 6908521828386340863, 8935141660164089791,
         9223934986808197120, 13605092999309557792, 16717361816799216127, 16717361816799223999,
         17005555242810474495, 17446871633794956420, 17870283321271910397, 17870283321406128127,
         18410715276682199039, 18428729675200069631, 18428729675200069632, 18437736874452713471,
-        18446462598732840959, 18446462598732840960, 18446463698110251007, 18446466996779287551,
+        18446462598732840959, 18446462598732840960, 18446464797621878783, 18446466996779287551,
         18446603336221163519, 18446603336221196287, 18446741874686295551, 18446743249075830783,
         18446744056529672000, 18446744056529682432, 18446744069414584320, 18446744069414601696,
         18446744069422972927, 18446744070475743231, 18446744071562067967, 18446744073707454463,
@@ -317,72 +320,72 @@ pub mod grapheme_extend {
     static BITSET_LAST_CHUNK_MAP: (u16, u8) = (896, 30);
     static BITSET_CHUNKS_MAP: [u8; 123] = [
         4, 15, 21, 27, 25, 3, 18, 23, 17, 0, 0, 14, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 2, 7, 10, 0, 8, 12, 29, 28, 24, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0,
-        11, 0, 9, 0, 20, 0, 13,
+        11, 0, 9, 0, 19, 0, 13,
     ];
     static BITSET_INDEX_CHUNKS: [[u8; 16]; 31] = [
         [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 18, 0],
-        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 0, 0, 0],
-        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 70, 102, 29],
-        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138, 62, 0, 0],
-        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 83, 0, 0, 0],
-        [0, 0, 0, 0, 0, 0, 0, 0, 0, 103, 35, 66, 0, 0, 0, 0],
-        [0, 0, 0, 0, 0, 0, 0, 0, 61, 0, 0, 0, 0, 0, 35, 0],
-        [0, 0, 0, 0, 0, 0, 0, 0, 117, 0, 0, 45, 0, 0, 0, 0],
-        [0, 0, 0, 0, 0, 0, 0, 0, 130, 78, 60, 0, 0, 0, 0, 0],
-        [0, 0, 0, 0, 0, 0, 0, 99, 0, 0, 0, 37, 0, 90, 0, 0],
-        [0, 0, 0, 0, 0, 129, 54, 0, 0, 3, 0, 0, 0, 0, 0, 0],
-        [0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0],
-        [0, 0, 0, 19, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [0, 0, 0, 67, 0, 114, 0, 137, 0, 0, 0, 0, 0, 0, 0, 0],
-        [0, 0, 7, 0, 0, 0, 125, 5, 24, 63, 0, 55, 135, 9, 64, 100],
-        [0, 0, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [10, 0, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [12, 0, 48, 0, 92, 0, 0, 0, 25, 119, 113, 0, 96, 71, 53, 68],
-        [46, 0, 0, 116, 57, 17, 101, 44, 81, 94, 127, 80, 0, 0, 0, 52],
-        [49, 0, 0, 0, 83, 0, 0, 0, 0, 0, 0, 58, 0, 0, 0, 0],
-        [56, 26, 0, 136, 95, 43, 107, 105, 93, 79, 93, 132, 128, 42, 104, 20],
-        [59, 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [85, 0, 0, 87, 0, 0, 0, 131, 0, 0, 0, 0, 0, 0, 0, 0],
-        [89, 0, 0, 0, 0, 0, 0, 38, 110, 27, 22, 0, 0, 0, 0, 0],
-        [109, 74, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0],
-        [124, 0, 82, 0, 123, 6, 21, 0, 0, 0, 0, 72, 0, 0, 0, 0],
-        [126, 40, 118, 39, 108, 41, 0, 34, 91, 14, 97, 13, 86, 112, 98, 4],
-        [133, 32, 120, 2, 0, 0, 122, 30, 121, 1, 84, 0, 51, 0, 0, 0],
-        [134, 115, 88, 0, 77, 69, 111, 11, 106, 0, 0, 50, 108, 76, 0, 0],
-        [137, 138, 0, 0, 138, 138, 138, 62, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 20, 46],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 74, 106, 31],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 143, 66, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 87, 0, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 107, 37, 70, 0, 0, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 0, 0, 0, 0, 37, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 121, 0, 0, 48, 0, 0, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 134, 82, 64, 0, 0, 0, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 103, 0, 0, 0, 39, 0, 94, 0, 0],
+        [0, 0, 0, 0, 0, 133, 58, 0, 0, 5, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 0, 49, 0, 0, 0, 0, 0, 55, 0, 0, 18, 0, 0],
+        [0, 0, 0, 21, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 71, 0, 118, 0, 142, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 9, 0, 0, 0, 129, 7, 26, 67, 0, 59, 140, 11, 68, 104],
+        [0, 0, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [12, 0, 0, 69, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [13, 0, 50, 0, 96, 0, 0, 0, 27, 123, 139, 1, 100, 75, 57, 72],
+        [51, 0, 0, 0, 87, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 0],
+        [54, 0, 0, 120, 61, 19, 105, 47, 85, 98, 131, 84, 0, 0, 0, 56],
+        [60, 28, 0, 141, 99, 45, 111, 109, 97, 83, 97, 136, 132, 44, 108, 22],
+        [63, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [89, 0, 0, 91, 0, 0, 0, 135, 0, 0, 0, 0, 0, 0, 0, 0],
+        [93, 0, 0, 0, 113, 3, 0, 40, 115, 29, 24, 0, 0, 0, 0, 0],
+        [114, 78, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 0, 0],
+        [128, 0, 86, 0, 127, 8, 23, 0, 0, 0, 0, 76, 0, 0, 0, 0],
+        [130, 42, 122, 41, 112, 43, 2, 36, 95, 15, 101, 14, 90, 117, 102, 6],
+        [137, 34, 124, 4, 0, 0, 126, 32, 125, 1, 88, 0, 53, 0, 0, 0],
+        [138, 119, 92, 0, 81, 73, 116, 17, 110, 0, 0, 52, 112, 80, 0, 0],
+        [142, 143, 0, 0, 143, 143, 143, 66, 0, 0, 0, 0, 0, 0, 0, 0],
     ];
-    static BITSET: [u64; 139] = [
-        0, 1, 13, 28, 64, 182, 191, 1016, 2032, 2047, 4096, 7680, 14336, 16128, 32640, 32768,
-        131008, 262016, 491520, 8323072, 8396801, 10682368, 58719232, 100663296, 134152192,
+    static BITSET: [u64; 144] = [
+        0, 1, 2, 8, 13, 28, 64, 182, 191, 1016, 2032, 2047, 4096, 14336, 16128, 32640, 32768,
+        40448, 131008, 262016, 491520, 8323072, 8396801, 10682368, 58719232, 100663296, 134152192,
         159383552, 234881024, 243138688, 536879204, 537919040, 805306369, 1073741824, 1073741916,
         1610612736, 2153546752, 3221225472, 3758096384, 4294967296, 4512022528, 51545911364,
-        51545914817, 51548004382, 51552198686, 51556262398, 137438953472, 412316860416,
-        412316862532, 1030792151040, 2199023255648, 8641373536127, 8763880767488, 17303886364672,
-        36421322670080, 65128884076547, 65970697670631, 67755789254656, 69200441769984,
-        70093866270720, 263882790666240, 277076930199552, 281470547525648, 281470681808895,
-        281474976710655, 281479271675904, 562675075514368, 562949953355776, 844424930131968,
-        985162418487296, 1023920203366400, 2251799813685248, 3377699721314304, 4494803534348292,
-        6755399441055744, 7881299349733376, 8444256867844096, 8725724278030336, 8760633780600833,
-        8989057312882695, 9042383626829823, 9851624185018758, 18067175067615234, 28848986089586688,
-        30958948903026688, 35747322042253312, 53805701016846336, 58529202969772032,
-        189151184399892480, 220713756545974272, 466122561432846339, 504262420777140224,
-        558446353793941504, 572520102629474304, 1009933895770046464, 1152921504606846982,
-        1152921504606851080, 1441151880758558727, 1724878657282899983, 2301902359539744768,
-        2305843009196908767, 2305843009213693952, 2310337812748042240, 3731232291276455943,
-        4589168020290535424, 4609293481125347328, 4611686018427387908, 4611686069975392286,
-        4671217976001691648, 5764607523034234882, 6341068275337658371, 7421334051581067264,
-        8788774672813524990, 9205357638345293827, 9222809086901354496, 9223090561878065152,
-        9223372036854775808, 9223372036854775935, 9224497932466651184, 9727775195120332910,
-        10376293541461622786, 11526998316797657088, 11959590285459062784, 12103423998558208000,
-        12699165786766311424, 13005832773892571136, 13798747783286489088, 13835058055282032640,
-        13835058055282163729, 13951307220663664640, 14987979559889010690, 17872468738205286400,
-        17906312118425092095, 18158513697557839871, 18158513749097456062, 18374686479671623680,
-        18374686479671623682, 18446462598732972032, 18446744056529158144, 18446744069414584320,
-        18446744073709551615,
+        51545914817, 51548004382, 51554295838, 51556262398, 68719476736, 137438953472, 412316860416,
+        1030792151040, 2199023255648, 8641373536127, 8763880767488, 17303886364672, 18004502906948,
+        26388279066624, 36421322670080, 65128884076547, 65970697670631, 67755789254656,
+        69200441769984, 70093866270720, 263882790666240, 277076930199552, 281470547525648,
+        281470681808895, 281474976710655, 281479271675904, 562675075514368, 562949953355776,
+        844424930131968, 985162418487296, 1023920203366400, 2251799813685248, 3377699721314304,
+        4494803534348292, 6755399441055744, 7881299349733376, 8444256867844096, 8725724278030336,
+        8760633780600833, 8989057312882695, 9042383626829823, 9851624185018758, 18067175067615234,
+        28848986089586688, 30958948903026688, 35747322042253312, 53805701016846336,
+        58529202969772032, 189151184399892480, 220713756545974272, 466122561432846339,
+        504262420777140224, 558446353793941504, 572520102629474304, 1009933895770046464,
+        1152921504606846982, 1152921504606851080, 1441151880758558727, 1724878657282899983,
+        2301902359539744768, 2305843009196908767, 2305843009213693952, 2310337812748042240,
+        3731232291276455943, 4589168020290535424, 4609293481125347328, 4611686018427387908,
+        4611686069975392286, 4671217976001691648, 5764607523034234882, 6341068275337658371,
+        6341349750314369024, 7421334051581067264, 8788774672813524990, 9205357638345293827,
+        9222809086901354496, 9223372036854775808, 9223372036854775935, 9224497932466651184,
+        9727775195120332910, 10376293541461622786, 11526998316797657088, 11959590285459062784,
+        12103423998558208000, 12699165786766311424, 13005832773892571136, 13798747783286489088,
+        13835058055282032640, 13835058055282163729, 13951307220663664640, 14987979559889010690,
+        17872468738205286400, 17906312118425092095, 18158513697557839871, 18158513749097456062,
+        18374686479671623680, 18374686479671623682, 18446462598732840960, 18446462598732972032,
+        18446744056529158144, 18446744069414584320, 18446744073709551615,
     ];
 
     pub fn lookup(c: char) -> bool {
@@ -430,7 +433,7 @@ pub mod lowercase {
         133143986179, 274877905920, 1099509514240, 4398046445568, 17592185782272, 36009005809663,
         46912496118442, 187649984473770, 281474972516352, 2251799813685247, 2339875276368554,
         4503599560261632, 61925590106570972, 71777214282006783, 72057592964186127,
-        144115188074807295, 297241973452963840, 504403158265495560, 576460743713488896,
+        144115188074807295, 297241973452963840, 522417556774978824, 576460743713488896,
         1152921487426978047, 1152921504590069760, 1814856824841797631, 3607524039012697088,
         4362299189061746720, 4539628424389459968, 4601013482110844927, 4611405638684049471,
         4674456033467236607, 6172933889249159850, 9223934986808197120, 10663022717737544362,
@@ -439,7 +442,7 @@ pub mod lowercase {
         12298110845996498944, 15324248332066007893, 16596095761559859497, 16717361816799215616,
         16987577794709946364, 17293822586148356092, 18158513701852807104, 18410715274543104000,
         18428729675466407935, 18446462598732840960, 18446462598732858304, 18446462598737002495,
-        18446463698110251007, 18446673704966422527, 18446726481523572736, 18446739675663105535,
+        18446464797621878783, 18446673704966422527, 18446726481523572736, 18446739675663105535,
         18446739675663106031, 18446742974197923840, 18446744056529682432, 18446744069414584320,
         18446744073709529733, 18446744073709551615,
     ];
@@ -457,56 +460,57 @@ pub fn lookup(c: char) -> bool {
 
 #[rustfmt::skip]
 pub mod n {
-    static BITSET_LAST_CHUNK_MAP: (u16, u8) = (124, 11);
-    static BITSET_CHUNKS_MAP: [u8; 124] = [
-        30, 7, 10, 24, 18, 3, 28, 20, 23, 27, 0, 15, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 2, 12, 17, 25, 16, 22, 19, 14, 21, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 6, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        4, 1, 0, 0, 9, 0, 13, 26,
+    static BITSET_LAST_CHUNK_MAP: (u16, u8) = (127, 0);
+    static BITSET_CHUNKS_MAP: [u8; 127] = [
+        31, 8, 11, 25, 19, 4, 29, 21, 24, 28, 0, 16, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 3, 13, 18, 26, 17, 23, 20, 15, 22, 0, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 7, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        5, 2, 0, 0, 10, 0, 14, 27, 12, 0, 1,
     ];
-    static BITSET_INDEX_CHUNKS: [[u8; 16]; 33] = [
+    static BITSET_INDEX_CHUNKS: [[u8; 16]; 34] = [
         [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71],
-        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0],
-        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 48],
-        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 0, 42, 0, 0],
-        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0],
-        [0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 21, 0, 0],
-        [0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 46, 0, 0, 0, 2],
-        [0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 30, 0, 0, 0, 0],
-        [0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 46, 0, 0, 0, 0],
-        [0, 0, 0, 0, 0, 30, 0, 44, 0, 30, 0, 30, 0, 40, 0, 33],
-        [0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [0, 0, 0, 0, 36, 43, 4, 0, 0, 0, 0, 51, 22, 3, 0, 12],
-        [0, 0, 0, 6, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [0, 0, 0, 53, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [0, 0, 0, 61, 46, 0, 0, 0, 0, 59, 0, 0, 23, 9, 0, 0],
-        [0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [0, 2, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0],
-        [0, 14, 0, 14, 0, 0, 0, 0, 0, 14, 0, 2, 50, 0, 0, 0],
-        [0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [0, 25, 0, 0, 0, 14, 24, 0, 0, 0, 0, 0, 0, 0, 0, 10],
-        [0, 31, 0, 46, 64, 0, 0, 38, 0, 0, 0, 46, 0, 0, 0, 0],
-        [0, 45, 2, 0, 0, 70, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [0, 58, 0, 30, 0, 41, 0, 30, 0, 14, 0, 14, 35, 0, 0, 0],
-        [0, 62, 29, 60, 17, 0, 54, 69, 0, 56, 19, 27, 0, 63, 28, 0],
-        [0, 65, 37, 0, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [0, 68, 18, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 8, 0],
-        [14, 0, 0, 0, 0, 7, 0, 16, 0, 0, 15, 0, 0, 14, 46, 0],
-        [39, 0, 0, 14, 2, 0, 0, 47, 0, 14, 0, 0, 0, 0, 0, 46],
-        [46, 0, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [49, 0, 0, 0, 0, 0, 11, 0, 24, 20, 66, 0, 0, 0, 0, 0],
-        [72, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 49],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 43, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 22, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 47, 0, 0, 0, 2],
+        [0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 31, 0, 0, 0, 0],
+        [0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0],
+        [0, 0, 0, 0, 0, 31, 0, 45, 0, 31, 0, 31, 0, 41, 0, 34],
+        [0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 0, 37, 44, 4, 0, 0, 0, 0, 52, 23, 3, 0, 13],
+        [0, 0, 0, 7, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 35, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 62, 47, 0, 0, 0, 0, 60, 0, 0, 24, 10, 0, 5],
+        [0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 2, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 0, 0],
+        [0, 15, 0, 15, 0, 0, 0, 0, 0, 15, 0, 2, 51, 0, 0, 0],
+        [0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 26, 0, 0, 0, 15, 25, 0, 0, 0, 0, 0, 0, 0, 0, 11],
+        [0, 32, 0, 47, 65, 0, 0, 39, 0, 0, 0, 47, 0, 0, 0, 0],
+        [0, 46, 2, 0, 0, 71, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 59, 0, 31, 0, 42, 0, 31, 0, 15, 0, 15, 36, 0, 0, 0],
+        [0, 63, 30, 61, 18, 0, 55, 70, 0, 57, 20, 28, 0, 64, 29, 0],
+        [0, 66, 38, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 69, 19, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 9, 0],
+        [15, 0, 0, 0, 0, 8, 0, 17, 0, 0, 16, 0, 0, 15, 47, 0],
+        [40, 0, 0, 15, 2, 0, 0, 48, 0, 15, 0, 0, 0, 0, 0, 47],
+        [47, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [50, 0, 0, 0, 0, 0, 12, 0, 25, 21, 67, 0, 0, 0, 0, 0],
+        [73, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
     ];
-    static BITSET: [u64; 73] = [
-        0, 999, 1023, 1026, 3072, 8191, 65408, 65472, 1048575, 1966080, 2097151, 3932160, 4063232,
-        8388607, 67043328, 67044351, 134152192, 264241152, 268435455, 3758096384, 4294901504,
-        17112694784, 64424509440, 549218942976, 4393751543808, 35184372023296, 140737488355327,
-        272678883688448, 279275953455104, 280925220896768, 281200098803712, 281474976448512,
-        492581209243648, 2251524935778304, 2251795518717952, 4503595332403200, 4503599627370368,
-        8708132091985919, 9007190731849728, 17732923532771328, 71212894229889024,
+    static BITSET: [u64; 74] = [
+        0, 999, 1023, 1026, 3072, 4064, 8191, 65408, 65472, 1048575, 1966080, 2097151, 3932160,
+        4063232, 8388607, 67043328, 67044351, 134152192, 264241152, 268435455, 3758096384,
+        4294901504, 17112694784, 64424509440, 549218942976, 4393751543808, 35184372023296,
+        140737488355327, 272678883688448, 279275953455104, 280925220896768, 281200098803712,
+        281474976448512, 492581209243648, 2251524935778304, 2251795518717952, 4503595332403200,
+        4503599627370368, 8708132091985919, 9007190731849728, 17732923532771328, 71212894229889024,
         144114915328655360, 144115183780888576, 144115188075855871, 284007976623144960,
         284008251501051904, 287948901175001088, 287948901242044416, 287953294926544896,
         504407547722072192, 1152640029630136320, 1152921496016912384, 2305840810190438400,
@@ -541,28 +545,28 @@ pub mod uppercase {
     static BITSET_INDEX_CHUNKS: [[u8; 16]; 17] = [
         [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
         [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0],
-        [0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0],
-        [0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 10, 0, 38, 46, 44, 2],
-        [0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [0, 0, 0, 0, 51, 24, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [0, 0, 0, 0, 60, 62, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [0, 0, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [0, 0, 54, 0, 0, 0, 0, 0, 43, 43, 40, 43, 56, 23, 34, 35],
-        [0, 0, 57, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 9, 0, 38, 46, 44, 28],
+        [0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 0, 51, 23, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 0, 60, 62, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 54, 0, 0, 0, 0, 0, 43, 43, 40, 43, 56, 22, 34, 35],
+        [0, 0, 57, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
         [0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [0, 0, 66, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 30],
-        [0, 11, 0, 12, 50, 37, 36, 45, 47, 6, 0, 0, 0, 49, 18, 53],
-        [15, 0, 60, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [22, 52, 43, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [25, 39, 42, 41, 59, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [58, 65, 29, 17, 48, 63, 31, 20, 55, 61, 64, 32, 28, 21, 16, 4],
+        [0, 0, 66, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 30],
+        [0, 10, 0, 11, 50, 37, 36, 45, 47, 5, 0, 0, 0, 49, 17, 53],
+        [14, 0, 60, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [21, 52, 43, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [24, 39, 42, 41, 59, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [58, 65, 29, 16, 48, 63, 31, 19, 55, 61, 64, 32, 27, 20, 15, 3],
     ];
     static BITSET: [u64; 67] = [
-        0, 8, 116, 1023, 1024, 8383, 21882, 65535, 1048575, 8388607, 89478485, 134217726,
-        2139095039, 4294967295, 17179869183, 1099511627775, 2199023190016, 4398046445568,
-        17575006099264, 23456248059221, 70368743129088, 140737484161024, 140737488355327,
-        280378317225728, 281470681743392, 281474976710655, 1169903278445909, 2251799813685247,
-        9007198986305536, 17977448100528131, 18014398509481983, 288230371856744511,
+        0, 8, 1023, 1024, 8383, 21882, 65535, 1048575, 8388607, 89478485, 134217726, 2139095039,
+        4294967295, 17179869183, 1099511627775, 2199023190016, 4398046445568, 17575006099264,
+        23456248059221, 70368743129088, 140737484161024, 140737488355327, 280378317225728,
+        281470681743392, 281474976710655, 1169903278445909, 2251799813685247, 9007198986305536,
+        9007199254741748, 17977448100528131, 18014398509481983, 288230371856744511,
         576460735123554305, 576460743713488896, 1080863910568919040, 1080897995681042176,
         1274187559846268630, 3122495741643543722, 6148633210533183488, 6148914689804861440,
         6148914690880001365, 6148914691236506283, 6148914691236516865, 6148914691236517205,
@@ -1202,20 +1206,21 @@ pub mod conversions {
         ('\u{a7ba}', ['\u{a7bb}', '\u{0}', '\u{0}']), ('\u{a7bc}', ['\u{a7bd}', '\u{0}', '\u{0}']),
         ('\u{a7be}', ['\u{a7bf}', '\u{0}', '\u{0}']), ('\u{a7c2}', ['\u{a7c3}', '\u{0}', '\u{0}']),
         ('\u{a7c4}', ['\u{a794}', '\u{0}', '\u{0}']), ('\u{a7c5}', ['\u{282}', '\u{0}', '\u{0}']),
-        ('\u{a7c6}', ['\u{1d8e}', '\u{0}', '\u{0}']), ('\u{ff21}', ['\u{ff41}', '\u{0}', '\u{0}']),
-        ('\u{ff22}', ['\u{ff42}', '\u{0}', '\u{0}']), ('\u{ff23}', ['\u{ff43}', '\u{0}', '\u{0}']),
-        ('\u{ff24}', ['\u{ff44}', '\u{0}', '\u{0}']), ('\u{ff25}', ['\u{ff45}', '\u{0}', '\u{0}']),
-        ('\u{ff26}', ['\u{ff46}', '\u{0}', '\u{0}']), ('\u{ff27}', ['\u{ff47}', '\u{0}', '\u{0}']),
-        ('\u{ff28}', ['\u{ff48}', '\u{0}', '\u{0}']), ('\u{ff29}', ['\u{ff49}', '\u{0}', '\u{0}']),
-        ('\u{ff2a}', ['\u{ff4a}', '\u{0}', '\u{0}']), ('\u{ff2b}', ['\u{ff4b}', '\u{0}', '\u{0}']),
-        ('\u{ff2c}', ['\u{ff4c}', '\u{0}', '\u{0}']), ('\u{ff2d}', ['\u{ff4d}', '\u{0}', '\u{0}']),
-        ('\u{ff2e}', ['\u{ff4e}', '\u{0}', '\u{0}']), ('\u{ff2f}', ['\u{ff4f}', '\u{0}', '\u{0}']),
-        ('\u{ff30}', ['\u{ff50}', '\u{0}', '\u{0}']), ('\u{ff31}', ['\u{ff51}', '\u{0}', '\u{0}']),
-        ('\u{ff32}', ['\u{ff52}', '\u{0}', '\u{0}']), ('\u{ff33}', ['\u{ff53}', '\u{0}', '\u{0}']),
-        ('\u{ff34}', ['\u{ff54}', '\u{0}', '\u{0}']), ('\u{ff35}', ['\u{ff55}', '\u{0}', '\u{0}']),
-        ('\u{ff36}', ['\u{ff56}', '\u{0}', '\u{0}']), ('\u{ff37}', ['\u{ff57}', '\u{0}', '\u{0}']),
-        ('\u{ff38}', ['\u{ff58}', '\u{0}', '\u{0}']), ('\u{ff39}', ['\u{ff59}', '\u{0}', '\u{0}']),
-        ('\u{ff3a}', ['\u{ff5a}', '\u{0}', '\u{0}']),
+        ('\u{a7c6}', ['\u{1d8e}', '\u{0}', '\u{0}']), ('\u{a7c7}', ['\u{a7c8}', '\u{0}', '\u{0}']),
+        ('\u{a7c9}', ['\u{a7ca}', '\u{0}', '\u{0}']), ('\u{a7f5}', ['\u{a7f6}', '\u{0}', '\u{0}']),
+        ('\u{ff21}', ['\u{ff41}', '\u{0}', '\u{0}']), ('\u{ff22}', ['\u{ff42}', '\u{0}', '\u{0}']),
+        ('\u{ff23}', ['\u{ff43}', '\u{0}', '\u{0}']), ('\u{ff24}', ['\u{ff44}', '\u{0}', '\u{0}']),
+        ('\u{ff25}', ['\u{ff45}', '\u{0}', '\u{0}']), ('\u{ff26}', ['\u{ff46}', '\u{0}', '\u{0}']),
+        ('\u{ff27}', ['\u{ff47}', '\u{0}', '\u{0}']), ('\u{ff28}', ['\u{ff48}', '\u{0}', '\u{0}']),
+        ('\u{ff29}', ['\u{ff49}', '\u{0}', '\u{0}']), ('\u{ff2a}', ['\u{ff4a}', '\u{0}', '\u{0}']),
+        ('\u{ff2b}', ['\u{ff4b}', '\u{0}', '\u{0}']), ('\u{ff2c}', ['\u{ff4c}', '\u{0}', '\u{0}']),
+        ('\u{ff2d}', ['\u{ff4d}', '\u{0}', '\u{0}']), ('\u{ff2e}', ['\u{ff4e}', '\u{0}', '\u{0}']),
+        ('\u{ff2f}', ['\u{ff4f}', '\u{0}', '\u{0}']), ('\u{ff30}', ['\u{ff50}', '\u{0}', '\u{0}']),
+        ('\u{ff31}', ['\u{ff51}', '\u{0}', '\u{0}']), ('\u{ff32}', ['\u{ff52}', '\u{0}', '\u{0}']),
+        ('\u{ff33}', ['\u{ff53}', '\u{0}', '\u{0}']), ('\u{ff34}', ['\u{ff54}', '\u{0}', '\u{0}']),
+        ('\u{ff35}', ['\u{ff55}', '\u{0}', '\u{0}']), ('\u{ff36}', ['\u{ff56}', '\u{0}', '\u{0}']),
+        ('\u{ff37}', ['\u{ff57}', '\u{0}', '\u{0}']), ('\u{ff38}', ['\u{ff58}', '\u{0}', '\u{0}']),
+        ('\u{ff39}', ['\u{ff59}', '\u{0}', '\u{0}']), ('\u{ff3a}', ['\u{ff5a}', '\u{0}', '\u{0}']),
         ('\u{10400}', ['\u{10428}', '\u{0}', '\u{0}']),
         ('\u{10401}', ['\u{10429}', '\u{0}', '\u{0}']),
         ('\u{10402}', ['\u{1042a}', '\u{0}', '\u{0}']),
@@ -2052,51 +2057,52 @@ pub mod conversions {
         ('\u{a7b7}', ['\u{a7b6}', '\u{0}', '\u{0}']), ('\u{a7b9}', ['\u{a7b8}', '\u{0}', '\u{0}']),
         ('\u{a7bb}', ['\u{a7ba}', '\u{0}', '\u{0}']), ('\u{a7bd}', ['\u{a7bc}', '\u{0}', '\u{0}']),
         ('\u{a7bf}', ['\u{a7be}', '\u{0}', '\u{0}']), ('\u{a7c3}', ['\u{a7c2}', '\u{0}', '\u{0}']),
-        ('\u{ab53}', ['\u{a7b3}', '\u{0}', '\u{0}']), ('\u{ab70}', ['\u{13a0}', '\u{0}', '\u{0}']),
-        ('\u{ab71}', ['\u{13a1}', '\u{0}', '\u{0}']), ('\u{ab72}', ['\u{13a2}', '\u{0}', '\u{0}']),
-        ('\u{ab73}', ['\u{13a3}', '\u{0}', '\u{0}']), ('\u{ab74}', ['\u{13a4}', '\u{0}', '\u{0}']),
-        ('\u{ab75}', ['\u{13a5}', '\u{0}', '\u{0}']), ('\u{ab76}', ['\u{13a6}', '\u{0}', '\u{0}']),
-        ('\u{ab77}', ['\u{13a7}', '\u{0}', '\u{0}']), ('\u{ab78}', ['\u{13a8}', '\u{0}', '\u{0}']),
-        ('\u{ab79}', ['\u{13a9}', '\u{0}', '\u{0}']), ('\u{ab7a}', ['\u{13aa}', '\u{0}', '\u{0}']),
-        ('\u{ab7b}', ['\u{13ab}', '\u{0}', '\u{0}']), ('\u{ab7c}', ['\u{13ac}', '\u{0}', '\u{0}']),
-        ('\u{ab7d}', ['\u{13ad}', '\u{0}', '\u{0}']), ('\u{ab7e}', ['\u{13ae}', '\u{0}', '\u{0}']),
-        ('\u{ab7f}', ['\u{13af}', '\u{0}', '\u{0}']), ('\u{ab80}', ['\u{13b0}', '\u{0}', '\u{0}']),
-        ('\u{ab81}', ['\u{13b1}', '\u{0}', '\u{0}']), ('\u{ab82}', ['\u{13b2}', '\u{0}', '\u{0}']),
-        ('\u{ab83}', ['\u{13b3}', '\u{0}', '\u{0}']), ('\u{ab84}', ['\u{13b4}', '\u{0}', '\u{0}']),
-        ('\u{ab85}', ['\u{13b5}', '\u{0}', '\u{0}']), ('\u{ab86}', ['\u{13b6}', '\u{0}', '\u{0}']),
-        ('\u{ab87}', ['\u{13b7}', '\u{0}', '\u{0}']), ('\u{ab88}', ['\u{13b8}', '\u{0}', '\u{0}']),
-        ('\u{ab89}', ['\u{13b9}', '\u{0}', '\u{0}']), ('\u{ab8a}', ['\u{13ba}', '\u{0}', '\u{0}']),
-        ('\u{ab8b}', ['\u{13bb}', '\u{0}', '\u{0}']), ('\u{ab8c}', ['\u{13bc}', '\u{0}', '\u{0}']),
-        ('\u{ab8d}', ['\u{13bd}', '\u{0}', '\u{0}']), ('\u{ab8e}', ['\u{13be}', '\u{0}', '\u{0}']),
-        ('\u{ab8f}', ['\u{13bf}', '\u{0}', '\u{0}']), ('\u{ab90}', ['\u{13c0}', '\u{0}', '\u{0}']),
-        ('\u{ab91}', ['\u{13c1}', '\u{0}', '\u{0}']), ('\u{ab92}', ['\u{13c2}', '\u{0}', '\u{0}']),
-        ('\u{ab93}', ['\u{13c3}', '\u{0}', '\u{0}']), ('\u{ab94}', ['\u{13c4}', '\u{0}', '\u{0}']),
-        ('\u{ab95}', ['\u{13c5}', '\u{0}', '\u{0}']), ('\u{ab96}', ['\u{13c6}', '\u{0}', '\u{0}']),
-        ('\u{ab97}', ['\u{13c7}', '\u{0}', '\u{0}']), ('\u{ab98}', ['\u{13c8}', '\u{0}', '\u{0}']),
-        ('\u{ab99}', ['\u{13c9}', '\u{0}', '\u{0}']), ('\u{ab9a}', ['\u{13ca}', '\u{0}', '\u{0}']),
-        ('\u{ab9b}', ['\u{13cb}', '\u{0}', '\u{0}']), ('\u{ab9c}', ['\u{13cc}', '\u{0}', '\u{0}']),
-        ('\u{ab9d}', ['\u{13cd}', '\u{0}', '\u{0}']), ('\u{ab9e}', ['\u{13ce}', '\u{0}', '\u{0}']),
-        ('\u{ab9f}', ['\u{13cf}', '\u{0}', '\u{0}']), ('\u{aba0}', ['\u{13d0}', '\u{0}', '\u{0}']),
-        ('\u{aba1}', ['\u{13d1}', '\u{0}', '\u{0}']), ('\u{aba2}', ['\u{13d2}', '\u{0}', '\u{0}']),
-        ('\u{aba3}', ['\u{13d3}', '\u{0}', '\u{0}']), ('\u{aba4}', ['\u{13d4}', '\u{0}', '\u{0}']),
-        ('\u{aba5}', ['\u{13d5}', '\u{0}', '\u{0}']), ('\u{aba6}', ['\u{13d6}', '\u{0}', '\u{0}']),
-        ('\u{aba7}', ['\u{13d7}', '\u{0}', '\u{0}']), ('\u{aba8}', ['\u{13d8}', '\u{0}', '\u{0}']),
-        ('\u{aba9}', ['\u{13d9}', '\u{0}', '\u{0}']), ('\u{abaa}', ['\u{13da}', '\u{0}', '\u{0}']),
-        ('\u{abab}', ['\u{13db}', '\u{0}', '\u{0}']), ('\u{abac}', ['\u{13dc}', '\u{0}', '\u{0}']),
-        ('\u{abad}', ['\u{13dd}', '\u{0}', '\u{0}']), ('\u{abae}', ['\u{13de}', '\u{0}', '\u{0}']),
-        ('\u{abaf}', ['\u{13df}', '\u{0}', '\u{0}']), ('\u{abb0}', ['\u{13e0}', '\u{0}', '\u{0}']),
-        ('\u{abb1}', ['\u{13e1}', '\u{0}', '\u{0}']), ('\u{abb2}', ['\u{13e2}', '\u{0}', '\u{0}']),
-        ('\u{abb3}', ['\u{13e3}', '\u{0}', '\u{0}']), ('\u{abb4}', ['\u{13e4}', '\u{0}', '\u{0}']),
-        ('\u{abb5}', ['\u{13e5}', '\u{0}', '\u{0}']), ('\u{abb6}', ['\u{13e6}', '\u{0}', '\u{0}']),
-        ('\u{abb7}', ['\u{13e7}', '\u{0}', '\u{0}']), ('\u{abb8}', ['\u{13e8}', '\u{0}', '\u{0}']),
-        ('\u{abb9}', ['\u{13e9}', '\u{0}', '\u{0}']), ('\u{abba}', ['\u{13ea}', '\u{0}', '\u{0}']),
-        ('\u{abbb}', ['\u{13eb}', '\u{0}', '\u{0}']), ('\u{abbc}', ['\u{13ec}', '\u{0}', '\u{0}']),
-        ('\u{abbd}', ['\u{13ed}', '\u{0}', '\u{0}']), ('\u{abbe}', ['\u{13ee}', '\u{0}', '\u{0}']),
-        ('\u{abbf}', ['\u{13ef}', '\u{0}', '\u{0}']), ('\u{fb00}', ['F', 'F', '\u{0}']),
-        ('\u{fb01}', ['F', 'I', '\u{0}']), ('\u{fb02}', ['F', 'L', '\u{0}']),
-        ('\u{fb03}', ['F', 'F', 'I']), ('\u{fb04}', ['F', 'F', 'L']),
-        ('\u{fb05}', ['S', 'T', '\u{0}']), ('\u{fb06}', ['S', 'T', '\u{0}']),
-        ('\u{fb13}', ['\u{544}', '\u{546}', '\u{0}']),
+        ('\u{a7c8}', ['\u{a7c7}', '\u{0}', '\u{0}']), ('\u{a7ca}', ['\u{a7c9}', '\u{0}', '\u{0}']),
+        ('\u{a7f6}', ['\u{a7f5}', '\u{0}', '\u{0}']), ('\u{ab53}', ['\u{a7b3}', '\u{0}', '\u{0}']),
+        ('\u{ab70}', ['\u{13a0}', '\u{0}', '\u{0}']), ('\u{ab71}', ['\u{13a1}', '\u{0}', '\u{0}']),
+        ('\u{ab72}', ['\u{13a2}', '\u{0}', '\u{0}']), ('\u{ab73}', ['\u{13a3}', '\u{0}', '\u{0}']),
+        ('\u{ab74}', ['\u{13a4}', '\u{0}', '\u{0}']), ('\u{ab75}', ['\u{13a5}', '\u{0}', '\u{0}']),
+        ('\u{ab76}', ['\u{13a6}', '\u{0}', '\u{0}']), ('\u{ab77}', ['\u{13a7}', '\u{0}', '\u{0}']),
+        ('\u{ab78}', ['\u{13a8}', '\u{0}', '\u{0}']), ('\u{ab79}', ['\u{13a9}', '\u{0}', '\u{0}']),
+        ('\u{ab7a}', ['\u{13aa}', '\u{0}', '\u{0}']), ('\u{ab7b}', ['\u{13ab}', '\u{0}', '\u{0}']),
+        ('\u{ab7c}', ['\u{13ac}', '\u{0}', '\u{0}']), ('\u{ab7d}', ['\u{13ad}', '\u{0}', '\u{0}']),
+        ('\u{ab7e}', ['\u{13ae}', '\u{0}', '\u{0}']), ('\u{ab7f}', ['\u{13af}', '\u{0}', '\u{0}']),
+        ('\u{ab80}', ['\u{13b0}', '\u{0}', '\u{0}']), ('\u{ab81}', ['\u{13b1}', '\u{0}', '\u{0}']),
+        ('\u{ab82}', ['\u{13b2}', '\u{0}', '\u{0}']), ('\u{ab83}', ['\u{13b3}', '\u{0}', '\u{0}']),
+        ('\u{ab84}', ['\u{13b4}', '\u{0}', '\u{0}']), ('\u{ab85}', ['\u{13b5}', '\u{0}', '\u{0}']),
+        ('\u{ab86}', ['\u{13b6}', '\u{0}', '\u{0}']), ('\u{ab87}', ['\u{13b7}', '\u{0}', '\u{0}']),
+        ('\u{ab88}', ['\u{13b8}', '\u{0}', '\u{0}']), ('\u{ab89}', ['\u{13b9}', '\u{0}', '\u{0}']),
+        ('\u{ab8a}', ['\u{13ba}', '\u{0}', '\u{0}']), ('\u{ab8b}', ['\u{13bb}', '\u{0}', '\u{0}']),
+        ('\u{ab8c}', ['\u{13bc}', '\u{0}', '\u{0}']), ('\u{ab8d}', ['\u{13bd}', '\u{0}', '\u{0}']),
+        ('\u{ab8e}', ['\u{13be}', '\u{0}', '\u{0}']), ('\u{ab8f}', ['\u{13bf}', '\u{0}', '\u{0}']),
+        ('\u{ab90}', ['\u{13c0}', '\u{0}', '\u{0}']), ('\u{ab91}', ['\u{13c1}', '\u{0}', '\u{0}']),
+        ('\u{ab92}', ['\u{13c2}', '\u{0}', '\u{0}']), ('\u{ab93}', ['\u{13c3}', '\u{0}', '\u{0}']),
+        ('\u{ab94}', ['\u{13c4}', '\u{0}', '\u{0}']), ('\u{ab95}', ['\u{13c5}', '\u{0}', '\u{0}']),
+        ('\u{ab96}', ['\u{13c6}', '\u{0}', '\u{0}']), ('\u{ab97}', ['\u{13c7}', '\u{0}', '\u{0}']),
+        ('\u{ab98}', ['\u{13c8}', '\u{0}', '\u{0}']), ('\u{ab99}', ['\u{13c9}', '\u{0}', '\u{0}']),
+        ('\u{ab9a}', ['\u{13ca}', '\u{0}', '\u{0}']), ('\u{ab9b}', ['\u{13cb}', '\u{0}', '\u{0}']),
+        ('\u{ab9c}', ['\u{13cc}', '\u{0}', '\u{0}']), ('\u{ab9d}', ['\u{13cd}', '\u{0}', '\u{0}']),
+        ('\u{ab9e}', ['\u{13ce}', '\u{0}', '\u{0}']), ('\u{ab9f}', ['\u{13cf}', '\u{0}', '\u{0}']),
+        ('\u{aba0}', ['\u{13d0}', '\u{0}', '\u{0}']), ('\u{aba1}', ['\u{13d1}', '\u{0}', '\u{0}']),
+        ('\u{aba2}', ['\u{13d2}', '\u{0}', '\u{0}']), ('\u{aba3}', ['\u{13d3}', '\u{0}', '\u{0}']),
+        ('\u{aba4}', ['\u{13d4}', '\u{0}', '\u{0}']), ('\u{aba5}', ['\u{13d5}', '\u{0}', '\u{0}']),
+        ('\u{aba6}', ['\u{13d6}', '\u{0}', '\u{0}']), ('\u{aba7}', ['\u{13d7}', '\u{0}', '\u{0}']),
+        ('\u{aba8}', ['\u{13d8}', '\u{0}', '\u{0}']), ('\u{aba9}', ['\u{13d9}', '\u{0}', '\u{0}']),
+        ('\u{abaa}', ['\u{13da}', '\u{0}', '\u{0}']), ('\u{abab}', ['\u{13db}', '\u{0}', '\u{0}']),
+        ('\u{abac}', ['\u{13dc}', '\u{0}', '\u{0}']), ('\u{abad}', ['\u{13dd}', '\u{0}', '\u{0}']),
+        ('\u{abae}', ['\u{13de}', '\u{0}', '\u{0}']), ('\u{abaf}', ['\u{13df}', '\u{0}', '\u{0}']),
+        ('\u{abb0}', ['\u{13e0}', '\u{0}', '\u{0}']), ('\u{abb1}', ['\u{13e1}', '\u{0}', '\u{0}']),
+        ('\u{abb2}', ['\u{13e2}', '\u{0}', '\u{0}']), ('\u{abb3}', ['\u{13e3}', '\u{0}', '\u{0}']),
+        ('\u{abb4}', ['\u{13e4}', '\u{0}', '\u{0}']), ('\u{abb5}', ['\u{13e5}', '\u{0}', '\u{0}']),
+        ('\u{abb6}', ['\u{13e6}', '\u{0}', '\u{0}']), ('\u{abb7}', ['\u{13e7}', '\u{0}', '\u{0}']),
+        ('\u{abb8}', ['\u{13e8}', '\u{0}', '\u{0}']), ('\u{abb9}', ['\u{13e9}', '\u{0}', '\u{0}']),
+        ('\u{abba}', ['\u{13ea}', '\u{0}', '\u{0}']), ('\u{abbb}', ['\u{13eb}', '\u{0}', '\u{0}']),
+        ('\u{abbc}', ['\u{13ec}', '\u{0}', '\u{0}']), ('\u{abbd}', ['\u{13ed}', '\u{0}', '\u{0}']),
+        ('\u{abbe}', ['\u{13ee}', '\u{0}', '\u{0}']), ('\u{abbf}', ['\u{13ef}', '\u{0}', '\u{0}']),
+        ('\u{fb00}', ['F', 'F', '\u{0}']), ('\u{fb01}', ['F', 'I', '\u{0}']),
+        ('\u{fb02}', ['F', 'L', '\u{0}']), ('\u{fb03}', ['F', 'F', 'I']),
+        ('\u{fb04}', ['F', 'F', 'L']), ('\u{fb05}', ['S', 'T', '\u{0}']),
+        ('\u{fb06}', ['S', 'T', '\u{0}']), ('\u{fb13}', ['\u{544}', '\u{546}', '\u{0}']),
         ('\u{fb14}', ['\u{544}', '\u{535}', '\u{0}']),
         ('\u{fb15}', ['\u{544}', '\u{53b}', '\u{0}']),
         ('\u{fb16}', ['\u{54e}', '\u{546}', '\u{0}']),
index 9ca7eee999fe0493b3f4f44421123ae32b797a6d..e138503b508d545a5ce5b97e5733134fd6bccb76 100644 (file)
@@ -176,7 +176,7 @@ pub struct Parser<'a> {
     skips: Vec<usize>,
     /// Span of the last opening brace seen, used for error reporting
     last_opening_brace: Option<InnerSpan>,
-    /// Wether the source string is comes from `println!` as opposed to `format!` or `print!`
+    /// Whether the source string is comes from `println!` as opposed to `format!` or `print!`
     append_newline: bool,
 }
 
index db7c250e21157810f35b357b6a2d072a924a042b..f44a875c9d0d5450b022631b138f59470d05fd12 100644 (file)
 #![feature(staged_api)]
 #![feature(rustc_attrs)]
 
-// Rust's "try" function, but if we're aborting on panics we just call the
-// function as there's nothing else we need to do here.
+use core::any::Any;
+
 #[rustc_std_internal_symbol]
-pub unsafe extern "C" fn __rust_maybe_catch_panic(
-    f: fn(*mut u8),
-    data: *mut u8,
-    _data_ptr: *mut usize,
-    _vtable_ptr: *mut usize,
-) -> u32 {
-    f(data);
-    0
+pub unsafe extern "C" fn __rust_panic_cleanup(_: *mut u8) -> *mut (dyn Any + Send + 'static) {
+    unreachable!()
 }
 
 // "Leak" the payload and shim to the relevant abort on the platform in
@@ -92,7 +86,7 @@ unsafe fn abort() -> ! {
 // binaries, but it should never be called as we don't link in an unwinding
 // runtime at all.
 pub mod personalities {
-    #[no_mangle]
+    #[rustc_std_internal_symbol]
     #[cfg(not(any(
         all(target_arch = "wasm32", not(target_os = "emscripten"),),
         all(target_os = "windows", target_env = "gnu", target_arch = "x86_64",),
@@ -101,7 +95,7 @@ pub extern "C" fn rust_eh_personality() {}
 
     // On x86_64-pc-windows-gnu we use our own personality function that needs
     // to return `ExceptionContinueSearch` as we're passing on all our frames.
-    #[no_mangle]
+    #[rustc_std_internal_symbol]
     #[cfg(all(target_os = "windows", target_env = "gnu", target_arch = "x86_64"))]
     pub extern "C" fn rust_eh_personality(
         _record: usize,
@@ -117,16 +111,16 @@ pub extern "C" fn rust_eh_personality(
     //
     // Note that we don't execute landing pads, so this is never called, so it's
     // body is empty.
-    #[no_mangle]
-    #[cfg(all(target_os = "windows", target_env = "gnu"))]
+    #[rustc_std_internal_symbol]
+    #[cfg(all(bootstrap, target_os = "windows", target_env = "gnu"))]
     pub extern "C" fn rust_eh_unwind_resume() {}
 
     // These two are called by our startup objects on i686-pc-windows-gnu, but
     // they don't need to do anything so the bodies are nops.
-    #[no_mangle]
+    #[rustc_std_internal_symbol]
     #[cfg(all(target_os = "windows", target_env = "gnu", target_arch = "x86"))]
     pub extern "C" fn rust_eh_register_frames() {}
-    #[no_mangle]
+    #[rustc_std_internal_symbol]
     #[cfg(all(target_os = "windows", target_env = "gnu", target_arch = "x86"))]
     pub extern "C" fn rust_eh_unregister_frames() {}
 }
index 8675632638712aa2593f77f1b1bcba0621316680..4667ede2baad5131ef5587f06c2c3b153f8f9bb8 100644 (file)
@@ -6,10 +6,6 @@
 use core::any::Any;
 use core::intrinsics;
 
-pub fn payload() -> *mut u8 {
-    core::ptr::null_mut()
-}
-
 pub unsafe fn cleanup(_ptr: *mut u8) -> Box<dyn Any + Send> {
     intrinsics::abort()
 }
index 9161d49959cf5cc1577264dcdb1502cde151115a..a0bdb1481c6b2460c2c3eb2140adb46ccedce5c5 100644 (file)
@@ -6,8 +6,6 @@
 //! Emscripten's runtime always implements those APIs and does not
 //! implement libunwind.
 
-#![allow(private_no_mangle_fns)]
-
 use alloc::boxed::Box;
 use core::any::Any;
 use core::mem;
@@ -48,15 +46,11 @@ unsafe impl Sync for TypeInfo {}
     name: b"rust_panic\0".as_ptr(),
 };
 
-pub fn payload() -> *mut u8 {
-    ptr::null_mut()
-}
-
 struct Exception {
     // This needs to be an Option because the object's lifetime follows C++
     // semantics: when catch_unwind moves the Box out of the exception it must
     // still leave the exception object in a valid state because its destructor
-    // is still going to be called by __cxa_end_catch..
+    // is still going to be called by __cxa_end_catch.
     data: Option<Box<dyn Any + Send>>,
 }
 
@@ -98,7 +92,6 @@ extern "C" fn exception_cleanup(ptr: *mut libc::c_void) -> DestructorRet {
 }
 
 #[lang = "eh_personality"]
-#[no_mangle]
 unsafe extern "C" fn rust_eh_personality(
     version: c_int,
     actions: uw::_Unwind_Action,
index 591ff9d7fdcaa3c24f7097b22b177d29063a0dcf..1622442a5eb450dae5058eb724f3aac8a878fd1b 100644 (file)
 //!
 //! Once stack has been unwound down to the handler frame level, unwinding stops
 //! and the last personality routine transfers control to the catch block.
-//!
-//! ## `eh_personality` and `eh_unwind_resume`
-//!
-//! These language items are used by the compiler when generating unwind info.
-//! The first one is the personality routine described above. The second one
-//! allows compilation target to customize the process of resuming unwind at the
-//! end of the landing pads. `eh_unwind_resume` is used only if
-//! `custom_unwind_resume` flag in the target options is set.
-
-#![allow(private_no_mangle_fns)]
 
 use alloc::boxed::Box;
 use core::any::Any;
-use core::ptr;
 
 use crate::dwarf::eh::{self, EHAction, EHContext};
 use libc::{c_int, uintptr_t};
@@ -83,10 +72,6 @@ extern "C" fn exception_cleanup(
     }
 }
 
-pub fn payload() -> *mut u8 {
-    ptr::null_mut()
-}
-
 pub unsafe fn cleanup(ptr: *mut u8) -> Box<dyn Any + Send> {
     let exception = Box::from_raw(ptr as *mut Exception);
     exception.cause
@@ -143,7 +128,6 @@ fn rust_exception_class() -> uw::_Unwind_Exception_Class {
         //
         // iOS uses the default routine instead since it uses SjLj unwinding.
         #[lang = "eh_personality"]
-        #[no_mangle]
         unsafe extern "C" fn rust_eh_personality(state: uw::_Unwind_State,
                                                  exception_object: *mut uw::_Unwind_Exception,
                                                  context: *mut uw::_Unwind_Context)
@@ -277,7 +261,6 @@ fn __gnu_unwind_frame(exception_object: *mut uw::_Unwind_Exception,
                 // On x86_64 MinGW targets, the unwinding mechanism is SEH however the unwind
                 // handler data (aka LSDA) uses GCC-compatible encoding.
                 #[lang = "eh_personality"]
-                #[no_mangle]
                 #[allow(nonstandard_style)]
                 unsafe extern "C" fn rust_eh_personality(exceptionRecord: *mut uw::EXCEPTION_RECORD,
                         establisherFrame: uw::LPVOID,
@@ -293,7 +276,6 @@ fn __gnu_unwind_frame(exception_object: *mut uw::_Unwind_Exception,
             } else {
                 // The personality routine for most of our targets.
                 #[lang = "eh_personality"]
-                #[no_mangle]
                 unsafe extern "C" fn rust_eh_personality(version: c_int,
                         actions: uw::_Unwind_Action,
                         exception_class: uw::_Unwind_Exception_Class,
@@ -329,8 +311,8 @@ unsafe fn find_eh_action(
     eh::find_eh_action(lsda, &eh_context, foreign_exception)
 }
 
-// See docs in the `unwind` module.
 #[cfg(all(
+    bootstrap,
     target_os = "windows",
     any(target_arch = "x86", target_arch = "x86_64"),
     target_env = "gnu"
@@ -364,12 +346,12 @@ pub mod eh_frame_registry {
         fn __deregister_frame_info(eh_frame_begin: *const u8, object: *mut u8);
     }
 
-    #[no_mangle]
+    #[rustc_std_internal_symbol]
     pub unsafe extern "C" fn rust_eh_register_frames(eh_frame_begin: *const u8, object: *mut u8) {
         __register_frame_info(eh_frame_begin, object);
     }
 
-    #[no_mangle]
+    #[rustc_std_internal_symbol]
     pub unsafe extern "C" fn rust_eh_unregister_frames(eh_frame_begin: *const u8, object: *mut u8) {
         __deregister_frame_info(eh_frame_begin, object);
     }
index 2f53df2861d4436bcf84ce88b4ddf7cdc87594d6..69b9edb77c5649a2be64e3e5f73a8abf53fc094a 100644 (file)
@@ -4,11 +4,6 @@
 
 use alloc::boxed::Box;
 use core::any::Any;
-use core::ptr;
-
-pub fn payload() -> *mut u8 {
-    ptr::null_mut()
-}
 
 pub unsafe fn cleanup(_ptr: *mut u8) -> Box<dyn Any + Send> {
     extern "C" {
index 6383ae39fb6dba0c6795de05873964bc528341bb..0a2a0e9e045c6bea287c2f1265f3620b54cc26fe 100644 (file)
 #![feature(libc)]
 #![feature(nll)]
 #![feature(panic_unwind)]
-#![feature(raw)]
 #![feature(staged_api)]
 #![feature(std_internals)]
 #![feature(unwind_attributes)]
 #![feature(abi_thiscall)]
+#![feature(rustc_attrs)]
+#![feature(raw)]
 #![panic_runtime]
 #![feature(panic_runtime)]
+// `real_imp` is unused with Miri, so silence warnings.
+#![cfg_attr(miri, allow(dead_code))]
 
 use alloc::boxed::Box;
-use core::intrinsics;
-use core::mem;
+use core::any::Any;
 use core::panic::BoxMeUp;
-use core::raw;
 
 cfg_if::cfg_if! {
     if #[cfg(target_os = "emscripten")] {
         #[path = "emcc.rs"]
-        mod imp;
+        mod real_imp;
     } else if #[cfg(target_arch = "wasm32")] {
         #[path = "dummy.rs"]
-        mod imp;
+        mod real_imp;
     } else if #[cfg(target_os = "hermit")] {
         #[path = "hermit.rs"]
-        mod imp;
+        mod real_imp;
     } else if #[cfg(all(target_env = "msvc", target_arch = "aarch64"))] {
         #[path = "dummy.rs"]
-        mod imp;
+        mod real_imp;
     } else if #[cfg(target_env = "msvc")] {
         #[path = "seh.rs"]
-        mod imp;
+        mod real_imp;
     } else {
         // Rust runtime's startup objects depend on these symbols, so make them public.
         #[cfg(all(target_os="windows", target_arch = "x86", target_env="gnu"))]
-        pub use imp::eh_frame_registry::*;
+        pub use real_imp::eh_frame_registry::*;
         #[path = "gcc.rs"]
+        mod real_imp;
+    }
+}
+
+cfg_if::cfg_if! {
+    if #[cfg(miri)] {
+        // Use the Miri runtime.
+        // We still need to also load the normal runtime above, as rustc expects certain lang
+        // items from there to be defined.
+        #[path = "miri.rs"]
         mod imp;
+    } else {
+        // Use the real runtime.
+        use real_imp as imp;
     }
 }
 
 
 mod dwarf;
 
-// Entry point for catching an exception, implemented using the `try` intrinsic
-// in the compiler.
-//
-// The interaction between the `payload` function and the compiler is pretty
-// hairy and tightly coupled, for more information see the compiler's
-// implementation of this.
-#[no_mangle]
-pub unsafe extern "C" fn __rust_maybe_catch_panic(
-    f: fn(*mut u8),
-    data: *mut u8,
-    data_ptr: *mut usize,
-    vtable_ptr: *mut usize,
-) -> u32 {
-    let mut payload = imp::payload();
-    if intrinsics::r#try(f, data, &mut payload as *mut _ as *mut _) == 0 {
-        0
-    } else {
-        let obj = mem::transmute::<_, raw::TraitObject>(imp::cleanup(payload));
-        *data_ptr = obj.data as usize;
-        *vtable_ptr = obj.vtable as usize;
-        1
-    }
+#[rustc_std_internal_symbol]
+pub unsafe extern "C" fn __rust_panic_cleanup(payload: *mut u8) -> *mut (dyn Any + Send + 'static) {
+    Box::into_raw(imp::cleanup(payload))
 }
 
 // Entry point for raising an exception, just delegates to the platform-specific
 // implementation.
-#[no_mangle]
+#[rustc_std_internal_symbol]
 #[unwind(allowed)]
 pub unsafe extern "C" fn __rust_start_panic(payload: usize) -> u32 {
     let payload = payload as *mut &mut dyn BoxMeUp;
     let payload = (*payload).take_box();
 
-    // Miri panic support: cfg'd out of normal builds just to be sure.
-    // When going through normal codegen, `miri_start_panic` is a NOP, so the
-    // Miri-enabled sysroot still supports normal unwinding. But when executed in
-    // Miri, this line initiates unwinding.
-    #[cfg(miri)]
-    core::intrinsics::miri_start_panic(payload);
-
     imp::panic(Box::from_raw(payload))
 }
diff --git a/src/libpanic_unwind/miri.rs b/src/libpanic_unwind/miri.rs
new file mode 100644 (file)
index 0000000..9d92b2b
--- /dev/null
@@ -0,0 +1,20 @@
+//! Unwinding panics for Miri.
+use alloc::boxed::Box;
+use core::any::Any;
+
+// The type of the payload that the Miri engine propagates through unwinding for us.
+// Must be pointer-sized.
+type Payload = Box<Box<dyn Any + Send>>;
+
+pub unsafe fn panic(payload: Box<dyn Any + Send>) -> u32 {
+    // The payload we pass to `miri_start_panic` will be exactly the argument we get
+    // in `cleanup` below. So we just box it up once, to get something pointer-sized.
+    let payload_box: Payload = Box::new(payload);
+    core::intrinsics::miri_start_panic(Box::into_raw(payload_box) as *mut u8)
+}
+
+pub unsafe fn cleanup(payload_box: *mut u8) -> Box<dyn Any + Send> {
+    // Recover the underlying `Box`.
+    let payload_box: Payload = Box::from_raw(payload_box as *mut _);
+    *payload_box
+}
index 6f507e85e742c59f6de1982c2fa76a5c23f4b3ff..10b765a5b411b60efe5f1484e5ab3c1c6228c98c 100644 (file)
 //! [llvm]: http://llvm.org/docs/ExceptionHandling.html#background-on-windows-exceptions
 
 #![allow(nonstandard_style)]
-#![allow(private_no_mangle_fns)]
 
 use alloc::boxed::Box;
 use core::any::Any;
-use core::mem;
-use core::raw;
+use core::mem::{self, ManuallyDrop};
 use libc::{c_int, c_uint, c_void};
 
+struct Exception {
+    // This needs to be an Option because we catch the exception by reference
+    // and its destructor is executed by the C++ runtime. When we take the Box
+    // out of the exception, we need to leave the exception in a valid state
+    // for its destructor to run without double-dropping the Box.
+    data: Option<Box<dyn Any + Send>>,
+}
+
 // First up, a whole bunch of type definitions. There's a few platform-specific
 // oddities here, and a lot that's just blatantly copied from LLVM. The purpose
 // of all this is to implement the `panic` function below through a call to
@@ -167,6 +173,9 @@ pub struct _TypeDescriptor {
 
 // Note that we intentionally ignore name mangling rules here: we don't want C++
 // to be able to catch Rust panics by simply declaring a `struct rust_panic`.
+//
+// When modifying, make sure that the type name string exactly matches
+// the one used in src/librustc_codegen_llvm/intrinsic.rs.
 const TYPE_NAME: [u8; 11] = *b"rust_panic\0";
 
 static mut THROW_INFO: _ThrowInfo = _ThrowInfo {
@@ -183,7 +192,7 @@ pub struct _TypeDescriptor {
     properties: 0,
     pType: ptr!(0),
     thisDisplacement: _PMD { mdisp: 0, pdisp: -1, vdisp: 0 },
-    sizeOrOffset: mem::size_of::<[u64; 2]>() as c_int,
+    sizeOrOffset: mem::size_of::<Exception>() as c_int,
     copyFunction: ptr!(0),
 };
 
@@ -199,12 +208,12 @@ pub struct _TypeDescriptor {
     static TYPE_INFO_VTABLE: *const u8;
 }
 
-// We use #[lang = "eh_catch_typeinfo"] here as this is the type descriptor which
-// we'll use in LLVM's `catchpad` instruction which ends up also being passed as
-// an argument to the C++ personality function.
+// This type descriptor is only used when throwing an exception. The catch part
+// is handled by the try intrinsic, which generates its own TypeDescriptor.
 //
-// Again, I'm not entirely sure what this is describing, it just seems to work.
-#[cfg_attr(not(test), lang = "eh_catch_typeinfo")]
+// This is fine since the MSVC runtime uses string comparison on the type name
+// to match TypeDescriptors rather than pointer equality.
+#[cfg_attr(bootstrap, lang = "eh_catch_typeinfo")]
 static mut TYPE_DESCRIPTOR: _TypeDescriptor = _TypeDescriptor {
     pVFTable: unsafe { &TYPE_INFO_VTABLE } as *const _ as *const _,
     spare: core::ptr::null_mut(),
@@ -226,16 +235,16 @@ pub struct _TypeDescriptor {
 // because Box<dyn Any> isn't clonable.
 macro_rules! define_cleanup {
     ($abi:tt) => {
-        unsafe extern $abi fn exception_cleanup(e: *mut [u64; 2]) {
-            if (*e)[0] != 0 {
-                cleanup(*e);
+        unsafe extern $abi fn exception_cleanup(e: *mut Exception) {
+            if let Exception { data: Some(b) } = e.read() {
+                drop(b);
                 super::__rust_drop_panic();
             }
         }
         #[unwind(allowed)]
-        unsafe extern $abi fn exception_copy(_dest: *mut [u64; 2],
-                                             _src: *mut [u64; 2])
-                                             -> *mut [u64; 2] {
+        unsafe extern $abi fn exception_copy(_dest: *mut Exception,
+                                             _src: *mut Exception)
+                                             -> *mut Exception {
             panic!("Rust panics cannot be copied");
         }
     }
@@ -255,12 +264,11 @@ pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
     // need to otherwise transfer `data` to the heap. We just pass a stack
     // pointer to this function.
     //
-    // The first argument is the payload being thrown (our two pointers), and
-    // the second argument is the type information object describing the
-    // exception (constructed above).
-    let ptrs = mem::transmute::<_, raw::TraitObject>(data);
-    let mut ptrs = [ptrs.data as u64, ptrs.vtable as u64];
-    let throw_ptr = ptrs.as_mut_ptr() as *mut _;
+    // The ManuallyDrop is needed here since we don't want Exception to be
+    // dropped when unwinding. Instead it will be dropped by exception_cleanup
+    // which is invoked by the C++ runtime.
+    let mut exception = ManuallyDrop::new(Exception { data: Some(data) });
+    let throw_ptr = &mut exception as *mut _ as *mut _;
 
     // This... may seems surprising, and justifiably so. On 32-bit MSVC the
     // pointers between these structure are just that, pointers. On 64-bit MSVC,
@@ -308,12 +316,9 @@ pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
     _CxxThrowException(throw_ptr, &mut THROW_INFO as *mut _ as *mut _);
 }
 
-pub fn payload() -> [u64; 2] {
-    [0; 2]
-}
-
-pub unsafe fn cleanup(payload: [u64; 2]) -> Box<dyn Any + Send> {
-    mem::transmute(raw::TraitObject { data: payload[0] as *mut _, vtable: payload[1] as *mut _ })
+pub unsafe fn cleanup(payload: *mut u8) -> Box<dyn Any + Send> {
+    let exception = &mut *(payload as *mut Exception);
+    exception.data.take().unwrap()
 }
 
 // This is required by the compiler to exist (e.g., it's a lang item), but
index dd948025c91cacfb256899427e6f02ff4f9e71ab..088db92253acfb857d0abcc725bd6eaf69668e13 100644 (file)
@@ -15,7 +15,7 @@ pub struct HandleCounters {
         }
 
         impl HandleCounters {
-            // FIXME(eddyb) use a reference to the `static COUNTERS`, intead of
+            // FIXME(eddyb) use a reference to the `static COUNTERS`, instead of
             // a wrapper `fn` pointer, once `const fn` can reference `static`s.
             extern "C" fn get() -> &'static Self {
                 static COUNTERS: HandleCounters = HandleCounters {
@@ -334,7 +334,7 @@ fn with<R>(f: impl FnOnce(&mut Bridge<'_>) -> R) -> R {
 #[repr(C)]
 #[derive(Copy, Clone)]
 pub struct Client<F> {
-    // FIXME(eddyb) use a reference to the `static COUNTERS`, intead of
+    // FIXME(eddyb) use a reference to the `static COUNTERS`, instead of
     // a wrapper `fn` pointer, once `const fn` can reference `static`s.
     pub(super) get_handle_counters: extern "C" fn() -> &'static HandleCounters,
     pub(super) run: extern "C" fn(Bridge<'_>, F) -> Buffer<u8>,
index fdf252e53387ecee7dcc4e2073cb55860e9e221e..7495468a05b6ccf74febb12fee681d73ab1c1760 100644 (file)
@@ -55,13 +55,15 @@ pub struct Diagnostic {
 }
 
 macro_rules! diagnostic_child_methods {
-    ($spanned:ident, $regular:ident, $level:expr) => (
+    ($spanned:ident, $regular:ident, $level:expr) => {
         /// Adds a new child diagnostic message to `self` with the level
         /// identified by this method's name with the given `spans` and
         /// `message`.
         #[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
         pub fn $spanned<S, T>(mut self, spans: S, message: T) -> Diagnostic
-            where S: MultiSpan, T: Into<String>
+        where
+            S: MultiSpan,
+            T: Into<String>,
         {
             self.children.push(Diagnostic::spanned(spans, $level, message));
             self
@@ -74,7 +76,7 @@ pub fn $regular<T: Into<String>>(mut self, message: T) -> Diagnostic {
             self.children.push(Diagnostic::new($level, message));
             self
         }
-    )
+    };
 }
 
 /// Iterator over the children diagnostics of a `Diagnostic`.
@@ -96,7 +98,7 @@ impl Diagnostic {
     /// Creates a new diagnostic with the given `level` and `message`.
     #[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
     pub fn new<T: Into<String>>(level: Level, message: T) -> Diagnostic {
-        Diagnostic { level: level, message: message.into(), spans: vec![], children: vec![] }
+        Diagnostic { level, message: message.into(), spans: vec![], children: vec![] }
     }
 
     /// Creates a new diagnostic with the given `level` and `message` pointing to
@@ -107,12 +109,7 @@ pub fn spanned<S, T>(spans: S, level: Level, message: T) -> Diagnostic
         S: MultiSpan,
         T: Into<String>,
     {
-        Diagnostic {
-            level: level,
-            message: message.into(),
-            spans: spans.into_spans(),
-            children: vec![],
-        }
+        Diagnostic { level, message: message.into(), spans: spans.into_spans(), children: vec![] }
     }
 
     diagnostic_child_methods!(span_error, error, Level::Error);
index c51db695a5b1581efd9e7bdd7c81bcffe34edfb6..8f16e3c08ec5b542ddf167b4d45a95a1b8002f50 100644 (file)
@@ -26,7 +26,8 @@
 #![feature(in_band_lifetimes)]
 #![feature(optin_builtin_traits)]
 #![feature(rustc_attrs)]
-#![feature(specialization)]
+#![cfg_attr(bootstrap, feature(specialization))]
+#![cfg_attr(not(bootstrap), feature(min_specialization))]
 #![recursion_limit = "256"]
 
 #[unstable(feature = "proc_macro_internals", issue = "27812")]
@@ -41,7 +42,7 @@
 use std::ops::{Bound, RangeBounds};
 use std::path::PathBuf;
 use std::str::FromStr;
-use std::{fmt, iter, mem};
+use std::{error, fmt, iter, mem};
 
 /// The main type provided by this crate, representing an abstract stream of
 /// tokens, or, more specifically, a sequence of token trees.
@@ -66,6 +67,16 @@ pub struct LexError {
     _inner: (),
 }
 
+#[stable(feature = "proc_macro_lexerror_impls", since = "1.44.0")]
+impl fmt::Display for LexError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.write_str("cannot parse string into token stream")
+    }
+}
+
+#[stable(feature = "proc_macro_lexerror_impls", since = "1.44.0")]
+impl error::Error for LexError {}
+
 #[stable(feature = "proc_macro_lib", since = "1.15.0")]
 impl !Send for LexError {}
 #[stable(feature = "proc_macro_lib", since = "1.15.0")]
index bac2540ab450a8c19aa27c86eaea121292a97d62..481d691b8e9b20c5dfb82bd1de5015bca040f9fe 100644 (file)
@@ -17,7 +17,7 @@ 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"
-polonius-engine = "0.11.0"
+polonius-engine = "0.12.0"
 rustc_apfloat = { path = "../librustc_apfloat" }
 rustc_attr = { path = "../librustc_attr" }
 rustc_feature = { path = "../librustc_feature" }
@@ -33,7 +33,6 @@ rustc_span = { path = "../librustc_span" }
 backtrace = "0.3.40"
 parking_lot = "0.9"
 byteorder = { version = "1.3" }
-chalk-engine = { version = "0.9.0", default-features=false }
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
 measureme = "0.7.1"
 rustc_session = { path = "../librustc_session" }
index c0e5c542bdc8b794e15e074db22cfabbe96f82ce..de58f546cd3b5d1fb053c5a2fd8bd2d03e3a4b55 100644 (file)
@@ -1,3 +1,3 @@
-For more information about how rustc works, see the [rustc guide].
+For more information about how rustc works, see the [rustc dev guide].
 
-[rustc guide]: https://rust-lang.github.io/rustc-guide/
+[rustc dev guide]: https://rustc-dev-guide.rust-lang.org/
index 0384a9f781578c77e892591939479136b0725f61..72258c0537a96eddafc86113c01bd7535925fc61 100644 (file)
@@ -161,6 +161,12 @@ macro_rules! arena_types {
             [] type_binding: rustc_hir::TypeBinding<$tcx>,
             [] variant: rustc_hir::Variant<$tcx>,
             [] where_predicate: rustc_hir::WherePredicate<$tcx>,
+
+            // HIR query types
+            [few] indexed_hir: rustc::hir::map::IndexedHir<$tcx>,
+            [few] hir_definitions: rustc::hir::map::definitions::Definitions,
+            [] hir_owner: rustc::hir::HirOwner<$tcx>,
+            [] hir_owner_items: rustc::hir::HirOwnerItems<$tcx>,
         ], $tcx);
     )
 }
index 91a06e452e5fd9c14b340e108e6f7838d20d39fa..b9d91cd35a8ddf6ce799b94d488bffc955b2efde 100644 (file)
@@ -1,4 +1,4 @@
 To learn more about how dependency tracking works in rustc, see the [rustc
 guide].
 
-[rustc guide]: https://rust-lang.github.io/rustc-guide/query.html
+[rustc dev guide]: https://rustc-dev-guide.rust-lang.org/query.html
index eb7e2871bfcd8371b6c1c3414559fe1b2c89c269..b32fa2cda80129e2d59a2646e63af51eaea1476f 100644 (file)
@@ -35,7 +35,7 @@
 //! "infer" some properties for each kind of `DepNode`:
 //!
 //! * Whether a `DepNode` of a given kind has any parameters at all. Some
-//!   `DepNode`s, like `AllLocalTraitImpls`, represent global concepts with only one value.
+//!   `DepNode`s could represent global concepts with only one value.
 //! * Whether it is possible, in principle, to reconstruct a query key from a
 //!   given `DepNode`. Many `DepKind`s only require a single `DefId` parameter,
 //!   in which case it is possible to map the node's fingerprint back to the
@@ -63,7 +63,7 @@
 use crate::ty::{self, ParamEnvAnd, Ty, TyCtxt};
 
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-use rustc_hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX};
+use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX};
 use rustc_hir::HirId;
 use rustc_span::symbol::Symbol;
 use std::fmt;
@@ -111,6 +111,7 @@ macro_rules! define_dep_nodes {
     ) => (
         #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash,
                  RustcEncodable, RustcDecodable)]
+        #[allow(non_camel_case_types)]
         pub enum DepKind {
             $($variant),*
         }
@@ -173,11 +174,12 @@ pub fn has_params(&self) -> bool {
 
         pub struct DepConstructor;
 
+        #[allow(non_camel_case_types)]
         impl DepConstructor {
             $(
                 #[inline(always)]
                 #[allow(unreachable_code, non_snake_case)]
-                pub fn $variant<'tcx>(_tcx: TyCtxt<'tcx>, $(arg: $tuple_arg_ty)*) -> DepNode {
+                pub fn $variant(_tcx: TyCtxt<'_>, $(arg: $tuple_arg_ty)*) -> DepNode {
                     // tuple args
                     $({
                         erase!($tuple_arg_ty);
@@ -221,8 +223,8 @@ impl DepNode {
             /// Construct a DepNode from the given DepKind and DefPathHash. This
             /// method will assert that the given DepKind actually requires a
             /// single DefId/DefPathHash parameter.
-            pub fn from_def_path_hash(kind: DepKind,
-                                      def_path_hash: DefPathHash)
+            pub fn from_def_path_hash(def_path_hash: DefPathHash,
+                                      kind: DepKind)
                                       -> DepNode {
                 debug_assert!(kind.can_reconstruct_query_key() && kind.has_params());
                 DepNode {
@@ -278,7 +280,7 @@ pub fn from_label_string(label: &str,
                 }
 
                 if kind.has_params() {
-                    Ok(def_path_hash.to_dep_node(kind))
+                    Ok(DepNode::from_def_path_hash(def_path_hash, kind))
                 } else {
                     Ok(DepNode::new_no_params(kind))
                 }
@@ -335,58 +337,19 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     }
 }
 
-impl DefPathHash {
-    pub fn to_dep_node(self, kind: DepKind) -> DepNode {
-        DepNode::from_def_path_hash(kind, self)
-    }
-}
-
 rustc_dep_node_append!([define_dep_nodes!][ <'tcx>
     // We use this for most things when incr. comp. is turned off.
     [] Null,
 
-    // Represents the body of a function or method. The def-id is that of the
-    // function/method.
-    [eval_always] HirBody(DefId),
-
-    // Represents the HIR node with the given node-id
-    [eval_always] Hir(DefId),
-
     // Represents metadata from an extern crate.
     [eval_always] CrateMetadata(CrateNum),
 
-    [eval_always] AllLocalTraitImpls,
-
     [anon] TraitSelect,
 
     [] CompileCodegenUnit(Symbol),
-
-    [eval_always] Analysis(CrateNum),
 ]);
 
-pub trait RecoverKey<'tcx>: Sized {
-    fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self>;
-}
-
-impl RecoverKey<'tcx> for CrateNum {
-    fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
-        dep_node.extract_def_id(tcx).map(|id| id.krate)
-    }
-}
-
-impl RecoverKey<'tcx> for DefId {
-    fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
-        dep_node.extract_def_id(tcx)
-    }
-}
-
-impl RecoverKey<'tcx> for DefIndex {
-    fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
-        dep_node.extract_def_id(tcx).map(|id| id.index)
-    }
-}
-
-trait DepNodeParams<'tcx>: fmt::Debug {
+pub(crate) trait DepNodeParams<'tcx>: fmt::Debug + Sized {
     const CAN_RECONSTRUCT_QUERY_KEY: bool;
 
     /// This method turns the parameters of a DepNodeConstructor into an opaque
@@ -400,6 +363,14 @@ fn to_fingerprint(&self, _: TyCtxt<'tcx>) -> Fingerprint {
     fn to_debug_str(&self, _: TyCtxt<'tcx>) -> String {
         format!("{:?}", self)
     }
+
+    /// This method tries to recover the query key from the given `DepNode`,
+    /// something which is needed when forcing `DepNode`s during red-green
+    /// evaluation. The query system will only call this method if
+    /// `CAN_RECONSTRUCT_QUERY_KEY` is `true`.
+    /// It is always valid to return `None` here, in which case incremental
+    /// compilation will treat the query as having changed instead of forcing it.
+    fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self>;
 }
 
 impl<'tcx, T> DepNodeParams<'tcx> for T
@@ -420,6 +391,10 @@ impl<'tcx, T> DepNodeParams<'tcx> for T
     default fn to_debug_str(&self, _: TyCtxt<'tcx>) -> String {
         format!("{:?}", *self)
     }
+
+    default fn recover(_: TyCtxt<'tcx>, _: &DepNode) -> Option<Self> {
+        None
+    }
 }
 
 impl<'tcx> DepNodeParams<'tcx> for DefId {
@@ -432,17 +407,25 @@ fn to_fingerprint(&self, tcx: TyCtxt<'_>) -> Fingerprint {
     fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
         tcx.def_path_str(*self)
     }
+
+    fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
+        dep_node.extract_def_id(tcx)
+    }
 }
 
-impl<'tcx> DepNodeParams<'tcx> for DefIndex {
+impl<'tcx> DepNodeParams<'tcx> for LocalDefId {
     const CAN_RECONSTRUCT_QUERY_KEY: bool = true;
 
     fn to_fingerprint(&self, tcx: TyCtxt<'_>) -> Fingerprint {
-        tcx.hir().definitions().def_path_hash(*self).0
+        self.to_def_id().to_fingerprint(tcx)
     }
 
     fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
-        tcx.def_path_str(DefId::local(*self))
+        self.to_def_id().to_debug_str(tcx)
+    }
+
+    fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
+        dep_node.extract_def_id(tcx).map(|id| id.expect_local())
     }
 }
 
@@ -457,6 +440,10 @@ fn to_fingerprint(&self, tcx: TyCtxt<'_>) -> Fingerprint {
     fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
         tcx.crate_name(*self).to_string()
     }
+
+    fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
+        dep_node.extract_def_id(tcx).map(|id| id.krate)
+    }
 }
 
 impl<'tcx> DepNodeParams<'tcx> for (DefId, DefId) {
@@ -490,7 +477,7 @@ impl<'tcx> DepNodeParams<'tcx> for HirId {
     fn to_fingerprint(&self, tcx: TyCtxt<'_>) -> Fingerprint {
         let HirId { owner, local_id } = *self;
 
-        let def_path_hash = tcx.def_path_hash(DefId::local(owner));
+        let def_path_hash = tcx.def_path_hash(owner.to_def_id());
         let local_id = Fingerprint::from_smaller_hash(local_id.as_u32().into());
 
         def_path_hash.0.combine(local_id)
index 33902fe913a9c9129010786c025ec84da6b8687b..f60d20b8cb75d0972ba4e06657d77978867758f0 100644 (file)
@@ -174,7 +174,7 @@ pub fn with_ignore<OP, R>(&self, op: OP) -> R
     /// what state they have access to. In particular, we want to
     /// prevent implicit 'leaks' of tracked state into the task (which
     /// could then be read without generating correct edges in the
-    /// dep-graph -- see the [rustc guide] for more details on
+    /// dep-graph -- see the [rustc dev guide] for more details on
     /// the dep-graph). To this end, the task function gets exactly two
     /// pieces of state: the context `cx` and an argument `arg`. Both
     /// of these bits of state must be of some type that implements
@@ -194,7 +194,7 @@ pub fn with_ignore<OP, R>(&self, op: OP) -> R
     /// - If you need 3+ arguments, use a tuple for the
     ///   `arg` parameter.
     ///
-    /// [rustc guide]: https://rust-lang.github.io/rustc-guide/incremental-compilation.html
+    /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/incremental-compilation.html
     pub fn with_task<'a, C, A, R>(
         &self,
         key: DepNode,
@@ -225,28 +225,6 @@ pub fn with_task<'a, C, A, R>(
         )
     }
 
-    /// Creates a new dep-graph input with value `input`
-    pub fn input_task<'a, C, R>(&self, key: DepNode, cx: C, input: R) -> (R, DepNodeIndex)
-    where
-        C: DepGraphSafe + StableHashingContextProvider<'a>,
-        R: for<'b> HashStable<StableHashingContext<'b>>,
-    {
-        fn identity_fn<C, A>(_: C, arg: A) -> A {
-            arg
-        }
-
-        self.with_task_impl(
-            key,
-            cx,
-            input,
-            true,
-            identity_fn,
-            |_| None,
-            |data, key, fingerprint, _| data.alloc_node(key, SmallVec::new(), fingerprint),
-            hash_result::<R>,
-        )
-    }
-
     fn with_task_impl<'a, C, A, R>(
         &self,
         key: DepNode,
@@ -524,7 +502,7 @@ pub fn serialize(&self) -> SerializedDepGraph {
             edge_list_indices.push((start, end));
         }
 
-        debug_assert!(edge_list_data.len() <= ::std::u32::MAX as usize);
+        debug_assert!(edge_list_data.len() <= u32::MAX as usize);
         debug_assert_eq!(edge_list_data.len(), total_edge_count);
 
         SerializedDepGraph { nodes, fingerprints, edge_list_indices, edge_list_data }
@@ -676,18 +654,25 @@ fn try_mark_previous_green<'tcx>(
                             continue;
                         }
                     } else {
+                        // FIXME: This match is just a workaround for incremental bugs and should
+                        // be removed. https://github.com/rust-lang/rust/issues/62649 is one such
+                        // bug that must be fixed before removing this.
                         match dep_dep_node.kind {
-                            DepKind::Hir | DepKind::HirBody | DepKind::CrateMetadata => {
+                            DepKind::hir_owner
+                            | DepKind::hir_owner_items
+                            | DepKind::CrateMetadata => {
                                 if let Some(def_id) = dep_dep_node.extract_def_id(tcx) {
                                     if def_id_corresponds_to_hir_dep_node(tcx, def_id) {
-                                        // The `DefPath` has corresponding node,
-                                        // and that node should have been marked
-                                        // either red or green in `data.colors`.
-                                        bug!(
-                                            "DepNode {:?} should have been \
+                                        if dep_dep_node.kind == DepKind::CrateMetadata {
+                                            // The `DefPath` has corresponding node,
+                                            // and that node should have been marked
+                                            // either red or green in `data.colors`.
+                                            bug!(
+                                                "DepNode {:?} should have been \
                                              pre-marked as red or green but wasn't.",
-                                            dep_dep_node
-                                        );
+                                                dep_dep_node
+                                            );
+                                        }
                                     } else {
                                         // This `DefPath` does not have a
                                         // corresponding `DepNode` (e.g. a
@@ -917,7 +902,7 @@ fn next_virtual_depnode_index(&self) -> DepNodeIndex {
 
 fn def_id_corresponds_to_hir_dep_node(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
     let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
-    def_id.index == hir_id.owner
+    def_id.index == hir_id.owner.local_def_index
 }
 
 /// A "work product" is an intermediate result that we save into the
index eb377d20f5963cc17ee6f2c8f5e948721e8f67ae..1fbd90743f402e764212ab57b8cfdca142f4f36b 100644 (file)
@@ -6,7 +6,8 @@
 mod safe;
 mod serialized;
 
-pub use self::dep_node::{label_strs, DepConstructor, DepKind, DepNode, RecoverKey, WorkProductId};
+pub(crate) use self::dep_node::DepNodeParams;
+pub use self::dep_node::{label_strs, DepConstructor, DepKind, DepNode, WorkProductId};
 pub use self::graph::WorkProductFileKind;
 pub use self::graph::{hash_result, DepGraph, DepNodeColor, DepNodeIndex, TaskDeps, WorkProduct};
 pub use self::prev::PreviousDepGraph;
index 618f9a018d1e7ac2a0cf1bac9e43e83e9bd99a7f..7024e86f95d06a169dabcd2675c3cad5d6b7cb03 100644 (file)
@@ -51,7 +51,7 @@ fn is_fn_like(&self) -> bool {
 impl MaybeFnLike for hir::ImplItem<'_> {
     fn is_fn_like(&self) -> bool {
         match self.kind {
-            hir::ImplItemKind::Method(..) => true,
+            hir::ImplItemKind::Fn(..) => true,
             _ => false,
         }
     }
@@ -60,7 +60,7 @@ fn is_fn_like(&self) -> bool {
 impl MaybeFnLike for hir::TraitItem<'_> {
     fn is_fn_like(&self) -> bool {
         match self.kind {
-            hir::TraitItemKind::Method(_, hir::TraitMethod::Provided(_)) => true,
+            hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)) => true,
             _ => false,
         }
     }
@@ -239,13 +239,13 @@ fn handle<A, I, M, C>(self, item_fn: I, method: M, closure: C) -> A
                 _ => bug!("item FnLikeNode that is not fn-like"),
             },
             Node::TraitItem(ti) => match ti.kind {
-                hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body)) => {
+                hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => {
                     method(ti.hir_id, ti.ident, sig, None, body, ti.span, &ti.attrs)
                 }
                 _ => bug!("trait method FnLikeNode that is not fn-like"),
             },
             Node::ImplItem(ii) => match ii.kind {
-                hir::ImplItemKind::Method(ref sig, body) => {
+                hir::ImplItemKind::Fn(ref sig, body) => {
                     method(ii.hir_id, ii.ident, sig, Some(&ii.vis), body, ii.span, &ii.attrs)
                 }
                 _ => bug!("impl method FnLikeNode that is not fn-like"),
index ebd335ab35504ee919c37916977b8a44e00ea036..de0cc61118fed9abe8142d2b1359c85287a9d956 100644 (file)
@@ -1,19 +1,19 @@
-use crate::dep_graph::{DepGraph, DepKind, DepNode, DepNodeIndex};
+use crate::arena::Arena;
 use crate::hir::map::definitions::{self, DefPathHash};
-use crate::hir::map::{Entry, HirEntryMap, Map};
+use crate::hir::map::{Entry, HirOwnerData, Map};
+use crate::hir::{HirItem, HirOwner, HirOwnerItems};
 use crate::ich::StableHashingContext;
 use crate::middle::cstore::CrateStore;
-use rustc_ast::ast::NodeId;
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::svh::Svh;
 use rustc_hir as hir;
 use rustc_hir::def_id::CRATE_DEF_INDEX;
-use rustc_hir::def_id::{CrateNum, DefIndex, LOCAL_CRATE};
+use rustc_hir::def_id::{LocalDefId, LOCAL_CRATE};
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::*;
-use rustc_index::vec::IndexVec;
+use rustc_index::vec::{Idx, IndexVec};
 use rustc_session::{CrateDisambiguator, Session};
 use rustc_span::source_map::SourceMap;
 use rustc_span::{Span, Symbol, DUMMY_SP};
 
 /// A visitor that walks over the HIR and collects `Node`s into a HIR map.
 pub(super) struct NodeCollector<'a, 'hir> {
+    arena: &'hir Arena<'hir>,
+
     /// The crate
     krate: &'hir Crate<'hir>,
 
     /// Source map
     source_map: &'a SourceMap,
 
-    /// The node map
-    map: HirEntryMap<'hir>,
+    map: IndexVec<LocalDefId, HirOwnerData<'hir>>,
+
     /// The parent of this node
     parent_node: hir::HirId,
 
-    // These fields keep track of the currently relevant DepNodes during
-    // the visitor's traversal.
-    current_dep_node_owner: DefIndex,
-    current_signature_dep_index: DepNodeIndex,
-    current_full_dep_index: DepNodeIndex,
-    currently_in_body: bool,
+    current_dep_node_owner: LocalDefId,
 
-    dep_graph: &'a DepGraph,
     definitions: &'a definitions::Definitions,
-    hir_to_node_id: &'a FxHashMap<HirId, NodeId>,
 
     hcx: StableHashingContext<'a>,
 
-    // We are collecting `DepNode::HirBody` hashes here so we can compute the
-    // crate hash from then later on.
+    // We are collecting HIR hashes here so we can compute the
+    // crate hash from them later on.
     hir_body_nodes: Vec<(DefPathHash, Fingerprint)>,
 }
 
-fn input_dep_node_and_hash(
-    dep_graph: &DepGraph,
+fn insert_vec_map<K: Idx, V: Clone>(map: &mut IndexVec<K, Option<V>>, k: K, v: V) {
+    let i = k.index();
+    let len = map.len();
+    if i >= len {
+        map.extend(repeat(None).take(i - len + 1));
+    }
+    map[k] = Some(v);
+}
+
+fn hash(
     hcx: &mut StableHashingContext<'_>,
-    dep_node: DepNode,
     input: impl for<'a> HashStable<StableHashingContext<'a>>,
-) -> (DepNodeIndex, Fingerprint) {
-    let dep_node_index = dep_graph.input_task(dep_node, &mut *hcx, &input).1;
-
-    let hash = if dep_graph.is_fully_enabled() {
-        dep_graph.fingerprint_of(dep_node_index)
-    } else {
-        let mut stable_hasher = StableHasher::new();
-        input.hash_stable(hcx, &mut stable_hasher);
-        stable_hasher.finish()
-    };
-
-    (dep_node_index, hash)
+) -> Fingerprint {
+    let mut stable_hasher = StableHasher::new();
+    input.hash_stable(hcx, &mut stable_hasher);
+    stable_hasher.finish()
 }
 
-fn alloc_hir_dep_nodes(
-    dep_graph: &DepGraph,
+fn hash_body(
     hcx: &mut StableHashingContext<'_>,
     def_path_hash: DefPathHash,
     item_like: impl for<'a> HashStable<StableHashingContext<'a>>,
     hir_body_nodes: &mut Vec<(DefPathHash, Fingerprint)>,
-) -> (DepNodeIndex, DepNodeIndex) {
-    let sig = dep_graph
-        .input_task(
-            def_path_hash.to_dep_node(DepKind::Hir),
-            &mut *hcx,
-            HirItemLike { item_like: &item_like, hash_bodies: false },
-        )
-        .1;
-    let (full, hash) = input_dep_node_and_hash(
-        dep_graph,
-        hcx,
-        def_path_hash.to_dep_node(DepKind::HirBody),
-        HirItemLike { item_like: &item_like, hash_bodies: true },
-    );
+) -> Fingerprint {
+    let hash = hash(hcx, HirItemLike { item_like: &item_like });
     hir_body_nodes.push((def_path_hash, hash));
-    (sig, full)
+    hash
 }
 
 fn upstream_crates(cstore: &dyn CrateStore) -> Vec<(Symbol, Fingerprint, Svh)> {
@@ -112,24 +93,19 @@ fn upstream_crates(cstore: &dyn CrateStore) -> Vec<(Symbol, Fingerprint, Svh)> {
 impl<'a, 'hir> NodeCollector<'a, 'hir> {
     pub(super) fn root(
         sess: &'a Session,
+        arena: &'hir Arena<'hir>,
         krate: &'hir Crate<'hir>,
-        dep_graph: &'a DepGraph,
         definitions: &'a definitions::Definitions,
-        hir_to_node_id: &'a FxHashMap<HirId, NodeId>,
         mut hcx: StableHashingContext<'a>,
     ) -> NodeCollector<'a, 'hir> {
-        let root_mod_def_path_hash = definitions.def_path_hash(CRATE_DEF_INDEX);
+        let root_mod_def_path_hash =
+            definitions.def_path_hash(LocalDefId { local_def_index: CRATE_DEF_INDEX });
 
         let mut hir_body_nodes = Vec::new();
 
-        // Allocate `DepNode`s for the root module.
-        let (root_mod_sig_dep_index, root_mod_full_dep_index) = {
+        let hash = {
             let Crate {
-                ref module,
-                // Crate attributes are not copied over to the root `Mod`, so hash
-                // them explicitly here.
-                ref attrs,
-                span,
+                ref item,
                 // These fields are handled separately:
                 exported_macros: _,
                 non_exported_macro_attrs: _,
@@ -143,45 +119,26 @@ pub(super) fn root(
                 proc_macros: _,
             } = *krate;
 
-            alloc_hir_dep_nodes(
-                dep_graph,
-                &mut hcx,
-                root_mod_def_path_hash,
-                (module, attrs, span),
-                &mut hir_body_nodes,
-            )
+            hash_body(&mut hcx, root_mod_def_path_hash, item, &mut hir_body_nodes)
         };
 
-        {
-            dep_graph.input_task(
-                DepNode::new_no_params(DepKind::AllLocalTraitImpls),
-                &mut hcx,
-                &krate.trait_impls,
-            );
-        }
-
         let mut collector = NodeCollector {
+            arena,
             krate,
             source_map: sess.source_map(),
-            map: IndexVec::from_elem_n(IndexVec::new(), definitions.def_index_count()),
             parent_node: hir::CRATE_HIR_ID,
-            current_signature_dep_index: root_mod_sig_dep_index,
-            current_full_dep_index: root_mod_full_dep_index,
-            current_dep_node_owner: CRATE_DEF_INDEX,
-            currently_in_body: false,
-            dep_graph,
+            current_dep_node_owner: LocalDefId { local_def_index: CRATE_DEF_INDEX },
             definitions,
-            hir_to_node_id,
             hcx,
             hir_body_nodes,
+            map: (0..definitions.def_index_count())
+                .map(|_| HirOwnerData { signature: None, with_bodies: None })
+                .collect(),
         };
         collector.insert_entry(
             hir::CRATE_HIR_ID,
-            Entry {
-                parent: hir::CRATE_HIR_ID,
-                dep_node: root_mod_sig_dep_index,
-                node: Node::Crate,
-            },
+            Entry { parent: hir::CRATE_HIR_ID, node: Node::Crate(&krate.item) },
+            hash,
         );
 
         collector
@@ -192,7 +149,13 @@ pub(super) fn finalize_and_compute_crate_hash(
         crate_disambiguator: CrateDisambiguator,
         cstore: &dyn CrateStore,
         commandline_args_hash: u64,
-    ) -> (HirEntryMap<'hir>, Svh) {
+    ) -> (IndexVec<LocalDefId, HirOwnerData<'hir>>, Svh) {
+        // Insert bodies into the map
+        for (id, body) in self.krate.bodies.iter() {
+            let bodies = &mut self.map[id.hir_id.owner].with_bodies.as_mut().unwrap().bodies;
+            assert!(bodies.insert(id.hir_id.local_id, body).is_none());
+        }
+
         self.hir_body_nodes.sort_unstable_by_key(|bn| bn.0);
 
         let node_hashes = self.hir_body_nodes.iter().fold(
@@ -213,7 +176,7 @@ pub(super) fn finalize_and_compute_crate_hash(
             .source_map
             .files()
             .iter()
-            .filter(|source_file| CrateNum::from_u32(source_file.crate_of_origin) == LOCAL_CRATE)
+            .filter(|source_file| source_file.cnum == LOCAL_CRATE)
             .map(|source_file| source_file.name_hash)
             .collect();
 
@@ -232,37 +195,58 @@ pub(super) fn finalize_and_compute_crate_hash(
         (self.map, svh)
     }
 
-    fn insert_entry(&mut self, id: HirId, entry: Entry<'hir>) {
-        debug!("hir_map: {:?} => {:?}", id, entry);
-        let local_map = &mut self.map[id.owner];
+    fn insert_entry(&mut self, id: HirId, entry: Entry<'hir>, hash: Fingerprint) {
         let i = id.local_id.as_u32() as usize;
-        let len = local_map.len();
-        if i >= len {
-            local_map.extend(repeat(None).take(i - len + 1));
+
+        let arena = self.arena;
+
+        let data = &mut self.map[id.owner];
+
+        if data.with_bodies.is_none() {
+            data.with_bodies = Some(arena.alloc(HirOwnerItems {
+                hash,
+                items: IndexVec::new(),
+                bodies: FxHashMap::default(),
+            }));
+        }
+
+        let items = data.with_bodies.as_mut().unwrap();
+
+        if i == 0 {
+            // Overwrite the dummy hash with the real HIR owner hash.
+            items.hash = hash;
+
+            // FIXME: feature(impl_trait_in_bindings) broken and trigger this assert
+            //assert!(data.signature.is_none());
+
+            data.signature =
+                Some(self.arena.alloc(HirOwner { parent: entry.parent, node: entry.node }));
+        } else {
+            assert_eq!(entry.parent.owner, id.owner);
+            insert_vec_map(
+                &mut items.items,
+                id.local_id,
+                HirItem { parent: entry.parent.local_id, node: entry.node },
+            );
         }
-        local_map[id.local_id] = Some(entry);
     }
 
     fn insert(&mut self, span: Span, hir_id: HirId, node: Node<'hir>) {
-        let entry = Entry {
-            parent: self.parent_node,
-            dep_node: if self.currently_in_body {
-                self.current_full_dep_index
-            } else {
-                self.current_signature_dep_index
-            },
-            node,
-        };
+        self.insert_with_hash(span, hir_id, node, Fingerprint::ZERO)
+    }
+
+    fn insert_with_hash(&mut self, span: Span, hir_id: HirId, node: Node<'hir>, hash: Fingerprint) {
+        let entry = Entry { parent: self.parent_node, node };
 
         // Make sure that the DepNode of some node coincides with the HirId
         // owner of that node.
         if cfg!(debug_assertions) {
-            let node_id = self.hir_to_node_id[&hir_id];
+            let node_id = self.definitions.hir_to_node_id(hir_id);
             assert_eq!(self.definitions.node_to_hir_id(node_id), hir_id);
 
             if hir_id.owner != self.current_dep_node_owner {
-                let node_str = match self.definitions.opt_def_index(node_id) {
-                    Some(def_index) => self.definitions.def_path(def_index).to_string_no_crate(),
+                let node_str = match self.definitions.opt_local_def_id(node_id) {
+                    Some(def_id) => self.definitions.def_path(def_id).to_string_no_crate(),
                     None => format!("{:?}", node),
                 };
 
@@ -287,7 +271,7 @@ fn insert(&mut self, span: Span, hir_id: HirId, node: Node<'hir>) {
             }
         }
 
-        self.insert_entry(hir_id, entry);
+        self.insert_entry(hir_id, entry, hash);
     }
 
     fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_node_id: HirId, f: F) {
@@ -299,37 +283,22 @@ fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_node_id: HirId, f: F) {
 
     fn with_dep_node_owner<
         T: for<'b> HashStable<StableHashingContext<'b>>,
-        F: FnOnce(&mut Self),
+        F: FnOnce(&mut Self, Fingerprint),
     >(
         &mut self,
-        dep_node_owner: DefIndex,
+        dep_node_owner: LocalDefId,
         item_like: &T,
         f: F,
     ) {
         let prev_owner = self.current_dep_node_owner;
-        let prev_signature_dep_index = self.current_signature_dep_index;
-        let prev_full_dep_index = self.current_full_dep_index;
-        let prev_in_body = self.currently_in_body;
 
         let def_path_hash = self.definitions.def_path_hash(dep_node_owner);
 
-        let (signature_dep_index, full_dep_index) = alloc_hir_dep_nodes(
-            self.dep_graph,
-            &mut self.hcx,
-            def_path_hash,
-            item_like,
-            &mut self.hir_body_nodes,
-        );
-        self.current_signature_dep_index = signature_dep_index;
-        self.current_full_dep_index = full_dep_index;
+        let hash = hash_body(&mut self.hcx, def_path_hash, item_like, &mut self.hir_body_nodes);
 
         self.current_dep_node_owner = dep_node_owner;
-        self.currently_in_body = false;
-        f(self);
-        self.currently_in_body = prev_in_body;
+        f(self, hash);
         self.current_dep_node_owner = prev_owner;
-        self.current_full_dep_index = prev_full_dep_index;
-        self.current_signature_dep_index = prev_signature_dep_index;
     }
 }
 
@@ -340,7 +309,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
     /// deep walking so that we walk nested items in the context of
     /// their outer items.
 
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, Self::Map> {
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
         panic!("`visit_nested_xxx` must be manually implemented in this visitor");
     }
 
@@ -358,10 +327,7 @@ fn visit_nested_impl_item(&mut self, item_id: ImplItemId) {
     }
 
     fn visit_nested_body(&mut self, id: BodyId) {
-        let prev_in_body = self.currently_in_body;
-        self.currently_in_body = true;
         self.visit_body(self.krate.body(id));
-        self.currently_in_body = prev_in_body;
     }
 
     fn visit_param(&mut self, param: &'hir Param<'hir>) {
@@ -376,10 +342,10 @@ fn visit_item(&mut self, i: &'hir Item<'hir>) {
         debug!("visit_item: {:?}", i);
         debug_assert_eq!(
             i.hir_id.owner,
-            self.definitions.opt_def_index(self.hir_to_node_id[&i.hir_id]).unwrap()
+            self.definitions.opt_local_def_id(self.definitions.hir_to_node_id(i.hir_id)).unwrap()
         );
-        self.with_dep_node_owner(i.hir_id.owner, i, |this| {
-            this.insert(i.span, i.hir_id, Node::Item(i));
+        self.with_dep_node_owner(i.hir_id.owner, i, |this, hash| {
+            this.insert_with_hash(i.span, i.hir_id, Node::Item(i), hash);
             this.with_parent(i.hir_id, |this| {
                 if let ItemKind::Struct(ref struct_def, _) = i.kind {
                     // If this is a tuple or unit-like struct, register the constructor.
@@ -408,10 +374,10 @@ fn visit_generic_param(&mut self, param: &'hir GenericParam<'hir>) {
     fn visit_trait_item(&mut self, ti: &'hir TraitItem<'hir>) {
         debug_assert_eq!(
             ti.hir_id.owner,
-            self.definitions.opt_def_index(self.hir_to_node_id[&ti.hir_id]).unwrap()
+            self.definitions.opt_local_def_id(self.definitions.hir_to_node_id(ti.hir_id)).unwrap()
         );
-        self.with_dep_node_owner(ti.hir_id.owner, ti, |this| {
-            this.insert(ti.span, ti.hir_id, Node::TraitItem(ti));
+        self.with_dep_node_owner(ti.hir_id.owner, ti, |this, hash| {
+            this.insert_with_hash(ti.span, ti.hir_id, Node::TraitItem(ti), hash);
 
             this.with_parent(ti.hir_id, |this| {
                 intravisit::walk_trait_item(this, ti);
@@ -422,10 +388,10 @@ fn visit_trait_item(&mut self, ti: &'hir TraitItem<'hir>) {
     fn visit_impl_item(&mut self, ii: &'hir ImplItem<'hir>) {
         debug_assert_eq!(
             ii.hir_id.owner,
-            self.definitions.opt_def_index(self.hir_to_node_id[&ii.hir_id]).unwrap()
+            self.definitions.opt_local_def_id(self.definitions.hir_to_node_id(ii.hir_id)).unwrap()
         );
-        self.with_dep_node_owner(ii.hir_id.owner, ii, |this| {
-            this.insert(ii.span, ii.hir_id, Node::ImplItem(ii));
+        self.with_dep_node_owner(ii.hir_id.owner, ii, |this, hash| {
+            this.insert_with_hash(ii.span, ii.hir_id, Node::ImplItem(ii), hash);
 
             this.with_parent(ii.hir_id, |this| {
                 intravisit::walk_impl_item(this, ii);
@@ -541,11 +507,13 @@ fn visit_vis(&mut self, visibility: &'hir Visibility<'hir>) {
     }
 
     fn visit_macro_def(&mut self, macro_def: &'hir MacroDef<'hir>) {
-        let node_id = self.hir_to_node_id[&macro_def.hir_id];
-        let def_index = self.definitions.opt_def_index(node_id).unwrap();
-
-        self.with_dep_node_owner(def_index, macro_def, |this| {
-            this.insert(macro_def.span, macro_def.hir_id, Node::MacroDef(macro_def));
+        self.with_dep_node_owner(macro_def.hir_id.owner, macro_def, |this, hash| {
+            this.insert_with_hash(
+                macro_def.span,
+                macro_def.hir_id,
+                Node::MacroDef(macro_def),
+                hash,
+            );
         });
     }
 
@@ -584,11 +552,8 @@ fn visit_impl_item_ref(&mut self, ii: &'hir ImplItemRef<'hir>) {
     }
 }
 
-// This is a wrapper structure that allows determining if span values within
-// the wrapped item should be hashed or not.
 struct HirItemLike<T> {
     item_like: T,
-    hash_bodies: bool,
 }
 
 impl<'hir, T> HashStable<StableHashingContext<'hir>> for HirItemLike<T>
@@ -596,7 +561,7 @@ impl<'hir, T> HashStable<StableHashingContext<'hir>> for HirItemLike<T>
     T: HashStable<StableHashingContext<'hir>>,
 {
     fn hash_stable(&self, hcx: &mut StableHashingContext<'hir>, hasher: &mut StableHasher) {
-        hcx.while_hashing_hir_bodies(self.hash_bodies, |hcx| {
+        hcx.while_hashing_hir_bodies(true, |hcx| {
             self.item_like.hash_stable(hcx, hasher);
         });
     }
index 047ce8b8445fd5c24cc53f669bf62d80688a477c..aa4742ea891bb7e19580f139ddc67d327e74d0e4 100644 (file)
@@ -5,22 +5,21 @@
 //! expressions) that are mostly just leftovers.
 
 use rustc_ast::ast;
-use rustc_ast::node_id::NodeMap;
-use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::StableHasher;
 use rustc_hir as hir;
-use rustc_hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_index::vec::IndexVec;
 use rustc_session::CrateDisambiguator;
 use rustc_span::hygiene::ExpnId;
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
 
-use std::borrow::Borrow;
 use std::fmt::Write;
 use std::hash::Hash;
 
+pub use rustc_hir::def_id::DefPathHash;
+
 /// The `DefPathTable` maps `DefIndex`es to `DefKey`s and vice versa.
 /// Internally the `DefPathTable` holds a tree of `DefKey`s, where each `DefKey`
 /// stores the `DefIndex` of its parent.
@@ -78,21 +77,29 @@ pub fn size(&self) -> usize {
 #[derive(Clone, Default)]
 pub struct Definitions {
     table: DefPathTable,
-    node_to_def_index: NodeMap<DefIndex>,
-    def_index_to_node: IndexVec<DefIndex, ast::NodeId>,
-    pub(super) node_to_hir_id: IndexVec<ast::NodeId, hir::HirId>,
+
+    def_id_to_span: IndexVec<LocalDefId, Span>,
+
+    // FIXME(eddyb) don't go through `ast::NodeId` to convert between `HirId`
+    // and `LocalDefId` - ideally all `LocalDefId`s would be HIR owners.
+    node_id_to_def_id: FxHashMap<ast::NodeId, LocalDefId>,
+    def_id_to_node_id: IndexVec<LocalDefId, ast::NodeId>,
+
+    pub(super) node_id_to_hir_id: IndexVec<ast::NodeId, hir::HirId>,
+    /// The reverse mapping of `node_id_to_hir_id`.
+    pub(super) hir_id_to_node_id: FxHashMap<hir::HirId, ast::NodeId>,
+
     /// If `ExpnId` is an ID of some macro expansion,
     /// then `DefId` is the normal module (`mod`) in which the expanded macro was defined.
     parent_modules_of_macro_defs: FxHashMap<ExpnId, DefId>,
-    /// Item with a given `DefIndex` was defined during macro expansion with ID `ExpnId`.
-    expansions_that_defined: FxHashMap<DefIndex, ExpnId>,
-    next_disambiguator: FxHashMap<(DefIndex, DefPathData), u32>,
-    def_index_to_span: FxHashMap<DefIndex, Span>,
+    /// Item with a given `LocalDefId` was defined during macro expansion with ID `ExpnId`.
+    expansions_that_defined: FxHashMap<LocalDefId, ExpnId>,
+    next_disambiguator: FxHashMap<(LocalDefId, DefPathData), u32>,
     /// When collecting definitions from an AST fragment produced by a macro invocation `ExpnId`
     /// we know what parent node that fragment should be attached to thanks to this table.
-    invocation_parents: FxHashMap<ExpnId, DefIndex>,
+    invocation_parents: FxHashMap<ExpnId, LocalDefId>,
     /// Indices of unnamed struct or variant fields with unresolved attributes.
-    placeholder_field_indices: NodeMap<usize>,
+    placeholder_field_indices: FxHashMap<ast::NodeId, usize>,
 }
 
 /// A unique identifier that we can use to lookup a definition
@@ -192,7 +199,7 @@ pub fn make<FN>(krate: CrateNum, start_index: DefIndex, mut get_key: FN) -> DefP
             }
         }
         data.reverse();
-        DefPath { data: data, krate: krate }
+        DefPath { data, krate }
     }
 
     /// Returns a string representation of the `DefPath` without
@@ -282,28 +289,6 @@ pub enum DefPathData {
     ImplTrait,
 }
 
-#[derive(
-    Copy,
-    Clone,
-    Hash,
-    PartialEq,
-    Eq,
-    PartialOrd,
-    Ord,
-    Debug,
-    RustcEncodable,
-    RustcDecodable,
-    HashStable
-)]
-pub struct DefPathHash(pub Fingerprint);
-
-impl Borrow<Fingerprint> for DefPathHash {
-    #[inline]
-    fn borrow(&self) -> &Fingerprint {
-        &self.0
-    }
-}
-
 impl Definitions {
     pub fn def_path_table(&self) -> &DefPathTable {
         &self.table
@@ -314,13 +299,13 @@ pub fn def_index_count(&self) -> usize {
         self.table.index_to_key.len()
     }
 
-    pub fn def_key(&self, index: DefIndex) -> DefKey {
-        self.table.def_key(index)
+    pub fn def_key(&self, id: LocalDefId) -> DefKey {
+        self.table.def_key(id.local_def_index)
     }
 
     #[inline(always)]
-    pub fn def_path_hash(&self, index: DefIndex) -> DefPathHash {
-        self.table.def_path_hash(index)
+    pub fn def_path_hash(&self, id: LocalDefId) -> DefPathHash {
+        self.table.def_path_hash(id.local_def_index)
     }
 
     /// Returns the path from the crate root to `index`. The root
@@ -328,29 +313,27 @@ pub fn def_path_hash(&self, index: DefIndex) -> DefPathHash {
     /// empty vector for the crate root). For an inlined item, this
     /// will be the path of the item in the external crate (but the
     /// path will begin with the path to the external crate).
-    pub fn def_path(&self, index: DefIndex) -> DefPath {
-        DefPath::make(LOCAL_CRATE, index, |p| self.def_key(p))
-    }
-
-    #[inline]
-    pub fn opt_def_index(&self, node: ast::NodeId) -> Option<DefIndex> {
-        self.node_to_def_index.get(&node).copied()
+    pub fn def_path(&self, id: LocalDefId) -> DefPath {
+        DefPath::make(LOCAL_CRATE, id.local_def_index, |index| {
+            self.def_key(LocalDefId { local_def_index: index })
+        })
     }
 
     #[inline]
-    pub fn opt_local_def_id(&self, node: ast::NodeId) -> Option<DefId> {
-        self.opt_def_index(node).map(DefId::local)
+    pub fn opt_local_def_id(&self, node: ast::NodeId) -> Option<LocalDefId> {
+        self.node_id_to_def_id.get(&node).copied()
     }
 
+    // FIXME(eddyb) this function can and should return `LocalDefId`.
     #[inline]
     pub fn local_def_id(&self, node: ast::NodeId) -> DefId {
-        self.opt_local_def_id(node).unwrap()
+        self.opt_local_def_id(node).unwrap().to_def_id()
     }
 
     #[inline]
     pub fn as_local_node_id(&self, def_id: DefId) -> Option<ast::NodeId> {
-        if def_id.krate == LOCAL_CRATE {
-            let node_id = self.def_index_to_node[def_id.index];
+        if let Some(def_id) = def_id.as_local() {
+            let node_id = self.def_id_to_node_id[def_id];
             if node_id != ast::DUMMY_NODE_ID {
                 return Some(node_id);
             }
@@ -360,34 +343,36 @@ pub fn as_local_node_id(&self, def_id: DefId) -> Option<ast::NodeId> {
 
     #[inline]
     pub fn as_local_hir_id(&self, def_id: DefId) -> Option<hir::HirId> {
-        if def_id.krate == LOCAL_CRATE {
-            let hir_id = self.def_index_to_hir_id(def_id.index);
+        if let Some(def_id) = def_id.as_local() {
+            let hir_id = self.local_def_id_to_hir_id(def_id);
             if hir_id != hir::DUMMY_HIR_ID { Some(hir_id) } else { None }
         } else {
             None
         }
     }
 
+    // FIXME(eddyb) rename to `hir_id_to_node_id`.
+    #[inline]
+    pub fn hir_to_node_id(&self, hir_id: hir::HirId) -> ast::NodeId {
+        self.hir_id_to_node_id[&hir_id]
+    }
+
+    // FIXME(eddyb) rename to `node_id_to_hir_id`.
     #[inline]
     pub fn node_to_hir_id(&self, node_id: ast::NodeId) -> hir::HirId {
-        self.node_to_hir_id[node_id]
+        self.node_id_to_hir_id[node_id]
     }
 
     #[inline]
-    pub fn def_index_to_hir_id(&self, def_index: DefIndex) -> hir::HirId {
-        let node_id = self.def_index_to_node[def_index];
-        self.node_to_hir_id[node_id]
+    pub fn local_def_id_to_hir_id(&self, id: LocalDefId) -> hir::HirId {
+        let node_id = self.def_id_to_node_id[id];
+        self.node_id_to_hir_id[node_id]
     }
 
-    /// Retrieves the span of the given `DefId` if `DefId` is in the local crate, the span exists
-    /// and it's not `DUMMY_SP`.
+    /// Retrieves the span of the given `DefId` if `DefId` is in the local crate.
     #[inline]
     pub fn opt_span(&self, def_id: DefId) -> Option<Span> {
-        if def_id.krate == LOCAL_CRATE {
-            self.def_index_to_span.get(&def_id.index).copied()
-        } else {
-            None
-        }
+        if let Some(def_id) = def_id.as_local() { Some(self.def_id_to_span[def_id]) } else { None }
     }
 
     /// Adds a root definition (no parent) and a few other reserved definitions.
@@ -395,7 +380,7 @@ pub fn create_root_def(
         &mut self,
         crate_name: &str,
         crate_disambiguator: CrateDisambiguator,
-    ) -> DefIndex {
+    ) -> LocalDefId {
         let key = DefKey {
             parent: None,
             disambiguated_data: DisambiguatedDefPathData {
@@ -408,36 +393,38 @@ pub fn create_root_def(
         let def_path_hash = key.compute_stable_hash(parent_hash);
 
         // Create the definition.
-        let root_index = self.table.allocate(key, def_path_hash);
-        assert_eq!(root_index, CRATE_DEF_INDEX);
-        assert!(self.def_index_to_node.is_empty());
-        self.def_index_to_node.push(ast::CRATE_NODE_ID);
-        self.node_to_def_index.insert(ast::CRATE_NODE_ID, root_index);
-        self.set_invocation_parent(ExpnId::root(), root_index);
+        let root = LocalDefId { local_def_index: self.table.allocate(key, def_path_hash) };
+        assert_eq!(root.local_def_index, CRATE_DEF_INDEX);
+
+        assert_eq!(self.def_id_to_node_id.push(ast::CRATE_NODE_ID), root);
+        assert_eq!(self.def_id_to_span.push(rustc_span::DUMMY_SP), root);
 
-        root_index
+        self.node_id_to_def_id.insert(ast::CRATE_NODE_ID, root);
+        self.set_invocation_parent(ExpnId::root(), root);
+
+        root
     }
 
     /// Adds a definition with a parent definition.
     pub fn create_def_with_parent(
         &mut self,
-        parent: DefIndex,
+        parent: LocalDefId,
         node_id: ast::NodeId,
         data: DefPathData,
         expn_id: ExpnId,
         span: Span,
-    ) -> DefIndex {
+    ) -> LocalDefId {
         debug!(
             "create_def_with_parent(parent={:?}, node_id={:?}, data={:?})",
             parent, node_id, data
         );
 
         assert!(
-            !self.node_to_def_index.contains_key(&node_id),
+            !self.node_id_to_def_id.contains_key(&node_id),
             "adding a def'n for node-id {:?} and data {:?} but a previous def'n exists: {:?}",
             node_id,
             data,
-            self.table.def_key(self.node_to_def_index[&node_id])
+            self.table.def_key(self.node_id_to_def_id[&node_id].local_def_index),
         );
 
         // The root node must be created with `create_root_def()`.
@@ -452,52 +439,55 @@ pub fn create_def_with_parent(
         };
 
         let key = DefKey {
-            parent: Some(parent),
+            parent: Some(parent.local_def_index),
             disambiguated_data: DisambiguatedDefPathData { data, disambiguator },
         };
 
-        let parent_hash = self.table.def_path_hash(parent);
+        let parent_hash = self.table.def_path_hash(parent.local_def_index);
         let def_path_hash = key.compute_stable_hash(parent_hash);
 
         debug!("create_def_with_parent: after disambiguation, key = {:?}", key);
 
         // Create the definition.
-        let index = self.table.allocate(key, def_path_hash);
-        assert_eq!(index.index(), self.def_index_to_node.len());
-        self.def_index_to_node.push(node_id);
+        let def_id = LocalDefId { local_def_index: self.table.allocate(key, def_path_hash) };
+
+        assert_eq!(self.def_id_to_node_id.push(node_id), def_id);
+        assert_eq!(self.def_id_to_span.push(span), def_id);
 
-        // Some things for which we allocate `DefIndex`es don't correspond to
+        // Some things for which we allocate `LocalDefId`s don't correspond to
         // anything in the AST, so they don't have a `NodeId`. For these cases
-        // we don't need a mapping from `NodeId` to `DefIndex`.
+        // we don't need a mapping from `NodeId` to `LocalDefId`.
         if node_id != ast::DUMMY_NODE_ID {
-            debug!("create_def_with_parent: def_index_to_node[{:?} <-> {:?}", index, node_id);
-            self.node_to_def_index.insert(node_id, index);
+            debug!("create_def_with_parent: def_id_to_node_id[{:?}] <-> {:?}", def_id, node_id);
+            self.node_id_to_def_id.insert(node_id, def_id);
         }
 
         if expn_id != ExpnId::root() {
-            self.expansions_that_defined.insert(index, expn_id);
-        }
-
-        // The span is added if it isn't dummy.
-        if !span.is_dummy() {
-            self.def_index_to_span.insert(index, span);
+            self.expansions_that_defined.insert(def_id, expn_id);
         }
 
-        index
+        def_id
     }
 
     /// Initializes the `ast::NodeId` to `HirId` mapping once it has been generated during
     /// AST to HIR lowering.
     pub fn init_node_id_to_hir_id_mapping(&mut self, mapping: IndexVec<ast::NodeId, hir::HirId>) {
         assert!(
-            self.node_to_hir_id.is_empty(),
+            self.node_id_to_hir_id.is_empty(),
             "trying to initialize `NodeId` -> `HirId` mapping twice"
         );
-        self.node_to_hir_id = mapping;
+        self.node_id_to_hir_id = mapping;
+
+        // Build the reverse mapping of `node_id_to_hir_id`.
+        self.hir_id_to_node_id = self
+            .node_id_to_hir_id
+            .iter_enumerated()
+            .map(|(node_id, &hir_id)| (hir_id, node_id))
+            .collect();
     }
 
-    pub fn expansion_that_defined(&self, index: DefIndex) -> ExpnId {
-        self.expansions_that_defined.get(&index).copied().unwrap_or(ExpnId::root())
+    pub fn expansion_that_defined(&self, id: LocalDefId) -> ExpnId {
+        self.expansions_that_defined.get(&id).copied().unwrap_or(ExpnId::root())
     }
 
     pub fn parent_module_of_macro_def(&self, expn_id: ExpnId) -> DefId {
@@ -508,13 +498,13 @@ pub fn add_parent_module_of_macro_def(&mut self, expn_id: ExpnId, module: DefId)
         self.parent_modules_of_macro_defs.insert(expn_id, module);
     }
 
-    pub fn invocation_parent(&self, invoc_id: ExpnId) -> DefIndex {
+    pub fn invocation_parent(&self, invoc_id: ExpnId) -> LocalDefId {
         self.invocation_parents[&invoc_id]
     }
 
-    pub fn set_invocation_parent(&mut self, invoc_id: ExpnId, parent: DefIndex) {
+    pub fn set_invocation_parent(&mut self, invoc_id: ExpnId, parent: LocalDefId) {
         let old_parent = self.invocation_parents.insert(invoc_id, parent);
-        assert!(old_parent.is_none(), "parent `DefIndex` is reset for an invocation");
+        assert!(old_parent.is_none(), "parent `LocalDefId` is reset for an invocation");
     }
 
     pub fn placeholder_field_index(&self, node_id: ast::NodeId) -> usize {
index a4f9193c0eb649ed535b3fad399150158b027373..e3386a2a910ed31596b5bb6cd4b3d2702ea46d2a 100644 (file)
@@ -1,18 +1,20 @@
 use crate::hir::map::Map;
+use crate::ty::TyCtxt;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::sync::{par_iter, Lock, ParallelIterator};
 use rustc_hir as hir;
-use rustc_hir::def_id::{DefId, DefIndex, CRATE_DEF_INDEX};
+use rustc_hir::def_id::{LocalDefId, CRATE_DEF_INDEX};
 use rustc_hir::intravisit;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_hir::{HirId, ItemLocalId};
 
-pub fn check_crate(hir_map: &Map<'_>, sess: &rustc_session::Session) {
-    hir_map.dep_graph.assert_ignored();
+pub fn check_crate(tcx: TyCtxt<'_>) {
+    tcx.dep_graph.assert_ignored();
 
     let errors = Lock::new(Vec::new());
+    let hir_map = tcx.hir();
 
-    par_iter(&hir_map.krate.modules).for_each(|(module_id, _)| {
+    par_iter(&hir_map.krate().modules).for_each(|(module_id, _)| {
         let local_def_id = hir_map.local_def_id(*module_id);
         hir_map.visit_item_likes_in_module(
             local_def_id,
@@ -24,27 +26,27 @@ pub fn check_crate(hir_map: &Map<'_>, sess: &rustc_session::Session) {
 
     if !errors.is_empty() {
         let message = errors.iter().fold(String::new(), |s1, s2| s1 + "\n" + s2);
-        sess.delay_span_bug(rustc_span::DUMMY_SP, &message);
+        tcx.sess.delay_span_bug(rustc_span::DUMMY_SP, &message);
     }
 }
 
 struct HirIdValidator<'a, 'hir> {
-    hir_map: &'a Map<'hir>,
-    owner_def_index: Option<DefIndex>,
+    hir_map: Map<'hir>,
+    owner: Option<LocalDefId>,
     hir_ids_seen: FxHashSet<ItemLocalId>,
     errors: &'a Lock<Vec<String>>,
 }
 
 struct OuterVisitor<'a, 'hir> {
-    hir_map: &'a Map<'hir>,
+    hir_map: Map<'hir>,
     errors: &'a Lock<Vec<String>>,
 }
 
 impl<'a, 'hir> OuterVisitor<'a, 'hir> {
-    fn new_inner_visitor(&self, hir_map: &'a Map<'hir>) -> HirIdValidator<'a, 'hir> {
+    fn new_inner_visitor(&self, hir_map: Map<'hir>) -> HirIdValidator<'a, 'hir> {
         HirIdValidator {
             hir_map,
-            owner_def_index: None,
+            owner: None,
             hir_ids_seen: Default::default(),
             errors: self.errors,
         }
@@ -76,12 +78,12 @@ fn error(&self, f: impl FnOnce() -> String) {
     }
 
     fn check<F: FnOnce(&mut HirIdValidator<'a, 'hir>)>(&mut self, hir_id: HirId, walk: F) {
-        assert!(self.owner_def_index.is_none());
-        let owner_def_index = self.hir_map.local_def_id(hir_id).index;
-        self.owner_def_index = Some(owner_def_index);
+        assert!(self.owner.is_none());
+        let owner = self.hir_map.local_def_id(hir_id).expect_local();
+        self.owner = Some(owner);
         walk(self);
 
-        if owner_def_index == CRATE_DEF_INDEX {
+        if owner.local_def_index == CRATE_DEF_INDEX {
             return;
         }
 
@@ -103,27 +105,26 @@ fn check<F: FnOnce(&mut HirIdValidator<'a, 'hir>)>(&mut self, hir_id: HirId, wal
             let mut missing_items = Vec::with_capacity(missing.len());
 
             for local_id in missing {
-                let hir_id =
-                    HirId { owner: owner_def_index, local_id: ItemLocalId::from_u32(local_id) };
+                let hir_id = HirId { owner, local_id: ItemLocalId::from_u32(local_id) };
 
                 trace!("missing hir id {:#?}", hir_id);
 
                 missing_items.push(format!(
-                    "[local_id: {}, node:{}]",
+                    "[local_id: {}, owner: {}]",
                     local_id,
-                    self.hir_map.node_to_string(hir_id)
+                    self.hir_map.def_path(owner).to_string_no_crate()
                 ));
             }
             self.error(|| {
                 format!(
                     "ItemLocalIds not assigned densely in {}. \
                 Max ItemLocalId = {}, missing IDs = {:?}; seens IDs = {:?}",
-                    self.hir_map.def_path(DefId::local(owner_def_index)).to_string_no_crate(),
+                    self.hir_map.def_path(owner).to_string_no_crate(),
                     max,
                     missing_items,
                     self.hir_ids_seen
                         .iter()
-                        .map(|&local_id| HirId { owner: owner_def_index, local_id })
+                        .map(|&local_id| HirId { owner, local_id })
                         .map(|h| format!("({:?} {})", h, self.hir_map.node_to_string(h)))
                         .collect::<Vec<_>>()
                 )
@@ -135,12 +136,12 @@ fn check<F: FnOnce(&mut HirIdValidator<'a, 'hir>)>(&mut self, hir_id: HirId, wal
 impl<'a, 'hir> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> {
     type Map = Map<'hir>;
 
-    fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, Self::Map> {
+    fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
         intravisit::NestedVisitorMap::OnlyBodies(self.hir_map)
     }
 
     fn visit_id(&mut self, hir_id: HirId) {
-        let owner = self.owner_def_index.expect("no owner_def_index");
+        let owner = self.owner.expect("no owner");
 
         if hir_id == hir::DUMMY_HIR_ID {
             self.error(|| {
@@ -157,8 +158,8 @@ fn visit_id(&mut self, hir_id: HirId) {
                 format!(
                     "HirIdValidator: The recorded owner of {} is {} instead of {}",
                     self.hir_map.node_to_string(hir_id),
-                    self.hir_map.def_path(DefId::local(hir_id.owner)).to_string_no_crate(),
-                    self.hir_map.def_path(DefId::local(owner)).to_string_no_crate()
+                    self.hir_map.def_path(hir_id.owner).to_string_no_crate(),
+                    self.hir_map.def_path(owner).to_string_no_crate()
                 )
             });
         }
index 4f7c4153ea173e773f6787188497e4830a441eac..36cb19c6c37c727f8c30adb1bf28adbd2a134c24 100644 (file)
@@ -3,14 +3,13 @@
     DefKey, DefPath, DefPathData, DefPathHash, Definitions, DisambiguatedDefPathData,
 };
 
-use crate::dep_graph::{DepGraph, DepKind, DepNode, DepNodeIndex};
-use crate::middle::cstore::CrateStoreDyn;
+use crate::hir::{HirOwner, HirOwnerItems};
 use crate::ty::query::Providers;
+use crate::ty::TyCtxt;
 use rustc_ast::ast::{self, Name, NodeId};
-use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::svh::Svh;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::{DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX};
+use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
 use rustc_hir::intravisit;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_hir::print::Nested;
 mod collector;
 pub mod definitions;
 mod hir_id_validator;
+pub use hir_id_validator::check_crate;
 
 /// Represents an entry and its parent `HirId`.
 #[derive(Copy, Clone, Debug)]
 pub struct Entry<'hir> {
     parent: HirId,
-    dep_node: DepNodeIndex,
     node: Node<'hir>,
 }
 
 impl<'hir> Entry<'hir> {
     fn parent_node(self) -> Option<HirId> {
         match self.node {
-            Node::Crate | Node::MacroDef(_) => None,
+            Node::Crate(_) | Node::MacroDef(_) => None,
             _ => Some(self.parent),
         }
     }
+}
 
-    fn fn_decl(&self) -> Option<&'hir FnDecl<'hir>> {
-        match self.node {
-            Node::Item(ref item) => match item.kind {
-                ItemKind::Fn(ref sig, _, _) => Some(&sig.decl),
-                _ => None,
-            },
-
-            Node::TraitItem(ref item) => match item.kind {
-                TraitItemKind::Method(ref sig, _) => Some(&sig.decl),
-                _ => None,
-            },
+fn fn_decl<'hir>(node: Node<'hir>) -> Option<&'hir FnDecl<'hir>> {
+    match node {
+        Node::Item(ref item) => match item.kind {
+            ItemKind::Fn(ref sig, _, _) => Some(&sig.decl),
+            _ => None,
+        },
 
-            Node::ImplItem(ref item) => match item.kind {
-                ImplItemKind::Method(ref sig, _) => Some(&sig.decl),
-                _ => None,
-            },
+        Node::TraitItem(ref item) => match item.kind {
+            TraitItemKind::Fn(ref sig, _) => Some(&sig.decl),
+            _ => None,
+        },
 
-            Node::Expr(ref expr) => match expr.kind {
-                ExprKind::Closure(_, ref fn_decl, ..) => Some(fn_decl),
-                _ => None,
-            },
+        Node::ImplItem(ref item) => match item.kind {
+            ImplItemKind::Fn(ref sig, _) => Some(&sig.decl),
+            _ => None,
+        },
 
+        Node::Expr(ref expr) => match expr.kind {
+            ExprKind::Closure(_, ref fn_decl, ..) => Some(fn_decl),
             _ => None,
-        }
-    }
+        },
 
-    fn fn_sig(&self) -> Option<&'hir FnSig<'hir>> {
-        match &self.node {
-            Node::Item(item) => match &item.kind {
-                ItemKind::Fn(sig, _, _) => Some(sig),
-                _ => None,
-            },
+        _ => None,
+    }
+}
 
-            Node::TraitItem(item) => match &item.kind {
-                TraitItemKind::Method(sig, _) => Some(sig),
-                _ => None,
-            },
+fn fn_sig<'hir>(node: Node<'hir>) -> Option<&'hir FnSig<'hir>> {
+    match &node {
+        Node::Item(item) => match &item.kind {
+            ItemKind::Fn(sig, _, _) => Some(sig),
+            _ => None,
+        },
 
-            Node::ImplItem(item) => match &item.kind {
-                ImplItemKind::Method(sig, _) => Some(sig),
-                _ => None,
-            },
+        Node::TraitItem(item) => match &item.kind {
+            TraitItemKind::Fn(sig, _) => Some(sig),
+            _ => None,
+        },
 
+        Node::ImplItem(item) => match &item.kind {
+            ImplItemKind::Fn(sig, _) => Some(sig),
             _ => None,
-        }
-    }
+        },
 
-    fn associated_body(self) -> Option<BodyId> {
-        match self.node {
-            Node::Item(item) => match item.kind {
-                ItemKind::Const(_, body) | ItemKind::Static(.., body) | ItemKind::Fn(.., body) => {
-                    Some(body)
-                }
-                _ => None,
-            },
+        _ => None,
+    }
+}
 
-            Node::TraitItem(item) => match item.kind {
-                TraitItemKind::Const(_, Some(body))
-                | TraitItemKind::Method(_, TraitMethod::Provided(body)) => Some(body),
-                _ => None,
-            },
+fn associated_body<'hir>(node: Node<'hir>) -> Option<BodyId> {
+    match node {
+        Node::Item(item) => match item.kind {
+            ItemKind::Const(_, body) | ItemKind::Static(.., body) | ItemKind::Fn(.., body) => {
+                Some(body)
+            }
+            _ => None,
+        },
 
-            Node::ImplItem(item) => match item.kind {
-                ImplItemKind::Const(_, body) | ImplItemKind::Method(_, body) => Some(body),
-                _ => None,
-            },
+        Node::TraitItem(item) => match item.kind {
+            TraitItemKind::Const(_, Some(body)) | TraitItemKind::Fn(_, TraitFn::Provided(body)) => {
+                Some(body)
+            }
+            _ => None,
+        },
 
-            Node::AnonConst(constant) => Some(constant.body),
+        Node::ImplItem(item) => match item.kind {
+            ImplItemKind::Const(_, body) | ImplItemKind::Fn(_, body) => Some(body),
+            _ => None,
+        },
 
-            Node::Expr(expr) => match expr.kind {
-                ExprKind::Closure(.., body, _, _) => Some(body),
-                _ => None,
-            },
+        Node::AnonConst(constant) => Some(constant.body),
 
+        Node::Expr(expr) => match expr.kind {
+            ExprKind::Closure(.., body, _, _) => Some(body),
             _ => None,
-        }
-    }
+        },
 
-    fn is_body_owner(self, hir_id: HirId) -> bool {
-        match self.associated_body() {
-            Some(b) => b.hir_id == hir_id,
-            None => false,
-        }
+        _ => None,
     }
 }
 
-/// This type is effectively a `HashMap<HirId, Entry<'hir>>`,
-/// but it is implemented as 2 layers of arrays.
-/// - first we have `A = IndexVec<DefIndex, B>` mapping `DefIndex`s to an inner value
-/// - which is `B = IndexVec<ItemLocalId, Option<Entry<'hir>>` which gives you the `Entry`.
-pub(super) type HirEntryMap<'hir> = IndexVec<DefIndex, IndexVec<ItemLocalId, Option<Entry<'hir>>>>;
-
-/// Represents a mapping from `NodeId`s to AST elements and their parent `NodeId`s.
-#[derive(Clone)]
-pub struct Map<'hir> {
-    krate: &'hir Crate<'hir>,
+fn is_body_owner<'hir>(node: Node<'hir>, hir_id: HirId) -> bool {
+    match associated_body(node) {
+        Some(b) => b.hir_id == hir_id,
+        None => false,
+    }
+}
 
-    pub dep_graph: DepGraph,
+pub(super) struct HirOwnerData<'hir> {
+    pub(super) signature: Option<&'hir HirOwner<'hir>>,
+    pub(super) with_bodies: Option<&'hir mut HirOwnerItems<'hir>>,
+}
 
+pub struct IndexedHir<'hir> {
     /// The SVH of the local crate.
     pub crate_hash: Svh,
 
-    map: HirEntryMap<'hir>,
-
-    definitions: Definitions,
+    pub(super) map: IndexVec<LocalDefId, HirOwnerData<'hir>>,
+}
 
-    /// The reverse mapping of `node_to_hir_id`.
-    hir_to_node_id: FxHashMap<HirId, NodeId>,
+#[derive(Copy, Clone)]
+pub struct Map<'hir> {
+    pub(super) tcx: TyCtxt<'hir>,
 }
 
 /// An iterator that walks up the ancestor tree of a given `HirId`.
@@ -186,53 +179,28 @@ fn next(&mut self) -> Option<Self::Item> {
 }
 
 impl<'hir> Map<'hir> {
-    /// This is used internally in the dependency tracking system.
-    /// Use the `krate` method to ensure your dependency on the
-    /// crate is tracked.
-    pub fn untracked_krate(&self) -> &Crate<'hir> {
-        &self.krate
+    pub fn krate(&self) -> &'hir Crate<'hir> {
+        self.tcx.hir_crate(LOCAL_CRATE)
     }
 
     #[inline]
-    fn lookup(&self, id: HirId) -> Option<&Entry<'hir>> {
-        let local_map = self.map.get(id.owner)?;
-        local_map.get(id.local_id)?.as_ref()
-    }
-
-    /// Registers a read in the dependency graph of the AST node with
-    /// the given `id`. This needs to be called each time a public
-    /// function returns the HIR for a node -- in other words, when it
-    /// "reveals" the content of a node to the caller (who might not
-    /// otherwise have had access to those contents, and hence needs a
-    /// read recorded). If the function just returns a DefId or
-    /// HirId, no actual content was returned, so no read is needed.
-    pub fn read(&self, hir_id: HirId) {
-        if let Some(entry) = self.lookup(hir_id) {
-            self.dep_graph.read_index(entry.dep_node);
-        } else {
-            bug!("called `HirMap::read()` with invalid `HirId`: {:?}", hir_id)
-        }
+    pub fn definitions(&self) -> &'hir Definitions {
+        &self.tcx.definitions
     }
 
-    #[inline]
-    pub fn definitions(&self) -> &Definitions {
-        &self.definitions
-    }
-
-    pub fn def_key(&self, def_id: DefId) -> DefKey {
-        assert!(def_id.is_local());
-        self.definitions.def_key(def_id.index)
+    pub fn def_key(&self, def_id: LocalDefId) -> DefKey {
+        self.tcx.definitions.def_key(def_id)
     }
 
     pub fn def_path_from_hir_id(&self, id: HirId) -> Option<DefPath> {
-        self.opt_local_def_id(id).map(|def_id| self.def_path(def_id))
+        self.opt_local_def_id(id).map(|def_id| self.def_path(def_id.expect_local()))
     }
 
-    pub fn def_path(&self, def_id: DefId) -> DefPath {
-        assert!(def_id.is_local());
-        self.definitions.def_path(def_id.index)
+    pub fn def_path(&self, def_id: LocalDefId) -> DefPath {
+        self.tcx.definitions.def_path(def_id)
     }
 
+    // FIXME(eddyb) this function can and should return `LocalDefId`.
     #[inline]
     pub fn local_def_id_from_node_id(&self, node: NodeId) -> DefId {
         self.opt_local_def_id_from_node_id(node).unwrap_or_else(|| {
@@ -245,6 +213,7 @@ pub fn local_def_id_from_node_id(&self, node: NodeId) -> DefId {
         })
     }
 
+    // FIXME(eddyb) this function can and should return `LocalDefId`.
     #[inline]
     pub fn local_def_id(&self, hir_id: HirId) -> DefId {
         self.opt_local_def_id(hir_id).unwrap_or_else(|| {
@@ -259,46 +228,41 @@ pub fn local_def_id(&self, hir_id: HirId) -> DefId {
     #[inline]
     pub fn opt_local_def_id(&self, hir_id: HirId) -> Option<DefId> {
         let node_id = self.hir_to_node_id(hir_id);
-        self.definitions.opt_local_def_id(node_id)
+        self.opt_local_def_id_from_node_id(node_id)
     }
 
     #[inline]
     pub fn opt_local_def_id_from_node_id(&self, node: NodeId) -> Option<DefId> {
-        self.definitions.opt_local_def_id(node)
+        Some(self.tcx.definitions.opt_local_def_id(node)?.to_def_id())
     }
 
     #[inline]
     pub fn as_local_node_id(&self, def_id: DefId) -> Option<NodeId> {
-        self.definitions.as_local_node_id(def_id)
+        self.tcx.definitions.as_local_node_id(def_id)
     }
 
     #[inline]
     pub fn as_local_hir_id(&self, def_id: DefId) -> Option<HirId> {
-        self.definitions.as_local_hir_id(def_id)
+        self.tcx.definitions.as_local_hir_id(def_id)
     }
 
     #[inline]
     pub fn hir_to_node_id(&self, hir_id: HirId) -> NodeId {
-        self.hir_to_node_id[&hir_id]
+        self.tcx.definitions.hir_to_node_id(hir_id)
     }
 
     #[inline]
     pub fn node_to_hir_id(&self, node_id: NodeId) -> HirId {
-        self.definitions.node_to_hir_id(node_id)
-    }
-
-    #[inline]
-    pub fn def_index_to_hir_id(&self, def_index: DefIndex) -> HirId {
-        self.definitions.def_index_to_hir_id(def_index)
+        self.tcx.definitions.node_to_hir_id(node_id)
     }
 
     #[inline]
     pub fn local_def_id_to_hir_id(&self, def_id: LocalDefId) -> HirId {
-        self.definitions.def_index_to_hir_id(def_id.to_def_id().index)
+        self.tcx.definitions.local_def_id_to_hir_id(def_id)
     }
 
     pub fn def_kind(&self, hir_id: HirId) -> Option<DefKind> {
-        let node = if let Some(node) = self.find(hir_id) { node } else { return None };
+        let node = self.find(hir_id)?;
 
         Some(match node {
             Node::Item(item) => match item.kind {
@@ -326,21 +290,20 @@ pub fn def_kind(&self, hir_id: HirId) -> Option<DefKind> {
             },
             Node::TraitItem(item) => match item.kind {
                 TraitItemKind::Const(..) => DefKind::AssocConst,
-                TraitItemKind::Method(..) => DefKind::Method,
+                TraitItemKind::Fn(..) => DefKind::AssocFn,
                 TraitItemKind::Type(..) => DefKind::AssocTy,
             },
             Node::ImplItem(item) => match item.kind {
                 ImplItemKind::Const(..) => DefKind::AssocConst,
-                ImplItemKind::Method(..) => DefKind::Method,
+                ImplItemKind::Fn(..) => DefKind::AssocFn,
                 ImplItemKind::TyAlias(..) => DefKind::AssocTy,
                 ImplItemKind::OpaqueTy(..) => DefKind::AssocOpaqueTy,
             },
             Node::Variant(_) => DefKind::Variant,
             Node::Ctor(variant_data) => {
                 // FIXME(eddyb) is this even possible, if we have a `Node::Ctor`?
-                if variant_data.ctor_hir_id().is_none() {
-                    return None;
-                }
+                variant_data.ctor_hir_id()?;
+
                 let ctor_of = match self.find(self.get_parent_node(hir_id)) {
                     Some(Node::Item(..)) => def::CtorOf::Struct,
                     Some(Node::Variant(..)) => def::CtorOf::Variant,
@@ -363,7 +326,7 @@ pub fn def_kind(&self, hir_id: HirId) -> Option<DefKind> {
             | Node::Lifetime(_)
             | Node::Visibility(_)
             | Node::Block(_)
-            | Node::Crate => return None,
+            | Node::Crate(_) => return None,
             Node::MacroDef(_) => DefKind::Macro(MacroKind::Bang),
             Node::GenericParam(param) => match param.kind {
                 GenericParamKind::Lifetime { .. } => return None,
@@ -374,54 +337,58 @@ pub fn def_kind(&self, hir_id: HirId) -> Option<DefKind> {
     }
 
     fn find_entry(&self, id: HirId) -> Option<Entry<'hir>> {
-        self.lookup(id).cloned()
+        Some(self.get_entry(id))
     }
 
-    pub fn item(&self, id: HirId) -> &'hir Item<'hir> {
-        self.read(id);
+    fn get_entry(&self, id: HirId) -> Entry<'hir> {
+        if id.local_id == ItemLocalId::from_u32(0) {
+            let owner = self.tcx.hir_owner(id.owner);
+            Entry { parent: owner.parent, node: owner.node }
+        } else {
+            let owner = self.tcx.hir_owner_items(id.owner);
+            let item = owner.items[id.local_id].as_ref().unwrap();
+            Entry { parent: HirId { owner: id.owner, local_id: item.parent }, node: item.node }
+        }
+    }
 
-        // N.B., intentionally bypass `self.krate()` so that we
-        // do not trigger a read of the whole krate here
-        self.krate.item(id)
+    pub fn item(&self, id: HirId) -> &'hir Item<'hir> {
+        match self.find(id).unwrap() {
+            Node::Item(item) => item,
+            _ => bug!(),
+        }
     }
 
     pub fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem<'hir> {
-        self.read(id.hir_id);
-
-        // N.B., intentionally bypass `self.krate()` so that we
-        // do not trigger a read of the whole krate here
-        self.krate.trait_item(id)
+        match self.find(id.hir_id).unwrap() {
+            Node::TraitItem(item) => item,
+            _ => bug!(),
+        }
     }
 
     pub fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem<'hir> {
-        self.read(id.hir_id);
-
-        // N.B., intentionally bypass `self.krate()` so that we
-        // do not trigger a read of the whole krate here
-        self.krate.impl_item(id)
+        match self.find(id.hir_id).unwrap() {
+            Node::ImplItem(item) => item,
+            _ => bug!(),
+        }
     }
 
     pub fn body(&self, id: BodyId) -> &'hir Body<'hir> {
-        self.read(id.hir_id);
-
-        // N.B., intentionally bypass `self.krate()` so that we
-        // do not trigger a read of the whole krate here
-        self.krate.body(id)
+        self.tcx.hir_owner_items(id.hir_id.owner).bodies.get(&id.hir_id.local_id).unwrap()
     }
 
     pub fn fn_decl_by_hir_id(&self, hir_id: HirId) -> Option<&'hir FnDecl<'hir>> {
-        if let Some(entry) = self.find_entry(hir_id) {
-            entry.fn_decl()
+        if let Some(node) = self.find(hir_id) {
+            fn_decl(node)
         } else {
-            bug!("no entry for hir_id `{}`", hir_id)
+            bug!("no node for hir_id `{}`", hir_id)
         }
     }
 
     pub fn fn_sig_by_hir_id(&self, hir_id: HirId) -> Option<&'hir FnSig<'hir>> {
-        if let Some(entry) = self.find_entry(hir_id) {
-            entry.fn_sig()
+        if let Some(node) = self.find(hir_id) {
+            fn_sig(node)
         } else {
-            bug!("no entry for hir_id `{}`", hir_id)
+            bug!("no node for hir_id `{}`", hir_id)
         }
     }
 
@@ -430,10 +397,11 @@ pub fn fn_sig_by_hir_id(&self, hir_id: HirId) -> Option<&'hir FnSig<'hir>> {
     /// item (possibly associated), a closure, or a `hir::AnonConst`.
     pub fn body_owner(&self, BodyId { hir_id }: BodyId) -> HirId {
         let parent = self.get_parent_node(hir_id);
-        assert!(self.lookup(parent).map_or(false, |e| e.is_body_owner(hir_id)));
+        assert!(self.find(parent).map_or(false, |n| is_body_owner(n, hir_id)));
         parent
     }
 
+    // FIXME(eddyb) this function can and should return `LocalDefId`.
     pub fn body_owner_def_id(&self, id: BodyId) -> DefId {
         self.local_def_id(self.body_owner(id))
     }
@@ -441,14 +409,8 @@ pub fn body_owner_def_id(&self, id: BodyId) -> DefId {
     /// Given a `HirId`, returns the `BodyId` associated with it,
     /// if the node is a body owner, otherwise returns `None`.
     pub fn maybe_body_owned_by(&self, hir_id: HirId) -> Option<BodyId> {
-        if let Some(entry) = self.find_entry(hir_id) {
-            if self.dep_graph.is_fully_enabled() {
-                let hir_id_owner = hir_id.owner;
-                let def_path_hash = self.definitions.def_path_hash(hir_id_owner);
-                self.dep_graph.read(def_path_hash.to_dep_node(DepKind::HirBody));
-            }
-
-            entry.associated_body()
+        if let Some(node) = self.find(hir_id) {
+            associated_body(node)
         } else {
             bug!("no entry for id `{}`", hir_id)
         }
@@ -473,8 +435,8 @@ pub fn body_owner_kind(&self, id: HirId) -> BodyOwnerKind {
             | Node::AnonConst(_) => BodyOwnerKind::Const,
             Node::Ctor(..)
             | Node::Item(&Item { kind: ItemKind::Fn(..), .. })
-            | Node::TraitItem(&TraitItem { kind: TraitItemKind::Method(..), .. })
-            | Node::ImplItem(&ImplItem { kind: ImplItemKind::Method(..), .. }) => BodyOwnerKind::Fn,
+            | Node::TraitItem(&TraitItem { kind: TraitItemKind::Fn(..), .. })
+            | Node::ImplItem(&ImplItem { kind: ImplItemKind::Fn(..), .. }) => BodyOwnerKind::Fn,
             Node::Item(&Item { kind: ItemKind::Static(_, m, _), .. }) => BodyOwnerKind::Static(m),
             Node::Expr(&Expr { kind: ExprKind::Closure(..), .. }) => BodyOwnerKind::Closure,
             node => bug!("{:#?} is not a body node", node),
@@ -500,29 +462,24 @@ pub fn ty_param_name(&self, id: HirId) -> Name {
     }
 
     pub fn trait_impls(&self, trait_did: DefId) -> &'hir [HirId] {
-        self.dep_graph.read(DepNode::new_no_params(DepKind::AllLocalTraitImpls));
-
-        // N.B., intentionally bypass `self.krate()` so that we
-        // do not trigger a read of the whole krate here
-        self.krate.trait_impls.get(&trait_did).map_or(&[], |xs| &xs[..])
+        self.tcx.all_local_trait_impls(LOCAL_CRATE).get(&trait_did).map_or(&[], |xs| &xs[..])
     }
 
     /// Gets the attributes on the crate. This is preferable to
     /// invoking `krate.attrs` because it registers a tighter
     /// dep-graph access.
     pub fn krate_attrs(&self) -> &'hir [ast::Attribute] {
-        let def_path_hash = self.definitions.def_path_hash(CRATE_DEF_INDEX);
-
-        self.dep_graph.read(def_path_hash.to_dep_node(DepKind::Hir));
-        &self.krate.attrs
+        match self.get_entry(CRATE_HIR_ID).node {
+            Node::Crate(item) => item.attrs,
+            _ => bug!(),
+        }
     }
 
     pub fn get_module(&self, module: DefId) -> (&'hir Mod<'hir>, Span, HirId) {
         let hir_id = self.as_local_hir_id(module).unwrap();
-        self.read(hir_id);
-        match self.find_entry(hir_id).unwrap().node {
+        match self.get_entry(hir_id).node {
             Node::Item(&Item { span, kind: ItemKind::Mod(ref m), .. }) => (m, span, hir_id),
-            Node::Crate => (&self.krate.module, self.krate.span, hir_id),
+            Node::Crate(item) => (&item.module, item.span, hir_id),
             node => panic!("not a module: {:?}", node),
         }
     }
@@ -531,15 +488,7 @@ pub fn visit_item_likes_in_module<V>(&self, module: DefId, visitor: &mut V)
     where
         V: ItemLikeVisitor<'hir>,
     {
-        let hir_id = self.as_local_hir_id(module).unwrap();
-
-        // Read the module so we'll be re-executed if new items
-        // appear immediately under in the module. If some new item appears
-        // in some nested item in the module, we'll be re-executed due to reads
-        // in the expect_* calls the loops below
-        self.read(hir_id);
-
-        let module = &self.krate.modules[&hir_id];
+        let module = self.tcx.hir_module_items(module.expect_local());
 
         for id in &module.items {
             visitor.visit_item(self.expect_item(*id));
@@ -556,12 +505,11 @@ pub fn visit_item_likes_in_module<V>(&self, module: DefId, visitor: &mut V)
 
     /// Retrieves the `Node` corresponding to `id`, panicking if it cannot be found.
     pub fn get(&self, id: HirId) -> Node<'hir> {
-        // read recorded by `find`
         self.find(id).unwrap_or_else(|| bug!("couldn't find hir id {} in the HIR map", id))
     }
 
     pub fn get_if_local(&self, id: DefId) -> Option<Node<'hir>> {
-        self.as_local_hir_id(id).map(|id| self.get(id)) // read recorded by `get`
+        self.as_local_hir_id(id).map(|id| self.get(id))
     }
 
     pub fn get_generics(&self, id: DefId) -> Option<&'hir Generics<'hir>> {
@@ -585,13 +533,8 @@ pub fn get_generics(&self, id: DefId) -> Option<&'hir Generics<'hir>> {
 
     /// Retrieves the `Node` corresponding to `id`, returning `None` if cannot be found.
     pub fn find(&self, hir_id: HirId) -> Option<Node<'hir>> {
-        let result = self
-            .find_entry(hir_id)
-            .and_then(|entry| if let Node::Crate = entry.node { None } else { Some(entry.node) });
-        if result.is_some() {
-            self.read(hir_id);
-        }
-        result
+        let node = self.get_entry(hir_id).node;
+        if let Node::Crate(..) = node { None } else { Some(node) }
     }
 
     /// Similar to `get_parent`; returns the parent HIR Id, or just `hir_id` if there
@@ -605,13 +548,7 @@ pub fn find(&self, hir_id: HirId) -> Option<Node<'hir>> {
     /// from a node to the root of the HIR (unless you get back the same ID here,
     /// which can happen if the ID is not in the map itself or is just weird).
     pub fn get_parent_node(&self, hir_id: HirId) -> HirId {
-        if self.dep_graph.is_fully_enabled() {
-            let hir_id_owner = hir_id.owner;
-            let def_path_hash = self.definitions.def_path_hash(hir_id_owner);
-            self.dep_graph.read(def_path_hash.to_dep_node(DepKind::HirBody));
-        }
-
-        self.find_entry(hir_id).and_then(|x| x.parent_node()).unwrap_or(hir_id)
+        self.get_entry(hir_id).parent_node().unwrap_or(hir_id)
     }
 
     /// Returns an iterator for the nodes in the ancestor tree of the `current_id`
@@ -654,11 +591,11 @@ pub fn is_const_context(&self, hir_id: HirId) -> bool {
         }
     }
 
-    /// Wether `hir_id` corresponds to a `mod` or a crate.
+    /// Whether `hir_id` corresponds to a `mod` or a crate.
     pub fn is_hir_id_module(&self, hir_id: HirId) -> bool {
-        match self.lookup(hir_id) {
-            Some(Entry { node: Node::Item(Item { kind: ItemKind::Mod(_), .. }), .. })
-            | Some(Entry { node: Node::Crate, .. }) => true,
+        match self.get_entry(hir_id) {
+            Entry { node: Node::Item(Item { kind: ItemKind::Mod(_), .. }), .. }
+            | Entry { node: Node::Crate(..), .. } => true,
             _ => false,
         }
     }
@@ -735,7 +672,7 @@ pub fn get_return_block(&self, id: HirId) -> Option<HirId> {
     pub fn get_parent_item(&self, hir_id: HirId) -> HirId {
         for (hir_id, node) in self.parent_iter(hir_id) {
             match node {
-                Node::Crate
+                Node::Crate(_)
                 | Node::Item(_)
                 | Node::ForeignItem(_)
                 | Node::TraitItem(_)
@@ -801,11 +738,11 @@ pub fn get_enclosing_scope(&self, hir_id: HirId) -> Option<HirId> {
                     _ => false,
                 },
                 Node::TraitItem(ti) => match ti.kind {
-                    TraitItemKind::Method(..) => true,
+                    TraitItemKind::Fn(..) => true,
                     _ => false,
                 },
                 Node::ImplItem(ii) => match ii.kind {
-                    ImplItemKind::Method(..) => true,
+                    ImplItemKind::Fn(..) => true,
                     _ => false,
                 },
                 Node::Block(_) => true,
@@ -837,6 +774,7 @@ pub fn get_defining_scope(&self, id: HirId) -> HirId {
         scope
     }
 
+    // FIXME(eddyb) this function can and should return `LocalDefId`.
     pub fn get_parent_did(&self, id: HirId) -> DefId {
         self.local_def_id(self.get_parent_item(id))
     }
@@ -848,7 +786,6 @@ pub fn get_foreign_abi(&self, hir_id: HirId) -> Abi {
                 node: Node::Item(Item { kind: ItemKind::ForeignMod(ref nm), .. }), ..
             } = entry
             {
-                self.read(hir_id); // reveals some of the content of a node
                 return nm.abi;
             }
         }
@@ -857,7 +794,6 @@ pub fn get_foreign_abi(&self, hir_id: HirId) -> Abi {
 
     pub fn expect_item(&self, id: HirId) -> &'hir Item<'hir> {
         match self.find(id) {
-            // read recorded by `find`
             Some(Node::Item(item)) => item,
             _ => bug!("expected item, found {}", self.node_to_string(id)),
         }
@@ -907,7 +843,6 @@ pub fn expect_foreign_item(&self, id: HirId) -> &'hir ForeignItem<'hir> {
 
     pub fn expect_expr(&self, id: HirId) -> &'hir Expr<'hir> {
         match self.find(id) {
-            // read recorded by find
             Some(Node::Expr(expr)) => expr,
             _ => bug!("expected expr, found {}", self.node_to_string(id)),
         }
@@ -939,7 +874,6 @@ pub fn name(&self, id: HirId) -> Name {
     /// Given a node ID, gets a list of attributes associated with the AST
     /// corresponding to the node-ID.
     pub fn attrs(&self, id: HirId) -> &'hir [ast::Attribute] {
-        self.read(id); // reveals attributes on the node
         let attrs = match self.find_entry(id).map(|entry| entry.node) {
             Some(Node::Param(a)) => Some(&a.attrs[..]),
             Some(Node::Local(l)) => Some(&l.attrs[..]),
@@ -956,53 +890,13 @@ pub fn attrs(&self, id: HirId) -> &'hir [ast::Attribute] {
             // Unit/tuple structs/variants take the attributes straight from
             // the struct/variant definition.
             Some(Node::Ctor(..)) => return self.attrs(self.get_parent_item(id)),
-            Some(Node::Crate) => Some(&self.krate.attrs[..]),
+            Some(Node::Crate(item)) => Some(&item.attrs[..]),
             _ => None,
         };
         attrs.unwrap_or(&[])
     }
 
-    /// Returns an iterator that yields all the hir ids in the map.
-    fn all_ids<'a>(&'a self) -> impl Iterator<Item = HirId> + 'a {
-        // This code is a bit awkward because the map is implemented as 2 levels of arrays,
-        // see the comment on `HirEntryMap`.
-        // Iterate over all the indices and return a reference to
-        // local maps and their index given that they exist.
-        self.map.iter_enumerated().flat_map(move |(owner, local_map)| {
-            // Iterate over each valid entry in the local map.
-            local_map.iter_enumerated().filter_map(move |(i, entry)| {
-                entry.map(move |_| {
-                    // Reconstruct the `HirId` based on the 3 indices we used to find it.
-                    HirId { owner, local_id: i }
-                })
-            })
-        })
-    }
-
-    /// Returns an iterator that yields the node id's with paths that
-    /// match `parts`.  (Requires `parts` is non-empty.)
-    ///
-    /// For example, if given `parts` equal to `["bar", "quux"]`, then
-    /// the iterator will produce node id's for items with paths
-    /// such as `foo::bar::quux`, `bar::quux`, `other::bar::quux`, and
-    /// any other such items it can find in the map.
-    pub fn nodes_matching_suffix<'a>(
-        &'a self,
-        parts: &'a [String],
-    ) -> impl Iterator<Item = NodeId> + 'a {
-        let nodes = NodesMatchingSuffix {
-            map: self,
-            item_name: parts.last().unwrap(),
-            in_which: &parts[..parts.len() - 1],
-        };
-
-        self.all_ids()
-            .filter(move |hir| nodes.matches_suffix(*hir))
-            .map(move |hir| self.hir_to_node_id(hir))
-    }
-
     pub fn span(&self, hir_id: HirId) -> Span {
-        self.read(hir_id); // reveals span from node
         match self.find_entry(hir_id).map(|entry| entry.node) {
             Some(Node::Param(param)) => param.span,
             Some(Node::Item(item)) => item.span,
@@ -1035,7 +929,7 @@ pub fn span(&self, hir_id: HirId) -> Span {
             Some(Node::Visibility(v)) => bug!("unexpected Visibility {:?}", v),
             Some(Node::Local(local)) => local.span,
             Some(Node::MacroDef(macro_def)) => macro_def.span,
-            Some(Node::Crate) => self.krate.span,
+            Some(Node::Crate(item)) => item.span,
             None => bug!("hir::map::Map::span: id not in map: {:?}", hir_id),
         }
     }
@@ -1083,82 +977,6 @@ fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem<'hir> {
     }
 }
 
-pub struct NodesMatchingSuffix<'a> {
-    map: &'a Map<'a>,
-    item_name: &'a String,
-    in_which: &'a [String],
-}
-
-impl<'a> NodesMatchingSuffix<'a> {
-    /// Returns `true` only if some suffix of the module path for parent
-    /// matches `self.in_which`.
-    ///
-    /// In other words: let `[x_0,x_1,...,x_k]` be `self.in_which`;
-    /// returns true if parent's path ends with the suffix
-    /// `x_0::x_1::...::x_k`.
-    fn suffix_matches(&self, parent: HirId) -> bool {
-        let mut cursor = parent;
-        for part in self.in_which.iter().rev() {
-            let (mod_id, mod_name) = match find_first_mod_parent(self.map, cursor) {
-                None => return false,
-                Some((node_id, name)) => (node_id, name),
-            };
-            if mod_name.as_str() != *part {
-                return false;
-            }
-            cursor = self.map.get_parent_item(mod_id);
-        }
-        return true;
-
-        // Finds the first mod in parent chain for `id`, along with
-        // that mod's name.
-        //
-        // If `id` itself is a mod named `m` with parent `p`, then
-        // returns `Some(id, m, p)`.  If `id` has no mod in its parent
-        // chain, then returns `None`.
-        fn find_first_mod_parent(map: &Map<'_>, mut id: HirId) -> Option<(HirId, Name)> {
-            loop {
-                if let Node::Item(item) = map.find(id)? {
-                    if item_is_mod(&item) {
-                        return Some((id, item.ident.name));
-                    }
-                }
-                let parent = map.get_parent_item(id);
-                if parent == id {
-                    return None;
-                }
-                id = parent;
-            }
-
-            fn item_is_mod(item: &Item<'_>) -> bool {
-                match item.kind {
-                    ItemKind::Mod(_) => true,
-                    _ => false,
-                }
-            }
-        }
-    }
-
-    // We are looking at some node `n` with a given name and parent
-    // id; do their names match what I am seeking?
-    fn matches_names(&self, parent_of_n: HirId, name: Name) -> bool {
-        name.as_str() == *self.item_name && self.suffix_matches(parent_of_n)
-    }
-
-    fn matches_suffix(&self, hir: HirId) -> bool {
-        let name = match self.map.find_entry(hir).map(|entry| entry.node) {
-            Some(Node::Item(n)) => n.name(),
-            Some(Node::ForeignItem(n)) => n.name(),
-            Some(Node::TraitItem(n)) => n.name(),
-            Some(Node::ImplItem(n)) => n.name(),
-            Some(Node::Variant(n)) => n.name(),
-            Some(Node::Field(n)) => n.name(),
-            _ => return false,
-        };
-        self.matches_names(self.map.get_parent_item(hir), name)
-    }
-}
-
 trait Named {
     fn name(&self) -> Name;
 }
@@ -1200,39 +1018,24 @@ fn name(&self) -> Name {
     }
 }
 
-pub fn map_crate<'hir>(
-    sess: &rustc_session::Session,
-    cstore: &CrateStoreDyn,
-    krate: &'hir Crate<'hir>,
-    dep_graph: DepGraph,
-    definitions: 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();
+pub(super) fn index_hir<'tcx>(tcx: TyCtxt<'tcx>, cnum: CrateNum) -> &'tcx IndexedHir<'tcx> {
+    assert_eq!(cnum, LOCAL_CRATE);
+
+    let _prof_timer = tcx.sess.prof.generic_activity("build_hir_map");
 
     let (map, crate_hash) = {
-        let hcx = crate::ich::StableHashingContext::new(sess, krate, &definitions, cstore);
+        let hcx = tcx.create_stable_hashing_context();
 
         let mut collector =
-            NodeCollector::root(sess, krate, &dep_graph, &definitions, &hir_to_node_id, hcx);
-        intravisit::walk_crate(&mut collector, krate);
+            NodeCollector::root(tcx.sess, &**tcx.arena, tcx.untracked_crate, &tcx.definitions, hcx);
+        intravisit::walk_crate(&mut collector, tcx.untracked_crate);
 
-        let crate_disambiguator = sess.local_crate_disambiguator();
-        let cmdline_args = sess.opts.dep_tracking_hash();
-        collector.finalize_and_compute_crate_hash(crate_disambiguator, cstore, cmdline_args)
+        let crate_disambiguator = tcx.sess.local_crate_disambiguator();
+        let cmdline_args = tcx.sess.opts.dep_tracking_hash();
+        collector.finalize_and_compute_crate_hash(crate_disambiguator, &*tcx.cstore, cmdline_args)
     };
 
-    let map = Map { krate, dep_graph, crate_hash, map, hir_to_node_id, definitions };
-
-    sess.time("validate_HIR_map", || {
-        hir_id_validator::check_crate(&map, sess);
-    });
+    let map = tcx.arena.alloc(IndexedHir { crate_hash, map });
 
     map
 }
@@ -1301,7 +1104,7 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId, include_id: bool) -> String {
             ImplItemKind::Const(..) => {
                 format!("assoc const {} in {}{}", ii.ident, path_str(), id_str)
             }
-            ImplItemKind::Method(..) => format!("method {} in {}{}", ii.ident, path_str(), id_str),
+            ImplItemKind::Fn(..) => format!("method {} in {}{}", ii.ident, path_str(), id_str),
             ImplItemKind::TyAlias(_) => {
                 format!("assoc type {} in {}{}", ii.ident, path_str(), id_str)
             }
@@ -1312,7 +1115,7 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId, include_id: bool) -> String {
         Some(Node::TraitItem(ti)) => {
             let kind = match ti.kind {
                 TraitItemKind::Const(..) => "assoc constant",
-                TraitItemKind::Method(..) => "trait method",
+                TraitItemKind::Fn(..) => "trait method",
                 TraitItemKind::Type(..) => "assoc type",
             };
 
@@ -1343,7 +1146,7 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId, include_id: bool) -> String {
         Some(Node::GenericParam(ref param)) => format!("generic_param {:?}{}", param, id_str),
         Some(Node::Visibility(ref vis)) => format!("visibility {:?}{}", vis, id_str),
         Some(Node::MacroDef(_)) => format!("macro {}{}", path_str(), id_str),
-        Some(Node::Crate) => String::from("root_crate"),
+        Some(Node::Crate(..)) => String::from("root_crate"),
         None => format!("unknown node{}", id_str),
     }
 }
index 1aa3b27bd1a5dfb418bdb590ce8dc1098fd70b13..0042b6a3bd42f65b09a9f242c206c991481aa955 100644 (file)
@@ -1,62 +1,86 @@
-//! HIR datatypes. See the [rustc guide] for more info.
+//! HIR datatypes. See the [rustc dev guide] for more info.
 //!
-//! [rustc guide]: https://rust-lang.github.io/rustc-guide/hir.html
+//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/hir.html
 
 pub mod exports;
 pub mod map;
 
+use crate::ich::StableHashingContext;
 use crate::ty::query::Providers;
 use crate::ty::TyCtxt;
-use rustc_hir::def_id::{DefId, LOCAL_CRATE};
-use rustc_hir::print;
-use rustc_hir::Crate;
+use rustc_data_structures::fingerprint::Fingerprint;
+use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_hir::def_id::{LocalDefId, LOCAL_CRATE};
+use rustc_hir::Body;
 use rustc_hir::HirId;
-use std::ops::Deref;
+use rustc_hir::ItemLocalId;
+use rustc_hir::Node;
+use rustc_index::vec::IndexVec;
 
-/// A wrapper type which allows you to access HIR.
-#[derive(Clone)]
-pub struct Hir<'tcx> {
-    tcx: TyCtxt<'tcx>,
-    map: &'tcx map::Map<'tcx>,
+pub struct HirOwner<'tcx> {
+    parent: HirId,
+    node: Node<'tcx>,
 }
 
-impl<'tcx> Hir<'tcx> {
-    pub fn krate(&self) -> &'tcx Crate<'tcx> {
-        self.tcx.hir_crate(LOCAL_CRATE)
+impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for HirOwner<'tcx> {
+    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
+        let HirOwner { parent, node } = self;
+        hcx.while_hashing_hir_bodies(false, |hcx| {
+            parent.hash_stable(hcx, hasher);
+            node.hash_stable(hcx, hasher);
+        });
     }
 }
 
-impl<'tcx> Deref for Hir<'tcx> {
-    type Target = &'tcx map::Map<'tcx>;
+#[derive(Clone)]
+pub struct HirItem<'tcx> {
+    parent: ItemLocalId,
+    node: Node<'tcx>,
+}
 
-    #[inline(always)]
-    fn deref(&self) -> &Self::Target {
-        &self.map
-    }
+pub struct HirOwnerItems<'tcx> {
+    hash: Fingerprint,
+    items: IndexVec<ItemLocalId, Option<HirItem<'tcx>>>,
+    bodies: FxHashMap<ItemLocalId, &'tcx Body<'tcx>>,
 }
 
-impl<'hir> print::PpAnn for Hir<'hir> {
-    fn nested(&self, state: &mut print::State<'_>, nested: print::Nested) {
-        self.map.nested(state, nested)
+impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for HirOwnerItems<'tcx> {
+    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
+        // We ignore the `items` and `bodies` fields since these refer to information included in
+        // `hash` which is hashed in the collector and used for the crate hash.
+        let HirOwnerItems { hash, items: _, bodies: _ } = *self;
+        hash.hash_stable(hcx, hasher);
     }
 }
 
 impl<'tcx> TyCtxt<'tcx> {
     #[inline(always)]
-    pub fn hir(self) -> Hir<'tcx> {
-        Hir { tcx: self, map: &self.hir_map }
+    pub fn hir(self) -> map::Map<'tcx> {
+        map::Map { tcx: self }
     }
 
-    pub fn parent_module(self, id: HirId) -> DefId {
-        self.parent_module_from_def_id(DefId::local(id.owner))
+    pub fn parent_module(self, id: HirId) -> LocalDefId {
+        self.parent_module_from_def_id(id.owner)
     }
 }
 
 pub fn provide(providers: &mut Providers<'_>) {
     providers.parent_module_from_def_id = |tcx, id| {
         let hir = tcx.hir();
-        hir.local_def_id(hir.get_module_parent_node(hir.as_local_hir_id(id).unwrap()))
+        hir.local_def_id(hir.get_module_parent_node(hir.as_local_hir_id(id.to_def_id()).unwrap()))
+            .expect_local()
+    };
+    providers.hir_crate = |tcx, _| tcx.untracked_crate;
+    providers.index_hir = map::index_hir;
+    providers.hir_module_items = |tcx, id| {
+        let hir = tcx.hir();
+        let module = hir.as_local_hir_id(id.to_def_id()).unwrap();
+        &tcx.untracked_crate.modules[&module]
+    };
+    providers.hir_owner = |tcx, id| tcx.index_hir(LOCAL_CRATE).map[id].signature.unwrap();
+    providers.hir_owner_items = |tcx, id| {
+        tcx.index_hir(LOCAL_CRATE).map[id].with_bodies.as_ref().map(|items| &**items).unwrap()
     };
-    providers.hir_crate = |tcx, _| tcx.hir_map.untracked_krate();
     map::provide(providers);
 }
index f28e26ef2c396b31f027785d2f84daf813db800c..ba3763f6ee0bd8818ede3eb30b8063bf1b7a5d5c 100644 (file)
@@ -1,16 +1,15 @@
-use crate::hir::map::definitions::Definitions;
-use crate::hir::map::DefPathHash;
+use crate::hir::map::definitions::{DefPathHash, Definitions};
 use crate::ich::{self, CachingSourceMapView};
 use crate::middle::cstore::CrateStore;
-use crate::session::Session;
 use crate::ty::{fast_reject, TyCtxt};
 
 use rustc_ast::ast;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::sync::Lrc;
 use rustc_hir as hir;
-use rustc_hir::def_id::{DefId, DefIndex};
+use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_session::Session;
 use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::Symbol;
 use rustc_span::{BytePos, SourceFile};
@@ -124,16 +123,16 @@ pub fn with_node_id_hashing_mode<F: FnOnce(&mut Self)>(
 
     #[inline]
     pub fn def_path_hash(&self, def_id: DefId) -> DefPathHash {
-        if def_id.is_local() {
-            self.definitions.def_path_hash(def_id.index)
+        if let Some(def_id) = def_id.as_local() {
+            self.local_def_path_hash(def_id)
         } else {
             self.cstore.def_path_hash(def_id)
         }
     }
 
     #[inline]
-    pub fn local_def_path_hash(&self, def_index: DefIndex) -> DefPathHash {
-        self.definitions.def_path_hash(def_index)
+    pub fn local_def_path_hash(&self, def_id: LocalDefId) -> DefPathHash {
+        self.definitions.def_path_hash(def_id)
     }
 
     #[inline]
@@ -164,15 +163,6 @@ pub fn is_ignored_attr(&self, name: Symbol) -> bool {
         }
         IGNORED_ATTRIBUTES.with(|attrs| attrs.contains(&name))
     }
-
-    pub fn hash_hir_item_like<F: FnOnce(&mut Self)>(&mut self, f: F) {
-        let prev_hash_node_ids = self.node_id_hashing_mode;
-        self.node_id_hashing_mode = NodeIdHashingMode::Ignore;
-
-        f(self);
-
-        self.node_id_hashing_mode = prev_hash_node_ids;
-    }
 }
 
 /// Something that can provide a stable hashing context.
@@ -206,19 +196,6 @@ fn get_stable_hashing_context(&self) -> StableHashingContext<'a> {
 
 impl<'a> crate::dep_graph::DepGraphSafe for StableHashingContext<'a> {}
 
-impl<'a> ToStableHashKey<StableHashingContext<'a>> for hir::HirId {
-    type KeyType = (DefPathHash, hir::ItemLocalId);
-
-    #[inline]
-    fn to_stable_hash_key(
-        &self,
-        hcx: &StableHashingContext<'a>,
-    ) -> (DefPathHash, hir::ItemLocalId) {
-        let def_path_hash = hcx.local_def_path_hash(self.owner);
-        (def_path_hash, self.local_id)
-    }
-}
-
 impl<'a> HashStable<StableHashingContext<'a>> for ast::NodeId {
     fn hash_stable(&self, _: &mut StableHashingContext<'a>, _: &mut StableHasher) {
         panic!("Node IDs should not appear in incremental state");
index eadc9ddeee6fc827af0b4736b02abc0bb7876f13..1722b29266ad264e2238bb46d5d5f65eefd13f1b 100644 (file)
@@ -105,6 +105,20 @@ fn hash_hir_visibility_kind(
             }
         }
     }
+
+    fn hash_hir_item_like<F: FnOnce(&mut Self)>(&mut self, f: F) {
+        let prev_hash_node_ids = self.node_id_hashing_mode;
+        self.node_id_hashing_mode = NodeIdHashingMode::Ignore;
+
+        f(self);
+
+        self.node_id_hashing_mode = prev_hash_node_ids;
+    }
+
+    #[inline]
+    fn local_def_path_hash(&self, def_id: LocalDefId) -> DefPathHash {
+        self.local_def_path_hash(def_id)
+    }
 }
 
 impl<'a> ToStableHashKey<StableHashingContext<'a>> for DefId {
@@ -158,59 +172,6 @@ fn to_stable_hash_key(&self, _: &StableHashingContext<'a>) -> hir::ItemLocalId {
     }
 }
 
-impl<'a> HashStable<StableHashingContext<'a>> for hir::TraitItem<'_> {
-    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
-        let hir::TraitItem { hir_id: _, ident, ref attrs, ref generics, ref kind, span } = *self;
-
-        hcx.hash_hir_item_like(|hcx| {
-            ident.name.hash_stable(hcx, hasher);
-            attrs.hash_stable(hcx, hasher);
-            generics.hash_stable(hcx, hasher);
-            kind.hash_stable(hcx, hasher);
-            span.hash_stable(hcx, hasher);
-        });
-    }
-}
-
-impl<'a> HashStable<StableHashingContext<'a>> for hir::ImplItem<'_> {
-    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
-        let hir::ImplItem {
-            hir_id: _,
-            ident,
-            ref vis,
-            defaultness,
-            ref attrs,
-            ref generics,
-            ref kind,
-            span,
-        } = *self;
-
-        hcx.hash_hir_item_like(|hcx| {
-            ident.name.hash_stable(hcx, hasher);
-            vis.hash_stable(hcx, hasher);
-            defaultness.hash_stable(hcx, hasher);
-            attrs.hash_stable(hcx, hasher);
-            generics.hash_stable(hcx, hasher);
-            kind.hash_stable(hcx, hasher);
-            span.hash_stable(hcx, hasher);
-        });
-    }
-}
-
-impl<'a> HashStable<StableHashingContext<'a>> for hir::Item<'_> {
-    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
-        let hir::Item { ident, ref attrs, hir_id: _, ref kind, ref vis, span } = *self;
-
-        hcx.hash_hir_item_like(|hcx| {
-            ident.name.hash_stable(hcx, hasher);
-            attrs.hash_stable(hcx, hasher);
-            kind.hash_stable(hcx, hasher);
-            vis.hash_stable(hcx, hasher);
-            span.hash_stable(hcx, hasher);
-        });
-    }
-}
-
 impl<'a> HashStable<StableHashingContext<'a>> for hir::Body<'_> {
     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
         let hir::Body { params, value, generator_kind } = self;
@@ -236,21 +197,6 @@ fn to_stable_hash_key(
     }
 }
 
-impl<'a> HashStable<StableHashingContext<'a>> for hir::def_id::DefIndex {
-    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
-        hcx.local_def_path_hash(*self).hash_stable(hcx, hasher);
-    }
-}
-
-impl<'a> ToStableHashKey<StableHashingContext<'a>> for hir::def_id::DefIndex {
-    type KeyType = DefPathHash;
-
-    #[inline]
-    fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> DefPathHash {
-        hcx.local_def_path_hash(*self)
-    }
-}
-
 impl<'a> HashStable<StableHashingContext<'a>> for hir::TraitCandidate {
     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
         hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
index daff8a0f1825ed14df420c1d75abca2a77950778..c5a4b53b10df85487663ba4d1bb238ff21aea3ea 100644 (file)
@@ -5,7 +5,6 @@
 
 use rustc_ast::ast;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX};
 use rustc_span::SourceFile;
 
 use smallvec::SmallVec;
@@ -59,7 +58,7 @@ fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHas
             name_hash,
             name_was_remapped,
             unmapped_path: _,
-            crate_of_origin,
+            cnum,
             // Do not hash the source as it is not encoded
             src: _,
             src_hash,
@@ -75,9 +74,6 @@ fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHas
         (name_hash as u64).hash_stable(hcx, hasher);
         name_was_remapped.hash_stable(hcx, hasher);
 
-        DefId { krate: CrateNum::from_u32(crate_of_origin), index: CRATE_DEF_INDEX }
-            .hash_stable(hcx, hasher);
-
         src_hash.hash_stable(hcx, hasher);
 
         // We only hash the relative position within this source_file
@@ -101,6 +97,8 @@ fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHas
         for &char_pos in normalized_pos.iter() {
             stable_normalized_pos(char_pos, start_pos).hash_stable(hcx, hasher);
         }
+
+        cnum.hash_stable(hcx, hasher);
     }
 }
 
index 76d0d57e233a34a1a0c22720aa4426b1efd53be0..5f7e8c849653c50f904f9e1ae45181f132f1308c 100644 (file)
@@ -17,9 +17,9 @@
 //! `instantiate_query_result` method.
 //!
 //! For a more detailed look at what is happening here, check
-//! out the [chapter in the rustc guide][c].
+//! out the [chapter in the rustc dev guide][c].
 //!
-//! [c]: https://rust-lang.github.io/rustc-guide/traits/canonicalization.html
+//! [c]: https://rustc-dev-guide.rust-lang.org/traits/canonicalization.html
 
 use crate::infer::MemberConstraint;
 use crate::ty::subst::GenericArg;
index 055d70effc6e6886257703e4e0b2f330ba2bd61b..8d0f604de6d7623daf29d6c4a7a16a6e3f252f6b 100644 (file)
@@ -14,9 +14,9 @@
 //!   (or `tcx`), which is the central context during most of
 //!   compilation, containing the interners and other things.
 //!
-//! For more information about how rustc works, see the [rustc guide].
+//! For more information about how rustc works, see the [rustc dev guide].
 //!
-//! [rustc guide]: https://rust-lang.github.io/rustc-guide/
+//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/
 //!
 //! # Note
 //!
@@ -26,6 +26,9 @@
 #![feature(bool_to_option)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
+#![feature(const_if_match)]
+#![feature(const_fn)]
+#![feature(const_panic)]
 #![feature(const_transmute)]
 #![feature(core_intrinsics)]
 #![feature(drain_filter)]
@@ -80,7 +83,6 @@
 pub mod lint;
 pub mod middle;
 pub mod mir;
-pub use rustc_session as session;
 pub mod traits;
 pub mod ty;
 
index 004835b230ab44e3260494aaa3c9611a34b28827..d4d01a716db97c32602f677796c4e47594b88f53 100644 (file)
@@ -5,7 +5,7 @@
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_errors::{pluralize, Applicability, DiagnosticBuilder, DiagnosticId};
 use rustc_hir::HirId;
-pub use rustc_session::lint::{builtin, Level, Lint, LintId, LintPass};
+use rustc_session::lint::{builtin, Level, Lint, LintId};
 use rustc_session::{DiagnosticMessageId, Session};
 use rustc_span::hygiene::MacroKind;
 use rustc_span::source_map::{DesugaringKind, ExpnKind, MultiSpan};
@@ -344,15 +344,8 @@ pub fn in_external_macro(sess: &Session, span: Span) -> bool {
         ExpnKind::Root | ExpnKind::Desugaring(DesugaringKind::ForLoop) => false,
         ExpnKind::AstPass(_) | ExpnKind::Desugaring(_) => true, // well, it's "external"
         ExpnKind::Macro(MacroKind::Bang, _) => {
-            if expn_data.def_site.is_dummy() {
-                // Dummy span for the `def_site` means it's an external macro.
-                return true;
-            }
-            match sess.source_map().span_to_snippet(expn_data.def_site) {
-                Ok(code) => !code.starts_with("macro_rules"),
-                // No snippet means external macro or compiler-builtin expansion.
-                Err(_) => true,
-            }
+            // Dummy span for the `def_site` means it's an external macro.
+            expn_data.def_site.is_dummy() || sess.source_map().is_imported(expn_data.def_site)
         }
         ExpnKind::Macro(..) => true, // definitely a plugin
     }
index 82adcfddc289ed5891d90ce31e4d699299ee5c99..61b25cc4864465e3ae2fe9abe8c01b24bd2e0527 100644 (file)
@@ -58,9 +58,6 @@ pub struct CodegenFnAttrFlags: u32 {
         /// "weird symbol" for the standard library in that it has slightly
         /// different linkage, visibility, and reachability rules.
         const RUSTC_STD_INTERNAL_SYMBOL = 1 << 6;
-        /// `#[no_debug]`: an indicator that no debugging information should be
-        /// generated for this function by LLVM.
-        const NO_DEBUG                  = 1 << 7;
         /// `#[thread_local]`: indicates a static is actually a thread local
         /// piece of memory
         const THREAD_LOCAL              = 1 << 8;
index 624bd9340987d35c928d31bd48983ff785f8b1cb..9f5a56903aa6e9ede938d32daf717c3351b7afe8 100644 (file)
@@ -2,10 +2,9 @@
 //! are *mostly* used as a part of that interface, but these should
 //! probably get a better home if someone can find one.
 
-use crate::hir::map as hir_map;
-use crate::hir::map::definitions::{DefKey, DefPathTable};
-use crate::session::search_paths::PathKind;
-use crate::session::CrateDisambiguator;
+pub use self::NativeLibraryKind::*;
+
+use crate::hir::map::definitions::{DefKey, DefPath, DefPathHash, DefPathTable};
 use crate::ty::TyCtxt;
 
 use rustc_ast::ast;
 use rustc_data_structures::sync::{self, MetadataRef};
 use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use rustc_macros::HashStable;
+use rustc_session::search_paths::PathKind;
+pub use rustc_session::utils::NativeLibraryKind;
+use rustc_session::CrateDisambiguator;
 use rustc_span::symbol::Symbol;
 use rustc_span::Span;
 use rustc_target::spec::Target;
+
 use std::any::Any;
 use std::path::{Path, PathBuf};
 
-pub use self::NativeLibraryKind::*;
-pub use rustc_session::utils::NativeLibraryKind;
-
 // lonely orphan structs and enums looking for a better home
 
 /// Where a crate came from on the local filesystem. One of these three options
@@ -53,9 +53,6 @@ pub fn paths(&self) -> impl Iterator<Item = &PathBuf> {
     HashStable
 )]
 pub enum DepKind {
-    /// A dependency that is only used for its macros, none of which are visible from other crates.
-    /// These are included in the metadata only as placeholders and are ignored when decoding.
-    UnexportedMacrosOnly,
     /// A dependency that is only used for its macros.
     MacrosOnly,
     /// A dependency that is always injected into the dependency list and so
@@ -69,7 +66,7 @@ pub enum DepKind {
 impl DepKind {
     pub fn macros_only(self) -> bool {
         match self {
-            DepKind::UnexportedMacrosOnly | DepKind::MacrosOnly => true,
+            DepKind::MacrosOnly => true,
             DepKind::Implicit | DepKind::Explicit => false,
         }
     }
@@ -200,8 +197,8 @@ pub trait CrateStore {
 
     // 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(&self, def: DefId) -> DefPath;
+    fn def_path_hash(&self, def: DefId) -> DefPathHash;
     fn def_path_table(&self, cnum: CrateNum) -> &DefPathTable;
 
     // "queries" used in resolve that aren't tracked for incremental compilation
index 6ece51fe866745d449ad8af4468ac601c2496483..ee5f822d3134c69267363292b1caab4b78b49b23 100644 (file)
@@ -4,7 +4,7 @@
 //! For all the gory details, see the provider of the `dependency_formats`
 //! query.
 
-use crate::session::config;
+use rustc_session::config;
 
 /// A list of dependencies for a certain crate type.
 ///
index c8e284be6fc09cf5cad7615b2d19fd125163d61e..36560371587a53c8b5d6c4937650604f60e356e1 100644 (file)
@@ -57,8 +57,7 @@ pub fn whitelisted(tcx: TyCtxt<'_>, lang_item: LangItem) -> bool {
     // symbols. Other panic runtimes ensure that the relevant symbols are
     // available to link things together, but they're never exercised.
     if tcx.sess.panic_strategy() != PanicStrategy::Unwind {
-        return lang_item == LangItem::EhPersonalityLangItem
-            || lang_item == LangItem::EhUnwindResumeLangItem;
+        return lang_item == LangItem::EhPersonalityLangItem;
     }
 
     false
diff --git a/src/librustc/middle/limits.rs b/src/librustc/middle/limits.rs
new file mode 100644 (file)
index 0000000..6de53c7
--- /dev/null
@@ -0,0 +1,66 @@
+//! Registering limits, recursion_limit, type_length_limit and const_eval_limit
+//!
+//! There are various parts of the compiler that must impose arbitrary limits
+//! on how deeply they recurse to prevent stack overflow. Users can override
+//! this via an attribute on the crate like `#![recursion_limit="22"]`. This pass
+//! just peeks and looks for that attribute.
+
+use rustc::bug;
+use rustc_ast::ast;
+use rustc_data_structures::sync::Once;
+use rustc_session::Session;
+use rustc_span::symbol::{sym, Symbol};
+
+use std::num::IntErrorKind;
+
+pub fn update_limits(sess: &Session, krate: &ast::Crate) {
+    update_limit(sess, krate, &sess.recursion_limit, sym::recursion_limit, 128);
+    update_limit(sess, krate, &sess.type_length_limit, sym::type_length_limit, 1048576);
+    update_limit(sess, krate, &sess.const_eval_limit, sym::const_eval_limit, 1_000_000);
+}
+
+fn update_limit(
+    sess: &Session,
+    krate: &ast::Crate,
+    limit: &Once<usize>,
+    name: Symbol,
+    default: usize,
+) {
+    for attr in &krate.attrs {
+        if !attr.check_name(name) {
+            continue;
+        }
+
+        if let Some(s) = attr.value_str() {
+            match s.as_str().parse() {
+                Ok(n) => {
+                    limit.set(n);
+                    return;
+                }
+                Err(e) => {
+                    let mut err =
+                        sess.struct_span_err(attr.span, "`limit` must be a non-negative integer");
+
+                    let value_span = attr
+                        .meta()
+                        .and_then(|meta| meta.name_value_literal().cloned())
+                        .map(|lit| lit.span)
+                        .unwrap_or(attr.span);
+
+                    let error_str = match e.kind() {
+                        IntErrorKind::Overflow => "`limit` is too large",
+                        IntErrorKind::Empty => "`limit` must be a non-negative integer",
+                        IntErrorKind::InvalidDigit => "not a valid integer",
+                        IntErrorKind::Underflow => bug!("`limit` should never underflow"),
+                        IntErrorKind::Zero => bug!("zero is a valid `limit`"),
+                        kind => bug!("unimplemented IntErrorKind variant: {:?}", kind),
+                    };
+
+                    err.span_label(value_span, error_str);
+                    err.emit();
+                }
+            }
+        }
+    }
+    limit.set(default);
+}
index b20f2cf3a85c133f53bec53c9ea3b041aa21ff43..464488964afb7b3c17e1c1b1054155d97472b2b0 100644 (file)
@@ -28,8 +28,8 @@ pub fn to_vec(&self) -> Vec<(Symbol, Option<Symbol>)> {
         }
     }
 }
+pub mod limits;
 pub mod privacy;
-pub mod recursion_limit;
 pub mod region;
 pub mod resolve_lifetime;
 pub mod stability;
diff --git a/src/librustc/middle/recursion_limit.rs b/src/librustc/middle/recursion_limit.rs
deleted file mode 100644 (file)
index ae31a2c..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-// Recursion limit.
-//
-// There are various parts of the compiler that must impose arbitrary limits
-// on how deeply they recurse to prevent stack overflow. Users can override
-// this via an attribute on the crate like `#![recursion_limit="22"]`. This pass
-// just peeks and looks for that attribute.
-
-use crate::session::Session;
-use core::num::IntErrorKind;
-use rustc::bug;
-use rustc_ast::ast;
-use rustc_span::symbol::{sym, Symbol};
-
-use rustc_data_structures::sync::Once;
-
-pub fn update_limits(sess: &Session, krate: &ast::Crate) {
-    update_limit(sess, krate, &sess.recursion_limit, sym::recursion_limit, 128);
-    update_limit(sess, krate, &sess.type_length_limit, sym::type_length_limit, 1048576);
-}
-
-fn update_limit(
-    sess: &Session,
-    krate: &ast::Crate,
-    limit: &Once<usize>,
-    name: Symbol,
-    default: usize,
-) {
-    for attr in &krate.attrs {
-        if !attr.check_name(name) {
-            continue;
-        }
-
-        if let Some(s) = attr.value_str() {
-            match s.as_str().parse() {
-                Ok(n) => {
-                    limit.set(n);
-                    return;
-                }
-                Err(e) => {
-                    let mut err = sess.struct_span_err(
-                        attr.span,
-                        "`recursion_limit` must be a non-negative integer",
-                    );
-
-                    let value_span = attr
-                        .meta()
-                        .and_then(|meta| meta.name_value_literal().cloned())
-                        .map(|lit| lit.span)
-                        .unwrap_or(attr.span);
-
-                    let error_str = match e.kind() {
-                        IntErrorKind::Overflow => "`recursion_limit` is too large",
-                        IntErrorKind::Empty => "`recursion_limit` must be a non-negative integer",
-                        IntErrorKind::InvalidDigit => "not a valid integer",
-                        IntErrorKind::Underflow => bug!("`recursion_limit` should never underflow"),
-                        IntErrorKind::Zero => bug!("zero is a valid `recursion_limit`"),
-                        kind => bug!("unimplemented IntErrorKind variant: {:?}", kind),
-                    };
-
-                    err.span_label(value_span, error_str);
-                    err.emit();
-                }
-            }
-        }
-    }
-    limit.set(default);
-}
index 1d043f5dcdefacd7198e2f2b3b9367cf0c358334..2735c4afca2c8ecd5f3dd46a86306950b11e14e0 100644 (file)
@@ -2,14 +2,13 @@
 //! the parent links in the region hierarchy.
 //!
 //! For more information about how MIR-based region-checking works,
-//! see the [rustc guide].
+//! see the [rustc dev guide].
 //!
-//! [rustc guide]: https://rust-lang.github.io/rustc-guide/mir/borrowck.html
+//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/mir/borrowck.html
 
 use crate::ich::{NodeIdHashingMode, StableHashingContext};
 use crate::ty::{self, DefIdTree, TyCtxt};
 use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
 use rustc_hir::Node;
 
 use rustc_data_structures::fx::FxHashMap;
@@ -594,7 +593,7 @@ pub fn early_free_scope(&self, tcx: TyCtxt<'tcx>, br: &ty::EarlyBoundRegion) ->
                               region scope tree for {:?} / {:?}",
                             param_owner,
                             self.root_parent.map(|id| tcx.hir().local_def_id(id)),
-                            self.root_body.map(|hir_id| DefId::local(hir_id.owner))
+                            self.root_body.map(|hir_id| hir_id.owner)
                         ),
                     );
                 }
index 9d3df9623bd62e5e93c662f0452f378ca6f93627..46525bdedad3554ab6669d0540ba4b5ef3815d13 100644 (file)
@@ -3,7 +3,6 @@
 
 pub use self::StabilityLevel::*;
 
-use crate::session::{DiagnosticMessageId, Session};
 use crate::ty::{self, TyCtxt};
 use rustc_ast::ast::CRATE_NODE_ID;
 use rustc_attr::{self as attr, ConstStability, Deprecation, RustcDeprecation, Stability};
@@ -17,6 +16,7 @@
 use rustc_session::lint::builtin::{DEPRECATED, DEPRECATED_IN_FUTURE, SOFT_UNSTABLE};
 use rustc_session::lint::{BuiltinLintDiagnostics, Lint, LintBuffer};
 use rustc_session::parse::feature_err_issue;
+use rustc_session::{DiagnosticMessageId, Session};
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::{MultiSpan, Span};
 
@@ -110,7 +110,7 @@ pub fn report_unstable(
     let span_key = msp.primary_span().and_then(|sp: Span| {
         if !sp.is_dummy() {
             let file = sm.lookup_char_pos(sp.lo()).file;
-            if file.name.is_macros() { None } else { Some(span) }
+            if file.is_imported() { None } else { Some(span) }
         } else {
             None
         }
@@ -250,7 +250,7 @@ pub enum EvalResult {
 fn skip_stability_check_due_to_privacy(tcx: TyCtxt<'_>, mut def_id: DefId) -> bool {
     // Check if `def_id` is a trait method.
     match tcx.def_kind(def_id) {
-        Some(DefKind::Method) | Some(DefKind::AssocTy) | Some(DefKind::AssocConst) => {
+        Some(DefKind::AssocFn) | Some(DefKind::AssocTy) | Some(DefKind::AssocConst) => {
             if let ty::TraitContainer(trait_def_id) = tcx.associated_item(def_id).container {
                 // Trait methods do not declare visibility (even
                 // for visibility info in cstore). Use containing
index d3efe62e8c15346c6eebd97ff14ca681ff0fb4f0..9474f05b55df7e9bbf1d02c86f9ee7acf5aa1fc4 100644 (file)
@@ -41,6 +41,7 @@ pub struct Allocation<Tag = (), Extra = ()> {
     /// The size of the allocation. Currently, must always equal `bytes.len()`.
     pub size: Size,
     /// The alignment of the allocation to detect unaligned reads.
+    /// (`Align` guarantees that this is a power of two.)
     pub align: Align,
     /// `true` if the allocation is mutable.
     /// Also used by codegen to determine if a static should be put into mutable memory,
@@ -314,7 +315,7 @@ pub fn read_c_str(
                 &self.get_bytes(cx, ptr, size_with_null)?[..size]
             }
             // This includes the case where `offset` is out-of-bounds to begin with.
-            None => throw_unsup!(UnterminatedCString(ptr.erase_tag())),
+            None => throw_ub!(UnterminatedCString(ptr.erase_tag())),
         })
     }
 
@@ -573,7 +574,7 @@ impl<'tcx, Tag, Extra> Allocation<Tag, Extra> {
     fn check_defined(&self, ptr: Pointer<Tag>, size: Size) -> InterpResult<'tcx> {
         self.undef_mask
             .is_range_defined(ptr.offset, ptr.offset + size)
-            .or_else(|idx| throw_unsup!(ReadUndefBytes(idx)))
+            .or_else(|idx| throw_ub!(InvalidUndefBytes(Some(Pointer::new(ptr.alloc_id, idx)))))
     }
 
     pub fn mark_definedness(&mut self, ptr: Pointer<Tag>, size: Size, new_state: bool) {
@@ -610,7 +611,7 @@ pub fn compress_undef_range(&self, src: Pointer<Tag>, size: Size) -> AllocationD
         // a naive undef mask copying algorithm would repeatedly have to read the undef mask from
         // the source and write it to the destination. Even if we optimized the memory accesses,
         // we'd be doing all of this `repeat` times.
-        // Therefor we precompute a compressed version of the undef mask of the source value and
+        // Therefore we precompute a compressed version of the undef mask of the source value and
         // then write it back `repeat` times without computing any more information from the source.
 
         // A precomputed cache for ranges of defined/undefined bits
@@ -818,9 +819,9 @@ pub fn set_range_inbounds(&mut self, start: Size, end: Size, new_state: bool) {
             // First set all bits except the first `bita`,
             // then unset the last `64 - bitb` bits.
             let range = if bitb == 0 {
-                u64::max_value() << bita
+                u64::MAX << bita
             } else {
-                (u64::max_value() << bita) & (u64::max_value() >> (64 - bitb))
+                (u64::MAX << bita) & (u64::MAX >> (64 - bitb))
             };
             if new_state {
                 self.blocks[blocka] |= range;
@@ -832,21 +833,21 @@ pub fn set_range_inbounds(&mut self, start: Size, end: Size, new_state: bool) {
         // across block boundaries
         if new_state {
             // Set `bita..64` to `1`.
-            self.blocks[blocka] |= u64::max_value() << bita;
+            self.blocks[blocka] |= u64::MAX << bita;
             // Set `0..bitb` to `1`.
             if bitb != 0 {
-                self.blocks[blockb] |= u64::max_value() >> (64 - bitb);
+                self.blocks[blockb] |= u64::MAX >> (64 - bitb);
             }
             // Fill in all the other blocks (much faster than one bit at a time).
             for block in (blocka + 1)..blockb {
-                self.blocks[block] = u64::max_value();
+                self.blocks[block] = u64::MAX;
             }
         } else {
             // Set `bita..64` to `0`.
-            self.blocks[blocka] &= !(u64::max_value() << bita);
+            self.blocks[blocka] &= !(u64::MAX << bita);
             // Set `0..bitb` to `0`.
             if bitb != 0 {
-                self.blocks[blockb] &= !(u64::max_value() >> (64 - bitb));
+                self.blocks[blockb] &= !(u64::MAX >> (64 - bitb));
             }
             // Fill in all the other blocks (much faster than one bit at a time).
             for block in (blocka + 1)..blockb {
index 28e197b2a7fc19182ac6c15f3eeac39676fa6ce5..ff107a5f1e268990a327581b67711ddc079aef5a 100644 (file)
@@ -1,19 +1,20 @@
-use super::{CheckInAllocMsg, Pointer, RawConst, ScalarMaybeUndef};
+use super::{AllocId, CheckInAllocMsg, Pointer, RawConst, ScalarMaybeUndef};
 
 use crate::hir::map::definitions::DefPathData;
-use crate::mir;
 use crate::mir::interpret::ConstValue;
 use crate::ty::layout::{Align, LayoutError, Size};
 use crate::ty::query::TyCtxtAt;
+use crate::ty::tls;
 use crate::ty::{self, layout, Ty};
 
 use backtrace::Backtrace;
+use rustc_data_structures::sync::Lock;
 use rustc_errors::{struct_span_err, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_macros::HashStable;
-use rustc_span::{Pos, Span};
-use rustc_target::spec::abi::Abi;
-use std::{any::Any, env, fmt};
+use rustc_session::CtfeBacktrace;
+use rustc_span::{def_id::DefId, Pos, Span};
+use std::{any::Any, fmt};
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, RustcEncodable, RustcDecodable)]
 pub enum ErrorHandled {
@@ -245,7 +246,7 @@ fn print_backtrace(backtrace: &mut Backtrace) {
     eprintln!("\n\nAn error occurred in miri:\n{:?}", backtrace);
 }
 
-impl From<ErrorHandled> for InterpErrorInfo<'tcx> {
+impl From<ErrorHandled> for InterpErrorInfo<'_> {
     fn from(err: ErrorHandled) -> Self {
         match err {
             ErrorHandled::Reported => err_inval!(ReferencedConstant),
@@ -257,21 +258,25 @@ fn from(err: ErrorHandled) -> Self {
 
 impl<'tcx> From<InterpError<'tcx>> for InterpErrorInfo<'tcx> {
     fn from(kind: InterpError<'tcx>) -> Self {
-        let backtrace = match env::var("RUSTC_CTFE_BACKTRACE") {
-            // Matching `RUST_BACKTRACE` -- we treat "0" the same as "not present".
-            Ok(ref val) if val != "0" => {
-                let mut backtrace = Backtrace::new_unresolved();
+        let capture_backtrace = tls::with_context_opt(|ctxt| {
+            if let Some(ctxt) = ctxt {
+                *Lock::borrow(&ctxt.tcx.sess.ctfe_backtrace)
+            } else {
+                CtfeBacktrace::Disabled
+            }
+        });
 
-                if val == "immediate" {
-                    // Print it now.
-                    print_backtrace(&mut backtrace);
-                    None
-                } else {
-                    Some(Box::new(backtrace))
-                }
+        let backtrace = match capture_backtrace {
+            CtfeBacktrace::Disabled => None,
+            CtfeBacktrace::Capture => Some(Box::new(Backtrace::new_unresolved())),
+            CtfeBacktrace::Immediate => {
+                // Print it now.
+                let mut backtrace = Backtrace::new_unresolved();
+                print_backtrace(&mut backtrace);
+                None
             }
-            _ => None,
         };
+
         InterpErrorInfo { kind, backtrace }
     }
 }
@@ -289,9 +294,11 @@ pub enum InvalidProgramInfo<'tcx> {
     TypeckError,
     /// An error occurred during layout computation.
     Layout(layout::LayoutError<'tcx>),
+    /// An invalid transmute happened.
+    TransmuteSizeDiff(Ty<'tcx>, Ty<'tcx>),
 }
 
-impl fmt::Debug for InvalidProgramInfo<'tcx> {
+impl fmt::Debug for InvalidProgramInfo<'_> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         use InvalidProgramInfo::*;
         match self {
@@ -299,6 +306,11 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
             ReferencedConstant => write!(f, "referenced constant has errors"),
             TypeckError => write!(f, "encountered constants with type errors, stopping evaluation"),
             Layout(ref err) => write!(f, "{}", err),
+            TransmuteSizeDiff(from_ty, to_ty) => write!(
+                f,
+                "tried to transmute from {:?} to {:?}, but their sizes differed",
+                from_ty, to_ty
+            ),
         }
     }
 }
@@ -314,13 +326,55 @@ pub enum UndefinedBehaviorInfo {
     /// An enum discriminant was set to a value which was outside the range of valid values.
     InvalidDiscriminant(ScalarMaybeUndef),
     /// A slice/array index projection went out-of-bounds.
-    BoundsCheckFailed { len: u64, index: u64 },
+    BoundsCheckFailed {
+        len: u64,
+        index: u64,
+    },
     /// Something was divided by 0 (x / 0).
     DivisionByZero,
     /// Something was "remainded" by 0 (x % 0).
     RemainderByZero,
     /// Overflowing inbounds pointer arithmetic.
     PointerArithOverflow,
+    /// Invalid metadata in a wide pointer (using `str` to avoid allocations).
+    InvalidMeta(&'static str),
+    /// Reading a C string that does not end within its allocation.
+    UnterminatedCString(Pointer),
+    /// Dereferencing a dangling pointer after it got freed.
+    PointerUseAfterFree(AllocId),
+    /// Used a pointer outside the bounds it is valid for.
+    PointerOutOfBounds {
+        ptr: Pointer,
+        msg: CheckInAllocMsg,
+        allocation_size: Size,
+    },
+    /// Used a pointer with bad alignment.
+    AlignmentCheckFailed {
+        required: Align,
+        has: Align,
+    },
+    /// Using an integer as a pointer in the wrong way.
+    InvalidIntPointerUsage(u64),
+    /// Writing to read-only memory.
+    WriteToReadOnly(AllocId),
+    /// Using a pointer-not-to-a-function as function pointer.
+    InvalidFunctionPointer(Pointer),
+    // Trying to access the data behind a function pointer.
+    DerefFunctionPointer(AllocId),
+    /// The value validity check found a problem.
+    /// Should only be thrown by `validity.rs` and always point out which part of the value
+    /// is the problem.
+    ValidationFailure(String),
+    /// Using a non-boolean `u8` as bool.
+    InvalidBool(u8),
+    /// Using a non-character `u32` as character.
+    InvalidChar(u32),
+    /// Using uninitialized data where it is not allowed.
+    InvalidUndefBytes(Option<Pointer>),
+    /// Working with a local that is not currently live.
+    DeadLocal,
+    /// Trying to read from the return place of a function.
+    ReadFromReturnPlace,
 }
 
 impl fmt::Debug for UndefinedBehaviorInfo {
@@ -338,6 +392,51 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
             DivisionByZero => write!(f, "dividing by zero"),
             RemainderByZero => write!(f, "calculating the remainder with a divisor of zero"),
             PointerArithOverflow => write!(f, "overflowing in-bounds pointer arithmetic"),
+            InvalidMeta(msg) => write!(f, "invalid metadata in wide pointer: {}", msg),
+            UnterminatedCString(p) => write!(
+                f,
+                "reading a null-terminated string starting at {:?} with no null found before end of allocation",
+                p,
+            ),
+            PointerUseAfterFree(a) => {
+                write!(f, "pointer to {:?} was dereferenced after this allocation got freed", a)
+            }
+            PointerOutOfBounds { ptr, msg, allocation_size } => write!(
+                f,
+                "{} failed: pointer must be in-bounds at offset {}, \
+                           but is outside bounds of {} which has size {}",
+                msg,
+                ptr.offset.bytes(),
+                ptr.alloc_id,
+                allocation_size.bytes()
+            ),
+            InvalidIntPointerUsage(0) => write!(f, "invalid use of NULL pointer"),
+            InvalidIntPointerUsage(i) => write!(f, "invalid use of {} as a pointer", i),
+            AlignmentCheckFailed { required, has } => write!(
+                f,
+                "accessing memory with alignment {}, but alignment {} is required",
+                has.bytes(),
+                required.bytes()
+            ),
+            WriteToReadOnly(a) => write!(f, "writing to {:?} which is read-only", a),
+            InvalidFunctionPointer(p) => {
+                write!(f, "using {:?} as function pointer but it does not point to a function", p)
+            }
+            DerefFunctionPointer(a) => write!(f, "accessing {:?} which contains a function", a),
+            ValidationFailure(ref err) => write!(f, "type validation failed: {}", err),
+            InvalidBool(b) => write!(f, "interpreting an invalid 8-bit value as a bool: {}", b),
+            InvalidChar(c) => write!(f, "interpreting an invalid 32-bit value as a char: {}", c),
+            InvalidUndefBytes(Some(p)) => write!(
+                f,
+                "reading uninitialized memory at {:?}, but this operation requires initialized memory",
+                p
+            ),
+            InvalidUndefBytes(None) => write!(
+                f,
+                "using uninitialized data, but this operation requires initialized memory"
+            ),
+            DeadLocal => write!(f, "accessing a dead local variable"),
+            ReadFromReturnPlace => write!(f, "tried to read from the return place"),
         }
     }
 }
@@ -349,203 +448,45 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 ///
 /// Currently, we also use this as fall-back error kind for errors that have not been
 /// categorized yet.
-pub enum UnsupportedOpInfo<'tcx> {
+pub enum UnsupportedOpInfo {
     /// Free-form case. Only for errors that are never caught!
     Unsupported(String),
-
     /// When const-prop encounters a situation it does not support, it raises this error.
-    /// This must not allocate for performance reasons.
-    ConstPropUnsupported(&'tcx str),
-
-    // -- Everything below is not categorized yet --
-    FunctionAbiMismatch(Abi, Abi),
-    FunctionArgMismatch(Ty<'tcx>, Ty<'tcx>),
-    FunctionRetMismatch(Ty<'tcx>, Ty<'tcx>),
-    FunctionArgCountMismatch,
-    UnterminatedCString(Pointer),
-    DanglingPointerDeref,
-    DoubleFree,
-    InvalidMemoryAccess,
-    InvalidFunctionPointer,
-    InvalidBool,
-    PointerOutOfBounds {
-        ptr: Pointer,
-        msg: CheckInAllocMsg,
-        allocation_size: Size,
-    },
-    InvalidNullPointerUsage,
+    /// This must not allocate for performance reasons (hence `str`, not `String`).
+    ConstPropUnsupported(&'static str),
+    /// Accessing an unsupported foreign static.
+    ReadForeignStatic(DefId),
+    /// Could not find MIR for a function.
+    NoMirFor(DefId),
+    /// Modified a static during const-eval.
+    /// FIXME: move this to `ConstEvalErrKind` through a machine hook.
+    ModifiedStatic,
+    /// Encountered a pointer where we needed raw bytes.
     ReadPointerAsBytes,
+    /// Encountered raw bytes where we needed a pointer.
     ReadBytesAsPointer,
-    ReadForeignStatic,
-    InvalidPointerMath,
-    ReadUndefBytes(Size),
-    DeadLocal,
-    InvalidBoolOp(mir::BinOp),
-    UnimplementedTraitSelection,
-    CalledClosureAsFunction,
-    NoMirFor(String),
-    DerefFunctionPointer,
-    ExecuteMemory,
-    InvalidChar(u128),
-    OutOfTls,
-    TlsOutOfBounds,
-    AlignmentCheckFailed {
-        required: Align,
-        has: Align,
-    },
-    ValidationFailure(String),
-    VtableForArgumentlessMethod,
-    ModifiedConstantMemory,
-    ModifiedStatic,
-    TypeNotPrimitive(Ty<'tcx>),
-    ReallocatedWrongMemoryKind(String, String),
-    DeallocatedWrongMemoryKind(String, String),
-    ReallocateNonBasePtr,
-    DeallocateNonBasePtr,
-    IncorrectAllocationInformation(Size, Size, Align, Align),
-    HeapAllocZeroBytes,
-    HeapAllocNonPowerOfTwoAlignment(u64),
-    ReadFromReturnPointer,
-    PathNotFound(Vec<String>),
-    TransmuteSizeDiff(Ty<'tcx>, Ty<'tcx>),
 }
 
-impl fmt::Debug for UnsupportedOpInfo<'tcx> {
+impl fmt::Debug for UnsupportedOpInfo {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         use UnsupportedOpInfo::*;
         match self {
-            PointerOutOfBounds { ptr, msg, allocation_size } => write!(
-                f,
-                "{} failed: pointer must be in-bounds at offset {}, \
-                           but is outside bounds of allocation {} which has size {}",
-                msg,
-                ptr.offset.bytes(),
-                ptr.alloc_id,
-                allocation_size.bytes()
-            ),
-            ValidationFailure(ref err) => write!(f, "type validation failed: {}", err),
-            NoMirFor(ref func) => write!(f, "no MIR for `{}`", func),
-            FunctionAbiMismatch(caller_abi, callee_abi) => write!(
-                f,
-                "tried to call a function with ABI {:?} using caller ABI {:?}",
-                callee_abi, caller_abi
-            ),
-            FunctionArgMismatch(caller_ty, callee_ty) => write!(
-                f,
-                "tried to call a function with argument of type {:?} \
-                           passing data of type {:?}",
-                callee_ty, caller_ty
-            ),
-            TransmuteSizeDiff(from_ty, to_ty) => write!(
-                f,
-                "tried to transmute from {:?} to {:?}, but their sizes differed",
-                from_ty, to_ty
-            ),
-            FunctionRetMismatch(caller_ty, callee_ty) => write!(
-                f,
-                "tried to call a function with return type {:?} \
-                           passing return place of type {:?}",
-                callee_ty, caller_ty
-            ),
-            FunctionArgCountMismatch => {
-                write!(f, "tried to call a function with incorrect number of arguments")
-            }
-            ReallocatedWrongMemoryKind(ref old, ref new) => {
-                write!(f, "tried to reallocate memory from `{}` to `{}`", old, new)
-            }
-            DeallocatedWrongMemoryKind(ref old, ref new) => {
-                write!(f, "tried to deallocate `{}` memory but gave `{}` as the kind", old, new)
-            }
-            InvalidChar(c) => {
-                write!(f, "tried to interpret an invalid 32-bit value as a char: {}", c)
-            }
-            AlignmentCheckFailed { required, has } => write!(
-                f,
-                "tried to access memory with alignment {}, but alignment {} is required",
-                has.bytes(),
-                required.bytes()
-            ),
-            TypeNotPrimitive(ty) => write!(f, "expected primitive type, got {}", ty),
-            PathNotFound(ref path) => write!(f, "cannot find path {:?}", path),
-            IncorrectAllocationInformation(size, size2, align, align2) => write!(
-                f,
-                "incorrect alloc info: expected size {} and align {}, \
-                           got size {} and align {}",
-                size.bytes(),
-                align.bytes(),
-                size2.bytes(),
-                align2.bytes()
-            ),
-            InvalidMemoryAccess => write!(f, "tried to access memory through an invalid pointer"),
-            DanglingPointerDeref => write!(f, "dangling pointer was dereferenced"),
-            DoubleFree => write!(f, "tried to deallocate dangling pointer"),
-            InvalidFunctionPointer => {
-                write!(f, "tried to use a function pointer after offsetting it")
-            }
-            InvalidBool => write!(f, "invalid boolean value read"),
-            InvalidNullPointerUsage => write!(f, "invalid use of NULL pointer"),
-            ReadPointerAsBytes => write!(
-                f,
-                "a raw memory access tried to access part of a pointer value as raw \
-                    bytes"
-            ),
-            ReadBytesAsPointer => {
-                write!(f, "a memory access tried to interpret some bytes as a pointer")
-            }
-            ReadForeignStatic => write!(f, "tried to read from foreign (extern) static"),
-            InvalidPointerMath => write!(
-                f,
-                "attempted to do invalid arithmetic on pointers that would leak base \
-                    addresses, e.g., comparing pointers into different allocations"
-            ),
-            DeadLocal => write!(f, "tried to access a dead local variable"),
-            DerefFunctionPointer => write!(f, "tried to dereference a function pointer"),
-            ExecuteMemory => write!(f, "tried to treat a memory pointer as a function pointer"),
-            OutOfTls => write!(f, "reached the maximum number of representable TLS keys"),
-            TlsOutOfBounds => write!(f, "accessed an invalid (unallocated) TLS key"),
-            CalledClosureAsFunction => {
-                write!(f, "tried to call a closure through a function pointer")
+            Unsupported(ref msg) => write!(f, "{}", msg),
+            ConstPropUnsupported(ref msg) => {
+                write!(f, "Constant propagation encountered an unsupported situation: {}", msg)
             }
-            VtableForArgumentlessMethod => {
-                write!(f, "tried to call a vtable function without arguments")
+            ReadForeignStatic(did) => {
+                write!(f, "tried to read from foreign (extern) static {:?}", did)
             }
-            ModifiedConstantMemory => write!(f, "tried to modify constant memory"),
+            NoMirFor(did) => write!(f, "could not load MIR for {:?}", did),
             ModifiedStatic => write!(
                 f,
                 "tried to modify a static's initial value from another static's \
                     initializer"
             ),
-            ReallocateNonBasePtr => write!(
-                f,
-                "tried to reallocate with a pointer not to the beginning of an \
-                    existing object"
-            ),
-            DeallocateNonBasePtr => write!(
-                f,
-                "tried to deallocate with a pointer not to the beginning of an \
-                    existing object"
-            ),
-            HeapAllocZeroBytes => write!(f, "tried to re-, de- or allocate zero bytes on the heap"),
-            ReadFromReturnPointer => write!(f, "tried to read from the return pointer"),
-            UnimplementedTraitSelection => {
-                write!(f, "there were unresolved type arguments during trait selection")
-            }
-            InvalidBoolOp(_) => write!(f, "invalid boolean operation"),
-            UnterminatedCString(_) => write!(
-                f,
-                "attempted to get length of a null-terminated string, but no null \
-                    found before end of allocation"
-            ),
-            ReadUndefBytes(_) => write!(f, "attempted to read undefined bytes"),
-            HeapAllocNonPowerOfTwoAlignment(_) => write!(
-                f,
-                "tried to re-, de-, or allocate heap memory with alignment that is \
-                    not a power of two"
-            ),
-            Unsupported(ref msg) => write!(f, "{}", msg),
-            ConstPropUnsupported(ref msg) => {
-                write!(f, "Constant propagation encountered an unsupported situation: {}", msg)
-            }
+
+            ReadPointerAsBytes => write!(f, "unable to turn pointer into raw bytes",),
+            ReadBytesAsPointer => write!(f, "unable to turn bytes into a pointer"),
         }
     }
 }
@@ -580,7 +521,7 @@ pub enum InterpError<'tcx> {
     UndefinedBehavior(UndefinedBehaviorInfo),
     /// The program did something the interpreter does not support (some of these *might* be UB
     /// but the interpreter is not sure).
-    Unsupported(UnsupportedOpInfo<'tcx>),
+    Unsupported(UnsupportedOpInfo),
     /// The program was invalid (ill-typed, bad MIR, not sufficiently monomorphized, ...).
     InvalidProgram(InvalidProgramInfo<'tcx>),
     /// The program exhausted the interpreter's resources (stack/heap too big,
@@ -596,7 +537,7 @@ pub enum InterpError<'tcx> {
 impl fmt::Display for InterpError<'_> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         // Forward `Display` to `Debug`.
-        write!(f, "{:?}", self)
+        fmt::Debug::fmt(self, f)
     }
 }
 
@@ -612,3 +553,19 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         }
     }
 }
+
+impl InterpError<'_> {
+    /// Some errors allocate to be created as they contain free-form strings.
+    /// And sometimes we want to be sure that did not happen as it is a
+    /// waste of resources.
+    pub fn allocates(&self) -> bool {
+        match self {
+            InterpError::MachineStop(_)
+            | InterpError::Unsupported(UnsupportedOpInfo::Unsupported(_))
+            | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::ValidationFailure(_))
+            | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::Ub(_))
+            | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::UbExperimental(_)) => true,
+            _ => false,
+        }
+    }
+}
index 64c07b431db388a4c4665769084b57c9b46cf653..0b5bb7f3c03faf01bfdb98dac9816587460418c1 100644 (file)
@@ -161,7 +161,13 @@ pub enum LitToConstError {
 
 impl fmt::Debug for AllocId {
     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(fmt, "alloc{}", self.0)
+        fmt::Display::fmt(self, fmt)
+    }
+}
+
+impl fmt::Display for AllocId {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "alloc{}", self.0)
     }
 }
 
@@ -351,12 +357,6 @@ pub fn decode_alloc_id<D>(&self, decoder: &mut D) -> Result<AllocId, D::Error>
     }
 }
 
-impl fmt::Display for AllocId {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "{}", self.0)
-    }
-}
-
 /// An allocation in the global (tcx-managed) memory can be either a function pointer,
 /// a static, or a "real" allocation with some data in it.
 #[derive(Debug, Clone, Eq, PartialEq, Hash, RustcDecodable, RustcEncodable, HashStable)]
index a4974fb541b6b01f0d95d566d061ff051626d444..2cbe25f9674261e899319d537f8480ead7eda068 100644 (file)
@@ -78,9 +78,9 @@ fn overflowing_offset(&self, val: u64, i: u64) -> (u64, bool) {
     fn overflowing_signed_offset(&self, val: u64, i: i128) -> (u64, bool) {
         // FIXME: is it possible to over/underflow here?
         if i < 0 {
-            // Trickery to ensure that `i64::min_value()` works fine: compute `n = -i`.
+            // Trickery to ensure that `i64::MIN` works fine: compute `n = -i`.
             // This formula only works for true negative values; it overflows for zero!
-            let n = u64::max_value() - (i as u64) + 1;
+            let n = u64::MAX - (i as u64) + 1;
             let res = val.overflowing_sub(n);
             self.truncate_to_ptr(res)
         } else {
@@ -213,20 +213,4 @@ pub fn wrapping_signed_offset(self, i: i64, cx: &impl HasDataLayout) -> Self {
     pub fn erase_tag(self) -> Pointer {
         Pointer { alloc_id: self.alloc_id, offset: self.offset, tag: () }
     }
-
-    /// Test if the pointer is "inbounds" of an allocation of the given size.
-    /// A pointer is "inbounds" even if its offset is equal to the size; this is
-    /// a "one-past-the-end" pointer.
-    #[inline(always)]
-    pub fn check_inbounds_alloc(
-        self,
-        allocation_size: Size,
-        msg: CheckInAllocMsg,
-    ) -> InterpResult<'tcx, ()> {
-        if self.offset > allocation_size {
-            throw_unsup!(PointerOutOfBounds { ptr: self.erase_tag(), msg, allocation_size })
-        } else {
-            Ok(())
-        }
-    }
 }
index 2c146b5d7b42647b3ca95de088976a9331e16ebc..04fe70b36c1e02bdd93c7f11d6e27ee26572a017 100644 (file)
@@ -170,6 +170,10 @@ fn from(f: Double) -> Self {
 }
 
 impl Scalar<()> {
+    /// Make sure the `data` fits in `size`.
+    /// This is guaranteed by all constructors here, but since the enum variants are public,
+    /// it could still be violated (even though no code outside this file should
+    /// construct `Scalar`s).
     #[inline(always)]
     fn check_data(data: u128, size: u8) {
         debug_assert_eq!(
@@ -268,11 +272,13 @@ pub fn ptr_wrapping_signed_offset(self, i: i64, cx: &impl HasDataLayout) -> Self
 
     #[inline]
     pub fn from_bool(b: bool) -> Self {
+        // Guaranteed to be truncated and does not need sign extension.
         Scalar::Raw { data: b as u128, size: 1 }
     }
 
     #[inline]
     pub fn from_char(c: char) -> Self {
+        // Guaranteed to be truncated and does not need sign extension.
         Scalar::Raw { data: c as u128, size: 4 }
     }
 
@@ -295,21 +301,25 @@ pub fn from_uint(i: impl Into<u128>, size: Size) -> Self {
 
     #[inline]
     pub fn from_u8(i: u8) -> Self {
+        // Guaranteed to be truncated and does not need sign extension.
         Scalar::Raw { data: i as u128, size: 1 }
     }
 
     #[inline]
     pub fn from_u16(i: u16) -> Self {
+        // Guaranteed to be truncated and does not need sign extension.
         Scalar::Raw { data: i as u128, size: 2 }
     }
 
     #[inline]
     pub fn from_u32(i: u32) -> Self {
+        // Guaranteed to be truncated and does not need sign extension.
         Scalar::Raw { data: i as u128, size: 4 }
     }
 
     #[inline]
     pub fn from_u64(i: u64) -> Self {
+        // Guaranteed to be truncated and does not need sign extension.
         Scalar::Raw { data: i as u128, size: 8 }
     }
 
@@ -337,6 +347,26 @@ pub fn from_int(i: impl Into<i128>, size: Size) -> Self {
             .unwrap_or_else(|| bug!("Signed value {:#x} does not fit in {} bits", i, size.bits()))
     }
 
+    #[inline]
+    pub fn from_i8(i: i8) -> Self {
+        Self::from_int(i, Size::from_bits(8))
+    }
+
+    #[inline]
+    pub fn from_i16(i: i16) -> Self {
+        Self::from_int(i, Size::from_bits(16))
+    }
+
+    #[inline]
+    pub fn from_i32(i: i32) -> Self {
+        Self::from_int(i, Size::from_bits(32))
+    }
+
+    #[inline]
+    pub fn from_i64(i: i64) -> Self {
+        Self::from_int(i, Size::from_bits(64))
+    }
+
     #[inline]
     pub fn from_machine_isize(i: i64, cx: &impl HasDataLayout) -> Self {
         Self::from_int(i, cx.data_layout().pointer_size)
@@ -364,10 +394,10 @@ pub fn to_bits_or_ptr(
         target_size: Size,
         cx: &impl HasDataLayout,
     ) -> Result<u128, Pointer<Tag>> {
+        assert_ne!(target_size.bytes(), 0, "you should never look at the bits of a ZST");
         match self {
             Scalar::Raw { data, 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)
             }
@@ -378,19 +408,15 @@ pub fn to_bits_or_ptr(
         }
     }
 
-    #[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`.
+    /// This method is intentionally private!
+    /// It is just a helper for other methods in this file.
     #[inline]
-    pub fn to_bits(self, target_size: Size) -> InterpResult<'tcx, u128> {
+    fn to_bits(self, target_size: Size) -> InterpResult<'tcx, u128> {
+        assert_ne!(target_size.bytes(), 0, "you should never look at the bits of a ZST");
         match self {
             Scalar::Raw { data, size } => {
-                Self::check_raw(data, size, target_size);
+                assert_eq!(target_size.bytes(), size as u64);
+                Scalar::check_data(data, size);
                 Ok(data)
             }
             Scalar::Ptr(_) => throw_unsup!(ReadPointerAsBytes),
@@ -402,22 +428,14 @@ pub fn assert_bits(self, target_size: Size) -> u128 {
         self.to_bits(target_size).expect("expected Raw bits but got a Pointer")
     }
 
-    /// Do not call this method!  Use either `assert_ptr` or `force_ptr`.
-    /// This method is intentionally private, do not make it public.
     #[inline]
-    fn to_ptr(self) -> InterpResult<'tcx, Pointer<Tag>> {
+    pub fn assert_ptr(self) -> Pointer<Tag> {
         match self {
-            Scalar::Raw { data: 0, .. } => throw_unsup!(InvalidNullPointerUsage),
-            Scalar::Raw { .. } => throw_unsup!(ReadBytesAsPointer),
-            Scalar::Ptr(p) => Ok(p),
+            Scalar::Ptr(p) => p,
+            Scalar::Raw { .. } => bug!("expected a Pointer but got Raw bits"),
         }
     }
 
-    #[inline(always)]
-    pub fn assert_ptr(self) -> Pointer<Tag> {
-        self.to_ptr().expect("expected a Pointer but got Raw bits")
-    }
-
     /// Do not call this method!  Dispatch based on the type instead.
     #[inline]
     pub fn is_bits(self) -> bool {
@@ -437,10 +455,11 @@ pub fn is_ptr(self) -> bool {
     }
 
     pub fn to_bool(self) -> InterpResult<'tcx, bool> {
-        match self {
-            Scalar::Raw { data: 0, size: 1 } => Ok(false),
-            Scalar::Raw { data: 1, size: 1 } => Ok(true),
-            _ => throw_unsup!(InvalidBool),
+        let val = self.to_u8()?;
+        match val {
+            0 => Ok(false),
+            1 => Ok(true),
+            _ => throw_ub!(InvalidBool(val)),
         }
     }
 
@@ -448,7 +467,7 @@ pub fn to_char(self) -> InterpResult<'tcx, char> {
         let val = self.to_u32()?;
         match ::std::char::from_u32(val) {
             Some(c) => Ok(c),
-            None => throw_unsup!(InvalidChar(val as u128)),
+            None => throw_ub!(InvalidChar(val)),
         }
     }
 
@@ -591,16 +610,10 @@ pub fn erase_tag(self) -> ScalarMaybeUndef {
     pub fn not_undef(self) -> InterpResult<'static, Scalar<Tag>> {
         match self {
             ScalarMaybeUndef::Scalar(scalar) => Ok(scalar),
-            ScalarMaybeUndef::Undef => throw_unsup!(ReadUndefBytes(Size::ZERO)),
+            ScalarMaybeUndef::Undef => throw_ub!(InvalidUndefBytes(None)),
         }
     }
 
-    /// Do not call this method!  Use either `assert_bits` or `force_bits`.
-    #[inline(always)]
-    pub fn to_bits(self, target_size: Size) -> InterpResult<'tcx, u128> {
-        self.not_undef()?.to_bits(target_size)
-    }
-
     #[inline(always)]
     pub fn to_bool(self) -> InterpResult<'tcx, bool> {
         self.not_undef()?.to_bool()
@@ -626,6 +639,11 @@ pub fn to_u8(self) -> InterpResult<'tcx, u8> {
         self.not_undef()?.to_u8()
     }
 
+    #[inline(always)]
+    pub fn to_u16(self) -> InterpResult<'tcx, u16> {
+        self.not_undef()?.to_u16()
+    }
+
     #[inline(always)]
     pub fn to_u32(self) -> InterpResult<'tcx, u32> {
         self.not_undef()?.to_u32()
@@ -646,6 +664,11 @@ pub fn to_i8(self) -> InterpResult<'tcx, i8> {
         self.not_undef()?.to_i8()
     }
 
+    #[inline(always)]
+    pub fn to_i16(self) -> InterpResult<'tcx, i16> {
+        self.not_undef()?.to_i16()
+    }
+
     #[inline(always)]
     pub fn to_i32(self) -> InterpResult<'tcx, i32> {
         self.not_undef()?.to_i32()
index 668240ab42b4cca11f26730f9b33f73e6421ca5e..9018cd2656f9fb1836217b43d4653ce65a00e874 100644 (file)
@@ -1,6 +1,6 @@
-//! MIR datatypes and passes. See the [rustc guide] for more info.
+//! MIR datatypes and passes. See the [rustc dev guide] for more info.
 //!
-//! [rustc guide]: https://rust-lang.github.io/rustc-guide/mir/index.html
+//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/mir/index.html
 
 use crate::mir::interpret::{GlobalAlloc, Scalar};
 use crate::mir::visit::MirVisitable;
@@ -189,7 +189,7 @@ pub fn new(
     ) -> Self {
         // We need `arg_count` locals, and one for the return place.
         assert!(
-            local_decls.len() >= arg_count + 1,
+            local_decls.len() > arg_count,
             "expected at least {} locals, got {}",
             arg_count + 1,
             local_decls.len()
@@ -403,7 +403,7 @@ pub enum ClearCrossCrate<T> {
 }
 
 impl<T> ClearCrossCrate<T> {
-    pub fn as_ref(&'a self) -> ClearCrossCrate<&'a T> {
+    pub fn as_ref(&self) -> ClearCrossCrate<&T> {
         match self {
             ClearCrossCrate::Clear => ClearCrossCrate::Clear,
             ClearCrossCrate::Set(v) => ClearCrossCrate::Set(v),
@@ -1198,7 +1198,7 @@ pub fn if_(
         t: BasicBlock,
         f: BasicBlock,
     ) -> TerminatorKind<'tcx> {
-        static BOOL_SWITCH_FALSE: &'static [u128] = &[0];
+        static BOOL_SWITCH_FALSE: &[u128] = &[0];
         TerminatorKind::SwitchInt {
             discr: cond,
             switch_ty: tcx.types.bool,
@@ -1446,7 +1446,7 @@ fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
         match successor_count {
             0 => Ok(()),
 
-            1 => write!(fmt, " -> {:?}", self.successors().nth(0).unwrap()),
+            1 => write!(fmt, " -> {:?}", self.successors().next().unwrap()),
 
             _ => {
                 write!(fmt, " -> [")?;
@@ -1827,9 +1827,9 @@ pub struct Field {
 }
 
 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
-pub struct PlaceRef<'a, 'tcx> {
+pub struct PlaceRef<'tcx> {
     pub local: Local,
-    pub projection: &'a [PlaceElem<'tcx>],
+    pub projection: &'tcx [PlaceElem<'tcx>],
 }
 
 impl<'tcx> Place<'tcx> {
@@ -1864,7 +1864,7 @@ pub fn as_local(&self) -> Option<Local> {
         self.as_ref().as_local()
     }
 
-    pub fn as_ref(&self) -> PlaceRef<'_, 'tcx> {
+    pub fn as_ref(&self) -> PlaceRef<'tcx> {
         PlaceRef { local: self.local, projection: &self.projection }
     }
 }
@@ -1875,7 +1875,7 @@ fn from(local: Local) -> Self {
     }
 }
 
-impl<'a, 'tcx> PlaceRef<'a, 'tcx> {
+impl<'tcx> PlaceRef<'tcx> {
     /// Finds the innermost `Local` from this `Place`, *if* it is either a local itself or
     /// a single deref of a local.
     //
@@ -2503,7 +2503,7 @@ pub(crate) fn leaf(mut self, field: Field) -> Self {
 
     pub(crate) fn variant(
         mut self,
-        adt_def: &'tcx AdtDef,
+        adt_def: &AdtDef,
         variant_index: VariantIdx,
         field: Field,
     ) -> Self {
@@ -2562,15 +2562,15 @@ fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
 
 impl<'tcx> Display for Constant<'tcx> {
     fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
+        use crate::ty::print::PrettyPrinter;
         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)
-        }
+        ty::tls::with(|tcx| {
+            let literal = tcx.lift(&self.literal).unwrap();
+            let mut cx = FmtPrinter::new(tcx, fmt, Namespace::ValueNS);
+            cx.print_alloc_ids = true;
+            cx.pretty_print_const(literal, true)?;
+            Ok(())
+        })
     }
 }
 
index 9a3ddfb0e82c9f583cf75c3357eec00379651a1b..27d82d25803c74b14101365a53df035bac2559c8 100644 (file)
@@ -1,6 +1,5 @@
 use crate::dep_graph::{DepConstructor, DepNode, WorkProduct, WorkProductId};
 use crate::ich::{Fingerprint, NodeIdHashingMode, StableHashingContext};
-use crate::session::config::OptLevel;
 use crate::ty::print::obsolete::DefPathBasedNames;
 use crate::ty::{subst::InternalSubsts, Instance, InstanceDef, SymbolName, TyCtxt};
 use rustc_attr::InlineAttr;
@@ -9,6 +8,7 @@
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use rustc_hir::HirId;
+use rustc_session::config::OptLevel;
 use rustc_span::source_map::Span;
 use rustc_span::symbol::Symbol;
 use std::fmt;
@@ -258,7 +258,7 @@ pub enum Visibility {
 
 impl<'tcx> CodegenUnit<'tcx> {
     pub fn new(name: Symbol) -> CodegenUnit<'tcx> {
-        CodegenUnit { name: name, items: Default::default(), size_estimate: None }
+        CodegenUnit { name, items: Default::default(), size_estimate: None }
     }
 
     pub fn name(&self) -> Symbol {
index 409c981801b34aa329bd69ad28009b4b4dbfddb8..2aca6f684f4fe5e0cd19f58ec3b1a6ac29f584a5 100644 (file)
@@ -888,7 +888,7 @@ fn process_projection_elem(
     () => (
         fn visit_projection(
             &mut self,
-            local: &Local,
+            local: Local,
             projection: &[PlaceElem<'tcx>],
             context: PlaceContext,
             location: Location,
@@ -898,7 +898,7 @@ fn visit_projection(
 
         fn visit_projection_elem(
             &mut self,
-            local: &Local,
+            local: Local,
             proj_base: &[PlaceElem<'tcx>],
             elem: &PlaceElem<'tcx>,
             context: PlaceContext,
@@ -925,7 +925,7 @@ fn super_place(
 
             self.visit_place_base(&place.local, context, location);
 
-            self.visit_projection(&place.local,
+            self.visit_projection(place.local,
                                   &place.projection,
                                   context,
                                   location);
@@ -933,7 +933,7 @@ fn super_place(
 
         fn super_projection(
             &mut self,
-            local: &Local,
+            local: Local,
             projection: &[PlaceElem<'tcx>],
             context: PlaceContext,
             location: Location,
@@ -947,7 +947,7 @@ fn super_projection(
 
         fn super_projection_elem(
             &mut self,
-            _local: &Local,
+            _local: Local,
             _proj_base: &[PlaceElem<'tcx>],
             elem: &PlaceElem<'tcx>,
             _context: PlaceContext,
index b3315cc3701daf1a3b52629b74244b1220892e37..de35c6d87e6f58d4d178726dc0bb3a28b03212ca 100644 (file)
@@ -1,4 +1,4 @@
-use crate::dep_graph::{DepKind, DepNode, RecoverKey, SerializedDepNodeIndex};
+use crate::dep_graph::SerializedDepNodeIndex;
 use crate::mir;
 use crate::mir::interpret::{GlobalId, LitToConstInput};
 use crate::traits;
@@ -11,7 +11,7 @@
 use crate::ty::query::QueryDescription;
 use crate::ty::subst::SubstsRef;
 use crate::ty::{self, ParamEnvAnd, Ty, TyCtxt};
-use rustc_hir::def_id::{CrateNum, DefId, DefIndex};
+use rustc_hir::def_id::{CrateNum, DefId, LocalDefId};
 
 use rustc_span::symbol::Symbol;
 use std::borrow::Cow;
@@ -55,11 +55,50 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
             desc { "get the crate HIR" }
         }
 
+        // The indexed HIR. This can be conveniently accessed by `tcx.hir()`.
+        // Avoid calling this query directly.
+        query index_hir(_: CrateNum) -> &'tcx map::IndexedHir<'tcx> {
+            eval_always
+            no_hash
+            desc { "index HIR" }
+        }
+
+        // The items in a module.
+        // This can be conveniently accessed by `tcx.hir().visit_item_likes_in_module`.
+        // Avoid calling this query directly.
+        query hir_module_items(key: LocalDefId) -> &'tcx hir::ModuleItems {
+            eval_always
+            desc { |tcx| "HIR module items in `{}`", tcx.def_path_str(key.to_def_id()) }
+        }
+
+        // An HIR item with a `LocalDefId` that can own other HIR items which do
+        // not themselves have a `LocalDefId`.
+        // This can be conveniently accessed by methods on `tcx.hir()`.
+        // Avoid calling this query directly.
+        query hir_owner(key: LocalDefId) -> &'tcx HirOwner<'tcx> {
+            eval_always
+            desc { |tcx| "HIR owner of `{}`", tcx.def_path_str(key.to_def_id()) }
+        }
+
+        // The HIR items which do not themselves have a `LocalDefId` and are
+        // owned by another HIR item with a `LocalDefId`.
+        // This can be conveniently accessed by methods on `tcx.hir()`.
+        // Avoid calling this query directly.
+        query hir_owner_items(key: LocalDefId) -> &'tcx HirOwnerItems<'tcx> {
+            eval_always
+            desc { |tcx| "HIR owner items in `{}`", tcx.def_path_str(key.to_def_id()) }
+        }
+
         /// Records the type of every item.
         query type_of(key: DefId) -> Ty<'tcx> {
             cache_on_disk_if { key.is_local() }
         }
 
+        query analysis(key: CrateNum) -> Result<(), ErrorReported> {
+            eval_always
+            desc { "running analysis passes on this crate" }
+        }
+
         /// Maps from the `DefId` of an item (trait/struct/enum/fn) to its
         /// associated generics.
         query generics_of(key: DefId) -> &'tcx ty::Generics {
@@ -99,8 +138,9 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
             desc { "computing the lint levels for items in this crate" }
         }
 
-        query parent_module_from_def_id(_: DefId) -> DefId {
+        query parent_module_from_def_id(key: LocalDefId) -> LocalDefId {
             eval_always
+            desc { |tcx| "parent module of `{}`", tcx.def_path_str(key.to_def_id()) }
         }
     }
 
@@ -195,7 +235,6 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
             // queries). Making it anonymous avoids hashing the result, which
             // may save a bit of time.
             anon
-            no_force
             desc { "erasing regions from `{:?}`", ty }
         }
 
@@ -204,7 +243,6 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
         }
 
         query program_clauses_for_env(_: traits::Environment<'tcx>) -> Clauses<'tcx> {
-            no_force
             desc { "generating chalk-style clauses for environment" }
         }
 
@@ -247,7 +285,6 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
         /// 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> {
-            no_force
             desc { |tcx| "computing the bounds for type parameter `{}`", {
                 let id = tcx.hir().as_local_hir_id(key.1).unwrap();
                 tcx.hir().ty_param_name(id)
@@ -503,7 +540,6 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
         /// form to be used outside of const eval.
         query const_eval_raw(key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>)
             -> ConstEvalRawResult<'tcx> {
-            no_force
             desc { |tcx|
                 "const-evaluating `{}`",
                 tcx.def_path_str(key.value.instance.def.def_id())
@@ -520,7 +556,6 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
         /// `tcx.const_eval_resolve`, `tcx.const_eval_instance`, or `tcx.const_eval_global_id`.
         query const_eval_validated(key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>)
             -> ConstEvalResult<'tcx> {
-            no_force
             desc { |tcx|
                 "const-evaluating + checking `{}`",
                 tcx.def_path_str(key.value.instance.def.def_id())
@@ -535,7 +570,6 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
         query const_field(
             key: ty::ParamEnvAnd<'tcx, (&'tcx ty::Const<'tcx>, mir::Field)>
         ) -> ConstValue<'tcx> {
-            no_force
             desc { "extract field of const" }
         }
 
@@ -544,19 +578,16 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
         query destructure_const(
             key: ty::ParamEnvAnd<'tcx, &'tcx ty::Const<'tcx>>
         ) -> mir::DestructuredConst<'tcx> {
-            no_force
             desc { "destructure constant" }
         }
 
         query const_caller_location(key: (rustc_span::Symbol, u32, u32)) -> ConstValue<'tcx> {
-            no_force
             desc { "get a &core::panic::Location referring to a span" }
         }
 
         query lit_to_const(
             key: LitToConstInput<'tcx>
         ) -> Result<&'tcx ty::Const<'tcx>, LitToConstError> {
-            no_force
             desc { "converting literal to const" }
         }
     }
@@ -587,7 +618,6 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
         query region_scope_tree(_: DefId) -> &'tcx region::ScopeTree {}
 
         query mir_shims(key: ty::InstanceDef<'tcx>) -> &'tcx mir::BodyAndCache<'tcx> {
-            no_force
             desc { |tcx| "generating MIR shim for `{}`", tcx.def_path_str(key.def_id()) }
         }
 
@@ -595,7 +625,6 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
         /// given instance from the local crate. In particular, it will also
         /// look up the correct symbol name of instances from upstream crates.
         query symbol_name(key: ty::Instance<'tcx>) -> ty::SymbolName {
-            no_force
             desc { "computing the symbol for `{}`", key }
             cache_on_disk_if { true }
         }
@@ -642,7 +671,6 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
     Other {
         query vtable_methods(key: ty::PolyTraitRef<'tcx>)
                             -> &'tcx [Option<(DefId, SubstsRef<'tcx>)>] {
-            no_force
             desc { |tcx| "finding all methods for trait {}", tcx.def_path_str(key.def_id()) }
         }
     }
@@ -650,8 +678,7 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
     Codegen {
         query codegen_fulfill_obligation(
             key: (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>)
-        ) -> Vtable<'tcx, ()> {
-            no_force
+        ) -> Option<Vtable<'tcx, ()>> {
             cache_on_disk_if { true }
             desc { |tcx|
                 "checking if `{}` fulfills its obligations",
@@ -661,6 +688,9 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
     }
 
     TypeChecking {
+        query all_local_trait_impls(key: CrateNum) -> &'tcx BTreeMap<DefId, Vec<hir::HirId>> {
+            desc { "local trait impls" }
+        }
         query trait_impls_of(key: DefId) -> &'tcx ty::trait_def::TraitImpls {
             desc { |tcx| "trait impls of `{}`", tcx.def_path_str(key) }
         }
@@ -683,22 +713,18 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
         /// Trait selection queries. These are best used by invoking `ty.is_copy_modulo_regions()`,
         /// `ty.is_copy()`, etc, since that will prune the environment where possible.
         query is_copy_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
-            no_force
             desc { "computing whether `{}` is `Copy`", env.value }
         }
         /// Query backing `TyS::is_sized`.
         query is_sized_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
-            no_force
             desc { "computing whether `{}` is `Sized`", env.value }
         }
         /// Query backing `TyS::is_freeze`.
         query is_freeze_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
-            no_force
             desc { "computing whether `{}` is freeze", env.value }
         }
         /// Query backing `TyS::needs_drop`.
         query needs_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
-            no_force
             desc { "computing whether `{}` needs drop", env.value }
         }
 
@@ -712,7 +738,6 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
         query layout_raw(
             env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>
         ) -> Result<&'tcx ty::layout::LayoutDetails, ty::layout::LayoutError<'tcx>> {
-            no_force
             desc { "computing layout of `{}`", env.value }
         }
     }
@@ -768,10 +793,9 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
 
     TypeChecking {
         query specializes(_: (DefId, DefId)) -> bool {
-            no_force
             desc { "computing whether impls specialize one another" }
         }
-        query in_scope_traits_map(_: DefIndex)
+        query in_scope_traits_map(_: LocalDefId)
             -> Option<&'tcx FxHashMap<ItemLocalId, StableVec<TraitCandidate>>> {
             eval_always
             desc { "traits in scope at a block" }
@@ -853,7 +877,6 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
         ///       (like `Clone::clone` for example).
         query upstream_drop_glue_for(substs: SubstsRef<'tcx>) -> Option<CrateNum> {
             desc { "available upstream drop-glue for `{:?}`", substs }
-            no_force
         }
     }
 
@@ -898,7 +921,6 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
     TypeChecking {
         query implementations_of_trait(_: (CrateNum, DefId))
             -> &'tcx [DefId] {
-            no_force
             desc { "looking up implementations of a trait in a crate" }
         }
         query all_trait_implementations(_: CrateNum)
@@ -930,15 +952,15 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
         query resolve_lifetimes(_: CrateNum) -> &'tcx ResolveLifetimes {
             desc { "resolving lifetimes" }
         }
-        query named_region_map(_: DefIndex) ->
+        query named_region_map(_: LocalDefId) ->
             Option<&'tcx FxHashMap<ItemLocalId, Region>> {
             desc { "looking up a named region" }
         }
-        query is_late_bound_map(_: DefIndex) ->
+        query is_late_bound_map(_: LocalDefId) ->
             Option<&'tcx FxHashSet<ItemLocalId>> {
             desc { "testing if a region is late bound" }
         }
-        query object_lifetime_defaults_map(_: DefIndex)
+        query object_lifetime_defaults_map(_: LocalDefId)
             -> Option<&'tcx FxHashMap<ItemLocalId, Vec<ObjectLifetimeDefault>>> {
             desc { "looking up lifetime defaults for a region" }
         }
@@ -1065,7 +1087,6 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
         }
         query is_codegened_item(_: DefId) -> bool {}
         query codegen_unit(_: Symbol) -> Arc<CodegenUnit<'tcx>> {
-            no_force
             desc { "codegen_unit" }
         }
         query backend_optimization_level(_: CrateNum) -> OptLevel {
@@ -1088,7 +1109,6 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
             &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, NormalizationResult<'tcx>>>,
             NoSolution,
         > {
-            no_force
             desc { "normalizing `{:?}`", goal }
         }
 
@@ -1096,7 +1116,6 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
         query normalize_ty_after_erasing_regions(
             goal: ParamEnvAnd<'tcx, Ty<'tcx>>
         ) -> Ty<'tcx> {
-            no_force
             desc { "normalizing `{:?}`", goal }
         }
 
@@ -1106,7 +1125,6 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
             &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, Vec<OutlivesBound<'tcx>>>>,
             NoSolution,
         > {
-            no_force
             desc { "computing implied outlives bounds for `{:?}`", goal }
         }
 
@@ -1117,7 +1135,6 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
             &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, DropckOutlivesResult<'tcx>>>,
             NoSolution,
         > {
-            no_force
             desc { "computing dropck types for `{:?}`", goal }
         }
 
@@ -1126,20 +1143,9 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
         query evaluate_obligation(
             goal: CanonicalPredicateGoal<'tcx>
         ) -> Result<traits::EvaluationResult, traits::OverflowError> {
-            no_force
             desc { "evaluating trait selection obligation `{}`", goal.value.value }
         }
 
-        query evaluate_goal(
-            goal: traits::ChalkCanonicalGoal<'tcx>
-        ) -> Result<
-            &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>,
-            NoSolution
-        > {
-            no_force
-            desc { "evaluating trait selection obligation `{}`", goal.value.goal }
-        }
-
         /// Do not call this query directly: part of the `Eq` type-op
         query type_op_ascribe_user_type(
             goal: CanonicalTypeOpAscribeUserTypeGoal<'tcx>
@@ -1147,7 +1153,6 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
             &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>,
             NoSolution,
         > {
-            no_force
             desc { "evaluating `type_op_ascribe_user_type` `{:?}`", goal }
         }
 
@@ -1158,7 +1163,6 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
             &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>,
             NoSolution,
         > {
-            no_force
             desc { "evaluating `type_op_eq` `{:?}`", goal }
         }
 
@@ -1169,7 +1173,6 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
             &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>,
             NoSolution,
         > {
-            no_force
             desc { "evaluating `type_op_subtype` `{:?}`", goal }
         }
 
@@ -1180,7 +1183,6 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
             &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>,
             NoSolution,
         > {
-            no_force
             desc { "evaluating `type_op_prove_predicate` `{:?}`", goal }
         }
 
@@ -1191,7 +1193,6 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
             &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, Ty<'tcx>>>,
             NoSolution,
         > {
-            no_force
             desc { "normalizing `{:?}`", goal }
         }
 
@@ -1202,7 +1203,6 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
             &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ty::Predicate<'tcx>>>,
             NoSolution,
         > {
-            no_force
             desc { "normalizing `{:?}`", goal }
         }
 
@@ -1213,7 +1213,6 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
             &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ty::PolyFnSig<'tcx>>>,
             NoSolution,
         > {
-            no_force
             desc { "normalizing `{:?}`", goal }
         }
 
@@ -1224,12 +1223,10 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
             &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ty::FnSig<'tcx>>>,
             NoSolution,
         > {
-            no_force
             desc { "normalizing `{:?}`", goal }
         }
 
         query substitute_normalize_and_test_predicates(key: (DefId, SubstsRef<'tcx>)) -> bool {
-            no_force
             desc { |tcx|
                 "testing substituted normalized predicates:`{}`",
                 tcx.def_path_str(key.0)
@@ -1239,7 +1236,6 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
         query method_autoderef_steps(
             goal: CanonicalTyGoal<'tcx>
         ) -> MethodAutoderefStepsResult<'tcx> {
-            no_force
             desc { "computing autoderef types for `{:?}`", goal }
         }
     }
@@ -1253,7 +1249,6 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
         // Get an estimate of the size of an InstanceDef based on its MIR for CGU partitioning.
         query instance_def_size_estimate(def: ty::InstanceDef<'tcx>)
             -> usize {
-            no_force
             desc { |tcx| "estimating size for `{}`", tcx.def_path_str(def.def_id()) }
         }
 
index 1a4ea66a5f1d979cb8ab0493b076fa0c2a841f5f..6ebcc8b075462966d271d4d00d3e83878fd2a6b8 100644 (file)
@@ -1,15 +1,13 @@
-//! Trait Resolution. See the [rustc guide] for more information on how this works.
+//! Trait Resolution. See the [rustc dev guide] for more information on how this works.
 //!
-//! [rustc guide]: https://rust-lang.github.io/rustc-guide/traits/resolution.html
+//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/resolution.html
 
 pub mod query;
 pub mod select;
 pub mod specialization_graph;
 mod structural_impls;
 
-use crate::infer::canonical::Canonical;
 use crate::mir::interpret::ErrorHandled;
-use crate::ty::fold::{TypeFolder, TypeVisitor};
 use crate::ty::subst::SubstsRef;
 use crate::ty::{self, AdtKind, List, Ty, TyCtxt};
 
@@ -25,8 +23,6 @@
 
 pub use self::select::{EvaluationCache, EvaluationResult, OverflowError, SelectionCache};
 
-pub type ChalkCanonicalGoal<'tcx> = Canonical<'tcx, InEnvironment<'tcx, ty::Predicate<'tcx>>>;
-
 pub use self::ObligationCauseCode::*;
 pub use self::SelectionError::*;
 pub use self::Vtable::*;
@@ -715,45 +711,6 @@ pub struct VtableTraitAliasData<'tcx, N> {
     pub nested: Vec<N>,
 }
 
-pub trait ExClauseFold<'tcx>
-where
-    Self: chalk_engine::context::Context + Clone,
-{
-    fn fold_ex_clause_with<F: TypeFolder<'tcx>>(
-        ex_clause: &chalk_engine::ExClause<Self>,
-        folder: &mut F,
-    ) -> chalk_engine::ExClause<Self>;
-
-    fn visit_ex_clause_with<V: TypeVisitor<'tcx>>(
-        ex_clause: &chalk_engine::ExClause<Self>,
-        visitor: &mut V,
-    ) -> bool;
-}
-
-pub trait ChalkContextLift<'tcx>
-where
-    Self: chalk_engine::context::Context + Clone,
-{
-    type LiftedExClause: Debug + 'tcx;
-    type LiftedDelayedLiteral: Debug + 'tcx;
-    type LiftedLiteral: Debug + 'tcx;
-
-    fn lift_ex_clause_to_tcx(
-        ex_clause: &chalk_engine::ExClause<Self>,
-        tcx: TyCtxt<'tcx>,
-    ) -> Option<Self::LiftedExClause>;
-
-    fn lift_delayed_literal_to_tcx(
-        ex_clause: &chalk_engine::DelayedLiteral<Self>,
-        tcx: TyCtxt<'tcx>,
-    ) -> Option<Self::LiftedDelayedLiteral>;
-
-    fn lift_literal_to_tcx(
-        ex_clause: &chalk_engine::Literal<Self>,
-        tcx: TyCtxt<'tcx>,
-    ) -> Option<Self::LiftedLiteral>;
-}
-
 #[derive(Clone, Debug, PartialEq, Eq, Hash, HashStable)]
 pub enum ObjectSafetyViolation {
     /// `Self: Sized` declared on the trait.
index ac3d0049c0c7c42908e6cff2df5b90e46ea13c50..d316d7659e222b1ef4c3fdb22a2ef92d4d796409 100644 (file)
@@ -1,6 +1,6 @@
-//! Candidate selection. See the [rustc guide] for more information on how this works.
+//! Candidate selection. See the [rustc dev guide] for more information on how this works.
 //!
-//! [rustc guide]: https://rust-lang.github.io/rustc-guide/traits/resolution.html#selection
+//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/resolution.html#selection
 
 use self::EvaluationResult::*;
 
@@ -288,3 +288,44 @@ pub fn get(&self, tcx: TyCtxt<'_>) -> T {
         self.cached_value.clone()
     }
 }
+
+#[derive(Clone, Debug)]
+pub enum IntercrateAmbiguityCause {
+    DownstreamCrate { trait_desc: String, self_desc: Option<String> },
+    UpstreamCrateUpdate { trait_desc: String, self_desc: Option<String> },
+    ReservationImpl { message: String },
+}
+
+impl IntercrateAmbiguityCause {
+    /// Emits notes when the overlap is caused by complex intercrate ambiguities.
+    /// See #23980 for details.
+    pub fn add_intercrate_ambiguity_hint(&self, err: &mut rustc_errors::DiagnosticBuilder<'_>) {
+        err.note(&self.intercrate_ambiguity_hint());
+    }
+
+    pub fn intercrate_ambiguity_hint(&self) -> String {
+        match self {
+            &IntercrateAmbiguityCause::DownstreamCrate { ref trait_desc, ref self_desc } => {
+                let self_desc = if let &Some(ref ty) = self_desc {
+                    format!(" for type `{}`", ty)
+                } else {
+                    String::new()
+                };
+                format!("downstream crates may implement trait `{}`{}", trait_desc, self_desc)
+            }
+            &IntercrateAmbiguityCause::UpstreamCrateUpdate { ref trait_desc, ref self_desc } => {
+                let self_desc = if let &Some(ref ty) = self_desc {
+                    format!(" for type `{}`", ty)
+                } else {
+                    String::new()
+                };
+                format!(
+                    "upstream crates may add a new impl of trait `{}`{} \
+                     in future versions",
+                    trait_desc, self_desc
+                )
+            }
+            &IntercrateAmbiguityCause::ReservationImpl { ref message } => message.clone(),
+        }
+    }
+}
index d481e578fc1ddacd62e8d0e9acdd6fbd0e08771d..1847326a742eb7897b2c83726ad84114da3c91c6 100644 (file)
@@ -4,6 +4,7 @@
 use rustc_ast::ast::Ident;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_errors::ErrorReported;
 use rustc_hir::def_id::{DefId, DefIdMap};
 
 /// A per-trait graph of impls in specialization order. At the moment, this
 ///   has at most one parent.
 #[derive(RustcEncodable, RustcDecodable, HashStable)]
 pub struct Graph {
-    // All impls have a parent; the "root" impls have as their parent the `def_id`
-    // of the trait.
+    /// All impls have a parent; the "root" impls have as their parent the `def_id`
+    /// of the trait.
     pub parent: DefIdMap<DefId>,
 
-    // The "root" impls are found by looking up the trait's def_id.
+    /// The "root" impls are found by looking up the trait's def_id.
     pub children: DefIdMap<Children>,
+
+    /// Whether an error was emitted while constructing the graph.
+    pub has_errored: bool,
 }
 
 impl Graph {
     pub fn new() -> Graph {
-        Graph { parent: Default::default(), children: Default::default() }
+        Graph { parent: Default::default(), children: Default::default(), has_errored: false }
     }
 
     /// The parent of a given impl, which is the `DefId` of the trait when the
@@ -179,17 +183,22 @@ pub fn leaf_def(
 }
 
 /// Walk up the specialization ancestors of a given impl, starting with that
-/// impl itself.
+/// impl itself. Returns `None` if an error was reported while building the
+/// specialization graph.
 pub fn ancestors(
     tcx: TyCtxt<'tcx>,
     trait_def_id: DefId,
     start_from_impl: DefId,
-) -> Ancestors<'tcx> {
+) -> Result<Ancestors<'tcx>, ErrorReported> {
     let specialization_graph = tcx.specialization_graph_of(trait_def_id);
-    Ancestors {
-        trait_def_id,
-        specialization_graph,
-        current_source: Some(Node::Impl(start_from_impl)),
+    if specialization_graph.has_errored {
+        Err(ErrorReported)
+    } else {
+        Ok(Ancestors {
+            trait_def_id,
+            specialization_graph,
+            current_source: Some(Node::Impl(start_from_impl)),
+        })
     }
 }
 
index 48ed29f2bb33841cc974147d5b81218453a2cb16..a5efea9e5fa4d73c4ea7720132ca2017f4c35966 100644 (file)
@@ -234,7 +234,7 @@ fn write_names(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
             start = false;
             write!(fmt, "{}", r)?;
         }
-        for (_, t) in &self.types {
+        for t in self.types.values() {
             if !start {
                 write!(fmt, ", ")?;
             }
@@ -415,9 +415,9 @@ fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
             super::ReferenceOutlivesReferent(ty) => {
                 tcx.lift(&ty).map(super::ReferenceOutlivesReferent)
             }
-            super::ObjectTypeBound(ty, r) => tcx
-                .lift(&ty)
-                .and_then(|ty| tcx.lift(&r).and_then(|r| Some(super::ObjectTypeBound(ty, r)))),
+            super::ObjectTypeBound(ty, r) => {
+                tcx.lift(&ty).and_then(|ty| tcx.lift(&r).map(|r| 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)? })
@@ -532,9 +532,9 @@ fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
                 nested,
             }) => tcx.lift(&substs).map(|substs| {
                 traits::VtableGenerator(traits::VtableGeneratorData {
-                    generator_def_id: generator_def_id,
-                    substs: substs,
-                    nested: nested,
+                    generator_def_id,
+                    substs,
+                    nested,
                 })
             }),
             traits::VtableClosure(traits::VtableClosureData { closure_def_id, substs, nested }) => {
@@ -595,42 +595,6 @@ fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
     }
 }
 
-impl<'tcx, C> Lift<'tcx> for chalk_engine::ExClause<C>
-where
-    C: chalk_engine::context::Context + Clone,
-    C: traits::ChalkContextLift<'tcx>,
-{
-    type Lifted = C::LiftedExClause;
-
-    fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
-        <C as traits::ChalkContextLift>::lift_ex_clause_to_tcx(self, tcx)
-    }
-}
-
-impl<'tcx, C> Lift<'tcx> for chalk_engine::DelayedLiteral<C>
-where
-    C: chalk_engine::context::Context + Clone,
-    C: traits::ChalkContextLift<'tcx>,
-{
-    type Lifted = C::LiftedDelayedLiteral;
-
-    fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
-        <C as traits::ChalkContextLift>::lift_delayed_literal_to_tcx(self, tcx)
-    }
-}
-
-impl<'tcx, C> Lift<'tcx> for chalk_engine::Literal<C>
-where
-    C: chalk_engine::context::Context + Clone,
-    C: traits::ChalkContextLift<'tcx>,
-{
-    type Lifted = C::LiftedLiteral;
-
-    fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
-        <C as traits::ChalkContextLift>::lift_literal_to_tcx(self, tcx)
-    }
-}
-
 ///////////////////////////////////////////////////////////////////////////
 // TypeFoldable implementations.
 
@@ -674,39 +638,3 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
         self.iter().any(|t| t.visit_with(visitor))
     }
 }
-
-impl<'tcx, C> TypeFoldable<'tcx> for chalk_engine::ExClause<C>
-where
-    C: traits::ExClauseFold<'tcx>,
-    C::Substitution: Clone,
-    C::RegionConstraint: Clone,
-{
-    fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
-        <C as traits::ExClauseFold>::fold_ex_clause_with(self, folder)
-    }
-
-    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
-        <C as traits::ExClauseFold>::visit_ex_clause_with(self, visitor)
-    }
-}
-
-EnumTypeFoldableImpl! {
-    impl<'tcx, C> TypeFoldable<'tcx> for chalk_engine::DelayedLiteral<C> {
-        (chalk_engine::DelayedLiteral::CannotProve)(a),
-        (chalk_engine::DelayedLiteral::Negative)(a),
-        (chalk_engine::DelayedLiteral::Positive)(a, b),
-    } where
-        C: chalk_engine::context::Context<CanonicalConstrainedSubst: TypeFoldable<'tcx>> + Clone,
-}
-
-EnumTypeFoldableImpl! {
-    impl<'tcx, C> TypeFoldable<'tcx> for chalk_engine::Literal<C> {
-        (chalk_engine::Literal::Negative)(a),
-        (chalk_engine::Literal::Positive)(a),
-    } where
-        C: chalk_engine::context::Context<GoalInEnvironment: Clone + TypeFoldable<'tcx>> + Clone,
-}
-
-CloneTypeFoldableAndLiftImpls! {
-    chalk_engine::TableIndex,
-}
index 20736b50831bb17ebf59a558b12a1304a7b501a5..742d57fb58a51bfb6d9170813f2b939117f5f1d7 100644 (file)
@@ -5,6 +5,7 @@
 use crate::dep_graph::{self, DepConstructor};
 use crate::hir::exports::Export;
 use crate::hir::map as hir_map;
+use crate::hir::map::definitions::Definitions;
 use crate::hir::map::{DefPathData, DefPathHash};
 use crate::ich::{NodeIdHashingMode, StableHashingContext};
 use crate::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos};
@@ -22,7 +23,6 @@
 };
 use crate::traits;
 use crate::traits::{Clause, Clauses, Goal, GoalKind, Goals};
-use crate::ty::free_region_map::FreeRegionMap;
 use crate::ty::layout::{LayoutDetails, TargetDataLayout, VariantIdx};
 use crate::ty::query;
 use crate::ty::steal::Steal;
@@ -55,7 +55,7 @@
 use rustc_data_structures::sync::{self, Lock, Lrc, WorkerLocal};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, DefIndex, LOCAL_CRATE};
+use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId, LOCAL_CRATE};
 use rustc_hir::{HirId, Node, TraitCandidate};
 use rustc_hir::{ItemKind, ItemLocalId, ItemLocalMap, ItemLocalSet};
 use rustc_index::vec::{Idx, IndexVec};
@@ -205,13 +205,13 @@ fn validate_hir_id_for_typeck_tables(
     mut_access: bool,
 ) {
     if let Some(local_id_root) = local_id_root {
-        if hir_id.owner != local_id_root.index {
+        if hir_id.owner.to_def_id() != local_id_root {
             ty::tls::with(|tcx| {
                 bug!(
                     "node {} with HirId::owner {:?} cannot be placed in \
                      TypeckTables with local_id_root {:?}",
                     tcx.hir().node_to_string(hir_id),
-                    DefId::local(hir_id.owner),
+                    hir_id.owner,
                     local_id_root
                 )
             });
@@ -415,11 +415,6 @@ pub struct TypeckTables<'tcx> {
     /// this field will be set to `true`.
     pub tainted_by_errors: bool,
 
-    /// Stores the free-region relationships that were deduced from
-    /// its where-clauses and parameter types. These are then
-    /// read-again by borrowck.
-    pub free_region_map: FreeRegionMap<'tcx>,
-
     /// All the opaque types that are restricted to concrete types
     /// by this function.
     pub concrete_opaque_types: FxHashMap<DefId, ResolvedOpaqueTy<'tcx>>,
@@ -455,7 +450,6 @@ pub fn empty(local_id_root: Option<DefId>) -> TypeckTables<'tcx> {
             coercion_casts: Default::default(),
             used_trait_imports: Lrc::new(Default::default()),
             tainted_by_errors: false,
-            free_region_map: Default::default(),
             concrete_opaque_types: Default::default(),
             upvar_list: Default::default(),
             generator_interior_types: Default::default(),
@@ -611,7 +605,7 @@ pub fn is_method_call(&self, expr: &hir::Expr<'_>) -> bool {
         }
 
         match self.type_dependent_defs().get(expr.hir_id) {
-            Some(Ok((DefKind::Method, _))) => true,
+            Some(Ok((DefKind::AssocFn, _))) => true,
             _ => false,
         }
     }
@@ -718,7 +712,6 @@ fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHas
 
             ref used_trait_imports,
             tainted_by_errors,
-            ref free_region_map,
             ref concrete_opaque_types,
             ref upvar_list,
             ref generator_interior_types,
@@ -739,10 +732,12 @@ fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHas
 
                 let local_id_root = local_id_root.expect("trying to hash invalid TypeckTables");
 
-                let var_owner_def_id =
-                    DefId { krate: local_id_root.krate, index: var_path.hir_id.owner };
+                let var_owner_def_id = DefId {
+                    krate: local_id_root.krate,
+                    index: var_path.hir_id.owner.local_def_index,
+                };
                 let closure_def_id =
-                    DefId { krate: local_id_root.krate, index: closure_expr_id.to_def_id().index };
+                    DefId { krate: local_id_root.krate, index: closure_expr_id.local_def_index };
                 (
                     hcx.def_path_hash(var_owner_def_id),
                     var_path.hir_id.local_id,
@@ -756,7 +751,6 @@ fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHas
             coercion_casts.hash_stable(hcx, hasher);
             used_trait_imports.hash_stable(hcx, hasher);
             tainted_by_errors.hash_stable(hcx, hasher);
-            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);
@@ -916,9 +910,9 @@ pub struct FreeRegionInfo {
 /// The central data structure of the compiler. It stores references
 /// to the various **arenas** and also houses the results of the
 /// various **compiler queries** that have been performed. See the
-/// [rustc guide] for more details.
+/// [rustc dev guide] for more details.
 ///
-/// [rustc guide]: https://rust-lang.github.io/rustc-guide/ty.html
+/// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/ty.html
 #[derive(Copy, Clone)]
 #[rustc_diagnostic_item = "TyCtxt"]
 pub struct TyCtxt<'tcx> {
@@ -938,7 +932,7 @@ pub struct GlobalCtxt<'tcx> {
 
     interners: CtxtInterners<'tcx>,
 
-    cstore: Box<CrateStoreDyn>,
+    pub(crate) cstore: Box<CrateStoreDyn>,
 
     pub sess: &'tcx Session,
 
@@ -966,13 +960,13 @@ pub struct GlobalCtxt<'tcx> {
 
     /// Map indicating what traits are in scope for places where this
     /// is relevant; generated by resolve.
-    trait_map: FxHashMap<DefIndex, FxHashMap<ItemLocalId, StableVec<TraitCandidate>>>,
+    trait_map: FxHashMap<LocalDefId, FxHashMap<ItemLocalId, StableVec<TraitCandidate>>>,
 
     /// Export map produced by name resolution.
     export_map: FxHashMap<DefId, Vec<Export<hir::HirId>>>,
 
-    /// This should usually be accessed with the `tcx.hir()` method.
-    pub(crate) hir_map: hir_map::Map<'tcx>,
+    pub(crate) untracked_crate: &'tcx hir::Crate<'tcx>,
+    pub(crate) definitions: &'tcx Definitions,
 
     /// A map from `DefPathHash` -> `DefId`. Includes `DefId`s from the local crate
     /// as well as all upstream crates. Only populated in incremental mode.
@@ -1116,7 +1110,9 @@ pub fn create_global_ctxt(
         extern_providers: ty::query::Providers<'tcx>,
         arena: &'tcx WorkerLocal<Arena<'tcx>>,
         resolutions: ty::ResolverOutputs,
-        hir: hir_map::Map<'tcx>,
+        krate: &'tcx hir::Crate<'tcx>,
+        definitions: &'tcx Definitions,
+        dep_graph: DepGraph,
         on_disk_query_result_cache: query::OnDiskCache<'tcx>,
         crate_name: &str,
         output_filenames: &OutputFilenames,
@@ -1128,7 +1124,6 @@ pub fn create_global_ctxt(
         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);
@@ -1139,7 +1134,7 @@ pub fn create_global_ctxt(
             let def_path_tables = crates
                 .iter()
                 .map(|&cnum| (cnum, cstore.def_path_table(cnum)))
-                .chain(iter::once((LOCAL_CRATE, hir.definitions().def_path_table())));
+                .chain(iter::once((LOCAL_CRATE, definitions.def_path_table())));
 
             // Precompute the capacity of the hashmap so we don't have to
             // re-allocate when populating it.
@@ -1159,11 +1154,11 @@ pub fn create_global_ctxt(
 
         let mut trait_map: FxHashMap<_, FxHashMap<_, _>> = FxHashMap::default();
         for (k, v) in resolutions.trait_map {
-            let hir_id = hir.node_to_hir_id(k);
+            let hir_id = definitions.node_to_hir_id(k);
             let map = trait_map.entry(hir_id.owner).or_default();
             let v = v
                 .into_iter()
-                .map(|tc| tc.map_import_ids(|id| hir.definitions().node_to_hir_id(id)))
+                .map(|tc| tc.map_import_ids(|id| definitions.node_to_hir_id(id)))
                 .collect();
             map.insert(hir_id.local_id, StableVec::new(v));
         }
@@ -1185,28 +1180,31 @@ pub fn create_global_ctxt(
                 .export_map
                 .into_iter()
                 .map(|(k, v)| {
-                    let exports: Vec<_> =
-                        v.into_iter().map(|e| e.map_id(|id| hir.node_to_hir_id(id))).collect();
+                    let exports: Vec<_> = v
+                        .into_iter()
+                        .map(|e| e.map_id(|id| definitions.node_to_hir_id(id)))
+                        .collect();
                     (k, exports)
                 })
                 .collect(),
             maybe_unused_trait_imports: resolutions
                 .maybe_unused_trait_imports
                 .into_iter()
-                .map(|id| hir.local_def_id_from_node_id(id))
+                .map(|id| definitions.local_def_id(id))
                 .collect(),
             maybe_unused_extern_crates: resolutions
                 .maybe_unused_extern_crates
                 .into_iter()
-                .map(|(id, sp)| (hir.local_def_id_from_node_id(id), sp))
+                .map(|(id, sp)| (definitions.local_def_id(id), sp))
                 .collect(),
             glob_map: resolutions
                 .glob_map
                 .into_iter()
-                .map(|(id, names)| (hir.local_def_id_from_node_id(id), names))
+                .map(|(id, names)| (definitions.local_def_id(id), names))
                 .collect(),
             extern_prelude: resolutions.extern_prelude,
-            hir_map: hir,
+            untracked_crate: krate,
+            definitions,
             def_path_hash_to_def_id,
             queries: query::Queries::new(providers, extern_providers, on_disk_query_result_cache),
             rcache: Default::default(),
@@ -1265,7 +1263,7 @@ pub fn features(self) -> &'tcx rustc_feature::Features {
     }
 
     pub fn def_key(self, id: DefId) -> hir_map::DefKey {
-        if id.is_local() { self.hir().def_key(id) } else { self.cstore.def_key(id) }
+        if let Some(id) = id.as_local() { self.hir().def_key(id) } else { self.cstore.def_key(id) }
     }
 
     /// Converts a `DefId` into its fully expanded `DefPath` (every
@@ -1274,7 +1272,11 @@ pub fn def_key(self, id: DefId) -> hir_map::DefKey {
     /// Note that if `id` is not local to this crate, the result will
     ///  be a non-local `DefPath`.
     pub fn def_path(self, id: DefId) -> hir_map::DefPath {
-        if id.is_local() { self.hir().def_path(id) } else { self.cstore.def_path(id) }
+        if let Some(id) = id.as_local() {
+            self.hir().def_path(id)
+        } else {
+            self.cstore.def_path(id)
+        }
     }
 
     /// Returns whether or not the crate with CrateNum 'cnum'
@@ -1285,8 +1287,8 @@ pub fn is_private_dep(self, cnum: CrateNum) -> bool {
 
     #[inline]
     pub fn def_path_hash(self, def_id: DefId) -> hir_map::DefPathHash {
-        if def_id.is_local() {
-            self.hir().definitions().def_path_hash(def_id.index)
+        if let Some(def_id) = def_id.as_local() {
+            self.definitions.def_path_hash(def_id)
         } else {
             self.cstore.def_path_hash(def_id)
         }
@@ -1333,9 +1335,9 @@ pub fn cstore_as_any(self) -> &'tcx dyn Any {
 
     #[inline(always)]
     pub fn create_stable_hashing_context(self) -> StableHashingContext<'tcx> {
-        let krate = self.gcx.hir_map.untracked_krate();
+        let krate = self.gcx.untracked_crate;
 
-        StableHashingContext::new(self.sess, krate, self.hir().definitions(), &*self.cstore)
+        StableHashingContext::new(self.sess, krate, self.definitions, &*self.cstore)
     }
 
     // This method makes sure that we have a DepNode and a Fingerprint for
@@ -1515,20 +1517,21 @@ pub fn caller_location_ty(&self) -> Ty<'tcx> {
 
     /// Returns a displayable description and article for the given `def_id` (e.g. `("a", "struct")`).
     pub fn article_and_description(&self, def_id: DefId) -> (&'static str, &'static str) {
-        match self.def_key(def_id).disambiguated_data.data {
-            DefPathData::TypeNs(..) | DefPathData::ValueNs(..) | DefPathData::MacroNs(..) => {
-                let kind = self.def_kind(def_id).unwrap();
-                (kind.article(), kind.descr(def_id))
-            }
-            DefPathData::ClosureExpr => match self.generator_kind(def_id) {
-                None => ("a", "closure"),
-                Some(rustc_hir::GeneratorKind::Async(..)) => ("an", "async closure"),
-                Some(rustc_hir::GeneratorKind::Gen) => ("a", "generator"),
-            },
-            DefPathData::LifetimeNs(..) => ("a", "lifetime"),
-            DefPathData::Impl => ("an", "implementation"),
-            _ => bug!("article_and_description called on def_id {:?}", def_id),
-        }
+        self.def_kind(def_id)
+            .map(|def_kind| (def_kind.article(), def_kind.descr(def_id)))
+            .unwrap_or_else(|| match self.def_key(def_id).disambiguated_data.data {
+                DefPathData::ClosureExpr => match self.generator_kind(def_id) {
+                    None => ("a", "closure"),
+                    Some(rustc_hir::GeneratorKind::Async(..)) => ("an", "async closure"),
+                    Some(rustc_hir::GeneratorKind::Gen) => ("a", "generator"),
+                },
+                DefPathData::LifetimeNs(..) => ("a", "lifetime"),
+                DefPathData::Impl => ("an", "implementation"),
+                DefPathData::TypeNs(..) | DefPathData::ValueNs(..) | DefPathData::MacroNs(..) => {
+                    unreachable!()
+                }
+                _ => bug!("article_and_description called on def_id {:?}", def_id),
+            })
     }
 }
 
@@ -2256,22 +2259,22 @@ pub fn mk_ref(self, r: Region<'tcx>, tm: TypeAndMut<'tcx>) -> Ty<'tcx> {
 
     #[inline]
     pub fn mk_mut_ref(self, r: Region<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
-        self.mk_ref(r, TypeAndMut { ty: ty, mutbl: hir::Mutability::Mut })
+        self.mk_ref(r, TypeAndMut { ty, mutbl: hir::Mutability::Mut })
     }
 
     #[inline]
     pub fn mk_imm_ref(self, r: Region<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
-        self.mk_ref(r, TypeAndMut { ty: ty, mutbl: hir::Mutability::Not })
+        self.mk_ref(r, TypeAndMut { ty, mutbl: hir::Mutability::Not })
     }
 
     #[inline]
     pub fn mk_mut_ptr(self, ty: Ty<'tcx>) -> Ty<'tcx> {
-        self.mk_ptr(TypeAndMut { ty: ty, mutbl: hir::Mutability::Mut })
+        self.mk_ptr(TypeAndMut { ty, mutbl: hir::Mutability::Mut })
     }
 
     #[inline]
     pub fn mk_imm_ptr(self, ty: Ty<'tcx>) -> Ty<'tcx> {
-        self.mk_ptr(TypeAndMut { ty: ty, mutbl: hir::Mutability::Not })
+        self.mk_ptr(TypeAndMut { ty, mutbl: hir::Mutability::Not })
     }
 
     #[inline]
@@ -2393,7 +2396,7 @@ pub fn mk_const_infer(self, ic: InferConst<'tcx>, ty: Ty<'tcx>) -> &'tcx ty::Con
 
     #[inline]
     pub fn mk_ty_param(self, index: u32, name: Symbol) -> Ty<'tcx> {
-        self.mk_ty(Param(ParamTy { index, name: name }))
+        self.mk_ty(Param(ParamTy { index, name }))
     }
 
     #[inline]
@@ -2750,18 +2753,15 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) {
     };
 
     providers.lookup_stability = |tcx, id| {
-        assert_eq!(id.krate, LOCAL_CRATE);
-        let id = tcx.hir().definitions().def_index_to_hir_id(id.index);
+        let id = tcx.hir().local_def_id_to_hir_id(id.expect_local());
         tcx.stability().local_stability(id)
     };
     providers.lookup_const_stability = |tcx, id| {
-        assert_eq!(id.krate, LOCAL_CRATE);
-        let id = tcx.hir().definitions().def_index_to_hir_id(id.index);
+        let id = tcx.hir().local_def_id_to_hir_id(id.expect_local());
         tcx.stability().local_const_stability(id)
     };
     providers.lookup_deprecation_entry = |tcx, id| {
-        assert_eq!(id.krate, LOCAL_CRATE);
-        let id = tcx.hir().definitions().def_index_to_hir_id(id.index);
+        let id = tcx.hir().local_def_id_to_hir_id(id.expect_local());
         tcx.stability().local_deprecation_entry(id)
     };
     providers.extern_mod_stmt_cnum = |tcx, id| {
index 4546eadc6e6e13c11be294577d9a357782d0bf12..5243e1fbf579b70cff52847ceadd1a135b41191a 100644 (file)
@@ -80,13 +80,10 @@ fn add_kind(&mut self, kind: &ty::TyKind<'_>) {
             &ty::Error => self.add_flags(TypeFlags::HAS_TY_ERR),
 
             &ty::Param(_) => {
-                self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES);
-                self.add_flags(TypeFlags::HAS_PARAMS);
+                self.add_flags(TypeFlags::HAS_TY_PARAM);
             }
 
             &ty::Generator(_, ref substs, _) => {
-                self.add_flags(TypeFlags::HAS_TY_CLOSURE);
-                self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES);
                 self.add_substs(substs);
             }
 
@@ -97,8 +94,6 @@ fn add_kind(&mut self, kind: &ty::TyKind<'_>) {
             }
 
             &ty::Closure(_, ref substs) => {
-                self.add_flags(TypeFlags::HAS_TY_CLOSURE);
-                self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES);
                 self.add_substs(substs);
             }
 
@@ -107,12 +102,10 @@ fn add_kind(&mut self, kind: &ty::TyKind<'_>) {
             }
 
             &ty::Placeholder(..) => {
-                self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES);
                 self.add_flags(TypeFlags::HAS_TY_PLACEHOLDER);
             }
 
             &ty::Infer(infer) => {
-                self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES); // it might, right?
                 self.add_flags(TypeFlags::HAS_TY_INFER);
                 match infer {
                     ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => {}
@@ -128,17 +121,17 @@ fn add_kind(&mut self, kind: &ty::TyKind<'_>) {
             }
 
             &ty::Projection(ref data) => {
-                self.add_flags(TypeFlags::HAS_PROJECTION);
+                self.add_flags(TypeFlags::HAS_TY_PROJECTION);
                 self.add_projection_ty(data);
             }
 
             &ty::UnnormalizedProjection(ref data) => {
-                self.add_flags(TypeFlags::HAS_PROJECTION);
+                self.add_flags(TypeFlags::HAS_TY_PROJECTION);
                 self.add_projection_ty(data);
             }
 
             &ty::Opaque(_, substs) => {
-                self.add_flags(TypeFlags::HAS_PROJECTION | TypeFlags::HAS_TY_OPAQUE);
+                self.add_flags(TypeFlags::HAS_TY_OPAQUE);
                 self.add_substs(substs);
             }
 
@@ -221,10 +214,10 @@ fn add_const(&mut self, c: &ty::Const<'_>) {
         match c.val {
             ty::ConstKind::Unevaluated(_, substs, _) => {
                 self.add_substs(substs);
-                self.add_flags(TypeFlags::HAS_PROJECTION);
+                self.add_flags(TypeFlags::HAS_CT_PROJECTION);
             }
             ty::ConstKind::Infer(infer) => {
-                self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES | TypeFlags::HAS_CT_INFER);
+                self.add_flags(TypeFlags::HAS_CT_INFER);
                 match infer {
                     InferConst::Fresh(_) => {}
                     InferConst::Var(_) => self.add_flags(TypeFlags::KEEP_IN_LOCAL_TCX),
@@ -232,11 +225,9 @@ fn add_const(&mut self, c: &ty::Const<'_>) {
             }
             ty::ConstKind::Bound(debruijn, _) => self.add_binder(debruijn),
             ty::ConstKind::Param(_) => {
-                self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES);
-                self.add_flags(TypeFlags::HAS_PARAMS);
+                self.add_flags(TypeFlags::HAS_CT_PARAM);
             }
             ty::ConstKind::Placeholder(_) => {
-                self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES);
                 self.add_flags(TypeFlags::HAS_CT_PLACEHOLDER);
             }
             ty::ConstKind::Value(_) => {}
index 3212bc7241783df6a4f3e506b4d2ea495295b3c9..4adca6c7d97723fc9da8bd663744ee4ff4a38b36 100644 (file)
@@ -85,11 +85,14 @@ fn references_error(&self) -> bool {
         self.has_type_flags(TypeFlags::HAS_TY_ERR)
     }
     fn has_param_types(&self) -> bool {
-        self.has_type_flags(TypeFlags::HAS_PARAMS)
+        self.has_type_flags(TypeFlags::HAS_TY_PARAM | TypeFlags::HAS_CT_PARAM)
     }
     fn has_infer_types(&self) -> bool {
         self.has_type_flags(TypeFlags::HAS_TY_INFER)
     }
+    fn has_infer_types_or_consts(&self) -> bool {
+        self.has_type_flags(TypeFlags::HAS_TY_INFER | TypeFlags::HAS_CT_INFER)
+    }
     fn has_infer_consts(&self) -> bool {
         self.has_type_flags(TypeFlags::HAS_CT_INFER)
     }
@@ -97,9 +100,7 @@ fn has_local_value(&self) -> bool {
         self.has_type_flags(TypeFlags::KEEP_IN_LOCAL_TCX)
     }
     fn needs_infer(&self) -> bool {
-        self.has_type_flags(
-            TypeFlags::HAS_TY_INFER | TypeFlags::HAS_RE_INFER | TypeFlags::HAS_CT_INFER,
-        )
+        self.has_type_flags(TypeFlags::NEEDS_INFER)
     }
     fn has_placeholders(&self) -> bool {
         self.has_type_flags(
@@ -114,9 +115,6 @@ fn needs_subst(&self) -> bool {
     fn has_re_placeholders(&self) -> bool {
         self.has_type_flags(TypeFlags::HAS_RE_PLACEHOLDER)
     }
-    fn has_closure_types(&self) -> bool {
-        self.has_type_flags(TypeFlags::HAS_TY_CLOSURE)
-    }
     /// "Free" regions in this context means that it has any region
     /// that is not (a) erased or (b) late-bound.
     fn has_free_regions(&self) -> bool {
index 144e3bc9c8bc6d16cb5e6962948ce2d01a29a3a2..b166c4dea0c850f1e50259a2044cbdc3fed74c95 100644 (file)
@@ -90,30 +90,46 @@ impl<'tcx> TyCtxt<'tcx> {
     /// ```
     /// This code should only compile in modules where the uninhabitedness of Foo is
     /// visible.
-    pub fn is_ty_uninhabited_from(self, module: DefId, ty: Ty<'tcx>) -> bool {
+    pub fn is_ty_uninhabited_from(
+        self,
+        module: DefId,
+        ty: Ty<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+    ) -> bool {
         // To check whether this type is uninhabited at all (not just from the
         // given node), you could check whether the forest is empty.
         // ```
         // forest.is_empty()
         // ```
-        ty.uninhabited_from(self).contains(self, module)
+        ty.uninhabited_from(self, param_env).contains(self, module)
     }
 
-    pub fn is_ty_uninhabited_from_any_module(self, ty: Ty<'tcx>) -> bool {
-        !ty.uninhabited_from(self).is_empty()
+    pub fn is_ty_uninhabited_from_any_module(
+        self,
+        ty: Ty<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+    ) -> bool {
+        !ty.uninhabited_from(self, param_env).is_empty()
     }
 }
 
 impl<'tcx> AdtDef {
     /// Calculates the forest of `DefId`s from which this ADT is visibly uninhabited.
-    fn uninhabited_from(&self, tcx: TyCtxt<'tcx>, substs: SubstsRef<'tcx>) -> DefIdForest {
+    fn uninhabited_from(
+        &self,
+        tcx: TyCtxt<'tcx>,
+        substs: SubstsRef<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+    ) -> DefIdForest {
         // Non-exhaustive ADTs from other crates are always considered inhabited.
         if self.is_variant_list_non_exhaustive() && !self.did.is_local() {
             DefIdForest::empty()
         } else {
             DefIdForest::intersection(
                 tcx,
-                self.variants.iter().map(|v| v.uninhabited_from(tcx, substs, self.adt_kind())),
+                self.variants
+                    .iter()
+                    .map(|v| v.uninhabited_from(tcx, substs, self.adt_kind(), param_env)),
             )
         }
     }
@@ -126,6 +142,7 @@ pub fn uninhabited_from(
         tcx: TyCtxt<'tcx>,
         substs: SubstsRef<'tcx>,
         adt_kind: AdtKind,
+        param_env: ty::ParamEnv<'tcx>,
     ) -> DefIdForest {
         let is_enum = match adt_kind {
             // For now, `union`s are never considered uninhabited.
@@ -140,7 +157,7 @@ pub fn uninhabited_from(
         } else {
             DefIdForest::union(
                 tcx,
-                self.fields.iter().map(|f| f.uninhabited_from(tcx, substs, is_enum)),
+                self.fields.iter().map(|f| f.uninhabited_from(tcx, substs, is_enum, param_env)),
             )
         }
     }
@@ -153,8 +170,9 @@ fn uninhabited_from(
         tcx: TyCtxt<'tcx>,
         substs: SubstsRef<'tcx>,
         is_enum: bool,
+        param_env: ty::ParamEnv<'tcx>,
     ) -> DefIdForest {
-        let data_uninhabitedness = move || self.ty(tcx, substs).uninhabited_from(tcx);
+        let data_uninhabitedness = move || self.ty(tcx, substs).uninhabited_from(tcx, param_env);
         // FIXME(canndrew): Currently enum fields are (incorrectly) stored with
         // `Visibility::Invisible` so we need to override `self.vis` if we're
         // dealing with an enum.
@@ -176,20 +194,21 @@ fn uninhabited_from(
 
 impl<'tcx> TyS<'tcx> {
     /// Calculates the forest of `DefId`s from which this type is visibly uninhabited.
-    fn uninhabited_from(&self, tcx: TyCtxt<'tcx>) -> DefIdForest {
+    fn uninhabited_from(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> DefIdForest {
         match self.kind {
-            Adt(def, substs) => def.uninhabited_from(tcx, substs),
+            Adt(def, substs) => def.uninhabited_from(tcx, substs, param_env),
 
             Never => DefIdForest::full(tcx),
 
-            Tuple(ref tys) => {
-                DefIdForest::union(tcx, tys.iter().map(|ty| ty.expect_ty().uninhabited_from(tcx)))
-            }
+            Tuple(ref tys) => DefIdForest::union(
+                tcx,
+                tys.iter().map(|ty| ty.expect_ty().uninhabited_from(tcx, param_env)),
+            ),
 
-            Array(ty, len) => match len.try_eval_usize(tcx, ty::ParamEnv::empty()) {
+            Array(ty, len) => match len.try_eval_usize(tcx, param_env) {
                 // If the array is definitely non-empty, it's uninhabited if
                 // the type of its elements is uninhabited.
-                Some(n) if n != 0 => ty.uninhabited_from(tcx),
+                Some(n) if n != 0 => ty.uninhabited_from(tcx, param_env),
                 _ => DefIdForest::empty(),
             },
 
index f65822aba4c9ecab6d7c49f74e2fd9ebff502785..13d58ea73ac6b9074b8d93b09301d67479997e36 100644 (file)
@@ -39,6 +39,10 @@ pub enum InstanceDef<'tcx> {
 
     /// `<fn() as FnTrait>::call_*`
     /// `DefId` is `FnTrait::call_*`.
+    ///
+    /// NB: the (`fn` pointer) type must currently be monomorphic to avoid double substitution
+    /// problems with the MIR shim bodies. `Instance::resolve` enforces this.
+    // FIXME(#69925) support polymorphic MIR shim bodies properly instead.
     FnPtrShim(DefId, Ty<'tcx>),
 
     /// `<dyn Trait as Trait>::fn`, "direct calls" of which are implicitly
@@ -57,9 +61,17 @@ pub enum InstanceDef<'tcx> {
     /// The `DefId` is for `core::ptr::drop_in_place`.
     /// The `Option<Ty<'tcx>>` is either `Some(T)`, or `None` for empty drop
     /// glue.
+    ///
+    /// NB: the type must currently be monomorphic to avoid double substitution
+    /// problems with the MIR shim bodies. `Instance::resolve` enforces this.
+    // FIXME(#69925) support polymorphic MIR shim bodies properly instead.
     DropGlue(DefId, Option<Ty<'tcx>>),
 
     ///`<T as Clone>::clone` shim.
+    ///
+    /// NB: the type must currently be monomorphic to avoid double substitution
+    /// problems with the MIR shim bodies. `Instance::resolve` enforces this.
+    // FIXME(#69925) support polymorphic MIR shim bodies properly instead.
     CloneShim(DefId, Ty<'tcx>),
 }
 
@@ -115,9 +127,7 @@ pub fn upstream_monomorphization(&self, tcx: TyCtxt<'tcx>) -> Option<CrateNum> {
         }
 
         // If this a non-generic instance, it cannot be a shared monomorphization.
-        if self.substs.non_erasable_generics().next().is_none() {
-            return None;
-        }
+        self.substs.non_erasable_generics().next()?;
 
         match self.def {
             InstanceDef::Item(def_id) => tcx
@@ -243,7 +253,7 @@ pub fn new(def_id: DefId, substs: SubstsRef<'tcx>) -> Instance<'tcx> {
             def_id,
             substs
         );
-        Instance { def: InstanceDef::Item(def_id), substs: substs }
+        Instance { def: InstanceDef::Item(def_id), substs }
     }
 
     pub fn mono(tcx: TyCtxt<'tcx>, def_id: DefId) -> Instance<'tcx> {
@@ -371,6 +381,32 @@ pub fn fn_once_adapter_instance(
         Instance { def, substs }
     }
 
+    /// FIXME(#69925) Depending on the kind of `InstanceDef`, the MIR body associated with an
+    /// instance is expressed in terms of the generic parameters of `self.def_id()`, and in other
+    /// cases the MIR body is expressed in terms of the types found in the substitution array.
+    /// In the former case, we want to substitute those generic types and replace them with the
+    /// values from the substs when monomorphizing the function body. But in the latter case, we
+    /// don't want to do that substitution, since it has already been done effectively.
+    ///
+    /// This function returns `Some(substs)` in the former case and None otherwise -- i.e., if
+    /// this function returns `None`, then the MIR body does not require substitution during
+    /// monomorphization.
+    pub fn substs_for_mir_body(&self) -> Option<SubstsRef<'tcx>> {
+        match self.def {
+            InstanceDef::CloneShim(..)
+            | InstanceDef::DropGlue(_, Some(_)) => None,
+            InstanceDef::ClosureOnceShim { .. }
+            | InstanceDef::DropGlue(..)
+            // FIXME(#69925): `FnPtrShim` should be in the other branch.
+            | InstanceDef::FnPtrShim(..)
+            | InstanceDef::Item(_)
+            | InstanceDef::Intrinsic(..)
+            | InstanceDef::ReifyShim(..)
+            | InstanceDef::Virtual(..)
+            | InstanceDef::VtableShim(..) => Some(self.substs),
+        }
+    }
+
     pub fn is_vtable_shim(&self) -> bool {
         if let InstanceDef::VtableShim(..) = self.def { true } else { false }
     }
index e10c024143564301ca72acde3cee6c0aa973e8a6..6d28796b34847231c42291b6de331f6f9f41c268 100644 (file)
@@ -1,31 +1,28 @@
-use crate::session::{self, DataTypeKind};
+use crate::ich::StableHashingContext;
+use crate::mir::{GeneratorLayout, GeneratorSavedLocal};
+use crate::ty::subst::Subst;
 use crate::ty::{self, subst::SubstsRef, ReprOptions, Ty, TyCtxt, TypeFoldable};
 
 use rustc_ast::ast::{self, Ident, IntTy, UintTy};
 use rustc_attr as attr;
-use rustc_span::DUMMY_SP;
-
-use std::cmp;
-use std::fmt;
-use std::i128;
-use std::iter;
-use std::mem;
-use std::ops::Bound;
-
-use crate::ich::StableHashingContext;
-use crate::mir::{GeneratorLayout, GeneratorSavedLocal};
-use crate::ty::subst::Subst;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_hir as hir;
 use rustc_index::bit_set::BitSet;
 use rustc_index::vec::{Idx, IndexVec};
-
+use rustc_session::{DataTypeKind, FieldInfo, SizeKind, VariantInfo};
+use rustc_span::DUMMY_SP;
 use rustc_target::abi::call::{
     ArgAbi, ArgAttribute, ArgAttributes, Conv, FnAbi, PassMode, Reg, RegKind,
 };
 pub use rustc_target::abi::*;
 use rustc_target::spec::{abi::Abi as SpecAbi, HasTargetSpec};
 
+use std::cmp;
+use std::fmt;
+use std::iter;
+use std::mem;
+use std::ops::Bound;
+
 pub trait IntegerExt {
     fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>, signed: bool) -> Ty<'tcx>;
     fn from_attr<C: HasDataLayout>(cx: &C, ity: attr::IntType) -> Integer;
@@ -502,7 +499,7 @@ fn layout_raw_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx LayoutDetails, Layou
         let univariant = |fields: &[TyLayout<'_>], repr: &ReprOptions, kind| {
             Ok(tcx.intern_layout(self.univariant_uninterned(ty, fields, repr, kind)?))
         };
-        debug_assert!(!ty.has_infer_types());
+        debug_assert!(!ty.has_infer_types_or_consts());
 
         Ok(match ty.kind {
             // Basic scalars.
@@ -783,8 +780,8 @@ fn layout_raw_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx LayoutDetails, Layou
                     present_first @ Some(_) => present_first,
                     // 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
+                    // If it's a struct, still compute a layout so that we can still compute the
+                    // field offsets.
                     None => Some(VariantIdx::new(0)),
                 };
 
@@ -1001,7 +998,7 @@ fn layout_raw_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx LayoutDetails, Layou
                     }
                 }
 
-                let (mut min, mut max) = (i128::max_value(), i128::min_value());
+                let (mut min, mut max) = (i128::MAX, i128::MIN);
                 let discr_type = def.repr.discr_type();
                 let bits = Integer::from_attr(self, discr_type).size().bits();
                 for (i, discr) in def.discriminants(tcx) {
@@ -1021,7 +1018,7 @@ fn layout_raw_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx LayoutDetails, Layou
                     }
                 }
                 // We might have no inhabited variants, so pretend there's at least one.
-                if (min, max) == (i128::max_value(), i128::min_value()) {
+                if (min, max) == (i128::MAX, i128::MIN) {
                     min = 0;
                     max = 0;
                 }
@@ -1382,10 +1379,8 @@ fn generator_saved_local_eligibility(
 
         // Write down the order of our locals that will be promoted to the prefix.
         {
-            let mut idx = 0u32;
-            for local in ineligible_locals.iter() {
-                assignments[local] = Ineligible(Some(idx));
-                idx += 1;
+            for (idx, local) in ineligible_locals.iter().enumerate() {
+                assignments[local] = Ineligible(Some(idx as u32));
             }
         }
         debug!("generator saved local assignments: {:?}", assignments);
@@ -1412,12 +1407,15 @@ fn generator_layout(
         // 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();
-        // FIXME(eddyb) set the correct vaidity range for the discriminant.
-        let discr_layout = self.layout_of(substs.as_generator().discr_ty(tcx))?;
-        let discr = match &discr_layout.abi {
-            Abi::Scalar(s) => s.clone(),
-            _ => bug!(),
-        };
+
+        // `info.variant_fields` already accounts for the reserved variants, so no need to add them.
+        let max_discr = (info.variant_fields.len() - 1) as u128;
+        let discr_int = Integer::fit_unsigned(max_discr);
+        let discr_int_ty = discr_int.to_ty(tcx, false);
+        let discr = Scalar { value: Primitive::Int(discr_int, false), valid_range: 0..=max_discr };
+        let discr_layout = self.tcx.intern_layout(LayoutDetails::scalar(self, discr.clone()));
+        let discr_layout = TyLayout { ty: discr_int_ty, details: discr_layout };
+
         let promoted_layouts = ineligible_locals
             .iter()
             .map(|local| subst_field(info.field_tys[local]))
@@ -1651,7 +1649,7 @@ fn record_layout_for_printing_outlined(&self, layout: TyLayout<'tcx>) {
                         if min_size < field_end {
                             min_size = field_end;
                         }
-                        session::FieldInfo {
+                        FieldInfo {
                             name: name.to_string(),
                             offset: offset.bytes(),
                             size: field_layout.size.bytes(),
@@ -1661,13 +1659,9 @@ fn record_layout_for_printing_outlined(&self, layout: TyLayout<'tcx>) {
                 })
                 .collect();
 
-            session::VariantInfo {
+            VariantInfo {
                 name: n.map(|n| n.to_string()),
-                kind: if layout.is_unsized() {
-                    session::SizeKind::Min
-                } else {
-                    session::SizeKind::Exact
-                },
+                kind: if layout.is_unsized() { SizeKind::Min } else { SizeKind::Exact },
                 align: layout.align.abi.bytes(),
                 size: if min_size.bytes() == 0 { layout.size.bytes() } else { min_size.bytes() },
                 fields: field_info,
@@ -1752,7 +1746,7 @@ pub fn compute(
         tcx: TyCtxt<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
     ) -> Result<SizeSkeleton<'tcx>, LayoutError<'tcx>> {
-        debug_assert!(!ty.has_infer_types());
+        debug_assert!(!ty.has_infer_types_or_consts());
 
         // First try computing a static layout.
         let err = match tcx.layout_of(param_env.and(ty)) {
@@ -1907,36 +1901,6 @@ fn tcx(&self) -> TyCtxt<'tcx> {
     }
 }
 
-pub trait MaybeResult<T> {
-    type Error;
-
-    fn from(x: Result<T, Self::Error>) -> Self;
-    fn to_result(self) -> Result<T, Self::Error>;
-}
-
-impl<T> MaybeResult<T> for T {
-    type Error = !;
-
-    fn from(x: Result<T, Self::Error>) -> Self {
-        let Ok(x) = x;
-        x
-    }
-    fn to_result(self) -> Result<T, Self::Error> {
-        Ok(self)
-    }
-}
-
-impl<T, E> MaybeResult<T> for Result<T, E> {
-    type Error = E;
-
-    fn from(x: Result<T, Self::Error>) -> Self {
-        x
-    }
-    fn to_result(self) -> Result<T, Self::Error> {
-        self
-    }
-}
-
 pub type TyLayout<'tcx> = ::rustc_target::abi::TyLayout<'tcx, Ty<'tcx>>;
 
 impl<'tcx> LayoutOf for LayoutCx<'tcx, TyCtxt<'tcx>> {
@@ -2023,7 +1987,15 @@ impl<'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx>
 {
     fn for_variant(this: TyLayout<'tcx>, cx: &C, variant_index: VariantIdx) -> TyLayout<'tcx> {
         let details = match this.variants {
-            Variants::Single { index } if index == variant_index => this.details,
+            Variants::Single { index }
+                // If all variants but one are uninhabited, the variant layout is the enum layout.
+                if index == variant_index &&
+                // Don't confuse variants of uninhabited enums with the enum itself.
+                // For more details see https://github.com/rust-lang/rust/issues/69763.
+                this.fields != FieldPlacement::Union(0) =>
+            {
+                this.details
+            }
 
             Variants::Single { index } => {
                 // Deny calling for_variant more than once for non-Single enums.
@@ -2582,7 +2554,7 @@ fn new_internal(
                 if let Some(kind) = pointee.safe {
                     attrs.pointee_align = Some(pointee.align);
 
-                    // `Box` (`UniqueBorrowed`) are not necessarily dereferencable
+                    // `Box` (`UniqueBorrowed`) are not necessarily dereferenceable
                     // for the entire duration of the function as they can be deallocated
                     // any time. Set their valid size to 0.
                     attrs.pointee_size = match kind {
index c9e58b6c771c0883480e3b31c056c81451157108..9e3853c51af13cb04afeb63fd9ad8d6b8058bfc8 100644 (file)
@@ -9,7 +9,6 @@
 use crate::arena::Arena;
 use crate::hir::exports::ExportMap;
 use crate::hir::map as hir_map;
-
 use crate::ich::Fingerprint;
 use crate::ich::StableHashingContext;
 use crate::infer::canonical::Canonical;
@@ -19,7 +18,6 @@
 use crate::mir::interpret::ErrorHandled;
 use crate::mir::GeneratorLayout;
 use crate::mir::ReadOnlyBodyAndCache;
-use crate::session::DataTypeKind;
 use crate::traits::{self, Reveal};
 use crate::ty;
 use crate::ty::layout::VariantIdx;
@@ -42,6 +40,7 @@
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_macros::HashStable;
 use rustc_serialize::{self, Encodable, Encoder};
+use rustc_session::DataTypeKind;
 use rustc_span::hygiene::ExpnId;
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::Span;
@@ -230,7 +229,7 @@ impl AssocItem {
     pub fn def_kind(&self) -> DefKind {
         match self.kind {
             AssocKind::Const => DefKind::AssocConst,
-            AssocKind::Method => DefKind::Method,
+            AssocKind::Method => DefKind::AssocFn,
             AssocKind::Type => DefKind::AssocTy,
             AssocKind::OpaqueTy => DefKind::AssocOpaqueTy,
         }
@@ -370,7 +369,7 @@ fn is_descendant_of(self, mut descendant: DefId, ancestor: DefId) -> bool {
 
 impl<'tcx> DefIdTree for TyCtxt<'tcx> {
     fn parent(self, id: DefId) -> Option<DefId> {
-        self.def_key(id).parent.map(|index| DefId { index: index, ..id })
+        self.def_key(id).parent.map(|index| DefId { index, ..id })
     }
 }
 
@@ -385,7 +384,9 @@ pub fn from_hir(visibility: &hir::Visibility<'_>, id: hir::HirId, tcx: TyCtxt<'_
                 Res::Err => Visibility::Public,
                 def => Visibility::Restricted(def.def_id()),
             },
-            hir::VisibilityKind::Inherited => Visibility::Restricted(tcx.parent_module(id)),
+            hir::VisibilityKind::Inherited => {
+                Visibility::Restricted(tcx.parent_module(id).to_def_id())
+            }
         }
     }
 
@@ -515,79 +516,110 @@ pub struct CReaderCacheKey {
     pub pos: usize,
 }
 
-// Flags that we track on types. These flags are propagated upwards
-// through the type during type construction, so that we can quickly
-// check whether the type has various kinds of types in it without
-// recursing over the type itself.
 bitflags! {
+    /// Flags that we track on types. These flags are propagated upwards
+    /// through the type during type construction, so that we can quickly check
+    /// whether the type has various kinds of types in it without recursing
+    /// over the type itself.
     pub struct TypeFlags: u32 {
-        const HAS_PARAMS         = 1 << 0;
-        const HAS_TY_INFER       = 1 << 1;
-        const HAS_RE_INFER       = 1 << 2;
-        const HAS_RE_PLACEHOLDER = 1 << 3;
-
-        /// Does this have any `ReEarlyBound` regions? Used to
-        /// determine whether substitition is required, since those
-        /// represent regions that are bound in a `ty::Generics` and
-        /// hence may be substituted.
-        const HAS_RE_EARLY_BOUND = 1 << 4;
-
-        /// Does this have any region that "appears free" in the type?
-        /// Basically anything but `ReLateBound` and `ReErased`.
-        const HAS_FREE_REGIONS   = 1 << 5;
-
-        /// Is an error type reachable?
-        const HAS_TY_ERR         = 1 << 6;
-        const HAS_PROJECTION     = 1 << 7;
-
-        // FIXME: Rename this to the actual property since it's used for generators too
-        const HAS_TY_CLOSURE     = 1 << 8;
+        // Does this have parameters? Used to determine whether substitution is
+        // required.
+        /// Does this have [Param]?
+        const HAS_TY_PARAM              = 1 << 0;
+        /// Does this have [ReEarlyBound]?
+        const HAS_RE_PARAM              = 1 << 1;
+        /// Does this have [ConstKind::Param]?
+        const HAS_CT_PARAM              = 1 << 2;
+
+        const NEEDS_SUBST               = TypeFlags::HAS_TY_PARAM.bits
+                                        | TypeFlags::HAS_RE_PARAM.bits
+                                        | TypeFlags::HAS_CT_PARAM.bits;
+
+        /// Does this have [Infer]?
+        const HAS_TY_INFER              = 1 << 3;
+        /// Does this have [ReVar]?
+        const HAS_RE_INFER              = 1 << 4;
+        /// Does this have [ConstKind::Infer]?
+        const HAS_CT_INFER              = 1 << 5;
+
+        /// Does this have inference variables? Used to determine whether
+        /// inference is required.
+        const NEEDS_INFER               = TypeFlags::HAS_TY_INFER.bits
+                                        | TypeFlags::HAS_RE_INFER.bits
+                                        | TypeFlags::HAS_CT_INFER.bits;
+
+        /// Does this have [Placeholder]?
+        const HAS_TY_PLACEHOLDER        = 1 << 6;
+        /// Does this have [RePlaceholder]?
+        const HAS_RE_PLACEHOLDER        = 1 << 7;
+        /// Does this have [ConstKind::Placeholder]?
+        const HAS_CT_PLACEHOLDER        = 1 << 8;
+
+        /// `true` if there are "names" of regions and so forth
+        /// that are local to a particular fn/inferctxt
+        const HAS_FREE_LOCAL_REGIONS    = 1 << 9;
 
         /// `true` if there are "names" of types and regions and so forth
         /// that are local to a particular fn
-        const HAS_FREE_LOCAL_NAMES = 1 << 9;
+        const HAS_FREE_LOCAL_NAMES      = TypeFlags::HAS_TY_PARAM.bits
+                                        | TypeFlags::HAS_CT_PARAM.bits
+                                        | TypeFlags::HAS_TY_INFER.bits
+                                        | TypeFlags::HAS_CT_INFER.bits
+                                        | TypeFlags::HAS_TY_PLACEHOLDER.bits
+                                        | TypeFlags::HAS_CT_PLACEHOLDER.bits
+                                        | TypeFlags::HAS_FREE_LOCAL_REGIONS.bits;
+
+        /// Does this have [Projection] or [UnnormalizedProjection]?
+        const HAS_TY_PROJECTION         = 1 << 10;
+        /// Does this have [Opaque]?
+        const HAS_TY_OPAQUE             = 1 << 11;
+        /// Does this have [ConstKind::Unevaluated]?
+        const HAS_CT_PROJECTION         = 1 << 12;
+
+        /// Could this type be normalized further?
+        const HAS_PROJECTION            = TypeFlags::HAS_TY_PROJECTION.bits
+                                        | TypeFlags::HAS_TY_OPAQUE.bits
+                                        | TypeFlags::HAS_CT_PROJECTION.bits;
 
         /// Present if the type belongs in a local type context.
-        /// Only set for Infer other than Fresh.
-        const KEEP_IN_LOCAL_TCX  = 1 << 10;
+        /// Set for placeholders and inference variables that are not "Fresh".
+        const KEEP_IN_LOCAL_TCX         = 1 << 13;
 
-        /// Does this have any `ReLateBound` regions? Used to check
-        /// if a global bound is safe to evaluate.
-        const HAS_RE_LATE_BOUND  = 1 << 11;
-
-        /// Does this have any `ReErased` regions?
-        const HAS_RE_ERASED  = 1 << 12;
+        /// Is an error type reachable?
+        const HAS_TY_ERR                = 1 << 14;
 
-        const HAS_TY_PLACEHOLDER = 1 << 13;
+        /// Does this have any region that "appears free" in the type?
+        /// Basically anything but [ReLateBound] and [ReErased].
+        const HAS_FREE_REGIONS          = 1 << 15;
 
-        const HAS_CT_INFER       = 1 << 14;
-        const HAS_CT_PLACEHOLDER = 1 << 15;
-        /// Does this have any [Opaque] types.
-        const HAS_TY_OPAQUE      = 1 << 16;
+        /// Does this have any [ReLateBound] regions? Used to check
+        /// if a global bound is safe to evaluate.
+        const HAS_RE_LATE_BOUND         = 1 << 16;
 
-        const NEEDS_SUBST        = TypeFlags::HAS_PARAMS.bits |
-                                   TypeFlags::HAS_RE_EARLY_BOUND.bits;
+        /// Does this have any [ReErased] regions?
+        const HAS_RE_ERASED             = 1 << 17;
 
         /// Flags representing the nominal content of a type,
         /// computed by FlagsComputation. If you add a new nominal
         /// flag, it should be added here too.
-        const NOMINAL_FLAGS     = TypeFlags::HAS_PARAMS.bits |
-                                  TypeFlags::HAS_TY_INFER.bits |
-                                  TypeFlags::HAS_RE_INFER.bits |
-                                  TypeFlags::HAS_RE_PLACEHOLDER.bits |
-                                  TypeFlags::HAS_RE_EARLY_BOUND.bits |
-                                  TypeFlags::HAS_FREE_REGIONS.bits |
-                                  TypeFlags::HAS_TY_ERR.bits |
-                                  TypeFlags::HAS_PROJECTION.bits |
-                                  TypeFlags::HAS_TY_CLOSURE.bits |
-                                  TypeFlags::HAS_FREE_LOCAL_NAMES.bits |
-                                  TypeFlags::KEEP_IN_LOCAL_TCX.bits |
-                                  TypeFlags::HAS_RE_LATE_BOUND.bits |
-                                  TypeFlags::HAS_RE_ERASED.bits |
-                                  TypeFlags::HAS_TY_PLACEHOLDER.bits |
-                                  TypeFlags::HAS_CT_INFER.bits |
-                                  TypeFlags::HAS_CT_PLACEHOLDER.bits |
-                                  TypeFlags::HAS_TY_OPAQUE.bits;
+        const NOMINAL_FLAGS             = TypeFlags::HAS_TY_PARAM.bits
+                                        | TypeFlags::HAS_RE_PARAM.bits
+                                        | TypeFlags::HAS_CT_PARAM.bits
+                                        | TypeFlags::HAS_TY_INFER.bits
+                                        | TypeFlags::HAS_RE_INFER.bits
+                                        | TypeFlags::HAS_CT_INFER.bits
+                                        | TypeFlags::HAS_TY_PLACEHOLDER.bits
+                                        | TypeFlags::HAS_RE_PLACEHOLDER.bits
+                                        | TypeFlags::HAS_CT_PLACEHOLDER.bits
+                                        | TypeFlags::HAS_FREE_LOCAL_REGIONS.bits
+                                        | TypeFlags::HAS_TY_PROJECTION.bits
+                                        | TypeFlags::HAS_TY_OPAQUE.bits
+                                        | TypeFlags::HAS_CT_PROJECTION.bits
+                                        | TypeFlags::KEEP_IN_LOCAL_TCX.bits
+                                        | TypeFlags::HAS_TY_ERR.bits
+                                        | TypeFlags::HAS_FREE_REGIONS.bits
+                                        | TypeFlags::HAS_RE_LATE_BOUND.bits
+                                        | TypeFlags::HAS_RE_ERASED.bits;
     }
 }
 
@@ -1669,7 +1701,7 @@ pub struct UniverseIndex {
 }
 
 impl UniverseIndex {
-    pub const ROOT: UniverseIndex = UniverseIndex::from_u32_const(0);
+    pub const ROOT: UniverseIndex = UniverseIndex::from_u32(0);
 
     /// Returns the "next" universe index in order -- this new index
     /// is considered to extend all previous universes. This
@@ -1816,10 +1848,10 @@ pub fn and<T: TypeFoldable<'tcx>>(self, value: T) -> ParamEnvAnd<'tcx, T> {
             Reveal::UserFacing => ParamEnvAnd { param_env: self, value },
 
             Reveal::All => {
-                if value.has_placeholders() || value.needs_infer() || value.has_param_types() {
-                    ParamEnvAnd { param_env: self, value }
-                } else {
+                if value.is_global() {
                     ParamEnvAnd { param_env: self.without_caller_bounds(), value }
+                } else {
+                    ParamEnvAnd { param_env: self, value }
                 }
             }
         }
@@ -2199,7 +2231,7 @@ pub fn new(tcx: TyCtxt<'_>, did: DefId) -> ReprOptions {
         if !tcx.consider_optimizing(|| format!("Reorder fields of {:?}", tcx.def_path_str(did))) {
             flags.insert(ReprFlags::IS_LINEAR);
         }
-        ReprOptions { int: size, align: max_align, pack: min_pack, flags: flags }
+        ReprOptions { int: size, align: max_align, pack: min_pack, flags }
     }
 
     #[inline]
@@ -2844,7 +2876,7 @@ pub fn opt_associated_item(self, def_id: DefId) -> Option<AssocItem> {
             }
         } else {
             match self.def_kind(def_id).expect("no def for `DefId`") {
-                DefKind::AssocConst | DefKind::Method | DefKind::AssocTy => true,
+                DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy => true,
                 _ => false,
             }
         };
@@ -3023,7 +3055,7 @@ pub fn trait_id_of_impl(self, def_id: DefId) -> Option<DefId> {
     /// `DefId` of the impl that the method belongs to; otherwise, returns `None`.
     pub fn impl_of_method(self, def_id: DefId) -> Option<DefId> {
         let item = if def_id.krate != LOCAL_CRATE {
-            if let Some(DefKind::Method) = self.def_kind(def_id) {
+            if let Some(DefKind::AssocFn) = self.def_kind(def_id) {
                 Some(self.associated_item(def_id))
             } else {
                 None
@@ -3055,7 +3087,7 @@ pub fn span_of_impl(self, impl_did: DefId) -> Result<Span, Symbol> {
     pub fn hygienic_eq(self, use_name: Ident, def_name: Ident, def_parent_def_id: DefId) -> bool {
         // We could use `Ident::eq` here, but we deliberately don't. The name
         // comparison fails frequently, and we want to avoid the expensive
-        // `modern()` calls required for the span comparison whenever possible.
+        // `normalize_to_macros_2_0()` calls required for the span comparison whenever possible.
         use_name.name == def_name.name
             && use_name
                 .span
@@ -3064,14 +3096,14 @@ pub fn hygienic_eq(self, use_name: Ident, def_name: Ident, def_parent_def_id: De
     }
 
     fn expansion_that_defined(self, scope: DefId) -> ExpnId {
-        match scope.krate {
-            LOCAL_CRATE => self.hir().definitions().expansion_that_defined(scope.index),
-            _ => ExpnId::root(),
+        match scope.as_local() {
+            Some(scope) => self.hir().definitions().expansion_that_defined(scope),
+            None => ExpnId::root(),
         }
     }
 
     pub fn adjust_ident(self, mut ident: Ident, scope: DefId) -> Ident {
-        ident.span.modernize_and_adjust(self.expansion_that_defined(scope));
+        ident.span.normalize_to_macros_2_0_and_adjust(self.expansion_that_defined(scope));
         ident
     }
 
@@ -3081,12 +3113,14 @@ pub fn adjust_ident_and_get_scope(
         scope: DefId,
         block: hir::HirId,
     ) -> (Ident, DefId) {
-        let scope = match ident.span.modernize_and_adjust(self.expansion_that_defined(scope)) {
-            Some(actual_expansion) => {
-                self.hir().definitions().parent_module_of_macro_def(actual_expansion)
-            }
-            None => self.parent_module(block),
-        };
+        let scope =
+            match ident.span.normalize_to_macros_2_0_and_adjust(self.expansion_that_defined(scope))
+            {
+                Some(actual_expansion) => {
+                    self.hir().definitions().parent_module_of_macro_def(actual_expansion)
+                }
+                None => self.parent_module(block).to_def_id(),
+            };
         (ident, scope)
     }
 
@@ -3114,8 +3148,11 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) {
     context::provide(providers);
     erase_regions::provide(providers);
     layout::provide(providers);
-    *providers =
-        ty::query::Providers { trait_impls_of: trait_def::trait_impls_of_provider, ..*providers };
+    *providers = ty::query::Providers {
+        trait_impls_of: trait_def::trait_impls_of_provider,
+        all_local_trait_impls: trait_def::all_local_trait_impls,
+        ..*providers
+    };
 }
 
 /// A map for the local crate mapping each type to a vector of its
index dc64482907f756a0b972161b726d0d7f03520db5..cbaabd8e1f1373a2c4ae788a2ad36703ece93239 100644 (file)
@@ -34,10 +34,7 @@ pub fn normalize_erasing_regions<T>(self, param_env: ty::ParamEnv<'tcx>, value:
         if !value.has_projections() {
             value
         } else {
-            value.fold_with(&mut NormalizeAfterErasingRegionsFolder {
-                tcx: self,
-                param_env: param_env,
-            })
+            value.fold_with(&mut NormalizeAfterErasingRegionsFolder { tcx: self, param_env })
         }
     }
 
index 3ade9661917a25efbe0764401c068e0660426e0c..8d784833bd310ef9f311ff3e45f0b3386c813088 100644 (file)
@@ -97,7 +97,7 @@ fn path_generic_args(
         args: &[GenericArg<'tcx>],
     ) -> Result<Self::Path, Self::Error>;
 
-    // Defaults (should not be overriden):
+    // Defaults (should not be overridden):
 
     fn default_print_def_path(
         self,
index 3bf92552c862449c053772371ea4d4724dd8868c..cb01d821c18712e5ba8e0824add0c1a92566aca0 100644 (file)
@@ -1,7 +1,7 @@
 use crate::hir::map::{DefPathData, DisambiguatedDefPathData};
 use crate::middle::cstore::{ExternCrate, ExternCrateSource};
 use crate::middle::region;
-use crate::mir::interpret::{sign_extend, truncate, ConstValue, Scalar};
+use crate::mir::interpret::{sign_extend, truncate, AllocId, ConstValue, Pointer, Scalar};
 use crate::ty::layout::{Integer, IntegerExt, Size};
 use crate::ty::subst::{GenericArg, GenericArgKind, Subst};
 use crate::ty::{self, DefIdTree, ParamConst, Ty, TyCtxt, TypeFoldable};
@@ -17,6 +17,7 @@
 use rustc_target::spec::abi::Abi;
 
 use std::cell::Cell;
+use std::char;
 use std::collections::BTreeMap;
 use std::fmt::{self, Write as _};
 use std::ops::{Deref, DerefMut};
@@ -210,6 +211,21 @@ fn comma_sep<T>(mut self, mut elems: impl Iterator<Item = T>) -> Result<Self, Se
         Ok(self)
     }
 
+    /// Prints `{f: t}` or `{f as t}` depending on the `cast` argument
+    fn typed_value(
+        mut self,
+        f: impl FnOnce(Self) -> Result<Self, Self::Error>,
+        t: impl FnOnce(Self) -> Result<Self, Self::Error>,
+        conversion: &str,
+    ) -> Result<Self::Const, Self::Error> {
+        self.write_str("{")?;
+        self = f(self)?;
+        self.write_str(conversion)?;
+        self = t(self)?;
+        self.write_str("}")?;
+        Ok(self)
+    }
+
     /// Prints `<...>` around what `f` prints.
     fn generic_delimiters(
         self,
@@ -221,7 +237,7 @@ fn generic_delimiters(
     /// This is typically the case for all non-`'_` regions.
     fn region_should_not_be_omitted(&self, region: ty::Region<'_>) -> bool;
 
-    // Defaults (should not be overriden):
+    // Defaults (should not be overridden):
 
     /// If possible, this returns a global path resolving to `def_id` that is visible
     /// from at least one local module, and returns `true`. If the crate defining `def_id` is
@@ -236,7 +252,7 @@ fn try_print_visible_def_path(self, def_id: DefId) -> Result<(Self, bool), Self:
     /// post-process it into the valid and visible version that
     /// accounts for re-exports.
     ///
-    /// This method should only be callled by itself or
+    /// This method should only be called by itself or
     /// `try_print_visible_def_path`.
     ///
     /// `callers` is a chain of visible_parent's leading to `def_id`,
@@ -517,14 +533,7 @@ fn pretty_print_type(mut self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error>
             ty::Error => p!(write("[type error]")),
             ty::Param(ref param_ty) => p!(write("{}", param_ty)),
             ty::Bound(debruijn, bound_ty) => match bound_ty.kind {
-                ty::BoundTyKind::Anon => {
-                    if debruijn == ty::INNERMOST {
-                        p!(write("^{}", bound_ty.var.index()))
-                    } else {
-                        p!(write("^{}_{}", debruijn.index(), bound_ty.var.index()))
-                    }
-                }
-
+                ty::BoundTyKind::Anon => self.pretty_print_bound_var(debruijn, bound_ty.var)?,
                 ty::BoundTyKind::Param(p) => p!(write("{}", p)),
             },
             ty::Adt(def, substs) => {
@@ -685,11 +694,11 @@ fn pretty_print_type(mut self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error>
                 if self.tcx().sess.verbose() {
                     p!(write("{:?}", sz));
                 } else if let ty::ConstKind::Unevaluated(..) = sz.val {
-                    // do not try to evalute unevaluated constants. If we are const evaluating an
+                    // do not try to evaluate 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.
                     p!(write("_"));
-                } else if let Some(n) = sz.try_eval_usize(self.tcx(), ty::ParamEnv::empty()) {
+                } else if let Some(n) = sz.val.try_to_bits(self.tcx().data_layout.pointer_size) {
                     p!(write("{}", n));
                 } else {
                     p!(write("_"));
@@ -702,6 +711,18 @@ fn pretty_print_type(mut self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error>
         Ok(self)
     }
 
+    fn pretty_print_bound_var(
+        &mut self,
+        debruijn: ty::DebruijnIndex,
+        var: ty::BoundVar,
+    ) -> Result<(), Self::Error> {
+        if debruijn == ty::INNERMOST {
+            write!(self, "^{}", var.index())
+        } else {
+            write!(self, "^{}_{}", debruijn.index(), var.index())
+        }
+    }
+
     fn infer_ty_name(&self, _: ty::TyVid) -> Option<String> {
         None
     }
@@ -842,16 +863,23 @@ fn pretty_print_const(
 
         macro_rules! print_underscore {
             () => {{
-                p!(write("_"));
                 if print_ty {
-                    p!(write(": "), print(ct.ty));
+                    self = self.typed_value(
+                        |mut this| {
+                            write!(this, "_")?;
+                            Ok(this)
+                        },
+                        |this| this.print_type(ct.ty),
+                        ": ",
+                    )?;
+                } else {
+                    write!(self, "_")?;
                 }
             }};
         }
 
-        match (ct.val, &ct.ty.kind) {
-            (_, ty::FnDef(did, substs)) => p!(print_value_path(*did, substs)),
-            (ty::ConstKind::Unevaluated(did, substs, promoted), _) => {
+        match ct.val {
+            ty::ConstKind::Unevaluated(did, substs, promoted) => {
                 if let Some(promoted) = promoted {
                     p!(print_value_path(did, substs));
                     p!(write("::{:?}", promoted));
@@ -876,143 +904,265 @@ macro_rules! print_underscore {
                     }
                 }
             }
-            (ty::ConstKind::Infer(..), _) => print_underscore!(),
-            (ty::ConstKind::Param(ParamConst { name, .. }), _) => p!(write("{}", name)),
-            (ty::ConstKind::Value(value), _) => {
+            ty::ConstKind::Infer(..) => print_underscore!(),
+            ty::ConstKind::Param(ParamConst { name, .. }) => p!(write("{}", name)),
+            ty::ConstKind::Value(value) => {
                 return self.pretty_print_const_value(value, ct.ty, print_ty);
             }
 
-            _ => {
-                // fallback
-                p!(write("{:?}", ct.val));
-                if print_ty {
-                    p!(write(": "), print(ct.ty));
-                }
+            ty::ConstKind::Bound(debruijn, bound_var) => {
+                self.pretty_print_bound_var(debruijn, bound_var)?
             }
+            ty::ConstKind::Placeholder(placeholder) => p!(write("Placeholder({:?})", placeholder)),
         };
         Ok(self)
     }
 
-    fn pretty_print_const_value(
+    fn pretty_print_const_scalar(
         mut self,
-        ct: ConstValue<'tcx>,
+        scalar: Scalar,
         ty: Ty<'tcx>,
         print_ty: bool,
     ) -> Result<Self::Const, Self::Error> {
         define_scoped_cx!(self);
 
-        if self.tcx().sess.verbose() {
-            p!(write("ConstValue({:?}: {:?})", ct, ty));
-            return Ok(self);
-        }
-
-        let u8 = self.tcx().types.u8;
-
-        match (ct, &ty.kind) {
-            (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)) => {
+        match (scalar, &ty.kind) {
+            // Byte strings (&[u8; N])
+            (
+                Scalar::Ptr(ptr),
+                ty::Ref(
+                    _,
+                    ty::TyS {
+                        kind:
+                            ty::Array(
+                                ty::TyS { kind: ty::Uint(ast::UintTy::U8), .. },
+                                ty::Const {
+                                    val:
+                                        ty::ConstKind::Value(ConstValue::Scalar(Scalar::Raw {
+                                            data,
+                                            ..
+                                        })),
+                                    ..
+                                },
+                            ),
+                        ..
+                    },
+                    _,
+                ),
+            ) => {
+                let byte_str = self
+                    .tcx()
+                    .alloc_map
+                    .lock()
+                    .unwrap_memory(ptr.alloc_id)
+                    .get_bytes(&self.tcx(), ptr, Size::from_bytes(*data as u64))
+                    .unwrap();
+                p!(pretty_print_byte_str(byte_str));
+            }
+            // Bool
+            (Scalar::Raw { data: 0, .. }, ty::Bool) => p!(write("false")),
+            (Scalar::Raw { data: 1, .. }, ty::Bool) => p!(write("true")),
+            // Float
+            (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)) => {
+            (Scalar::Raw { data, .. }, ty::Float(ast::FloatTy::F64)) => {
                 p!(write("{}f64", Double::from_bits(data)))
             }
-            (ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Uint(ui)) => {
+            // Int
+            (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);
+                let max = truncate(u128::MAX, bit_size);
 
                 let ui_str = ui.name_str();
                 if data == max {
                     p!(write("std::{}::MAX", ui_str))
                 } else {
-                    p!(write("{}{}", data, ui_str))
+                    if print_ty { p!(write("{}{}", data, ui_str)) } else { p!(write("{}", data)) }
                 };
             }
-            (ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Int(i)) => {
-                let bit_size = Integer::from_attr(&self.tcx(), SignedInt(*i)).size().bits() as u128;
+            (Scalar::Raw { data, .. }, ty::Int(i)) => {
+                let size = Integer::from_attr(&self.tcx(), SignedInt(*i)).size();
+                let bit_size = size.bits() as u128;
                 let min = 1u128 << (bit_size - 1);
                 let max = min - 1;
 
-                let ty = self.tcx().lift(&ty).unwrap();
-                let size = self.tcx().layout_of(ty::ParamEnv::empty().and(ty)).unwrap().size;
                 let i_str = i.name_str();
                 match data {
                     d if d == min => p!(write("std::{}::MIN", i_str)),
                     d if d == max => p!(write("std::{}::MAX", i_str)),
-                    _ => p!(write("{}{}", sign_extend(data, size) as i128, i_str)),
+                    _ => {
+                        let data = sign_extend(data, size) as i128;
+                        if print_ty {
+                            p!(write("{}{}", data, i_str))
+                        } else {
+                            p!(write("{}", data))
+                        }
+                    }
                 }
             }
-            (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(_)) => {
+            // Char
+            (Scalar::Raw { data, .. }, ty::Char) if char::from_u32(data as u32).is_some() => {
+                p!(write("{:?}", char::from_u32(data as u32).unwrap()))
+            }
+            // Raw pointers
+            (Scalar::Raw { data, .. }, ty::RawPtr(_)) => {
+                self = self.typed_value(
+                    |mut this| {
+                        write!(this, "0x{:x}", data)?;
+                        Ok(this)
+                    },
+                    |this| this.print_type(ty),
+                    " as ",
+                )?;
+            }
+            (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, _) = ty.kind {
-                    let byte_str = match (ct, &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,
-                    };
-
-                    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, &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
+                self = self.typed_value(
+                    |this| this.print_value_path(instance.def_id(), instance.substs),
+                    |this| this.print_type(ty),
+                    " as ",
+                )?;
+            }
+            // For function type zsts just printing the path is enough
+            (Scalar::Raw { size: 0, .. }, ty::FnDef(d, s)) => p!(print_value_path(*d, s)),
+            // Empty tuples are frequently occurring, so don't print the fallback.
+            (Scalar::Raw { size: 0, .. }, ty::Tuple(ts)) if ts.is_empty() => p!(write("()")),
+            // Zero element arrays have a trivial representation.
+            (
+                Scalar::Raw { size: 0, .. },
+                ty::Array(
+                    _,
+                    ty::Const {
+                        val: ty::ConstKind::Value(ConstValue::Scalar(Scalar::Raw { data: 0, .. })),
+                        ..
+                    },
+                ),
+            ) => p!(write("[]")),
+            // Nontrivial types with scalar bit representation
+            (Scalar::Raw { data, size }, _) => {
+                let print = |mut this: Self| {
+                    if size == 0 {
+                        write!(this, "transmute(())")?;
                     } else {
-                        false
+                        write!(this, "transmute(0x{:01$x})", data, size as usize * 2)?;
                     }
+                    Ok(this)
+                };
+                self = if print_ty {
+                    self.typed_value(print, |this| this.print_type(ty), ": ")?
                 } else {
-                    false
+                    print(self)?
                 };
-                if !printed {
-                    // fallback
-                    p!(write("{:?}", ct));
-                    if print_ty {
-                        p!(write(": "), print(ty));
-                    }
-                }
             }
-        };
+            // Any pointer values not covered by a branch above
+            (Scalar::Ptr(p), _) => {
+                self = self.pretty_print_const_pointer(p, ty, print_ty)?;
+            }
+        }
         Ok(self)
     }
+
+    /// This is overridden for MIR printing because we only want to hide alloc ids from users, not
+    /// from MIR where it is actually useful.
+    fn pretty_print_const_pointer(
+        mut self,
+        _: Pointer,
+        ty: Ty<'tcx>,
+        print_ty: bool,
+    ) -> Result<Self::Const, Self::Error> {
+        if print_ty {
+            self.typed_value(
+                |mut this| {
+                    this.write_str("&_")?;
+                    Ok(this)
+                },
+                |this| this.print_type(ty),
+                ": ",
+            )
+        } else {
+            self.write_str("&_")?;
+            Ok(self)
+        }
+    }
+
+    fn pretty_print_byte_str(mut self, byte_str: &'tcx [u8]) -> Result<Self::Const, Self::Error> {
+        define_scoped_cx!(self);
+        p!(write("b\""));
+        for &c in byte_str {
+            for e in std::ascii::escape_default(c) {
+                self.write_char(e as char)?;
+            }
+        }
+        p!(write("\""));
+        Ok(self)
+    }
+
+    fn pretty_print_const_value(
+        mut self,
+        ct: ConstValue<'tcx>,
+        ty: Ty<'tcx>,
+        print_ty: bool,
+    ) -> Result<Self::Const, Self::Error> {
+        define_scoped_cx!(self);
+
+        if self.tcx().sess.verbose() {
+            p!(write("ConstValue({:?}: {:?})", ct, ty));
+            return Ok(self);
+        }
+
+        let u8_type = self.tcx().types.u8;
+
+        match (ct, &ty.kind) {
+            (ConstValue::Scalar(scalar), _) => self.pretty_print_const_scalar(scalar, ty, print_ty),
+            (
+                ConstValue::Slice { data, start, end },
+                ty::Ref(_, ty::TyS { kind: ty::Slice(t), .. }, _),
+            ) if *t == u8_type => {
+                // 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.
+                let byte_str = data.inspect_with_undef_and_ptr_outside_interpreter(start..end);
+                self.pretty_print_byte_str(byte_str)
+            }
+            (
+                ConstValue::Slice { data, start, end },
+                ty::Ref(_, ty::TyS { kind: 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));
+                Ok(self)
+            }
+            (ConstValue::ByRef { alloc, offset }, ty::Array(t, n)) if *t == u8_type => {
+                let n = n.val.try_to_bits(self.tcx().data_layout.pointer_size).unwrap();
+                // cast is ok because we already checked for pointer size (32 or 64 bit) above
+                let n = Size::from_bytes(n as u64);
+                let ptr = Pointer::new(AllocId(0), offset);
+
+                let byte_str = alloc.get_bytes(&self.tcx(), ptr, n).unwrap();
+                p!(write("*"));
+                p!(pretty_print_byte_str(byte_str));
+                Ok(self)
+            }
+            // FIXME(oli-obk): also pretty print arrays and other aggregate constants by reading
+            // their fields instead of just dumping the memory.
+            _ => {
+                // fallback
+                p!(write("{:?}", ct));
+                if print_ty {
+                    p!(write(": "), print(ty));
+                }
+                Ok(self)
+            }
+        }
+    }
 }
 
 // HACK(eddyb) boxed to avoid moving around a large struct by-value.
@@ -1024,6 +1174,7 @@ pub struct FmtPrinterData<'a, 'tcx, F> {
 
     empty_path: bool,
     in_value: bool,
+    pub print_alloc_ids: bool,
 
     used_region_names: FxHashSet<Symbol>,
     region_index: usize,
@@ -1054,6 +1205,7 @@ pub fn new(tcx: TyCtxt<'tcx>, fmt: F, ns: Namespace) -> Self {
             fmt,
             empty_path: false,
             in_value: ns == Namespace::ValueNS,
+            print_alloc_ids: false,
             used_region_names: Default::default(),
             region_index: 0,
             binder_depth: 0,
@@ -1326,6 +1478,22 @@ fn in_binder<T>(self, value: &ty::Binder<T>) -> Result<Self, Self::Error>
         self.pretty_in_binder(value)
     }
 
+    fn typed_value(
+        mut self,
+        f: impl FnOnce(Self) -> Result<Self, Self::Error>,
+        t: impl FnOnce(Self) -> Result<Self, Self::Error>,
+        conversion: &str,
+    ) -> Result<Self::Const, Self::Error> {
+        self.write_str("{")?;
+        self = f(self)?;
+        self.write_str(conversion)?;
+        let was_in_value = std::mem::replace(&mut self.in_value, false);
+        self = t(self)?;
+        self.in_value = was_in_value;
+        self.write_str("}")?;
+        Ok(self)
+    }
+
     fn generic_delimiters(
         mut self,
         f: impl FnOnce(Self) -> Result<Self, Self::Error>,
@@ -1382,6 +1550,28 @@ fn region_should_not_be_omitted(&self, region: ty::Region<'_>) -> bool {
             ty::ReStatic | ty::ReEmpty(_) | ty::ReClosureBound(_) => true,
         }
     }
+
+    fn pretty_print_const_pointer(
+        self,
+        p: Pointer,
+        ty: Ty<'tcx>,
+        print_ty: bool,
+    ) -> Result<Self::Const, Self::Error> {
+        let print = |mut this: Self| {
+            define_scoped_cx!(this);
+            if this.print_alloc_ids {
+                p!(write("{:?}", p));
+            } else {
+                p!(write("&_"));
+            }
+            Ok(this)
+        };
+        if print_ty {
+            self.typed_value(print, |this| this.print_type(ty), ": ")
+        } else {
+            print(self)
+        }
+    }
 }
 
 // HACK(eddyb) limited to `FmtPrinter` because of `region_highlight_mode`.
index 4b5e08cecd99c0719783fd538fe5e8044c293b3f..8ec07b9fdeb7844820f565350d72f2b102ea6496 100644 (file)
@@ -1,3 +1,3 @@
-For more information about how the query system works, see the [rustc guide].
+For more information about how the query system works, see the [rustc dev guide].
 
-[rustc guide]: https://rust-lang.github.io/rustc-guide/query.html
+[rustc dev guide]: https://rustc-dev-guide.rust-lang.org/query.html
index e0e1ca374d9aef8deacadeabbbf29974773ecbd6..178c2362def6e9db554cbdef6f8c67c63c2048f5 100644 (file)
@@ -2,11 +2,10 @@
 use crate::dep_graph::{DepKind, DepNode};
 use crate::ty::query::caches::QueryCache;
 use crate::ty::query::plumbing::CycleError;
-use crate::ty::query::queries;
 use crate::ty::query::{Query, QueryState};
 use crate::ty::TyCtxt;
 use rustc_data_structures::profiling::ProfileCategory;
-use rustc_hir::def_id::{CrateNum, DefId};
+use rustc_hir::def_id::DefId;
 
 use crate::ich::StableHashingContext;
 use rustc_data_structures::fingerprint::Fingerprint;
@@ -87,9 +86,3 @@ impl<'tcx, M: QueryAccessors<'tcx, Key = DefId>> QueryDescription<'tcx> for M
         bug!("QueryDescription::load_from_disk() called for an unsupported query.")
     }
 }
-
-impl<'tcx> QueryDescription<'tcx> for queries::analysis<'tcx> {
-    fn describe(_tcx: TyCtxt<'_>, _: CrateNum) -> Cow<'static, str> {
-        "running analysis passes on this crate".into()
-    }
-}
index 09fb307a1ceb416cb6aec8b5030a7a676002bee1..6073d3a545f6db9c7b6dbb12186e188518037a06 100644 (file)
@@ -7,7 +7,7 @@
 use crate::ty::query::caches::DefaultCacheSelector;
 use crate::ty::subst::SubstsRef;
 use crate::ty::{self, Ty, TyCtxt};
-use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE};
+use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
 use rustc_span::symbol::Symbol;
 use rustc_span::{Span, DUMMY_SP};
 
@@ -84,14 +84,14 @@ fn default_span(&self, _: TyCtxt<'_>) -> Span {
     }
 }
 
-impl Key for DefIndex {
+impl Key for LocalDefId {
     type CacheSelector = DefaultCacheSelector;
 
     fn query_crate(&self) -> CrateNum {
-        LOCAL_CRATE
+        self.to_def_id().query_crate()
     }
-    fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
-        DUMMY_SP
+    fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
+        self.to_def_id().default_span(tcx)
     }
 }
 
index 8614fd5cdca9a8715966a5c7c69e443978982b70..7ac8358c78a611ed6c38dc9e6cbd3f0c35783bb3 100644 (file)
@@ -1,5 +1,7 @@
-use crate::dep_graph::{self, DepConstructor, DepNode};
+use crate::dep_graph::{self, DepConstructor, DepNode, DepNodeParams};
 use crate::hir::exports::Export;
+use crate::hir::map;
+use crate::hir::{HirOwner, HirOwnerItems};
 use crate::infer::canonical::{self, Canonical};
 use crate::lint::LintLevelMap;
 use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
@@ -17,8 +19,6 @@
 use crate::mir::interpret::{ConstEvalRawResult, ConstEvalResult, ConstValue};
 use crate::mir::interpret::{LitToConstError, LitToConstInput};
 use crate::mir::mono::CodegenUnit;
-use crate::session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion};
-use crate::session::CrateDisambiguator;
 use crate::traits::query::{
     CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal,
     CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpEqGoal, CanonicalTypeOpNormalizeGoal,
 use rustc_data_structures::sync::Lrc;
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
-use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, DefIndex};
+use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId};
 use rustc_hir::{Crate, HirIdSet, ItemLocalId, TraitCandidate};
 use rustc_index::vec::IndexVec;
+use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion};
+use rustc_session::CrateDisambiguator;
 use rustc_target::spec::PanicStrategy;
 
 use rustc_ast::ast;
 use rustc_span::symbol::Symbol;
 use rustc_span::{Span, DUMMY_SP};
 use std::borrow::Cow;
+use std::collections::BTreeMap;
 use std::convert::TryFrom;
 use std::ops::Deref;
 use std::sync::Arc;
 
 #[macro_use]
 mod plumbing;
+pub use self::plumbing::CycleError;
 use self::plumbing::*;
-pub use self::plumbing::{force_from_dep_node, CycleError};
 
 mod stats;
 pub use self::stats::print_stats;
 // Queries marked with `fatal_cycle` do not need the latter implementation,
 // as they will raise an fatal error on query cycles instead.
 
-rustc_query_append! { [define_queries!][ <'tcx>
-    Other {
-        /// Runs analysis passes on the crate.
-        [eval_always] fn analysis: Analysis(CrateNum) -> Result<(), ErrorReported>,
-    },
-]}
+rustc_query_append! { [define_queries!][<'tcx>] }
+
+/// The red/green evaluation system will try to mark a specific DepNode in the
+/// dependency graph as green by recursively trying to mark the dependencies of
+/// that `DepNode` as green. While doing so, it will sometimes encounter a `DepNode`
+/// where we don't know if it is red or green and we therefore actually have
+/// to recompute its value in order to find out. Since the only piece of
+/// information that we have at that point is the `DepNode` we are trying to
+/// re-evaluate, we need some way to re-run a query from just that. This is what
+/// `force_from_dep_node()` implements.
+///
+/// In the general case, a `DepNode` consists of a `DepKind` and an opaque
+/// GUID/fingerprint that will uniquely identify the node. This GUID/fingerprint
+/// is usually constructed by computing a stable hash of the query-key that the
+/// `DepNode` corresponds to. Consequently, it is not in general possible to go
+/// back from hash to query-key (since hash functions are not reversible). For
+/// this reason `force_from_dep_node()` is expected to fail from time to time
+/// because we just cannot find out, from the `DepNode` alone, what the
+/// corresponding query-key is and therefore cannot re-run the query.
+///
+/// The system deals with this case letting `try_mark_green` fail which forces
+/// the root query to be re-evaluated.
+///
+/// Now, if `force_from_dep_node()` would always fail, it would be pretty useless.
+/// Fortunately, we can use some contextual information that will allow us to
+/// reconstruct query-keys for certain kinds of `DepNode`s. In particular, we
+/// enforce by construction that the GUID/fingerprint of certain `DepNode`s is a
+/// valid `DefPathHash`. Since we also always build a huge table that maps every
+/// `DefPathHash` in the current codebase to the corresponding `DefId`, we have
+/// everything we need to re-run the query.
+///
+/// Take the `mir_validated` query as an example. Like many other queries, it
+/// just has a single parameter: the `DefId` of the item it will compute the
+/// validated MIR for. Now, when we call `force_from_dep_node()` on a `DepNode`
+/// with kind `MirValidated`, we know that the GUID/fingerprint of the `DepNode`
+/// is actually a `DefPathHash`, and can therefore just look up the corresponding
+/// `DefId` in `tcx.def_path_hash_to_def_id`.
+///
+/// When you implement a new query, it will likely have a corresponding new
+/// `DepKind`, and you'll have to support it here in `force_from_dep_node()`. As
+/// a rule of thumb, if your query takes a `DefId` or `LocalDefId` as sole parameter,
+/// then `force_from_dep_node()` should not fail for it. Otherwise, you can just
+/// add it to the "We don't have enough information to reconstruct..." group in
+/// the match below.
+pub fn force_from_dep_node<'tcx>(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> bool {
+    use crate::dep_graph::DepKind;
+
+    // We must avoid ever having to call `force_from_dep_node()` for a
+    // `DepNode::codegen_unit`:
+    // Since we cannot reconstruct the query key of a `DepNode::codegen_unit`, we
+    // would always end up having to evaluate the first caller of the
+    // `codegen_unit` query that *is* reconstructible. This might very well be
+    // the `compile_codegen_unit` query, thus re-codegenning the whole CGU just
+    // to re-trigger calling the `codegen_unit` query with the right key. At
+    // that point we would already have re-done all the work we are trying to
+    // avoid doing in the first place.
+    // The solution is simple: Just explicitly call the `codegen_unit` query for
+    // each CGU, right after partitioning. This way `try_mark_green` will always
+    // hit the cache instead of having to go through `force_from_dep_node`.
+    // This assertion makes sure, we actually keep applying the solution above.
+    debug_assert!(
+        dep_node.kind != DepKind::codegen_unit,
+        "calling force_from_dep_node() on DepKind::codegen_unit"
+    );
+
+    if !dep_node.kind.can_reconstruct_query_key() {
+        return false;
+    }
+
+    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.
+        DepKind::CrateMetadata |
+
+        // These are anonymous nodes.
+        DepKind::TraitSelect |
+
+        // We don't have enough information to reconstruct the query key of
+        // these.
+        DepKind::CompileCodegenUnit => {
+            bug!("force_from_dep_node: encountered {:?}", dep_node)
+        }
+    );
+
+    false
+}
+
+impl DepNode {
+    /// Check whether the query invocation corresponding to the given
+    /// DepNode is eligible for on-disk-caching. If so, this is method
+    /// will execute the query corresponding to the given DepNode.
+    /// Also, as a sanity check, it expects that the corresponding query
+    /// invocation has been marked as green already.
+    pub fn try_load_from_on_disk_cache<'tcx>(&self, tcx: TyCtxt<'tcx>) {
+        use crate::dep_graph::DepKind;
+
+        rustc_dep_node_try_load_from_on_disk_cache!(self, tcx)
+    }
+}
index 109ac97fe62651c33ded7e6fa426dab945e20713..781abea75d9f7bd7d8f90be2691468cfb3680b1a 100644 (file)
@@ -3,7 +3,6 @@
 use crate::ich::{CachingSourceMapView, Fingerprint};
 use crate::mir::interpret::{AllocDecodingSession, AllocDecodingState};
 use crate::mir::{self, interpret};
-use crate::session::{CrateDisambiguator, Session};
 use crate::ty::codec::{self as ty_codec, TyDecoder, TyEncoder};
 use crate::ty::context::TyCtxt;
 use crate::ty::{self, Ty};
 use rustc_data_structures::sync::{HashMapExt, Lock, Lrc, Once};
 use rustc_data_structures::thin_vec::ThinVec;
 use rustc_errors::Diagnostic;
-use rustc_hir as hir;
 use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, LOCAL_CRATE};
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_serialize::{
     opaque, Decodable, Decoder, Encodable, Encoder, SpecializedDecoder, SpecializedEncoder,
     UseSpecializedDecodable, UseSpecializedEncodable,
 };
+use rustc_session::{CrateDisambiguator, Session};
 use rustc_span::hygiene::{ExpnId, SyntaxContext};
 use rustc_span::source_map::{SourceMap, StableSourceFileId};
 use rustc_span::{BytePos, SourceFile, Span, DUMMY_SP};
@@ -92,7 +91,7 @@ struct Footer {
 
 impl AbsoluteBytePos {
     fn new(pos: usize) -> AbsoluteBytePos {
-        debug_assert!(pos <= ::std::u32::MAX as usize);
+        debug_assert!(pos <= u32::MAX as usize);
         AbsoluteBytePos(pos as u32)
     }
 
@@ -425,7 +424,7 @@ fn compute_cnum_map(
 
 //- DECODING -------------------------------------------------------------------
 
-/// A decoder that can read fro the incr. comp. cache. It is similar to the one
+/// A decoder that can read from the incr. comp. cache. It is similar to the one
 /// we use for crate metadata decoding in that it can rebase spans and eventually
 /// will also handle things that contain `Ty` instances.
 struct CacheDecoder<'a, 'tcx> {
@@ -657,26 +656,7 @@ fn specialized_decode(&mut self) -> Result<DefId, Self::Error> {
 impl<'a, 'tcx> SpecializedDecoder<LocalDefId> for CacheDecoder<'a, 'tcx> {
     #[inline]
     fn specialized_decode(&mut self) -> Result<LocalDefId, Self::Error> {
-        Ok(LocalDefId::from_def_id(DefId::decode(self)?))
-    }
-}
-
-impl<'a, 'tcx> SpecializedDecoder<hir::HirId> for CacheDecoder<'a, 'tcx> {
-    fn specialized_decode(&mut self) -> Result<hir::HirId, Self::Error> {
-        // Load the `DefPathHash` which is what we encoded the `DefIndex` as.
-        let def_path_hash = DefPathHash::decode(self)?;
-
-        // Use the `DefPathHash` to map to the current `DefId`.
-        let def_id = self.tcx().def_path_hash_to_def_id.as_ref().unwrap()[&def_path_hash];
-
-        debug_assert!(def_id.is_local());
-
-        // The `ItemLocalId` needs no remapping.
-        let local_id = hir::ItemLocalId::decode(self)?;
-
-        // Reconstruct the `HirId` and look up the corresponding `NodeId` in the
-        // context of the current session.
-        Ok(hir::HirId { owner: def_id.index, local_id })
+        Ok(DefId::decode(self)?.expect_local())
     }
 }
 
@@ -873,21 +853,6 @@ fn specialized_encode(
     }
 }
 
-impl<'a, 'tcx, E> SpecializedEncoder<hir::HirId> for CacheEncoder<'a, 'tcx, E>
-where
-    E: 'a + TyEncoder,
-{
-    #[inline]
-    fn specialized_encode(&mut self, id: &hir::HirId) -> Result<(), Self::Error> {
-        let hir::HirId { owner, local_id } = *id;
-
-        let def_path_hash = self.tcx.hir().definitions().def_path_hash(owner);
-
-        def_path_hash.encode(self)?;
-        local_id.encode(self)
-    }
-}
-
 impl<'a, 'tcx, E> SpecializedEncoder<DefId> for CacheEncoder<'a, 'tcx, E>
 where
     E: 'a + TyEncoder,
index a61256b9fcbbc82652c873c20ef15ebd62c17d2e..acf67f52dceaa94ebe9bb50ebd6a4979e78cf73c 100644 (file)
@@ -2,7 +2,7 @@
 //! generate the actual methods on tcx which find and execute the provider,
 //! manage the caches, and so forth.
 
-use crate::dep_graph::{DepKind, DepNode, DepNodeIndex, SerializedDepNodeIndex};
+use crate::dep_graph::{DepNode, DepNodeIndex, SerializedDepNodeIndex};
 use crate::ty::query::caches::QueryCache;
 use crate::ty::query::config::{QueryAccessors, QueryDescription};
 use crate::ty::query::job::{QueryInfo, QueryJob, QueryJobId, QueryShardJobId};
@@ -720,7 +720,7 @@ pub(super) fn ensure_query<Q: QueryDescription<'tcx> + 'tcx>(self, key: Q::Key)
     }
 
     #[allow(dead_code)]
-    fn force_query<Q: QueryDescription<'tcx> + 'tcx>(
+    pub(super) fn force_query<Q: QueryDescription<'tcx> + 'tcx>(
         self,
         key: Q::Key,
         span: Span,
@@ -1053,7 +1053,7 @@ fn deref(&self) -> &Self::Target {
 
         impl TyCtxt<$tcx> {
             /// Returns a transparent wrapper for `TyCtxt`, which ensures queries
-            /// are executed instead of just returing their results.
+            /// are executed instead of just returning their results.
             #[inline(always)]
             pub fn ensure(self) -> TyCtxtEnsure<$tcx> {
                 TyCtxtEnsure {
@@ -1162,105 +1162,3 @@ fn default() -> Self {
         }
     };
 }
-
-/// The red/green evaluation system will try to mark a specific DepNode in the
-/// dependency graph as green by recursively trying to mark the dependencies of
-/// that `DepNode` as green. While doing so, it will sometimes encounter a `DepNode`
-/// where we don't know if it is red or green and we therefore actually have
-/// to recompute its value in order to find out. Since the only piece of
-/// information that we have at that point is the `DepNode` we are trying to
-/// re-evaluate, we need some way to re-run a query from just that. This is what
-/// `force_from_dep_node()` implements.
-///
-/// In the general case, a `DepNode` consists of a `DepKind` and an opaque
-/// GUID/fingerprint that will uniquely identify the node. This GUID/fingerprint
-/// is usually constructed by computing a stable hash of the query-key that the
-/// `DepNode` corresponds to. Consequently, it is not in general possible to go
-/// back from hash to query-key (since hash functions are not reversible). For
-/// this reason `force_from_dep_node()` is expected to fail from time to time
-/// because we just cannot find out, from the `DepNode` alone, what the
-/// corresponding query-key is and therefore cannot re-run the query.
-///
-/// The system deals with this case letting `try_mark_green` fail which forces
-/// the root query to be re-evaluated.
-///
-/// Now, if `force_from_dep_node()` would always fail, it would be pretty useless.
-/// Fortunately, we can use some contextual information that will allow us to
-/// reconstruct query-keys for certain kinds of `DepNode`s. In particular, we
-/// enforce by construction that the GUID/fingerprint of certain `DepNode`s is a
-/// valid `DefPathHash`. Since we also always build a huge table that maps every
-/// `DefPathHash` in the current codebase to the corresponding `DefId`, we have
-/// everything we need to re-run the query.
-///
-/// Take the `mir_validated` query as an example. Like many other queries, it
-/// just has a single parameter: the `DefId` of the item it will compute the
-/// validated MIR for. Now, when we call `force_from_dep_node()` on a `DepNode`
-/// with kind `MirValidated`, we know that the GUID/fingerprint of the `DepNode`
-/// is actually a `DefPathHash`, and can therefore just look up the corresponding
-/// `DefId` in `tcx.def_path_hash_to_def_id`.
-///
-/// When you implement a new query, it will likely have a corresponding new
-/// `DepKind`, and you'll have to support it here in `force_from_dep_node()`. As
-/// a rule of thumb, if your query takes a `DefId` or `DefIndex` as sole parameter,
-/// then `force_from_dep_node()` should not fail for it. Otherwise, you can just
-/// add it to the "We don't have enough information to reconstruct..." group in
-/// the match below.
-pub fn force_from_dep_node(tcx: TyCtxt<'_>, dep_node: &DepNode) -> bool {
-    use crate::dep_graph::RecoverKey;
-
-    // We must avoid ever having to call `force_from_dep_node()` for a
-    // `DepNode::codegen_unit`:
-    // Since we cannot reconstruct the query key of a `DepNode::codegen_unit`, we
-    // would always end up having to evaluate the first caller of the
-    // `codegen_unit` query that *is* reconstructible. This might very well be
-    // the `compile_codegen_unit` query, thus re-codegenning the whole CGU just
-    // to re-trigger calling the `codegen_unit` query with the right key. At
-    // that point we would already have re-done all the work we are trying to
-    // avoid doing in the first place.
-    // The solution is simple: Just explicitly call the `codegen_unit` query for
-    // each CGU, right after partitioning. This way `try_mark_green` will always
-    // hit the cache instead of having to go through `force_from_dep_node`.
-    // This assertion makes sure, we actually keep applying the solution above.
-    debug_assert!(
-        dep_node.kind != DepKind::codegen_unit,
-        "calling force_from_dep_node() on DepKind::codegen_unit"
-    );
-
-    if !dep_node.kind.can_reconstruct_query_key() {
-        return false;
-    }
-
-    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.
-        DepKind::AllLocalTraitImpls |
-        DepKind::CrateMetadata |
-        DepKind::HirBody |
-        DepKind::Hir |
-
-        // These are anonymous nodes.
-        DepKind::TraitSelect |
-
-        // We don't have enough information to reconstruct the query key of
-        // these.
-        DepKind::CompileCodegenUnit => {
-            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::<crate::ty::query::queries::analysis<'_>>(
-                def_id.krate,
-                DUMMY_SP,
-                *dep_node
-            );
-        }
-    );
-
-    true
-}
index 3b9df72266f09a688f0ff5c2061f529c1a8accfc..fb4184a9fb34762dcc658b28639ab21d7f542117 100644 (file)
@@ -72,7 +72,7 @@ fn relate_with_variance<T: Relate<'tcx>>(
         b: &T,
     ) -> RelateResult<'tcx, T>;
 
-    // Overrideable relations. You shouldn't typically call these
+    // Overridable relations. You shouldn't typically call these
     // directly, instead call `relate()`, which in turn calls
     // these. This is both more uniform but also allows us to add
     // additional hooks for other types in the future if needed
@@ -287,7 +287,7 @@ fn relate<R: TypeRelation<'tcx>>(
             Err(TypeError::Traits(expected_found(relation, &a.def_id, &b.def_id)))
         } else {
             let substs = relate_substs(relation, None, a.substs, b.substs)?;
-            Ok(ty::TraitRef { def_id: a.def_id, substs: substs })
+            Ok(ty::TraitRef { def_id: a.def_id, substs })
         }
     }
 }
@@ -303,7 +303,7 @@ fn relate<R: TypeRelation<'tcx>>(
             Err(TypeError::Traits(expected_found(relation, &a.def_id, &b.def_id)))
         } else {
             let substs = relate_substs(relation, None, a.substs, b.substs)?;
-            Ok(ty::ExistentialTraitRef { def_id: a.def_id, substs: substs })
+            Ok(ty::ExistentialTraitRef { def_id: a.def_id, substs })
         }
     }
 }
index fcf23b9023b28a1f17cea93d4a1c32851e2d8a92..e265a2f8257fb77d50bb3ed29bac88ccad11bdf0 100644 (file)
@@ -1193,7 +1193,7 @@ pub struct ParamTy {
 
 impl<'tcx> ParamTy {
     pub fn new(index: u32, name: Symbol) -> ParamTy {
-        ParamTy { index, name: name }
+        ParamTy { index, name }
     }
 
     pub fn for_self() -> ParamTy {
@@ -1396,11 +1396,11 @@ pub struct DebruijnIndex {
 /// the inference variable is supposed to satisfy the relation
 /// *for every value of the placeholder region*. To ensure that doesn't
 /// happen, you can use `leak_check`. This is more clearly explained
-/// by the [rustc guide].
+/// by the [rustc dev guide].
 ///
 /// [1]: http://smallcultfollowing.com/babysteps/blog/2013/10/29/intermingled-parameter-lists/
 /// [2]: http://smallcultfollowing.com/babysteps/blog/2013/11/04/intermingled-parameter-lists/
-/// [rustc guide]: https://rust-lang.github.io/rustc-guide/traits/hrtb.html
+/// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html
 #[derive(Clone, PartialEq, Eq, Hash, Copy, RustcEncodable, RustcDecodable, PartialOrd, Ord)]
 pub enum RegionKind {
     /// Region bound in a type or fn declaration which will be
@@ -1743,47 +1743,42 @@ pub fn shifted_out_to_binder(&self, to_binder: ty::DebruijnIndex) -> RegionKind
         }
     }
 
-    pub fn keep_in_local_tcx(&self) -> bool {
-        if let ty::ReVar(..) = self { true } else { false }
-    }
-
     pub fn type_flags(&self) -> TypeFlags {
         let mut flags = TypeFlags::empty();
 
-        if self.keep_in_local_tcx() {
-            flags = flags | TypeFlags::KEEP_IN_LOCAL_TCX;
-        }
-
         match *self {
             ty::ReVar(..) => {
                 flags = flags | TypeFlags::HAS_FREE_REGIONS;
+                flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS;
                 flags = flags | TypeFlags::HAS_RE_INFER;
+                flags = flags | TypeFlags::KEEP_IN_LOCAL_TCX;
             }
             ty::RePlaceholder(..) => {
                 flags = flags | TypeFlags::HAS_FREE_REGIONS;
+                flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS;
                 flags = flags | TypeFlags::HAS_RE_PLACEHOLDER;
             }
-            ty::ReLateBound(..) => {
-                flags = flags | TypeFlags::HAS_RE_LATE_BOUND;
-            }
             ty::ReEarlyBound(..) => {
                 flags = flags | TypeFlags::HAS_FREE_REGIONS;
-                flags = flags | TypeFlags::HAS_RE_EARLY_BOUND;
+                flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS;
+                flags = flags | TypeFlags::HAS_RE_PARAM;
             }
-            ty::ReEmpty(_) | ty::ReStatic | ty::ReFree { .. } | ty::ReScope { .. } => {
+            ty::ReFree { .. } | ty::ReScope { .. } => {
                 flags = flags | TypeFlags::HAS_FREE_REGIONS;
+                flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS;
             }
-            ty::ReErased => {
-                flags = flags | TypeFlags::HAS_RE_ERASED;
+            ty::ReEmpty(_) | ty::ReStatic => {
+                flags = flags | TypeFlags::HAS_FREE_REGIONS;
             }
             ty::ReClosureBound(..) => {
                 flags = flags | TypeFlags::HAS_FREE_REGIONS;
             }
-        }
-
-        match *self {
-            ty::ReStatic | ty::ReEmpty(_) | ty::ReErased | ty::ReLateBound(..) => (),
-            _ => flags = flags | TypeFlags::HAS_FREE_LOCAL_NAMES,
+            ty::ReLateBound(..) => {
+                flags = flags | TypeFlags::HAS_RE_LATE_BOUND;
+            }
+            ty::ReErased => {
+                flags = flags | TypeFlags::HAS_RE_ERASED;
+            }
         }
 
         debug!("type_flags({:?}) = {:?}", self, flags);
@@ -2576,7 +2571,7 @@ pub fn try_to_scalar(&self) -> Option<Scalar> {
 
     #[inline]
     pub fn try_to_bits(&self, size: ty::layout::Size) -> Option<u128> {
-        self.try_to_scalar()?.to_bits(size).ok()
+        if let ConstKind::Value(val) = self { val.try_to_bits(size) } else { None }
     }
 }
 
index 0cf1c397648edcfe29787d6ac570f1b53cbceffc..b0287be65294f1ae57ef7c7fb8f0f4129d9d6270 100644 (file)
@@ -5,11 +5,14 @@
 use crate::ty::fold::TypeFoldable;
 use crate::ty::{Ty, TyCtxt};
 use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
+use rustc_hir::def_id::{CrateNum, DefId};
+use rustc_hir::HirId;
 
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_errors::ErrorReported;
 use rustc_macros::HashStable;
+use std::collections::BTreeMap;
 
 /// A trait's definition with type information.
 #[derive(HashStable)]
@@ -33,11 +36,33 @@ pub struct TraitDef {
     /// and thus `impl`s of it are allowed to overlap.
     pub is_marker: bool,
 
+    /// Used to determine whether the standard library is allowed to specialize
+    /// on this trait.
+    pub specialization_kind: TraitSpecializationKind,
+
     /// The ICH of this trait's DefPath, cached here so it doesn't have to be
     /// recomputed all the time.
     pub def_path_hash: DefPathHash,
 }
 
+/// Whether this trait is treated specially by the standard library
+/// specialization lint.
+#[derive(HashStable, PartialEq, Clone, Copy, RustcEncodable, RustcDecodable)]
+pub enum TraitSpecializationKind {
+    /// The default. Specializing on this trait is not allowed.
+    None,
+    /// Specializing on this trait is allowed because it doesn't have any
+    /// methods. For example `Sized` or `FusedIterator`.
+    /// Applies to traits with the `rustc_unsafe_specialization_marker`
+    /// attribute.
+    Marker,
+    /// Specializing on this trait is allowed because all of the impls of this
+    /// trait are "always applicable". Always applicable means that if
+    /// `X<'x>: T<'y>` for any lifetimes, then `for<'a, 'b> X<'a>: T<'b>`.
+    /// Applies to traits with the `rustc_specialization_trait` attribute.
+    AlwaysApplicable,
+}
+
 #[derive(Default)]
 pub struct TraitImpls {
     blanket_impls: Vec<DefId>,
@@ -52,16 +77,25 @@ pub fn new(
         paren_sugar: bool,
         has_auto_impl: bool,
         is_marker: bool,
+        specialization_kind: TraitSpecializationKind,
         def_path_hash: DefPathHash,
     ) -> TraitDef {
-        TraitDef { def_id, unsafety, paren_sugar, has_auto_impl, is_marker, def_path_hash }
+        TraitDef {
+            def_id,
+            unsafety,
+            paren_sugar,
+            has_auto_impl,
+            is_marker,
+            specialization_kind,
+            def_path_hash,
+        }
     }
 
     pub fn ancestors(
         &self,
         tcx: TyCtxt<'tcx>,
         of_impl: DefId,
-    ) -> specialization_graph::Ancestors<'tcx> {
+    ) -> Result<specialization_graph::Ancestors<'tcx>, ErrorReported> {
         specialization_graph::ancestors(tcx, self.def_id, of_impl)
     }
 }
@@ -146,6 +180,14 @@ pub fn all_impls(self, def_id: DefId) -> Vec<DefId> {
     }
 }
 
+// Query provider for `all_local_trait_impls`.
+pub(super) fn all_local_trait_impls<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    krate: CrateNum,
+) -> &'tcx BTreeMap<DefId, Vec<HirId>> {
+    &tcx.hir_crate(krate).trait_impls
+}
+
 // Query provider for `trait_impls_of`.
 pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> &TraitImpls {
     let mut impls = TraitImpls::default();
index 7b1f821877baa46eaf8597459b58b42c82a1d35d..69daa2da1fd0e1e9bc39fa1182b05b24a9833abb 100644 (file)
@@ -50,11 +50,11 @@ fn signed_min(size: Size) -> i128 {
 }
 
 fn signed_max(size: Size) -> i128 {
-    i128::max_value() >> (128 - size.bits())
+    i128::MAX >> (128 - size.bits())
 }
 
 fn unsigned_max(size: Size) -> u128 {
-    u128::max_value() >> (128 - size.bits())
+    u128::MAX >> (128 - size.bits())
 }
 
 fn int_size_and_signed<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> (Size, bool) {
@@ -77,7 +77,7 @@ pub fn checked_add(self, tcx: TyCtxt<'tcx>, n: u128) -> (Self, bool) {
             let min = signed_min(size);
             let max = signed_max(size);
             let val = sign_extend(self.val, size) as i128;
-            assert!(n < (i128::max_value() as u128));
+            assert!(n < (i128::MAX as u128));
             let n = n as i128;
             let oflo = val > max - n;
             let val = if oflo { min + (n - (max - val) - 1) } else { val + n };
@@ -346,18 +346,13 @@ pub fn calculate_dtor(
         adt_did: DefId,
         validate: &mut dyn FnMut(Self, DefId) -> Result<(), ErrorReported>,
     ) -> Option<ty::Destructor> {
-        let drop_trait = if let Some(def_id) = self.lang_items().drop_trait() {
-            def_id
-        } else {
-            return None;
-        };
-
+        let drop_trait = self.lang_items().drop_trait()?;
         self.ensure().coherent_trait(drop_trait);
 
         let mut dtor_did = None;
         let ty = self.type_of(adt_did);
         self.for_each_relevant_impl(drop_trait, ty, |impl_did| {
-            if let Some(item) = self.associated_items(impl_did).in_definition_order().nth(0) {
+            if let Some(item) = self.associated_items(impl_did).in_definition_order().next() {
                 if validate(self, impl_did).is_ok() {
                     dtor_did = Some(item.def_id);
                 }
index daa252ef4551b38715776b9a1a71a862c17727c9..dd407dba1f4cca03b3e19bce687b40e49a3ead68 100644 (file)
@@ -1,9 +1,9 @@
-The `syntax` crate contains those things concerned purely with syntax
+The `rustc_ast` crate contains those things concerned purely with syntax
 – that is, the AST ("abstract syntax tree"), parser, pretty-printer,
 lexer, macro expander, and utilities for traversing ASTs.
 
 For more information about how these things work in rustc, see the
-rustc guide:
+rustc dev guide:
 
-- [Parsing](https://rust-lang.github.io/rustc-guide/the-parser.html)
-- [Macro Expansion](https://rust-lang.github.io/rustc-guide/macro-expansion.html)
+- [Parsing](https://rustc-dev-guide.rust-lang.org/the-parser.html)
+- [Macro Expansion](https://rustc-dev-guide.rust-lang.org/macro-expansion.html)
index 62ff4f5183a70a8ebf12c7328a3077b97d5064a4..e3077b9897c18fcd08712eda6f611a2b4d735b76 100644 (file)
@@ -14,7 +14,7 @@
 //! - [`Generics`], [`GenericParam`], [`WhereClause`]: Metadata associated with generic parameters.
 //! - [`EnumDef`] and [`Variant`]: Enum declaration.
 //! - [`Lit`] and [`LitKind`]: Literal expressions.
-//! - [`MacroDef`], [`MacStmtStyle`], [`Mac`], [`MacDelimeter`]: Macro definition and invocation.
+//! - [`MacroDef`], [`MacStmtStyle`], [`MacCall`], [`MacDelimeter`]: Macro definition and invocation.
 //! - [`Attribute`]: Metadata associated with item.
 //! - [`UnOp`], [`UnOpKind`], [`BinOp`], [`BinOpKind`]: Unary and binary operators.
 
@@ -38,6 +38,7 @@
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::{Span, DUMMY_SP};
 
+use std::convert::TryFrom;
 use std::fmt;
 use std::iter;
 
@@ -512,7 +513,7 @@ pub fn to_ty(&self) -> Option<P<Ty>> {
                 TyKind::Path(None, Path::from_ident(*ident))
             }
             PatKind::Path(qself, path) => TyKind::Path(qself.clone(), path.clone()),
-            PatKind::Mac(mac) => TyKind::Mac(mac.clone()),
+            PatKind::MacCall(mac) => TyKind::MacCall(mac.clone()),
             // `&mut? P` can be reinterpreted as `&mut? T` where `T` is `P` reparsed as a type.
             PatKind::Ref(pat, mutbl) => {
                 pat.to_ty().map(|ty| TyKind::Rptr(None, MutTy { ty, mutbl: *mutbl }))?
@@ -566,7 +567,7 @@ pub fn walk(&self, it: &mut impl FnMut(&Pat) -> bool) {
             | PatKind::Range(..)
             | PatKind::Ident(..)
             | PatKind::Path(..)
-            | PatKind::Mac(_) => {}
+            | PatKind::MacCall(_) => {}
         }
     }
 
@@ -681,7 +682,7 @@ pub enum PatKind {
     Paren(P<Pat>),
 
     /// A macro pattern; pre-expansion.
-    Mac(Mac),
+    MacCall(MacCall),
 }
 
 #[derive(
@@ -880,9 +881,9 @@ impl Stmt {
     pub fn add_trailing_semicolon(mut self) -> Self {
         self.kind = match self.kind {
             StmtKind::Expr(expr) => StmtKind::Semi(expr),
-            StmtKind::Mac(mac) => {
-                StmtKind::Mac(mac.map(|(mac, _style, attrs)| (mac, MacStmtStyle::Semicolon, attrs)))
-            }
+            StmtKind::MacCall(mac) => StmtKind::MacCall(
+                mac.map(|(mac, _style, attrs)| (mac, MacStmtStyle::Semicolon, attrs)),
+            ),
             kind => kind,
         };
         self
@@ -913,8 +914,10 @@ pub enum StmtKind {
     Expr(P<Expr>),
     /// Expr with a trailing semi-colon.
     Semi(P<Expr>),
+    /// Just a trailing semi-colon.
+    Empty,
     /// Macro.
-    Mac(P<(Mac, MacStmtStyle, AttrVec)>),
+    MacCall(P<(MacCall, MacStmtStyle, AttrVec)>),
 }
 
 #[derive(Clone, Copy, PartialEq, RustcEncodable, RustcDecodable, Debug)]
@@ -1054,7 +1057,7 @@ pub fn to_ty(&self) -> Option<P<Ty>> {
         let kind = match &self.kind {
             // Trivial conversions.
             ExprKind::Path(qself, path) => TyKind::Path(qself.clone(), path.clone()),
-            ExprKind::Mac(mac) => TyKind::Mac(mac.clone()),
+            ExprKind::MacCall(mac) => TyKind::MacCall(mac.clone()),
 
             ExprKind::Paren(expr) => expr.to_ty().map(TyKind::Paren)?,
 
@@ -1075,7 +1078,7 @@ pub fn to_ty(&self) -> Option<P<Ty>> {
 
             // If binary operator is `Add` and both `lhs` and `rhs` are trait bounds,
             // then type of result is trait object.
-            // Othewise we don't assume the result type.
+            // Otherwise we don't assume the result type.
             ExprKind::Binary(binop, lhs, rhs) if binop.node == BinOpKind::Add => {
                 if let (Some(lhs), Some(rhs)) = (lhs.to_bound(), rhs.to_bound()) {
                     TyKind::TraitObject(vec![lhs, rhs], TraitObjectSyntax::None)
@@ -1124,7 +1127,7 @@ pub fn precedence(&self) -> ExprPrecedence {
             ExprKind::Continue(..) => ExprPrecedence::Continue,
             ExprKind::Ret(..) => ExprPrecedence::Ret,
             ExprKind::InlineAsm(..) => ExprPrecedence::InlineAsm,
-            ExprKind::Mac(..) => ExprPrecedence::Mac,
+            ExprKind::MacCall(..) => ExprPrecedence::Mac,
             ExprKind::Struct(..) => ExprPrecedence::Struct,
             ExprKind::Repeat(..) => ExprPrecedence::Repeat,
             ExprKind::Paren(..) => ExprPrecedence::Paren,
@@ -1256,7 +1259,7 @@ pub enum ExprKind {
     InlineAsm(P<InlineAsm>),
 
     /// A macro invocation; pre-expansion.
-    Mac(Mac),
+    MacCall(MacCall),
 
     /// A struct literal expression.
     ///
@@ -1342,13 +1345,13 @@ pub enum Movability {
 /// Represents a macro invocation. The `path` indicates which macro
 /// is being invoked, and the `args` are arguments passed to it.
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
-pub struct Mac {
+pub struct MacCall {
     pub path: Path,
     pub args: P<MacArgs>,
     pub prior_type_ascription: Option<(Span, bool)>,
 }
 
-impl Mac {
+impl MacCall {
     pub fn span(&self) -> Span {
         self.path.span.to(self.args.span().unwrap_or(self.path.span))
     }
@@ -1443,11 +1446,11 @@ pub fn from_token(delim: DelimToken) -> Option<MacDelimiter> {
 }
 
 /// Represents a macro definition.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
 pub struct MacroDef {
     pub body: P<MacArgs>,
     /// `true` if macro was defined with `macro_rules`.
-    pub legacy: bool,
+    pub macro_rules: bool,
 }
 
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy, Hash, Eq, PartialEq)]
@@ -1878,7 +1881,7 @@ pub enum TyKind {
     /// Inferred type of a `self` or `&self` argument in a method.
     ImplicitSelf,
     /// A macro in the type position.
-    Mac(Mac),
+    MacCall(MacCall),
     /// Placeholder for a kind that has failed to be defined.
     Err,
     /// Placeholder for a `va_list`.
@@ -2086,7 +2089,7 @@ pub fn is_async(self) -> bool {
         if let Async::Yes { .. } = self { true } else { false }
     }
 
-    /// In ths case this is an `async` return, the `NodeId` for the generated `impl Trait` item.
+    /// In this case this is an `async` return, the `NodeId` for the generated `impl Trait` item.
     pub fn opt_return_id(self) -> Option<NodeId> {
         match self {
             Async::Yes { return_impl_trait_id, .. } => Some(return_impl_trait_id),
@@ -2115,14 +2118,14 @@ pub enum ImplPolarity {
     /// `impl Trait for Type`
     Positive,
     /// `impl !Trait for Type`
-    Negative,
+    Negative(Span),
 }
 
 impl fmt::Debug for ImplPolarity {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match *self {
             ImplPolarity::Positive => "positive".fmt(f),
-            ImplPolarity::Negative => "negative".fmt(f),
+            ImplPolarity::Negative(_) => "negative".fmt(f),
         }
     }
 }
@@ -2150,7 +2153,7 @@ pub fn span(&self) -> Span {
 /// Module declaration.
 ///
 /// E.g., `mod foo;` or `mod foo { .. }`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Default)]
 pub struct Mod {
     /// A span from the first token past `{` to the last token until `}`.
     /// For `mod foo;`, the inner span ranges from the first token
@@ -2441,10 +2444,10 @@ pub fn span_with_attributes(&self) -> Span {
     }
 }
 
-impl<K: IntoItemKind> Item<K> {
+impl<K: Into<ItemKind>> Item<K> {
     pub fn into_item(self) -> Item {
         let Item { attrs, id, span, vis, ident, kind, tokens } = self;
-        Item { attrs, id, span, vis, ident, kind: kind.into_item_kind(), tokens }
+        Item { attrs, id, span, vis, ident, kind: kind.into(), tokens }
     }
 }
 
@@ -2571,7 +2574,7 @@ pub enum ItemKind {
     /// A macro invocation.
     ///
     /// E.g., `foo!(..)`.
-    Mac(Mac),
+    MacCall(MacCall),
 
     /// A macro definition.
     MacroDef(MacroDef),
@@ -2583,7 +2586,7 @@ pub fn article(&self) -> &str {
         match self {
             Use(..) | Static(..) | Const(..) | Fn(..) | Mod(..) | GlobalAsm(..) | TyAlias(..)
             | Struct(..) | Union(..) | Trait(..) | TraitAlias(..) | MacroDef(..) => "a",
-            ExternCrate(..) | ForeignMod(..) | Mac(..) | Enum(..) | Impl { .. } => "an",
+            ExternCrate(..) | ForeignMod(..) | MacCall(..) | Enum(..) | Impl { .. } => "an",
         }
     }
 
@@ -2603,7 +2606,7 @@ pub fn descr(&self) -> &str {
             ItemKind::Union(..) => "union",
             ItemKind::Trait(..) => "trait",
             ItemKind::TraitAlias(..) => "trait alias",
-            ItemKind::Mac(..) => "item macro invocation",
+            ItemKind::MacCall(..) => "item macro invocation",
             ItemKind::MacroDef(..) => "macro definition",
             ItemKind::Impl { .. } => "implementation",
         }
@@ -2624,20 +2627,11 @@ pub fn generics(&self) -> Option<&Generics> {
     }
 }
 
-pub trait IntoItemKind {
-    fn into_item_kind(self) -> ItemKind;
-}
-
-// FIXME(Centril): These definitions should be unmerged;
-// see https://github.com/rust-lang/rust/pull/69194#discussion_r379899975
-pub type ForeignItem = Item<AssocItemKind>;
-pub type ForeignItemKind = AssocItemKind;
-
 /// Represents associated items.
 /// These include items in `impl` and `trait` definitions.
 pub type AssocItem = Item<AssocItemKind>;
 
-/// Represents non-free item kinds.
+/// Represents associated item kinds.
 ///
 /// The term "provided" in the variants below refers to the item having a default
 /// definition / body. Meanwhile, a "required" item lacks a definition / body.
@@ -2646,36 +2640,87 @@ pub trait IntoItemKind {
 /// means "provided" and conversely `None` means "required".
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub enum AssocItemKind {
-    /// A constant, `const $ident: $ty $def?;` where `def ::= "=" $expr? ;`.
+    /// An associated constant, `const $ident: $ty $def?;` where `def ::= "=" $expr? ;`.
     /// If `def` is parsed, then the constant is provided, and otherwise required.
     Const(Defaultness, P<Ty>, Option<P<Expr>>),
-    /// A static item (`static FOO: u8`).
-    Static(P<Ty>, Mutability, Option<P<Expr>>),
-    /// A function.
+    /// An associated function.
     Fn(Defaultness, FnSig, Generics, Option<P<Block>>),
-    /// A type.
+    /// An associated type.
     TyAlias(Defaultness, Generics, GenericBounds, Option<P<Ty>>),
-    /// A macro expanding to items.
-    Macro(Mac),
+    /// A macro expanding to associated items.
+    MacCall(MacCall),
 }
 
 impl AssocItemKind {
     pub fn defaultness(&self) -> Defaultness {
         match *self {
             Self::Const(def, ..) | Self::Fn(def, ..) | Self::TyAlias(def, ..) => def,
-            Self::Macro(..) | Self::Static(..) => Defaultness::Final,
+            Self::MacCall(..) => Defaultness::Final,
         }
     }
 }
 
-impl IntoItemKind for AssocItemKind {
-    fn into_item_kind(self) -> ItemKind {
-        match self {
+impl From<AssocItemKind> for ItemKind {
+    fn from(assoc_item_kind: AssocItemKind) -> ItemKind {
+        match assoc_item_kind {
             AssocItemKind::Const(a, b, c) => ItemKind::Const(a, b, c),
-            AssocItemKind::Static(a, b, c) => ItemKind::Static(a, b, c),
             AssocItemKind::Fn(a, b, c, d) => ItemKind::Fn(a, b, c, d),
             AssocItemKind::TyAlias(a, b, c, d) => ItemKind::TyAlias(a, b, c, d),
-            AssocItemKind::Macro(a) => ItemKind::Mac(a),
+            AssocItemKind::MacCall(a) => ItemKind::MacCall(a),
         }
     }
 }
+
+impl TryFrom<ItemKind> for AssocItemKind {
+    type Error = ItemKind;
+
+    fn try_from(item_kind: ItemKind) -> Result<AssocItemKind, ItemKind> {
+        Ok(match item_kind {
+            ItemKind::Const(a, b, c) => AssocItemKind::Const(a, b, c),
+            ItemKind::Fn(a, b, c, d) => AssocItemKind::Fn(a, b, c, d),
+            ItemKind::TyAlias(a, b, c, d) => AssocItemKind::TyAlias(a, b, c, d),
+            ItemKind::MacCall(a) => AssocItemKind::MacCall(a),
+            _ => return Err(item_kind),
+        })
+    }
+}
+
+/// An item in `extern` block.
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+pub enum ForeignItemKind {
+    /// A foreign static item (`static FOO: u8`).
+    Static(P<Ty>, Mutability, Option<P<Expr>>),
+    /// A foreign function.
+    Fn(Defaultness, FnSig, Generics, Option<P<Block>>),
+    /// A foreign type.
+    TyAlias(Defaultness, Generics, GenericBounds, Option<P<Ty>>),
+    /// A macro expanding to foreign items.
+    MacCall(MacCall),
+}
+
+impl From<ForeignItemKind> for ItemKind {
+    fn from(foreign_item_kind: ForeignItemKind) -> ItemKind {
+        match foreign_item_kind {
+            ForeignItemKind::Static(a, b, c) => ItemKind::Static(a, b, c),
+            ForeignItemKind::Fn(a, b, c, d) => ItemKind::Fn(a, b, c, d),
+            ForeignItemKind::TyAlias(a, b, c, d) => ItemKind::TyAlias(a, b, c, d),
+            ForeignItemKind::MacCall(a) => ItemKind::MacCall(a),
+        }
+    }
+}
+
+impl TryFrom<ItemKind> for ForeignItemKind {
+    type Error = ItemKind;
+
+    fn try_from(item_kind: ItemKind) -> Result<ForeignItemKind, ItemKind> {
+        Ok(match item_kind {
+            ItemKind::Static(a, b, c) => ForeignItemKind::Static(a, b, c),
+            ItemKind::Fn(a, b, c, d) => ForeignItemKind::Fn(a, b, c, d),
+            ItemKind::TyAlias(a, b, c, d) => ForeignItemKind::TyAlias(a, b, c, d),
+            ItemKind::MacCall(a) => ForeignItemKind::MacCall(a),
+            _ => return Err(item_kind),
+        })
+    }
+}
+
+pub type ForeignItem = Item<ForeignItemKind>;
index bc5c86b02b3c090e46e1485ef3ce3ce89bb15adb..249311851fb1bed7d19bebd79b1a9543dad39804 100644 (file)
@@ -286,6 +286,10 @@ pub fn is_meta_item_list(&self) -> bool {
 }
 
 impl AttrItem {
+    pub fn span(&self) -> Span {
+        self.args.span().map_or(self.path.span, |args_span| self.path.span.to(args_span))
+    }
+
     pub fn meta(&self, span: Span) -> Option<MetaItem> {
         Some(MetaItem {
             path: self.path.clone(),
@@ -437,7 +441,7 @@ fn from_tokens<I>(tokens: &mut iter::Peekable<I>) -> Option<MetaItem>
         I: Iterator<Item = TokenTree>,
     {
         // FIXME: Share code with `parse_path`.
-        let path = match tokens.next() {
+        let path = match tokens.next().map(TokenTree::uninterpolate) {
             Some(TokenTree::Token(Token { kind: kind @ token::Ident(..), span }))
             | Some(TokenTree::Token(Token { kind: kind @ token::ModSep, span })) => 'arm: {
                 let mut segments = if let token::Ident(name, _) = kind {
@@ -453,7 +457,7 @@ fn from_tokens<I>(tokens: &mut iter::Peekable<I>) -> Option<MetaItem>
                 };
                 loop {
                     if let Some(TokenTree::Token(Token { kind: token::Ident(name, _), span })) =
-                        tokens.next()
+                        tokens.next().map(TokenTree::uninterpolate)
                     {
                         segments.push(PathSegment::from_ident(Ident::new(name, span)));
                     } else {
@@ -470,7 +474,6 @@ fn from_tokens<I>(tokens: &mut iter::Peekable<I>) -> Option<MetaItem>
                 Path { span, segments }
             }
             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::NtPath(ref path) => path.clone(),
                 _ => return None,
@@ -674,9 +677,9 @@ impl HasAttrs for StmtKind {
     fn attrs(&self) -> &[Attribute] {
         match *self {
             StmtKind::Local(ref local) => local.attrs(),
-            StmtKind::Item(..) => &[],
             StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => expr.attrs(),
-            StmtKind::Mac(ref mac) => {
+            StmtKind::Empty | StmtKind::Item(..) => &[],
+            StmtKind::MacCall(ref mac) => {
                 let (_, _, ref attrs) = **mac;
                 attrs.attrs()
             }
@@ -686,10 +689,9 @@ fn attrs(&self) -> &[Attribute] {
     fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) {
         match self {
             StmtKind::Local(local) => local.visit_attrs(f),
-            StmtKind::Item(..) => {}
-            StmtKind::Expr(expr) => expr.visit_attrs(f),
-            StmtKind::Semi(expr) => expr.visit_attrs(f),
-            StmtKind::Mac(mac) => {
+            StmtKind::Expr(expr) | StmtKind::Semi(expr) => expr.visit_attrs(f),
+            StmtKind::Empty | StmtKind::Item(..) => {}
+            StmtKind::MacCall(mac) => {
                 let (_mac, _style, attrs) = mac.deref_mut();
                 attrs.visit_attrs(f);
             }
@@ -722,6 +724,6 @@ fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) {
 }
 
 derive_has_attrs! {
-    Item, Expr, Local, ast::ForeignItem, ast::StructField, ast::Arm,
+    Item, Expr, Local, ast::AssocItem, ast::ForeignItem, ast::StructField, ast::Arm,
     ast::Field, ast::FieldPat, ast::Variant, ast::Param, GenericParam
 }
index adb96356aae7d53fec41564461d6cb918d47ec81..2594cc536ac5f893b17c308f619940e60d0b3440 100644 (file)
@@ -7,7 +7,9 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/", test(attr(deny(warnings))))]
 #![feature(bool_to_option)]
 #![feature(box_syntax)]
+#![feature(const_if_match)]
 #![feature(const_fn)] // For the `transmute` in `P::new`
+#![feature(const_panic)]
 #![feature(const_transmute)]
 #![feature(crate_visibility_modifier)]
 #![feature(label_break_value)]
index b3abd4fc755e46b721b1a4d376650008b6079f89..aa2968b3cbe44dc3826869a720b0c25bd7872ffa 100644 (file)
@@ -202,7 +202,7 @@ fn visit_local(&mut self, l: &mut P<Local>) {
         noop_visit_local(l, self);
     }
 
-    fn visit_mac(&mut self, _mac: &mut Mac) {
+    fn visit_mac(&mut self, _mac: &mut MacCall) {
         panic!("visit_mac disabled by default");
         // N.B., see note about macros above. If you really want a visitor that
         // works on macros, use this definition in your trait impl:
@@ -482,7 +482,7 @@ pub fn noop_visit_ty<T: MutVisitor>(ty: &mut P<Ty>, vis: &mut T) {
             vis.visit_id(id);
             visit_vec(bounds, |bound| vis.visit_param_bound(bound));
         }
-        TyKind::Mac(mac) => vis.visit_mac(mac),
+        TyKind::MacCall(mac) => vis.visit_mac(mac),
     }
     vis.visit_span(span);
 }
@@ -584,14 +584,14 @@ pub fn noop_visit_attribute<T: MutVisitor>(attr: &mut Attribute, vis: &mut T) {
     vis.visit_span(span);
 }
 
-pub fn noop_visit_mac<T: MutVisitor>(mac: &mut Mac, vis: &mut T) {
-    let Mac { path, args, prior_type_ascription: _ } = mac;
+pub fn noop_visit_mac<T: MutVisitor>(mac: &mut MacCall, vis: &mut T) {
+    let MacCall { path, args, prior_type_ascription: _ } = mac;
     vis.visit_path(path);
     visit_mac_args(args, vis);
 }
 
 pub fn noop_visit_macro_def<T: MutVisitor>(macro_def: &mut MacroDef, vis: &mut T) {
-    let MacroDef { body, legacy: _ } = macro_def;
+    let MacroDef { body, macro_rules: _ } = macro_def;
     visit_mac_args(body, vis);
 }
 
@@ -926,7 +926,7 @@ pub fn noop_visit_item_kind<T: MutVisitor>(kind: &mut ItemKind, vis: &mut T) {
             vis.visit_generics(generics);
             visit_bounds(bounds, vis);
         }
-        ItemKind::Mac(m) => vis.visit_mac(m),
+        ItemKind::MacCall(m) => vis.visit_mac(m),
         ItemKind::MacroDef(def) => vis.visit_macro_def(def),
     }
 }
@@ -936,25 +936,12 @@ pub fn noop_flat_map_assoc_item<T: MutVisitor>(
     visitor: &mut T,
 ) -> SmallVec<[P<AssocItem>; 1]> {
     let Item { id, ident, vis, attrs, kind, span, tokens: _ } = item.deref_mut();
-    walk_nested_item(visitor, id, span, ident, vis, attrs, kind);
-    smallvec![item]
-}
-
-pub fn walk_nested_item(
-    visitor: &mut impl MutVisitor,
-    id: &mut NodeId,
-    span: &mut Span,
-    ident: &mut Ident,
-    vis: &mut Visibility,
-    attrs: &mut Vec<Attribute>,
-    kind: &mut AssocItemKind,
-) {
     visitor.visit_id(id);
     visitor.visit_ident(ident);
     visitor.visit_vis(vis);
     visit_attrs(attrs, visitor);
     match kind {
-        AssocItemKind::Const(_, ty, expr) | AssocItemKind::Static(ty, _, expr) => {
+        AssocItemKind::Const(_, ty, expr) => {
             visitor.visit_ty(ty);
             visit_opt(expr, |expr| visitor.visit_expr(expr));
         }
@@ -968,9 +955,10 @@ pub fn walk_nested_item(
             visit_bounds(bounds, visitor);
             visit_opt(ty, |ty| visitor.visit_ty(ty));
         }
-        AssocItemKind::Macro(mac) => visitor.visit_mac(mac),
+        AssocItemKind::MacCall(mac) => visitor.visit_mac(mac),
     }
     visitor.visit_span(span);
+    smallvec![item]
 }
 
 pub fn noop_visit_fn_header<T: MutVisitor>(header: &mut FnHeader, vis: &mut T) {
@@ -1036,7 +1024,28 @@ pub fn noop_flat_map_foreign_item<T: MutVisitor>(
     visitor: &mut T,
 ) -> SmallVec<[P<ForeignItem>; 1]> {
     let Item { ident, attrs, id, kind, vis, span, tokens: _ } = item.deref_mut();
-    walk_nested_item(visitor, id, span, ident, vis, attrs, kind);
+    visitor.visit_id(id);
+    visitor.visit_ident(ident);
+    visitor.visit_vis(vis);
+    visit_attrs(attrs, visitor);
+    match kind {
+        ForeignItemKind::Static(ty, _, expr) => {
+            visitor.visit_ty(ty);
+            visit_opt(expr, |expr| visitor.visit_expr(expr));
+        }
+        ForeignItemKind::Fn(_, sig, generics, body) => {
+            visitor.visit_generics(generics);
+            visit_fn_sig(sig, visitor);
+            visit_opt(body, |body| visitor.visit_block(body));
+        }
+        ForeignItemKind::TyAlias(_, generics, bounds, ty) => {
+            visitor.visit_generics(generics);
+            visit_bounds(bounds, visitor);
+            visit_opt(ty, |ty| visitor.visit_ty(ty));
+        }
+        ForeignItemKind::MacCall(mac) => visitor.visit_mac(mac),
+    }
+    visitor.visit_span(span);
     smallvec![item]
 }
 
@@ -1073,7 +1082,7 @@ pub fn noop_visit_pat<T: MutVisitor>(pat: &mut P<Pat>, vis: &mut T) {
             visit_vec(elems, |elem| vis.visit_pat(elem))
         }
         PatKind::Paren(inner) => vis.visit_pat(inner),
-        PatKind::Mac(mac) => vis.visit_mac(mac),
+        PatKind::MacCall(mac) => vis.visit_mac(mac),
     }
     vis.visit_span(span);
 }
@@ -1210,7 +1219,7 @@ pub fn noop_visit_expr<T: MutVisitor>(Expr { kind, id, span, attrs }: &mut Expr,
             }
             visit_vec(inputs, |(_c, expr)| vis.visit_expr(expr));
         }
-        ExprKind::Mac(mac) => vis.visit_mac(mac),
+        ExprKind::MacCall(mac) => vis.visit_mac(mac),
         ExprKind::Struct(path, fields, expr) => {
             vis.visit_path(path);
             fields.flat_map_in_place(|field| vis.flat_map_field(field));
@@ -1265,11 +1274,12 @@ pub fn noop_flat_map_stmt_kind<T: MutVisitor>(
         StmtKind::Item(item) => vis.flat_map_item(item).into_iter().map(StmtKind::Item).collect(),
         StmtKind::Expr(expr) => vis.filter_map_expr(expr).into_iter().map(StmtKind::Expr).collect(),
         StmtKind::Semi(expr) => vis.filter_map_expr(expr).into_iter().map(StmtKind::Semi).collect(),
-        StmtKind::Mac(mut mac) => {
+        StmtKind::Empty => smallvec![StmtKind::Empty],
+        StmtKind::MacCall(mut mac) => {
             let (mac_, _semi, attrs) = mac.deref_mut();
             vis.visit_mac(mac_);
             visit_thin_attrs(attrs, vis);
-            smallvec![StmtKind::Mac(mac)]
+            smallvec![StmtKind::MacCall(mac)]
         }
     }
 }
index 58d2334a7b148ccf150bd0acb04d04489b582710..cd562c48e9115eb24f12bd73bf5eb138d974f533 100644 (file)
@@ -12,7 +12,7 @@ pub struct NodeId {
 rustc_data_structures::define_id_collections!(NodeMap, NodeSet, NodeId);
 
 /// `NodeId` used to represent the root of the crate.
-pub const CRATE_NODE_ID: NodeId = NodeId::from_u32_const(0);
+pub const CRATE_NODE_ID: NodeId = NodeId::from_u32(0);
 
 /// When parsing and doing expansions, we initially give all AST nodes this AST
 /// node value. Then later, in the renumber pass, we renumber them to have
index a8a2c9b2fb3187dccfd197c43c506dd8354a9d50..3fc6444168e24297b8e1118ad9e1b384d9100a60 100644 (file)
@@ -14,8 +14,8 @@
 use rustc_span::symbol::kw;
 use rustc_span::symbol::Symbol;
 use rustc_span::{self, Span, DUMMY_SP};
-use std::fmt;
-use std::mem;
+use std::borrow::Cow;
+use std::{fmt, mem};
 
 #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
 #[derive(HashStable_Generic)]
@@ -225,8 +225,15 @@ pub enum TokenKind {
     /* Literals */
     Literal(Lit),
 
-    /* Name components */
+    /// Identifier token.
+    /// Do not forget about `NtIdent` when you want to match on identifiers.
+    /// It's recommended to use `Token::(ident,uninterpolate,uninterpolated_span)` to
+    /// treat regular and interpolated identifiers in the same way.
     Ident(ast::Name, /* is_raw */ bool),
+    /// Lifetime identifier token.
+    /// Do not forget about `NtLifetime` when you want to match on lifetime identifiers.
+    /// It's recommended to use `Token::(lifetime,uninterpolate,uninterpolated_span)` to
+    /// treat regular and interpolated lifetime identifiers in the same way.
     Lifetime(ast::Name),
 
     Interpolated(Lrc<Nonterminal>),
@@ -328,6 +335,19 @@ pub fn take(&mut self) -> Self {
         mem::replace(self, Token::dummy())
     }
 
+    /// For interpolated tokens, returns a span of the fragment to which the interpolated
+    /// token refers. For all other tokens this is just a regular span.
+    /// It is particularly important to use this for identifiers and lifetimes
+    /// for which spans affect name resolution and edition checks.
+    /// Note that keywords are also identifiers, so they should use this
+    /// if they keep spans or perform edition checks.
+    pub fn uninterpolated_span(&self) -> Span {
+        match &self.kind {
+            Interpolated(nt) => nt.span(),
+            _ => self.span,
+        }
+    }
+
     pub fn is_op(&self) -> bool {
         match self.kind {
             OpenDelim(..) | CloseDelim(..) | Literal(..) | DocComment(..) | Ident(..)
@@ -345,7 +365,7 @@ pub fn is_like_plus(&self) -> bool {
 
     /// Returns `true` if the token can appear at the start of an expression.
     pub fn can_begin_expr(&self) -> bool {
-        match self.kind {
+        match self.uninterpolate().kind {
             Ident(name, is_raw)              =>
                 ident_can_begin_expr(name, self.span, is_raw), // value name or keyword
             OpenDelim(..)                     | // tuple, array or block
@@ -363,12 +383,10 @@ pub fn can_begin_expr(&self) -> bool {
             Lifetime(..)                      | // labeled loop
             Pound                             => true, // expression attributes
             Interpolated(ref nt) => match **nt {
-                NtIdent(ident, is_raw) => ident_can_begin_expr(ident.name, ident.span, is_raw),
                 NtLiteral(..) |
                 NtExpr(..)    |
                 NtBlock(..)   |
-                NtPath(..)    |
-                NtLifetime(..) => true,
+                NtPath(..) => true,
                 _ => false,
             },
             _ => false,
@@ -377,7 +395,7 @@ pub fn can_begin_expr(&self) -> bool {
 
     /// Returns `true` if the token can appear at the start of a type.
     pub fn can_begin_type(&self) -> bool {
-        match self.kind {
+        match self.uninterpolate().kind {
             Ident(name, is_raw)        =>
                 ident_can_begin_type(name, self.span, is_raw), // type name or keyword
             OpenDelim(Paren)            | // tuple
@@ -391,8 +409,7 @@ pub fn can_begin_type(&self) -> bool {
             Lt | BinOp(Shl)             | // associated path
             ModSep                      => true, // global path
             Interpolated(ref nt) => match **nt {
-                NtIdent(ident, is_raw) => ident_can_begin_type(ident.name, ident.span, is_raw),
-                NtTy(..) | NtPath(..) | NtLifetime(..) => true,
+                NtTy(..) | NtPath(..) => true,
                 _ => false,
             },
             _ => false,
@@ -433,11 +450,10 @@ pub fn is_lit(&self) -> bool {
     ///
     /// Keep this in sync with `Lit::from_token`.
     pub fn can_begin_literal_or_bool(&self) -> bool {
-        match self.kind {
+        match self.uninterpolate().kind {
             Literal(..) | BinOp(Minus) => true,
             Ident(name, false) if name.is_bool_lit() => true,
             Interpolated(ref nt) => match &**nt {
-                NtIdent(ident, false) if ident.name.is_bool_lit() => true,
                 NtExpr(e) | NtLiteral(e) => matches!(e.kind, ast::ExprKind::Lit(_)),
                 _ => false,
             },
@@ -445,26 +461,37 @@ pub fn can_begin_literal_or_bool(&self) -> bool {
         }
     }
 
+    // A convenience function for matching on identifiers during parsing.
+    // Turns interpolated identifier (`$i: ident`) or lifetime (`$l: lifetime`) token
+    // into the regular identifier or lifetime token it refers to,
+    // otherwise returns the original token.
+    pub fn uninterpolate(&self) -> Cow<'_, Token> {
+        match &self.kind {
+            Interpolated(nt) => match **nt {
+                NtIdent(ident, is_raw) => {
+                    Cow::Owned(Token::new(Ident(ident.name, is_raw), ident.span))
+                }
+                NtLifetime(ident) => Cow::Owned(Token::new(Lifetime(ident.name), ident.span)),
+                _ => Cow::Borrowed(self),
+            },
+            _ => Cow::Borrowed(self),
+        }
+    }
+
     /// Returns an identifier if this token is an identifier.
     pub fn ident(&self) -> Option<(ast::Ident, /* is_raw */ bool)> {
-        match self.kind {
-            Ident(name, is_raw) => Some((ast::Ident::new(name, self.span), is_raw)),
-            Interpolated(ref nt) => match **nt {
-                NtIdent(ident, is_raw) => Some((ident, is_raw)),
-                _ => None,
-            },
+        let token = self.uninterpolate();
+        match token.kind {
+            Ident(name, is_raw) => Some((ast::Ident::new(name, token.span), is_raw)),
             _ => None,
         }
     }
 
     /// Returns a lifetime identifier if this token is a lifetime.
     pub fn lifetime(&self) -> Option<ast::Ident> {
-        match self.kind {
-            Lifetime(name) => Some(ast::Ident::new(name, self.span)),
-            Interpolated(ref nt) => match **nt {
-                NtLifetime(ident) => Some(ident),
-                _ => None,
-            },
+        let token = self.uninterpolate();
+        match token.kind {
+            Lifetime(name) => Some(ast::Ident::new(name, token.span)),
             _ => None,
         }
     }
@@ -508,6 +535,16 @@ pub fn is_whole_expr(&self) -> bool {
         false
     }
 
+    // Is the token an interpolated block (`$b:block`)?
+    pub fn is_whole_block(&self) -> bool {
+        if let Interpolated(ref nt) = self.kind {
+            if let NtBlock(..) = **nt {
+                return true;
+            }
+        }
+        false
+    }
+
     /// Returns `true` if the token is either the `mut` or `const` keyword.
     pub fn is_mutability(&self) -> bool {
         self.is_keyword(kw::Mut) || self.is_keyword(kw::Const)
@@ -714,6 +751,24 @@ pub enum Nonterminal {
 #[cfg(target_arch = "x86_64")]
 rustc_data_structures::static_assert_size!(Nonterminal, 40);
 
+impl Nonterminal {
+    fn span(&self) -> Span {
+        match self {
+            NtItem(item) => item.span,
+            NtBlock(block) => block.span,
+            NtStmt(stmt) => stmt.span,
+            NtPat(pat) => pat.span,
+            NtExpr(expr) | NtLiteral(expr) => expr.span,
+            NtTy(ty) => ty.span,
+            NtIdent(ident, _) | NtLifetime(ident) => ident.span,
+            NtMeta(attr_item) => attr_item.span(),
+            NtPath(path) => path.span,
+            NtVis(vis) => vis.span,
+            NtTT(tt) => tt.span(),
+        }
+    }
+}
+
 impl PartialEq for Nonterminal {
     fn eq(&self, rhs: &Self) -> bool {
         match (self, rhs) {
index 03e8fff247b396d61a4a6f37d5c4da5ef59ba5fa..916a5ff6f46f49a0d6969f6e0d809e19f41b623a 100644 (file)
@@ -116,6 +116,13 @@ pub fn open_tt(span: DelimSpan, delim: DelimToken) -> TokenTree {
     pub fn close_tt(span: DelimSpan, delim: DelimToken) -> TokenTree {
         TokenTree::token(token::CloseDelim(delim), span.close)
     }
+
+    pub fn uninterpolate(self) -> TokenTree {
+        match self {
+            TokenTree::Token(token) => TokenTree::Token(token.uninterpolate().into_owned()),
+            tt => tt,
+        }
+    }
 }
 
 impl<CTX> HashStable<CTX> for TokenStream
index ecf17efc4e0d1ba605215719ca729fb72e1d45cc..d1757394f3a1dee633881c5720e6695022c9727c 100644 (file)
@@ -191,23 +191,16 @@ pub fn from_lit_token(token: token::Lit, span: Span) -> Result<Lit, LitError> {
     ///
     /// Keep this in sync with `Token::can_begin_literal_or_bool`.
     pub fn from_token(token: &Token) -> Result<Lit, LitError> {
-        let lit = match token.kind {
+        let lit = match token.uninterpolate().kind {
             token::Ident(name, false) if name.is_bool_lit() => {
                 token::Lit::new(token::Bool, name, None)
             }
             token::Literal(lit) => lit,
             token::Interpolated(ref nt) => {
-                match &**nt {
-                    token::NtIdent(ident, false) if ident.name.is_bool_lit() => {
-                        let lit = token::Lit::new(token::Bool, ident.name, None);
-                        return Lit::from_lit_token(lit, ident.span);
+                if let token::NtExpr(expr) | token::NtLiteral(expr) = &**nt {
+                    if let ast::ExprKind::Lit(lit) = &expr.kind {
+                        return Ok(lit.clone());
                     }
-                    token::NtExpr(expr) | token::NtLiteral(expr) => {
-                        if let ast::ExprKind::Lit(lit) = &expr.kind {
-                            return Ok(lit.clone());
-                        }
-                    }
-                    _ => {}
                 }
                 return Err(LitError::NotLiteral);
             }
index 96149ad7947ce208a0501483d608a146dcd062df..39028b7583c63429ad90d8ef3d580d5d0473161b 100644 (file)
@@ -168,7 +168,7 @@ fn visit_label(&mut self, label: &'ast Label) {
     fn visit_lifetime(&mut self, lifetime: &'ast Lifetime) {
         walk_lifetime(self, lifetime)
     }
-    fn visit_mac(&mut self, _mac: &'ast Mac) {
+    fn visit_mac(&mut self, _mac: &'ast MacCall) {
         panic!("visit_mac disabled by default");
         // N.B., see note about macros above.
         // if you really want a visitor that
@@ -350,7 +350,7 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
             visitor.visit_generics(generics);
             walk_list!(visitor, visit_param_bound, bounds);
         }
-        ItemKind::Mac(ref mac) => visitor.visit_mac(mac),
+        ItemKind::MacCall(ref mac) => visitor.visit_mac(mac),
         ItemKind::MacroDef(ref ts) => visitor.visit_mac_def(ts, item.id),
     }
     walk_list!(visitor, visit_attribute, &item.attrs);
@@ -418,7 +418,7 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) {
         }
         TyKind::Typeof(ref expression) => visitor.visit_anon_const(expression),
         TyKind::Infer | TyKind::ImplicitSelf | TyKind::Err => {}
-        TyKind::Mac(ref mac) => visitor.visit_mac(mac),
+        TyKind::MacCall(ref mac) => visitor.visit_mac(mac),
         TyKind::Never | TyKind::CVarArgs => {}
     }
 }
@@ -521,13 +521,34 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) {
         PatKind::Tuple(ref elems) | PatKind::Slice(ref elems) | PatKind::Or(ref elems) => {
             walk_list!(visitor, visit_pat, elems);
         }
-        PatKind::Mac(ref mac) => visitor.visit_mac(mac),
+        PatKind::MacCall(ref mac) => visitor.visit_mac(mac),
     }
 }
 
 pub fn walk_foreign_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a ForeignItem) {
-    let Item { id, span, ident, vis, attrs, kind, tokens: _ } = item;
-    walk_nested_item(visitor, *id, *span, *ident, vis, attrs, kind, FnCtxt::Foreign);
+    let Item { id, span, ident, ref vis, ref attrs, ref kind, tokens: _ } = *item;
+    visitor.visit_vis(vis);
+    visitor.visit_ident(ident);
+    walk_list!(visitor, visit_attribute, attrs);
+    match kind {
+        ForeignItemKind::Static(ty, _, expr) => {
+            visitor.visit_ty(ty);
+            walk_list!(visitor, visit_expr, expr);
+        }
+        ForeignItemKind::Fn(_, sig, generics, body) => {
+            visitor.visit_generics(generics);
+            let kind = FnKind::Fn(FnCtxt::Foreign, ident, sig, vis, body.as_deref());
+            visitor.visit_fn(kind, span, id);
+        }
+        ForeignItemKind::TyAlias(_, generics, bounds, ty) => {
+            visitor.visit_generics(generics);
+            walk_list!(visitor, visit_param_bound, bounds);
+            walk_list!(visitor, visit_ty, ty);
+        }
+        ForeignItemKind::MacCall(mac) => {
+            visitor.visit_mac(mac);
+        }
+    }
 }
 
 pub fn walk_global_asm<'a, V: Visitor<'a>>(_: &mut V, _: &'a GlobalAsm) {
@@ -610,31 +631,18 @@ pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>, _span: Spa
 }
 
 pub fn walk_assoc_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem, ctxt: AssocCtxt) {
-    let Item { id, span, ident, vis, attrs, kind, tokens: _ } = item;
-    walk_nested_item(visitor, *id, *span, *ident, vis, attrs, kind, FnCtxt::Assoc(ctxt));
-}
-
-fn walk_nested_item<'a, V: Visitor<'a>>(
-    visitor: &mut V,
-    id: NodeId,
-    span: Span,
-    ident: Ident,
-    vis: &'a Visibility,
-    attrs: &'a [Attribute],
-    kind: &'a AssocItemKind,
-    ctxt: FnCtxt,
-) {
+    let Item { id, span, ident, ref vis, ref attrs, ref kind, tokens: _ } = *item;
     visitor.visit_vis(vis);
     visitor.visit_ident(ident);
     walk_list!(visitor, visit_attribute, attrs);
     match kind {
-        AssocItemKind::Const(_, ty, expr) | AssocItemKind::Static(ty, _, expr) => {
+        AssocItemKind::Const(_, ty, expr) => {
             visitor.visit_ty(ty);
             walk_list!(visitor, visit_expr, expr);
         }
         AssocItemKind::Fn(_, sig, generics, body) => {
             visitor.visit_generics(generics);
-            let kind = FnKind::Fn(ctxt, ident, sig, vis, body.as_deref());
+            let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), ident, sig, vis, body.as_deref());
             visitor.visit_fn(kind, span, id);
         }
         AssocItemKind::TyAlias(_, generics, bounds, ty) => {
@@ -642,7 +650,7 @@ fn walk_nested_item<'a, V: Visitor<'a>>(
             walk_list!(visitor, visit_param_bound, bounds);
             walk_list!(visitor, visit_ty, ty);
         }
-        AssocItemKind::Macro(mac) => {
+        AssocItemKind::MacCall(mac) => {
             visitor.visit_mac(mac);
         }
     }
@@ -669,10 +677,9 @@ pub fn walk_stmt<'a, V: Visitor<'a>>(visitor: &mut V, statement: &'a Stmt) {
     match statement.kind {
         StmtKind::Local(ref local) => visitor.visit_local(local),
         StmtKind::Item(ref item) => visitor.visit_item(item),
-        StmtKind::Expr(ref expression) | StmtKind::Semi(ref expression) => {
-            visitor.visit_expr(expression)
-        }
-        StmtKind::Mac(ref mac) => {
+        StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => visitor.visit_expr(expr),
+        StmtKind::Empty => {}
+        StmtKind::MacCall(ref mac) => {
             let (ref mac, _, ref attrs) = **mac;
             visitor.visit_mac(mac);
             for attr in attrs.iter() {
@@ -682,7 +689,7 @@ pub fn walk_stmt<'a, V: Visitor<'a>>(visitor: &mut V, statement: &'a Stmt) {
     }
 }
 
-pub fn walk_mac<'a, V: Visitor<'a>>(visitor: &mut V, mac: &'a Mac) {
+pub fn walk_mac<'a, V: Visitor<'a>>(visitor: &mut V, mac: &'a MacCall) {
     visitor.visit_path(&mac.path, DUMMY_NODE_ID);
 }
 
@@ -804,7 +811,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
         ExprKind::Ret(ref optional_expression) => {
             walk_list!(visitor, visit_expr, optional_expression);
         }
-        ExprKind::Mac(ref mac) => visitor.visit_mac(mac),
+        ExprKind::MacCall(ref mac) => visitor.visit_mac(mac),
         ExprKind::Paren(ref subexpression) => visitor.visit_expr(subexpression),
         ExprKind::InlineAsm(ref ia) => {
             for &(_, ref input) in &ia.inputs {
index 7038387caa9bfb8e8b0787d22223c4d9c897e9cc..a212f0a71077b32618db04b0f5ca676de90b4089 100644 (file)
@@ -198,7 +198,7 @@ pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'hir> {
                 return self.lower_expr_for(e, pat, head, body, opt_label);
             }
             ExprKind::Try(ref sub_expr) => self.lower_expr_try(e.span, sub_expr),
-            ExprKind::Mac(_) => panic!("Shouldn't exist here"),
+            ExprKind::MacCall(_) => panic!("Shouldn't exist here"),
         };
 
         hir::Expr {
@@ -470,6 +470,15 @@ fn lower_arm(&mut self, arm: &Arm) -> hir::Arm<'hir> {
         }
     }
 
+    /// Lower an `async` construct to a generator that is then wrapped so it implements `Future`.
+    ///
+    /// This results in:
+    ///
+    /// ```text
+    /// std::future::from_generator(static move? |_task_context| -> <ret_ty> {
+    ///     <body>
+    /// })
+    /// ```
     pub(super) fn make_async_expr(
         &mut self,
         capture_clause: CaptureBy,
@@ -480,17 +489,42 @@ pub(super) fn make_async_expr(
         body: impl FnOnce(&mut Self) -> hir::Expr<'hir>,
     ) -> hir::ExprKind<'hir> {
         let output = match ret_ty {
-            Some(ty) => FnRetTy::Ty(ty),
-            None => FnRetTy::Default(span),
+            Some(ty) => hir::FnRetTy::Return(self.lower_ty(&ty, ImplTraitContext::disallowed())),
+            None => hir::FnRetTy::DefaultReturn(span),
         };
-        let ast_decl = FnDecl { inputs: vec![], output };
-        let decl = self.lower_fn_decl(&ast_decl, None, /* impl trait allowed */ false, None);
-        let body_id = self.lower_fn_body(&ast_decl, |this| {
+
+        // Resume argument type. We let the compiler infer this to simplify the lowering. It is
+        // fully constrained by `future::from_generator`.
+        let input_ty = hir::Ty { hir_id: self.next_id(), kind: hir::TyKind::Infer, span };
+
+        // The closure/generator `FnDecl` takes a single (resume) argument of type `input_ty`.
+        let decl = self.arena.alloc(hir::FnDecl {
+            inputs: arena_vec![self; input_ty],
+            output,
+            c_variadic: false,
+            implicit_self: hir::ImplicitSelfKind::None,
+        });
+
+        // Lower the argument pattern/ident. The ident is used again in the `.await` lowering.
+        let (pat, task_context_hid) = self.pat_ident_binding_mode(
+            span,
+            Ident::with_dummy_span(sym::_task_context),
+            hir::BindingAnnotation::Mutable,
+        );
+        let param = hir::Param { attrs: &[], hir_id: self.next_id(), pat, span };
+        let params = arena_vec![self; param];
+
+        let body_id = self.lower_body(move |this| {
             this.generator_kind = Some(hir::GeneratorKind::Async(async_gen_kind));
-            body(this)
+
+            let old_ctx = this.task_context;
+            this.task_context = Some(task_context_hid);
+            let res = body(this);
+            this.task_context = old_ctx;
+            (params, res)
         });
 
-        // `static || -> <ret_ty> { body }`:
+        // `static |_task_context| -> <ret_ty> { body }`:
         let generator_kind = hir::ExprKind::Closure(
             capture_clause,
             decl,
@@ -523,13 +557,14 @@ pub(super) fn make_async_expr(
     /// ```rust
     /// match <expr> {
     ///     mut pinned => loop {
-    ///         match ::std::future::poll_with_tls_context(unsafe {
-    ///             <::std::pin::Pin>::new_unchecked(&mut pinned)
-    ///         }) {
+    ///         match unsafe { ::std::future::poll_with_context(
+    ///             <::std::pin::Pin>::new_unchecked(&mut pinned),
+    ///             task_context,
+    ///         ) } {
     ///             ::std::task::Poll::Ready(result) => break result,
     ///             ::std::task::Poll::Pending => {}
     ///         }
-    ///         yield ();
+    ///         task_context = yield ();
     ///     }
     /// }
     /// ```
@@ -561,12 +596,23 @@ fn lower_expr_await(&mut self, await_span: Span, expr: &Expr) -> hir::ExprKind<'
         let (pinned_pat, pinned_pat_hid) =
             self.pat_ident_binding_mode(span, pinned_ident, hir::BindingAnnotation::Mutable);
 
-        // ::std::future::poll_with_tls_context(unsafe {
-        //     ::std::pin::Pin::new_unchecked(&mut pinned)
-        // })`
+        let task_context_ident = Ident::with_dummy_span(sym::_task_context);
+
+        // unsafe {
+        //     ::std::future::poll_with_context(
+        //         ::std::pin::Pin::new_unchecked(&mut pinned),
+        //         task_context,
+        //     )
+        // }
         let poll_expr = {
             let pinned = self.expr_ident(span, pinned_ident, pinned_pat_hid);
             let ref_mut_pinned = self.expr_mut_addr_of(span, pinned);
+            let task_context = if let Some(task_context_hid) = self.task_context {
+                self.expr_ident_mut(span, task_context_ident, task_context_hid)
+            } else {
+                // Use of `await` outside of an async context, we cannot use `task_context` here.
+                self.expr_err(span)
+            };
             let pin_ty_id = self.next_id();
             let new_unchecked_expr_kind = self.expr_call_std_assoc_fn(
                 pin_ty_id,
@@ -575,14 +621,13 @@ fn lower_expr_await(&mut self, await_span: Span, expr: &Expr) -> hir::ExprKind<'
                 "new_unchecked",
                 arena_vec![self; ref_mut_pinned],
             );
-            let new_unchecked =
-                self.arena.alloc(self.expr(span, new_unchecked_expr_kind, ThinVec::new()));
-            let unsafe_expr = self.expr_unsafe(new_unchecked);
-            self.expr_call_std_path(
+            let new_unchecked = self.expr(span, new_unchecked_expr_kind, ThinVec::new());
+            let call = self.expr_call_std_path(
                 gen_future_span,
-                &[sym::future, sym::poll_with_tls_context],
-                arena_vec![self; unsafe_expr],
-            )
+                &[sym::future, sym::poll_with_context],
+                arena_vec![self; new_unchecked, task_context],
+            );
+            self.arena.alloc(self.expr_unsafe(call))
         };
 
         // `::std::task::Poll::Ready(result) => break result`
@@ -622,6 +667,7 @@ fn lower_expr_await(&mut self, await_span: Span, expr: &Expr) -> hir::ExprKind<'
             self.stmt_expr(span, match_expr)
         };
 
+        // task_context = yield ();
         let yield_stmt = {
             let unit = self.expr_unit(span);
             let yield_expr = self.expr(
@@ -629,7 +675,18 @@ fn lower_expr_await(&mut self, await_span: Span, expr: &Expr) -> hir::ExprKind<'
                 hir::ExprKind::Yield(unit, hir::YieldSource::Await),
                 ThinVec::new(),
             );
-            self.stmt_expr(span, yield_expr)
+            let yield_expr = self.arena.alloc(yield_expr);
+
+            if let Some(task_context_hid) = self.task_context {
+                let lhs = self.expr_ident(span, task_context_ident, task_context_hid);
+                let assign =
+                    self.expr(span, hir::ExprKind::Assign(lhs, yield_expr, span), AttrVec::new());
+                self.stmt_expr(span, assign)
+            } else {
+                // Use of `await` outside of an async context. Return `yield_expr` so that we can
+                // proceed with type checking.
+                self.stmt(span, hir::StmtKind::Semi(yield_expr))
+            }
         };
 
         let loop_block = self.block_all(span, arena_vec![self; inner_match_stmt, yield_stmt], None);
index 13148d97a67f30473a081a9a99aad240081b591e..c22b2812a9e3c43af282e70656bbd213f201c2b6 100644 (file)
@@ -6,11 +6,12 @@
 use rustc_ast::ast::*;
 use rustc_ast::attr;
 use rustc_ast::node_id::NodeMap;
+use rustc_ast::ptr::P;
 use rustc_ast::visit::{self, AssocCtxt, Visitor};
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::DefId;
+use rustc_hir::def_id::LocalDefId;
 use rustc_span::source_map::{respan, DesugaringKind};
 use rustc_span::symbol::{kw, sym};
 use rustc_span::Span;
@@ -114,7 +115,7 @@ fn with_parent_item_lifetime_defs<T>(
             _ => &[],
         };
         let lt_def_names = parent_generics.iter().filter_map(|param| match param.kind {
-            hir::GenericParamKind::Lifetime { .. } => Some(param.name.modern()),
+            hir::GenericParamKind::Lifetime { .. } => Some(param.name.normalize_to_macros_2_0()),
             _ => None,
         });
         self.in_scope_lifetimes.extend(lt_def_names);
@@ -219,18 +220,17 @@ pub fn lower_item(&mut self, i: &Item) -> Option<hir::Item<'hir>> {
         let mut vis = self.lower_visibility(&i.vis, None);
         let attrs = self.lower_attrs(&i.attrs);
 
-        if let ItemKind::MacroDef(ref def) = i.kind {
-            if !def.legacy || attr::contains_name(&i.attrs, sym::macro_export) {
-                let body = self.lower_token_stream(def.body.inner_tokens());
+        if let ItemKind::MacroDef(MacroDef { ref body, macro_rules }) = i.kind {
+            if !macro_rules || attr::contains_name(&i.attrs, sym::macro_export) {
                 let hir_id = self.lower_node_id(i.id);
+                let body = P(self.lower_mac_args(body));
                 self.exported_macros.push(hir::MacroDef {
-                    name: ident.name,
+                    ident,
                     vis,
                     attrs,
                     hir_id,
                     span: i.span,
-                    body,
-                    legacy: def.legacy,
+                    ast: MacroDef { body, macro_rules },
                 });
             } else {
                 self.non_exported_macro_attrs.extend(attrs.iter().cloned());
@@ -269,7 +269,7 @@ fn lower_item_kind(
                 hir::ItemKind::Const(ty, body_id)
             }
             ItemKind::Fn(_, FnSig { ref decl, header }, ref generics, ref body) => {
-                let fn_def_id = self.resolver.definitions().local_def_id(id);
+                let fn_def_id = self.resolver.definitions().local_def_id(id).expect_local();
                 self.with_new_scopes(|this| {
                     this.current_item = Some(ident.span);
 
@@ -287,7 +287,12 @@ fn lower_item_kind(
                         AnonymousLifetimeMode::PassThrough,
                         |this, idty| {
                             let ret_id = asyncness.opt_return_id();
-                            this.lower_fn_decl(&decl, Some((fn_def_id, idty)), true, ret_id)
+                            this.lower_fn_decl(
+                                &decl,
+                                Some((fn_def_id.to_def_id(), idty)),
+                                true,
+                                ret_id,
+                            )
                         },
                     );
                     let sig = hir::FnSig { decl, header: this.lower_fn_header(header) };
@@ -351,7 +356,7 @@ fn lower_item_kind(
                 self_ty: ref ty,
                 items: ref impl_items,
             } => {
-                let def_id = self.resolver.definitions().local_def_id(id);
+                let def_id = self.resolver.definitions().local_def_id(id).expect_local();
 
                 // Lower the "impl header" first. This ordering is important
                 // for in-band lifetimes! Consider `'a` here:
@@ -426,7 +431,7 @@ fn lower_item_kind(
                 self.lower_generics(generics, ImplTraitContext::disallowed()),
                 self.lower_param_bounds(bounds, ImplTraitContext::disallowed()),
             ),
-            ItemKind::MacroDef(..) | ItemKind::Mac(..) => {
+            ItemKind::MacroDef(..) | ItemKind::MacCall(..) => {
                 bug!("`TyMac` should have been expanded by now")
             }
         }
@@ -648,7 +653,7 @@ fn rebuild_vis(&mut self, vis: &hir::Visibility<'hir>) -> hir::Visibility<'hir>
     }
 
     fn lower_foreign_item(&mut self, i: &ForeignItem) -> hir::ForeignItem<'hir> {
-        let def_id = self.resolver.definitions().local_def_id(i.id);
+        let def_id = self.resolver.definitions().local_def_id(i.id).expect_local();
         hir::ForeignItem {
             hir_id: self.lower_node_id(i.id),
             ident: i.ident,
@@ -675,13 +680,8 @@ fn lower_foreign_item(&mut self, i: &ForeignItem) -> hir::ForeignItem<'hir> {
                     let ty = self.lower_ty(t, ImplTraitContext::disallowed());
                     hir::ForeignItemKind::Static(ty, m)
                 }
-                ForeignItemKind::Const(_, ref t, _) => {
-                    // For recovery purposes.
-                    let ty = self.lower_ty(t, ImplTraitContext::disallowed());
-                    hir::ForeignItemKind::Static(ty, Mutability::Not)
-                }
                 ForeignItemKind::TyAlias(..) => hir::ForeignItemKind::Type,
-                ForeignItemKind::Macro(_) => panic!("macro shouldn't exist here"),
+                ForeignItemKind::MacCall(_) => panic!("macro shouldn't exist here"),
             },
             vis: self.lower_visibility(&i.vis, None),
             span: i.span,
@@ -754,11 +754,10 @@ fn lower_struct_field(&mut self, (index, f): (usize, &StructField)) -> hir::Stru
     }
 
     fn lower_trait_item(&mut self, i: &AssocItem) -> hir::TraitItem<'hir> {
-        let trait_item_def_id = self.resolver.definitions().local_def_id(i.id);
+        let trait_item_def_id = self.resolver.definitions().local_def_id(i.id).expect_local();
 
         let (generics, kind) = match i.kind {
-            AssocItemKind::Static(ref ty, _, ref default) // Let's pretend this is a `const`.
-            | AssocItemKind::Const(_, ref ty, ref default) => {
+            AssocItemKind::Const(_, ref ty, ref default) => {
                 let ty = self.lower_ty(ty, ImplTraitContext::disallowed());
                 let body = default.as_ref().map(|x| self.lower_const_body(i.span, Some(x)));
                 (hir::Generics::empty(), hir::TraitItemKind::Const(ty, body))
@@ -767,13 +766,13 @@ fn lower_trait_item(&mut self, i: &AssocItem) -> hir::TraitItem<'hir> {
                 let names = self.lower_fn_params_to_names(&sig.decl);
                 let (generics, sig) =
                     self.lower_method_sig(generics, sig, trait_item_def_id, false, None);
-                (generics, hir::TraitItemKind::Method(sig, hir::TraitMethod::Required(names)))
+                (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)))
             }
             AssocItemKind::Fn(_, ref sig, ref generics, Some(ref body)) => {
                 let body_id = self.lower_fn_body_block(i.span, &sig.decl, Some(body));
                 let (generics, sig) =
                     self.lower_method_sig(generics, sig, trait_item_def_id, false, None);
-                (generics, hir::TraitItemKind::Method(sig, hir::TraitMethod::Provided(body_id)))
+                (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)))
             }
             AssocItemKind::TyAlias(_, ref generics, ref bounds, ref default) => {
                 let ty = default.as_ref().map(|x| self.lower_ty(x, ImplTraitContext::disallowed()));
@@ -785,7 +784,7 @@ fn lower_trait_item(&mut self, i: &AssocItem) -> hir::TraitItem<'hir> {
 
                 (generics, kind)
             }
-            AssocItemKind::Macro(..) => bug!("macro item shouldn't exist at this point"),
+            AssocItemKind::MacCall(..) => bug!("macro item shouldn't exist at this point"),
         };
 
         hir::TraitItem {
@@ -800,15 +799,14 @@ fn lower_trait_item(&mut self, i: &AssocItem) -> hir::TraitItem<'hir> {
 
     fn lower_trait_item_ref(&mut self, i: &AssocItem) -> hir::TraitItemRef {
         let (kind, has_default) = match &i.kind {
-            AssocItemKind::Static(_, _, default) // Let's pretend this is a `const` for recovery.
-            | AssocItemKind::Const(_, _, default) => {
-                (hir::AssocItemKind::Const, default.is_some())
+            AssocItemKind::Const(_, _, default) => (hir::AssocItemKind::Const, default.is_some()),
+            AssocItemKind::TyAlias(_, _, _, default) => {
+                (hir::AssocItemKind::Type, default.is_some())
             }
-            AssocItemKind::TyAlias(_, _, _, default) => (hir::AssocItemKind::Type, default.is_some()),
             AssocItemKind::Fn(_, sig, _, default) => {
                 (hir::AssocItemKind::Method { has_self: sig.decl.has_self() }, default.is_some())
             }
-            AssocItemKind::Macro(..) => unimplemented!(),
+            AssocItemKind::MacCall(..) => unimplemented!(),
         };
         let id = hir::TraitItemId { hir_id: self.lower_node_id(i.id) };
         let defaultness = hir::Defaultness::Default { has_value: has_default };
@@ -816,15 +814,15 @@ fn lower_trait_item_ref(&mut self, i: &AssocItem) -> hir::TraitItemRef {
     }
 
     /// Construct `ExprKind::Err` for the given `span`.
-    fn expr_err(&mut self, span: Span) -> hir::Expr<'hir> {
+    crate fn expr_err(&mut self, span: Span) -> hir::Expr<'hir> {
         self.expr(span, hir::ExprKind::Err, AttrVec::new())
     }
 
     fn lower_impl_item(&mut self, i: &AssocItem) -> hir::ImplItem<'hir> {
-        let impl_item_def_id = self.resolver.definitions().local_def_id(i.id);
+        let impl_item_def_id = self.resolver.definitions().local_def_id(i.id).expect_local();
 
         let (generics, kind) = match &i.kind {
-            AssocItemKind::Static(ty, _, expr) | AssocItemKind::Const(_, ty, expr) => {
+            AssocItemKind::Const(_, ty, expr) => {
                 let ty = self.lower_ty(ty, ImplTraitContext::disallowed());
                 (
                     hir::Generics::empty(),
@@ -845,7 +843,7 @@ fn lower_impl_item(&mut self, i: &AssocItem) -> hir::ImplItem<'hir> {
                     asyncness.opt_return_id(),
                 );
 
-                (generics, hir::ImplItemKind::Method(sig, body_id))
+                (generics, hir::ImplItemKind::Fn(sig, body_id))
             }
             AssocItemKind::TyAlias(_, generics, _, ty) => {
                 let generics = self.lower_generics(generics, ImplTraitContext::disallowed());
@@ -867,7 +865,7 @@ fn lower_impl_item(&mut self, i: &AssocItem) -> hir::ImplItem<'hir> {
                 };
                 (generics, kind)
             }
-            AssocItemKind::Macro(..) => bug!("`TyMac` should have been expanded by now"),
+            AssocItemKind::MacCall(..) => bug!("`TyMac` should have been expanded by now"),
         };
 
         hir::ImplItem {
@@ -892,8 +890,7 @@ fn lower_impl_item_ref(&mut self, i: &AssocItem) -> hir::ImplItemRef<'hir> {
             vis: self.lower_visibility(&i.vis, Some(i.id)),
             defaultness: self.lower_defaultness(i.kind.defaultness(), true /* [1] */),
             kind: match &i.kind {
-                AssocItemKind::Static(..) // Let's pretend this is a `const` for recovery.
-                | AssocItemKind::Const(..) => hir::AssocItemKind::Const,
+                AssocItemKind::Const(..) => hir::AssocItemKind::Const,
                 AssocItemKind::TyAlias(.., ty) => {
                     match ty.as_deref().and_then(|ty| ty.kind.opaque_top_hack()) {
                         None => hir::AssocItemKind::Type,
@@ -903,7 +900,7 @@ fn lower_impl_item_ref(&mut self, i: &AssocItem) -> hir::ImplItemRef<'hir> {
                 AssocItemKind::Fn(_, sig, ..) => {
                     hir::AssocItemKind::Method { has_self: sig.decl.has_self() }
                 }
-                AssocItemKind::Macro(..) => unimplemented!(),
+                AssocItemKind::MacCall(..) => unimplemented!(),
             },
         }
 
@@ -963,7 +960,7 @@ fn record_body(
         id
     }
 
-    fn lower_body(
+    pub(super) fn lower_body(
         &mut self,
         f: impl FnOnce(&mut Self) -> (&'hir [hir::Param<'hir>], hir::Expr<'hir>),
     ) -> hir::BodyId {
@@ -1219,7 +1216,7 @@ fn lower_method_sig(
         &mut self,
         generics: &Generics,
         sig: &FnSig,
-        fn_def_id: DefId,
+        fn_def_id: LocalDefId,
         impl_trait_return_allow: bool,
         is_async: Option<NodeId>,
     ) -> (hir::Generics<'hir>, hir::FnSig<'hir>) {
@@ -1231,7 +1228,7 @@ fn lower_method_sig(
             |this, idty| {
                 this.lower_fn_decl(
                     &sig.decl,
-                    Some((fn_def_id, idty)),
+                    Some((fn_def_id.to_def_id(), idty)),
                     impl_trait_return_allow,
                     is_async,
                 )
index 0f7ed9f72f8f61a95dd8785efad3d2fcc5e80efd..24fe51fc4d0d1290bcc8d57de4d043d09ac807f0 100644 (file)
@@ -37,7 +37,6 @@
 use rustc::arena::Arena;
 use rustc::dep_graph::DepGraph;
 use rustc::hir::map::definitions::{DefKey, DefPathData, Definitions};
-use rustc::hir::map::Map;
 use rustc::{bug, span_bug};
 use rustc_ast::ast;
 use rustc_ast::ast::*;
@@ -54,7 +53,7 @@
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Namespace, PartialRes, PerNS, Res};
-use rustc_hir::def_id::{DefId, DefIdMap, DefIndex, CRATE_DEF_INDEX};
+use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId, CRATE_DEF_INDEX};
 use rustc_hir::intravisit;
 use rustc_hir::{ConstArg, GenericArg, ParamName};
 use rustc_index::vec::IndexVec;
@@ -117,6 +116,10 @@ struct LoweringContext<'a, 'hir: 'a> {
 
     generator_kind: Option<hir::GeneratorKind>,
 
+    /// When inside an `async` context, this is the `HirId` of the
+    /// `task_context` local bound to the resume argument of the generator.
+    task_context: Option<hir::HirId>,
+
     /// Used to get the current `fn`'s def span to point to when using `await`
     /// outside of an `async fn`.
     current_item: Option<Span>,
@@ -153,7 +156,7 @@ struct LoweringContext<'a, 'hir: 'a> {
     /// against this list to see if it is already in-scope, or if a definition
     /// needs to be created for it.
     ///
-    /// We always store a `modern()` version of the param-name in this
+    /// We always store a `normalize_to_macros_2_0()` version of the param-name in this
     /// vector.
     in_scope_lifetimes: Vec<ParamName>,
 
@@ -161,7 +164,7 @@ struct LoweringContext<'a, 'hir: 'a> {
 
     type_def_lifetime_params: DefIdMap<usize>,
 
-    current_hir_id_owner: Vec<(DefIndex, u32)>,
+    current_hir_id_owner: Vec<(LocalDefId, u32)>,
     item_local_id_counters: NodeMap<u32>,
     node_id_to_hir_id: IndexVec<NodeId, hir::HirId>,
 
@@ -291,10 +294,11 @@ pub fn lower_crate<'a, 'hir>(
         anonymous_lifetime_mode: AnonymousLifetimeMode::PassThrough,
         type_def_lifetime_params: Default::default(),
         current_module: hir::CRATE_HIR_ID,
-        current_hir_id_owner: vec![(CRATE_DEF_INDEX, 0)],
+        current_hir_id_owner: vec![(LocalDefId { local_def_index: CRATE_DEF_INDEX }, 0)],
         item_local_id_counters: Default::default(),
         node_id_to_hir_id: IndexVec::new(),
         generator_kind: None,
+        task_context: None,
         current_item: None,
         lifetimes_to_define: Vec::new(),
         is_collecting_in_band_lifetimes: false,
@@ -408,7 +412,7 @@ struct MiscCollector<'tcx, 'lowering, 'hir> {
         }
 
         impl MiscCollector<'_, '_, '_> {
-            fn allocate_use_tree_hir_id_counters(&mut self, tree: &UseTree, owner: DefIndex) {
+            fn allocate_use_tree_hir_id_counters(&mut self, tree: &UseTree, owner: LocalDefId) {
                 match tree.kind {
                     UseTreeKind::Simple(_, id1, id2) => {
                         for &id in &[id1, id2] {
@@ -464,7 +468,8 @@ fn visit_item(&mut self, item: &'tcx Item) {
                     | ItemKind::Enum(_, ref generics)
                     | ItemKind::TyAlias(_, ref generics, ..)
                     | ItemKind::Trait(_, _, ref generics, ..) => {
-                        let def_id = self.lctx.resolver.definitions().local_def_id(item.id);
+                        let def_id =
+                            self.lctx.resolver.definitions().local_def_id(item.id).expect_local();
                         let count = generics
                             .params
                             .iter()
@@ -473,7 +478,7 @@ fn visit_item(&mut self, item: &'tcx Item) {
                                 _ => false,
                             })
                             .count();
-                        self.lctx.type_def_lifetime_params.insert(def_id, count);
+                        self.lctx.type_def_lifetime_params.insert(def_id.to_def_id(), count);
                     }
                     ItemKind::Use(ref use_tree) => {
                         self.allocate_use_tree_hir_id_counters(use_tree, hir_id.owner);
@@ -535,9 +540,7 @@ fn visit_ty(&mut self, t: &'tcx Ty) {
         self.resolver.definitions().init_node_id_to_hir_id_mapping(self.node_id_to_hir_id);
 
         hir::Crate {
-            module,
-            attrs,
-            span: c.span,
+            item: hir::CrateItem { module, attrs, span: c.span },
             exported_macros: self.arena.alloc_from_iter(self.exported_macros),
             non_exported_macro_attrs: self.arena.alloc_from_iter(self.non_exported_macro_attrs),
             items: self.items,
@@ -601,12 +604,12 @@ fn with_hir_id_owner<T>(&mut self, owner: NodeId, f: impl FnOnce(&mut Self) -> T
             .item_local_id_counters
             .insert(owner, HIR_ID_COUNTER_LOCKED)
             .unwrap_or_else(|| panic!("no `item_local_id_counters` entry for {:?}", owner));
-        let def_index = self.resolver.definitions().opt_def_index(owner).unwrap();
-        self.current_hir_id_owner.push((def_index, counter));
+        let def_id = self.resolver.definitions().local_def_id(owner).expect_local();
+        self.current_hir_id_owner.push((def_id, counter));
         let ret = f(self);
-        let (new_def_index, new_counter) = self.current_hir_id_owner.pop().unwrap();
+        let (new_def_id, new_counter) = self.current_hir_id_owner.pop().unwrap();
 
-        debug_assert!(def_index == new_def_index);
+        debug_assert!(def_id == new_def_id);
         debug_assert!(new_counter >= counter);
 
         let prev = self.item_local_id_counters.insert(owner, new_counter).unwrap();
@@ -622,11 +625,11 @@ fn with_hir_id_owner<T>(&mut self, owner: NodeId, f: impl FnOnce(&mut Self) -> T
     /// properly. Calling the method twice with the same `NodeId` is fine though.
     fn lower_node_id(&mut self, ast_node_id: NodeId) -> hir::HirId {
         self.lower_node_id_generic(ast_node_id, |this| {
-            let &mut (def_index, ref mut local_id_counter) =
+            let &mut (owner, ref mut local_id_counter) =
                 this.current_hir_id_owner.last_mut().unwrap();
             let local_id = *local_id_counter;
             *local_id_counter += 1;
-            hir::HirId { owner: def_index, local_id: hir::ItemLocalId::from_u32(local_id) }
+            hir::HirId { owner, local_id: hir::ItemLocalId::from_u32(local_id) }
         })
     }
 
@@ -644,12 +647,12 @@ fn lower_node_id_with_owner(&mut self, ast_node_id: NodeId, owner: NodeId) -> hi
             debug_assert!(local_id != HIR_ID_COUNTER_LOCKED);
 
             *local_id_counter += 1;
-            let def_index = this.resolver.definitions().opt_def_index(owner).expect(
+            let owner = this.resolver.definitions().opt_local_def_id(owner).expect(
                 "you forgot to call `create_def_with_parent` or are lowering node-IDs \
-                         that do not belong to the current owner",
+                 that do not belong to the current owner",
             );
 
-            hir::HirId { owner: def_index, local_id: hir::ItemLocalId::from_u32(local_id) }
+            hir::HirId { owner, local_id: hir::ItemLocalId::from_u32(local_id) }
         })
     }
 
@@ -727,7 +730,7 @@ fn with_anonymous_lifetime_mode<R>(
     /// parameter while `f` is running (and restored afterwards).
     fn collect_in_band_defs<T>(
         &mut self,
-        parent_id: DefId,
+        parent_def_id: LocalDefId,
         anonymous_lifetime_mode: AnonymousLifetimeMode,
         f: impl FnOnce(&mut Self) -> (Vec<hir::GenericParam<'hir>>, T),
     ) -> (Vec<hir::GenericParam<'hir>>, T) {
@@ -747,7 +750,7 @@ fn collect_in_band_defs<T>(
 
         let params = lifetimes_to_define
             .into_iter()
-            .map(|(span, hir_name)| self.lifetime_to_generic_param(span, hir_name, parent_id.index))
+            .map(|(span, hir_name)| self.lifetime_to_generic_param(span, hir_name, parent_def_id))
             .chain(in_band_ty_params.into_iter())
             .collect();
 
@@ -759,7 +762,7 @@ fn lifetime_to_generic_param(
         &mut self,
         span: Span,
         hir_name: ParamName,
-        parent_index: DefIndex,
+        parent_def_id: LocalDefId,
     ) -> hir::GenericParam<'hir> {
         let node_id = self.resolver.next_node_id();
 
@@ -774,7 +777,7 @@ fn lifetime_to_generic_param(
 
         // Add a definition for the in-band lifetime def.
         self.resolver.definitions().create_def_with_parent(
-            parent_index,
+            parent_def_id,
             node_id,
             DefPathData::LifetimeNs(str_name),
             ExpnId::root(),
@@ -805,14 +808,15 @@ fn maybe_collect_in_band_lifetime(&mut self, ident: Ident) {
             return;
         }
 
-        if self.in_scope_lifetimes.contains(&ParamName::Plain(ident.modern())) {
+        if self.in_scope_lifetimes.contains(&ParamName::Plain(ident.normalize_to_macros_2_0())) {
             return;
         }
 
         let hir_name = ParamName::Plain(ident);
 
-        if self.lifetimes_to_define.iter().any(|(_, lt_name)| lt_name.modern() == hir_name.modern())
-        {
+        if self.lifetimes_to_define.iter().any(|(_, lt_name)| {
+            lt_name.normalize_to_macros_2_0() == hir_name.normalize_to_macros_2_0()
+        }) {
             return;
         }
 
@@ -840,7 +844,9 @@ fn with_in_scope_lifetime_defs<T>(
     ) -> T {
         let old_len = self.in_scope_lifetimes.len();
         let lt_def_names = params.iter().filter_map(|param| match param.kind {
-            GenericParamKind::Lifetime { .. } => Some(ParamName::Plain(param.ident.modern())),
+            GenericParamKind::Lifetime { .. } => {
+                Some(ParamName::Plain(param.ident.normalize_to_macros_2_0()))
+            }
             _ => None,
         });
         self.in_scope_lifetimes.extend(lt_def_names);
@@ -860,13 +866,13 @@ fn with_in_scope_lifetime_defs<T>(
     fn add_in_band_defs<T>(
         &mut self,
         generics: &Generics,
-        parent_id: DefId,
+        parent_def_id: LocalDefId,
         anonymous_lifetime_mode: AnonymousLifetimeMode,
         f: impl FnOnce(&mut Self, &mut Vec<hir::GenericParam<'hir>>) -> T,
     ) -> (hir::Generics<'hir>, T) {
         let (in_band_defs, (mut lowered_generics, res)) =
             self.with_in_scope_lifetime_defs(&generics.params, |this| {
-                this.collect_in_band_defs(parent_id, anonymous_lifetime_mode, |this| {
+                this.collect_in_band_defs(parent_def_id, anonymous_lifetime_mode, |this| {
                     let mut params = Vec::new();
                     // Note: it is necessary to lower generics *before* calling `f`.
                     // When lowering `async fn`, there's a final step when lowering
@@ -1048,9 +1054,9 @@ fn lower_assoc_ty_constraint(
                     // constructing the HIR for `impl bounds...` and then lowering that.
 
                     let impl_trait_node_id = self.resolver.next_node_id();
-                    let parent_def_index = self.current_hir_id_owner.last().unwrap().0;
+                    let parent_def_id = self.current_hir_id_owner.last().unwrap().0;
                     self.resolver.definitions().create_def_with_parent(
-                        parent_def_index,
+                        parent_def_id,
                         impl_trait_node_id,
                         DefPathData::ImplTrait,
                         ExpnId::root(),
@@ -1096,7 +1102,7 @@ fn lower_generic_arg(
         match arg {
             ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(&lt)),
             ast::GenericArg::Type(ty) => {
-                // We parse const arguments as path types as we cannot distiguish them durring
+                // We parse const arguments as path types as we cannot distinguish them during
                 // parsing. We try to resolve that ambiguity by attempting resolution in both the
                 // type and value namespaces. If we resolved the path in the value namespace, we
                 // transform it into a generic const argument.
@@ -1111,12 +1117,12 @@ fn lower_generic_arg(
 
                             // Construct a AnonConst where the expr is the "ty"'s path.
 
-                            let parent_def_index = self.current_hir_id_owner.last().unwrap().0;
+                            let parent_def_id = self.current_hir_id_owner.last().unwrap().0;
                             let node_id = self.resolver.next_node_id();
 
                             // Add a definition for the in-band const def.
                             self.resolver.definitions().create_def_with_parent(
-                                parent_def_index,
+                                parent_def_id,
                                 node_id,
                                 DefPathData::AnonConst,
                                 ExpnId::root(),
@@ -1278,8 +1284,8 @@ fn lower_ty_direct(&mut self, t: &Ty, mut itctx: ImplTraitContext<'_, 'hir>) ->
                     }
                     ImplTraitContext::Universal(in_band_ty_params) => {
                         // Add a definition for the in-band `Param`.
-                        let def_index =
-                            self.resolver.definitions().opt_def_index(def_node_id).unwrap();
+                        let def_id =
+                            self.resolver.definitions().local_def_id(def_node_id).expect_local();
 
                         let hir_bounds = self.lower_param_bounds(
                             bounds,
@@ -1304,7 +1310,7 @@ fn lower_ty_direct(&mut self, t: &Ty, mut itctx: ImplTraitContext<'_, 'hir>) ->
                             None,
                             self.arena.alloc(hir::Path {
                                 span,
-                                res: Res::Def(DefKind::TyParam, DefId::local(def_index)),
+                                res: Res::Def(DefKind::TyParam, def_id.to_def_id()),
                                 segments: arena_vec![self; hir::PathSegment::from_ident(ident)],
                             }),
                         ))
@@ -1334,7 +1340,7 @@ fn lower_ty_direct(&mut self, t: &Ty, mut itctx: ImplTraitContext<'_, 'hir>) ->
                     }
                 }
             }
-            TyKind::Mac(_) => bug!("`TyKind::Mac` should have been expanded by now"),
+            TyKind::MacCall(_) => bug!("`TyKind::MacCall` should have been expanded by now"),
             TyKind::CVarArgs => {
                 self.sess.delay_span_bug(
                     t.span,
@@ -1367,18 +1373,15 @@ fn lower_opaque_impl_trait(
         // frequently opened issues show.
         let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::OpaqueTy, span, None);
 
-        let opaque_ty_def_index =
-            self.resolver.definitions().opt_def_index(opaque_ty_node_id).unwrap();
+        let opaque_ty_def_id =
+            self.resolver.definitions().local_def_id(opaque_ty_node_id).expect_local();
 
         self.allocate_hir_id_counter(opaque_ty_node_id);
 
         let hir_bounds = self.with_hir_id_owner(opaque_ty_node_id, lower_bounds);
 
-        let (lifetimes, lifetime_defs) = self.lifetimes_from_impl_trait_bounds(
-            opaque_ty_node_id,
-            opaque_ty_def_index,
-            &hir_bounds,
-        );
+        let (lifetimes, lifetime_defs) =
+            self.lifetimes_from_impl_trait_bounds(opaque_ty_node_id, opaque_ty_def_id, &hir_bounds);
 
         debug!("lower_opaque_impl_trait: lifetimes={:#?}", lifetimes,);
 
@@ -1396,7 +1399,7 @@ fn lower_opaque_impl_trait(
                 origin,
             };
 
-            trace!("lower_opaque_impl_trait: {:#?}", opaque_ty_def_index);
+            trace!("lower_opaque_impl_trait: {:#?}", opaque_ty_def_id);
             let opaque_ty_id =
                 lctx.generate_opaque_type(opaque_ty_node_id, opaque_ty_item, span, opaque_ty_span);
 
@@ -1437,14 +1440,14 @@ fn generate_opaque_type(
     fn lifetimes_from_impl_trait_bounds(
         &mut self,
         opaque_ty_id: NodeId,
-        parent_index: DefIndex,
+        parent_def_id: LocalDefId,
         bounds: hir::GenericBounds<'hir>,
     ) -> (&'hir [hir::GenericArg<'hir>], &'hir [hir::GenericParam<'hir>]) {
         debug!(
             "lifetimes_from_impl_trait_bounds(opaque_ty_id={:?}, \
-             parent_index={:?}, \
+             parent_def_id={:?}, \
              bounds={:#?})",
-            opaque_ty_id, parent_index, bounds,
+            opaque_ty_id, parent_def_id, bounds,
         );
 
         // This visitor walks over `impl Trait` bounds and creates defs for all lifetimes that
@@ -1452,7 +1455,7 @@ fn lifetimes_from_impl_trait_bounds(
         // E.g., `'a`, `'b`, but not `'c` in `impl for<'c> SomeTrait<'a, 'b, 'c>`.
         struct ImplTraitLifetimeCollector<'r, 'a, 'hir> {
             context: &'r mut LoweringContext<'a, 'hir>,
-            parent: DefIndex,
+            parent: LocalDefId,
             opaque_ty_id: NodeId,
             collect_elided_lifetimes: bool,
             currently_bound_lifetimes: Vec<hir::LifetimeName>,
@@ -1462,9 +1465,9 @@ struct ImplTraitLifetimeCollector<'r, 'a, 'hir> {
         }
 
         impl<'r, 'a, 'v, 'hir> intravisit::Visitor<'v> for ImplTraitLifetimeCollector<'r, 'a, 'hir> {
-            type Map = Map<'v>;
+            type Map = intravisit::ErasedMap<'v>;
 
-            fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> {
+            fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
                 intravisit::NestedVisitorMap::None
             }
 
@@ -1590,7 +1593,7 @@ fn visit_lifetime(&mut self, lifetime: &'v hir::Lifetime) {
 
         let mut lifetime_collector = ImplTraitLifetimeCollector {
             context: self,
-            parent: parent_index,
+            parent: parent_def_id,
             opaque_ty_id,
             collect_elided_lifetimes: true,
             currently_bound_lifetimes: Vec::new(),
@@ -1620,12 +1623,15 @@ fn visit_lifetime(&mut self, lifetime: &'v hir::Lifetime) {
                 visitor.visit_ty(ty);
             }
         }
-        let parent_def_id = DefId::local(self.current_hir_id_owner.last().unwrap().0);
+        let parent_def_id = self.current_hir_id_owner.last().unwrap().0;
         let ty = l.ty.as_ref().map(|t| {
             self.lower_ty(
                 t,
                 if self.sess.features_untracked().impl_trait_in_bindings {
-                    ImplTraitContext::OpaqueTy(Some(parent_def_id), hir::OpaqueTyOrigin::Misc)
+                    ImplTraitContext::OpaqueTy(
+                        Some(parent_def_id.to_def_id()),
+                        hir::OpaqueTyOrigin::Misc,
+                    )
                 } else {
                     ImplTraitContext::Disallowed(ImplTraitPosition::Binding)
                 },
@@ -1797,8 +1803,8 @@ fn lower_async_fn_ret_ty(
 
         let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::Async, span, None);
 
-        let opaque_ty_def_index =
-            self.resolver.definitions().opt_def_index(opaque_ty_node_id).unwrap();
+        let opaque_ty_def_id =
+            self.resolver.definitions().local_def_id(opaque_ty_node_id).expect_local();
 
         self.allocate_hir_id_counter(opaque_ty_node_id);
 
@@ -1886,7 +1892,7 @@ fn lower_async_fn_ret_ty(
 
             let generic_params =
                 this.arena.alloc_from_iter(lifetime_params.iter().map(|(span, hir_name)| {
-                    this.lifetime_to_generic_param(*span, *hir_name, opaque_ty_def_index)
+                    this.lifetime_to_generic_param(*span, *hir_name, opaque_ty_def_id)
                 }));
 
             let opaque_ty_item = hir::OpaqueTy {
@@ -1900,7 +1906,7 @@ fn lower_async_fn_ret_ty(
                 origin: hir::OpaqueTyOrigin::AsyncFn,
             };
 
-            trace!("exist ty from async fn def index: {:#?}", opaque_ty_def_index);
+            trace!("exist ty from async fn def id: {:#?}", opaque_ty_def_id);
             let opaque_ty_id =
                 this.generate_opaque_type(opaque_ty_node_id, opaque_ty_item, span, opaque_ty_span);
 
@@ -2281,7 +2287,8 @@ fn lower_anon_const(&mut self, c: &AnonConst) -> hir::AnonConst {
             }
             StmtKind::Expr(ref e) => hir::StmtKind::Expr(self.lower_expr(e)),
             StmtKind::Semi(ref e) => hir::StmtKind::Semi(self.lower_expr(e)),
-            StmtKind::Mac(..) => panic!("shouldn't exist here"),
+            StmtKind::Empty => return smallvec![],
+            StmtKind::MacCall(..) => panic!("shouldn't exist here"),
         };
         smallvec![hir::Stmt { hir_id: self.lower_node_id(s.id), kind, span: s.span }]
     }
index d6f4ba1529be640a470b09b9cb914ac24f513234..8ba6576f6926598a16e2b2b413a9f0f9ed34151b 100644 (file)
@@ -75,7 +75,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 self.ban_illegal_rest_pat(p.span)
             }
             PatKind::Paren(ref inner) => return self.lower_pat(inner),
-            PatKind::Mac(_) => panic!("Shouldn't exist here"),
+            PatKind::MacCall(_) => panic!("Shouldn't exist here"),
         };
 
         self.pat_with_node_id_of(p, node)
index 80d7e3d0d465a11c47e8abd667df6046a44b42b2..b5b0a3089ce0f55054a9667bcf688e4e50bd76f0 100644 (file)
@@ -1,7 +1,6 @@
 use super::{AnonymousLifetimeMode, ImplTraitContext, LoweringContext, ParamMode};
 use super::{GenericArgsCtor, ParenthesizedGenericArgs};
 
-use rustc::lint::builtin::ELIDED_LIFETIMES_IN_PATHS;
 use rustc::span_bug;
 use rustc_ast::ast::{self, *};
 use rustc_errors::{struct_span_err, Applicability};
@@ -9,6 +8,7 @@
 use rustc_hir::def::{DefKind, PartialRes, Res};
 use rustc_hir::def_id::DefId;
 use rustc_hir::GenericArg;
+use rustc_session::lint::builtin::ELIDED_LIFETIMES_IN_PATHS;
 use rustc_session::lint::BuiltinLintDiagnostics;
 use rustc_span::Span;
 
@@ -75,7 +75,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                             ParenthesizedGenericArgs::Ok
                         }
                         // `a::b::Trait(Args)::TraitItem`
-                        Res::Def(DefKind::Method, _)
+                        Res::Def(DefKind::AssocFn, _)
                         | Res::Def(DefKind::AssocConst, _)
                         | Res::Def(DefKind::AssocTy, _)
                             if i + 2 == proj_start =>
index 9f04c01bfa8f4781ebd143ace6ff17a6a639ac1a..541c681840f12cf371e1f8cac325f8b2eb083e8b 100644 (file)
@@ -9,6 +9,7 @@
 use rustc_ast::ast::*;
 use rustc_ast::attr;
 use rustc_ast::expand::is_proc_macro_attr;
+use rustc_ast::ptr::P;
 use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
 use rustc_ast::walk_list;
 use rustc_ast_pretty::pprust;
@@ -594,6 +595,54 @@ fn check_item_named(&self, ident: Ident, kind: &str) {
             .span_label(ident.span, format!("`_` is not a valid name for this `{}` item", kind))
             .emit();
     }
+
+    fn deny_generic_params(&self, generics: &Generics, ident_span: Span) {
+        if !generics.params.is_empty() {
+            struct_span_err!(
+                self.session,
+                generics.span,
+                E0567,
+                "auto traits cannot have generic parameters"
+            )
+            .span_label(ident_span, "auto trait cannot have generic parameters")
+            .span_suggestion(
+                generics.span,
+                "remove the parameters",
+                String::new(),
+                Applicability::MachineApplicable,
+            )
+            .emit();
+        }
+    }
+
+    fn deny_super_traits(&self, bounds: &GenericBounds, ident_span: Span) {
+        if let [first @ last] | [first, .., last] = &bounds[..] {
+            let span = first.span().to(last.span());
+            struct_span_err!(self.session, span, E0568, "auto traits cannot have super traits")
+                .span_label(ident_span, "auto trait cannot have super traits")
+                .span_suggestion(
+                    span,
+                    "remove the super traits",
+                    String::new(),
+                    Applicability::MachineApplicable,
+                )
+                .emit();
+        }
+    }
+
+    fn deny_items(&self, trait_items: &[P<AssocItem>], ident_span: Span) {
+        if !trait_items.is_empty() {
+            let spans: Vec<_> = trait_items.iter().map(|i| i.ident.span).collect();
+            struct_span_err!(
+                self.session,
+                spans,
+                E0380,
+                "auto traits cannot have methods or associated items"
+            )
+            .span_label(ident_span, "auto trait cannot have items")
+            .emit();
+        }
+    }
 }
 
 fn validate_generic_param_order<'a>(
@@ -779,7 +828,7 @@ fn visit_item(&mut self, item: &'a Item) {
                 defaultness: _,
                 constness: _,
                 generics: _,
-                of_trait: Some(_),
+                of_trait: Some(ref t),
                 ref self_ty,
                 items: _,
             } => {
@@ -794,13 +843,14 @@ fn visit_item(&mut self, item: &'a Item) {
                             .help("use `auto trait Trait {}` instead")
                             .emit();
                     }
-                    if let (Unsafe::Yes(span), ImplPolarity::Negative) = (unsafety, polarity) {
+                    if let (Unsafe::Yes(span), ImplPolarity::Negative(sp)) = (unsafety, polarity) {
                         struct_span_err!(
                             this.session,
-                            item.span,
+                            sp.to(t.path.span),
                             E0198,
                             "negative impls cannot be unsafe"
                         )
+                        .span_label(sp, "negative because of this")
                         .span_label(span, "unsafe because of this")
                         .emit();
                     }
@@ -816,38 +866,36 @@ fn visit_item(&mut self, item: &'a Item) {
                 constness,
                 generics: _,
                 of_trait: None,
-                self_ty: _,
+                ref self_ty,
                 items: _,
             } => {
+                let error = |annotation_span, annotation| {
+                    let mut err = self.err_handler().struct_span_err(
+                        self_ty.span,
+                        &format!("inherent impls cannot be {}", annotation),
+                    );
+                    err.span_label(annotation_span, &format!("{} because of this", annotation));
+                    err.span_label(self_ty.span, "inherent impl for this type");
+                    err
+                };
+
                 self.invalid_visibility(
                     &item.vis,
                     Some("place qualifiers on individual impl items instead"),
                 );
                 if let Unsafe::Yes(span) = unsafety {
-                    struct_span_err!(
-                        self.session,
-                        item.span,
-                        E0197,
-                        "inherent impls cannot be unsafe"
-                    )
-                    .span_label(span, "unsafe because of this")
-                    .emit();
+                    error(span, "unsafe").code(error_code!(E0197)).emit();
                 }
-                if polarity == ImplPolarity::Negative {
-                    self.err_handler().span_err(item.span, "inherent impls cannot be negative");
+                if let ImplPolarity::Negative(span) = polarity {
+                    error(span, "negative").emit();
                 }
                 if let Defaultness::Default(def_span) = defaultness {
-                    let span = self.session.source_map().def_span(item.span);
-                    self.err_handler()
-                        .struct_span_err(span, "inherent impls cannot be `default`")
-                        .span_label(def_span, "`default` because of this")
+                    error(def_span, "`default`")
                         .note("only trait implementations may be annotated with `default`")
                         .emit();
                 }
                 if let Const::Yes(span) = constness {
-                    self.err_handler()
-                        .struct_span_err(item.span, "inherent impls cannot be `const`")
-                        .span_label(span, "`const` because of this")
+                    error(span, "`const`")
                         .note("only trait implementations may be annotated with `const`")
                         .emit();
                 }
@@ -882,33 +930,9 @@ fn visit_item(&mut self, item: &'a Item) {
             ItemKind::Trait(is_auto, _, ref generics, ref bounds, ref trait_items) => {
                 if is_auto == IsAuto::Yes {
                     // Auto traits cannot have generics, super traits nor contain items.
-                    if !generics.params.is_empty() {
-                        struct_span_err!(
-                            self.session,
-                            item.span,
-                            E0567,
-                            "auto traits cannot have generic parameters"
-                        )
-                        .emit();
-                    }
-                    if !bounds.is_empty() {
-                        struct_span_err!(
-                            self.session,
-                            item.span,
-                            E0568,
-                            "auto traits cannot have super traits"
-                        )
-                        .emit();
-                    }
-                    if !trait_items.is_empty() {
-                        struct_span_err!(
-                            self.session,
-                            item.span,
-                            E0380,
-                            "auto traits cannot have methods or associated items"
-                        )
-                        .emit();
-                    }
+                    self.deny_generic_params(generics, item.ident.span);
+                    self.deny_super_traits(bounds, item.ident.span);
+                    self.deny_items(trait_items, item.ident.span);
                 }
                 self.no_questions_in_bounds(bounds, "supertraits", true);
 
@@ -976,7 +1000,7 @@ fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
             ForeignItemKind::Static(_, _, body) => {
                 self.check_foreign_kind_bodyless(fi.ident, "static", body.as_ref().map(|b| b.span));
             }
-            ForeignItemKind::Const(..) | ForeignItemKind::Macro(..) => {}
+            ForeignItemKind::MacCall(..) => {}
         }
 
         visit::walk_foreign_item(self, fi)
@@ -1153,9 +1177,13 @@ fn visit_fn(&mut self, fk: FnKind<'a>, span: Span, id: NodeId) {
         }) = fk.header()
         {
             self.err_handler()
-                .struct_span_err(span, "functions cannot be both `const` and `async`")
+                .struct_span_err(
+                    vec![*cspan, *aspan],
+                    "functions cannot be both `const` and `async`",
+                )
                 .span_label(*cspan, "`const` because of this")
                 .span_label(*aspan, "`async` because of this")
+                .span_label(span, "") // Point at the fn header.
                 .emit();
         }
 
index 05e69d0cfd74e1b7548b8bc01dde71fb07b7a551..364c86bd99b4e60c00e0a9b24255b745fc69c2b7 100644 (file)
@@ -245,7 +245,6 @@ macro_rules! gate_doc { ($($name:ident => $feature:ident)*) => {
                     include => external_doc
                     cfg => doc_cfg
                     masked => doc_masked
-                    spotlight => doc_spotlight
                     alias => doc_alias
                     keyword => doc_keyword
                 );
@@ -338,14 +337,14 @@ fn visit_item(&mut self, i: &'a ast::Item) {
                 }
             }
 
-            ast::ItemKind::Impl { polarity, defaultness, .. } => {
-                if polarity == ast::ImplPolarity::Negative {
+            ast::ItemKind::Impl { polarity, defaultness, ref of_trait, .. } => {
+                if let ast::ImplPolarity::Negative(span) = polarity {
                     gate_feature_post!(
                         &self,
                         optin_builtin_traits,
-                        i.span,
+                        span.to(of_trait.as_ref().map(|t| t.path.span).unwrap_or(span)),
                         "negative trait bounds are not yet fully implemented; \
-                                        use marker types for now"
+                         use marker types for now"
                     );
                 }
 
@@ -367,7 +366,7 @@ fn visit_item(&mut self, i: &'a ast::Item) {
                 gate_feature_post!(&self, trait_alias, i.span, "trait aliases are experimental");
             }
 
-            ast::ItemKind::MacroDef(ast::MacroDef { legacy: false, .. }) => {
+            ast::ItemKind::MacroDef(ast::MacroDef { macro_rules: false, .. }) => {
                 let msg = "`macro` is experimental";
                 gate_feature_post!(&self, decl_macro, i.span, msg);
             }
@@ -400,7 +399,7 @@ fn visit_foreign_item(&mut self, i: &'a ast::ForeignItem) {
             ast::ForeignItemKind::TyAlias(..) => {
                 gate_feature_post!(&self, extern_types, i.span, "extern types are experimental");
             }
-            ast::ForeignItemKind::Macro(..) | ast::ForeignItemKind::Const(..) => {}
+            ast::ForeignItemKind::MacCall(..) => {}
         }
 
         visit::walk_foreign_item(self, i)
@@ -543,15 +542,12 @@ fn visit_assoc_ty_constraint(&mut self, constraint: &'a AssocTyConstraint) {
     }
 
     fn visit_assoc_item(&mut self, i: &'a ast::AssocItem, ctxt: AssocCtxt) {
-        if let ast::Defaultness::Default(_) = i.kind.defaultness() {
-            gate_feature_post!(&self, specialization, i.span, "specialization is unstable");
-        }
-
-        match i.kind {
+        let is_fn = match i.kind {
             ast::AssocItemKind::Fn(_, ref sig, _, _) => {
                 if let (ast::Const::Yes(_), AssocCtxt::Trait) = (sig.header.constness, ctxt) {
                     gate_feature_post!(&self, const_fn, i.span, "const fn is unstable");
                 }
+                true
             }
             ast::AssocItemKind::TyAlias(_, ref generics, _, ref ty) => {
                 if let (Some(_), AssocCtxt::Trait) = (ty, ctxt) {
@@ -566,8 +562,19 @@ fn visit_assoc_item(&mut self, i: &'a ast::AssocItem, ctxt: AssocCtxt) {
                     self.check_impl_trait(ty);
                 }
                 self.check_gat(generics, i.span);
+                false
             }
-            _ => {}
+            _ => false,
+        };
+        if let ast::Defaultness::Default(_) = i.kind.defaultness() {
+            // Limit `min_specialization` to only specializing functions.
+            gate_feature_fn!(
+                &self,
+                |x: &Features| x.specialization || (is_fn && x.min_specialization),
+                i.span,
+                sym::specialization,
+                "specialization is unstable"
+            );
         }
         visit::walk_assoc_item(self, i, ctxt)
     }
index 520a7ac3e566539f7c819d90499dbd9f88962586..10081d36754ba43f652593ee3ab13e91a69fdcf4 100644 (file)
@@ -1,3 +1,4 @@
+#![feature(bindings_after_at)]
 //! The `rustc_ast_passes` crate contains passes which validate the AST in `syntax`
 //! parsed by `rustc_parse` and then lowered, after the passes in this crate,
 //! by `rustc_ast_lowering`.
index 16bcec8360e3421ed7551faaf950043675c82ae0..534d6c7b1ea703fe32d0b4e86bb935e0af9d1aa9 100644 (file)
@@ -113,7 +113,7 @@ fn visit_lifetime(&mut self, lifetime: &Lifetime) {
         self.count += 1;
         walk_lifetime(self, lifetime)
     }
-    fn visit_mac(&mut self, _mac: &Mac) {
+    fn visit_mac(&mut self, _mac: &MacCall) {
         self.count += 1;
         walk_mac(self, _mac)
     }
index 73a66ba566bc6a20a3584b6f53deef6da466c3da..2366426d4dcbaa581ba0dc18df907f86cd3b1b65 100644 (file)
@@ -55,7 +55,7 @@ fn visit_ty(&mut self, t: &'a ast::Ty) {
         visit::walk_ty(self, t);
     }
 
-    fn visit_mac(&mut self, mac: &'a ast::Mac) {
+    fn visit_mac(&mut self, mac: &'a ast::MacCall) {
         visit::walk_mac(self, mac);
     }
 }
index ea8535eabef3f2cccbbb3f373889f95a974b243d..bb73e982a9c28aa098bfaf993f6797a3deb8428e 100644 (file)
@@ -148,12 +148,19 @@ pub fn to_string(f: impl FnOnce(&mut State<'_>)) -> String {
 
 // This makes comma-separated lists look slightly nicer,
 // and also addresses a specific regression described in issue #63896.
-fn tt_prepend_space(tt: &TokenTree) -> bool {
+fn tt_prepend_space(tt: &TokenTree, prev: &TokenTree) -> bool {
     match tt {
         TokenTree::Token(token) => match token.kind {
             token::Comma => false,
             _ => true,
         },
+        TokenTree::Delimited(_, DelimToken::Paren, _) => match prev {
+            TokenTree::Token(token) => match token.kind {
+                token::Ident(_, _) => false,
+                _ => true,
+            },
+            _ => true,
+        },
         _ => true,
     }
 }
@@ -650,11 +657,14 @@ fn print_tt(&mut self, tt: tokenstream::TokenTree, convert_dollar_crate: bool) {
     }
 
     fn print_tts(&mut self, tts: tokenstream::TokenStream, convert_dollar_crate: bool) {
-        for (i, tt) in tts.into_trees().enumerate() {
-            if i != 0 && tt_prepend_space(&tt) {
+        let mut iter = tts.into_trees().peekable();
+        while let Some(tt) = iter.next() {
+            let show_space =
+                if let Some(next) = iter.peek() { tt_prepend_space(next, &tt) } else { false };
+            self.print_tt(tt, convert_dollar_crate);
+            if show_space {
                 self.space();
             }
-            self.print_tt(tt, convert_dollar_crate);
         }
     }
 
@@ -960,7 +970,7 @@ pub fn print_type(&mut self, ty: &ast::Ty) {
             ast::TyKind::ImplicitSelf => {
                 self.s.word("Self");
             }
-            ast::TyKind::Mac(ref m) => {
+            ast::TyKind::MacCall(ref m) => {
                 self.print_mac(m);
             }
             ast::TyKind::CVarArgs => {
@@ -971,19 +981,7 @@ pub fn print_type(&mut self, ty: &ast::Ty) {
     }
 
     crate fn print_foreign_item(&mut self, item: &ast::ForeignItem) {
-        let ast::Item { id, span, ident, attrs, kind, vis, tokens: _ } = item;
-        self.print_nested_item_kind(*id, *span, *ident, attrs, kind, vis);
-    }
-
-    fn print_nested_item_kind(
-        &mut self,
-        id: ast::NodeId,
-        span: Span,
-        ident: ast::Ident,
-        attrs: &[Attribute],
-        kind: &ast::AssocItemKind,
-        vis: &ast::Visibility,
-    ) {
+        let ast::Item { id, span, ident, ref attrs, ref kind, ref vis, tokens: _ } = *item;
         self.ann.pre(self, AnnNode::SubItem(id));
         self.hardbreak_if_not_bol();
         self.maybe_print_comment(span.lo());
@@ -992,9 +990,6 @@ fn print_nested_item_kind(
             ast::ForeignItemKind::Fn(def, sig, gen, body) => {
                 self.print_fn_full(sig, ident, gen, vis, *def, body.as_deref(), attrs);
             }
-            ast::ForeignItemKind::Const(def, ty, body) => {
-                self.print_item_const(ident, None, ty, body.as_deref(), vis, *def);
-            }
             ast::ForeignItemKind::Static(ty, mutbl, body) => {
                 let def = ast::Defaultness::Final;
                 self.print_item_const(ident, Some(*mutbl), ty, body.as_deref(), vis, def);
@@ -1002,7 +997,7 @@ fn print_nested_item_kind(
             ast::ForeignItemKind::TyAlias(def, generics, bounds, ty) => {
                 self.print_associated_type(ident, generics, bounds, ty.as_deref(), vis, *def);
             }
-            ast::ForeignItemKind::Macro(m) => {
+            ast::ForeignItemKind::MacCall(m) => {
                 self.print_mac(m);
                 if m.args.need_semicolon() {
                     self.s.word(";");
@@ -1175,7 +1170,7 @@ fn print_associated_type(
                     self.s.space();
                 }
 
-                if polarity == ast::ImplPolarity::Negative {
+                if let ast::ImplPolarity::Negative(_) = polarity {
                     self.s.word("!");
                 }
 
@@ -1246,14 +1241,14 @@ fn print_associated_type(
                 self.print_where_clause(&generics.where_clause);
                 self.s.word(";");
             }
-            ast::ItemKind::Mac(ref mac) => {
+            ast::ItemKind::MacCall(ref mac) => {
                 self.print_mac(mac);
                 if mac.args.need_semicolon() {
                     self.s.word(";");
                 }
             }
             ast::ItemKind::MacroDef(ref macro_def) => {
-                let (kw, has_bang) = if macro_def.legacy {
+                let (kw, has_bang) = if macro_def.macro_rules {
                     ("macro_rules", true)
                 } else {
                     self.print_visibility(&item.vis);
@@ -1413,8 +1408,29 @@ fn print_poly_trait_ref(&mut self, t: &ast::PolyTraitRef) {
     }
 
     crate fn print_assoc_item(&mut self, item: &ast::AssocItem) {
-        let ast::Item { id, span, ident, attrs, kind, vis, tokens: _ } = item;
-        self.print_nested_item_kind(*id, *span, *ident, attrs, kind, vis);
+        let ast::Item { id, span, ident, ref attrs, ref kind, ref vis, tokens: _ } = *item;
+        self.ann.pre(self, AnnNode::SubItem(id));
+        self.hardbreak_if_not_bol();
+        self.maybe_print_comment(span.lo());
+        self.print_outer_attributes(attrs);
+        match kind {
+            ast::AssocItemKind::Fn(def, sig, gen, body) => {
+                self.print_fn_full(sig, ident, gen, vis, *def, body.as_deref(), attrs);
+            }
+            ast::AssocItemKind::Const(def, ty, body) => {
+                self.print_item_const(ident, None, ty, body.as_deref(), vis, *def);
+            }
+            ast::AssocItemKind::TyAlias(def, generics, bounds, ty) => {
+                self.print_associated_type(ident, generics, bounds, ty.as_deref(), vis, *def);
+            }
+            ast::AssocItemKind::MacCall(m) => {
+                self.print_mac(m);
+                if m.args.need_semicolon() {
+                    self.s.word(";");
+                }
+            }
+        }
+        self.ann.post(self, AnnNode::SubItem(id))
     }
 
     crate fn print_stmt(&mut self, st: &ast::Stmt) {
@@ -1446,21 +1462,15 @@ fn print_poly_trait_ref(&mut self, t: &ast::PolyTraitRef) {
                 }
             }
             ast::StmtKind::Semi(ref expr) => {
-                match expr.kind {
-                    // Filter out empty `Tup` exprs created for the `redundant_semicolon`
-                    // lint, as they shouldn't be visible and interact poorly
-                    // with proc macros.
-                    ast::ExprKind::Tup(ref exprs) if exprs.is_empty() && expr.attrs.is_empty() => {
-                        ()
-                    }
-                    _ => {
-                        self.space_if_not_bol();
-                        self.print_expr_outer_attr_style(expr, false);
-                        self.s.word(";");
-                    }
-                }
+                self.space_if_not_bol();
+                self.print_expr_outer_attr_style(expr, false);
+                self.s.word(";");
+            }
+            ast::StmtKind::Empty => {
+                self.space_if_not_bol();
+                self.s.word(";");
             }
-            ast::StmtKind::Mac(ref mac) => {
+            ast::StmtKind::MacCall(ref mac) => {
                 let (ref mac, style, ref attrs) = **mac;
                 self.space_if_not_bol();
                 self.print_outer_attributes(attrs);
@@ -1570,7 +1580,7 @@ fn print_else(&mut self, els: Option<&ast::Expr>) {
         self.print_else(elseopt)
     }
 
-    crate fn print_mac(&mut self, m: &ast::Mac) {
+    crate fn print_mac(&mut self, m: &ast::MacCall) {
         self.print_mac_common(
             Some(MacHeader::Path(&m.path)),
             true,
@@ -2070,7 +2080,7 @@ fn print_expr_outer_attr_style(&mut self, expr: &ast::Expr, is_inline: bool) {
 
                 self.pclose();
             }
-            ast::ExprKind::Mac(ref m) => self.print_mac(m),
+            ast::ExprKind::MacCall(ref m) => self.print_mac(m),
             ast::ExprKind::Paren(ref e) => {
                 self.popen();
                 self.print_inner_attributes_inline(attrs);
@@ -2254,7 +2264,7 @@ fn print_qpath(&mut self, path: &ast::Path, qself: &ast::QSelf, colons_before_pa
                 self.print_pat(inner);
                 self.pclose();
             }
-            PatKind::Mac(ref m) => self.print_mac(m),
+            PatKind::MacCall(ref m) => self.print_mac(m),
         }
         self.ann.post(self, AnnNode::Pat(pat))
     }
index 08eae24da9b688185fc36f1e224b4643ff33b77e..99083cca6cb3443a6424aff1eec92335172bc74e 100644 (file)
@@ -1024,7 +1024,7 @@ pub enum TransparencyError {
 
 pub fn find_transparency(
     attrs: &[Attribute],
-    is_legacy: bool,
+    macro_rules: bool,
 ) -> (Transparency, Option<TransparencyError>) {
     let mut transparency = None;
     let mut error = None;
@@ -1049,7 +1049,7 @@ pub fn find_transparency(
             }
         }
     }
-    let fallback = if is_legacy { Transparency::SemiTransparent } else { Transparency::Opaque };
+    let fallback = if macro_rules { Transparency::SemiTransparent } else { Transparency::Opaque };
     (transparency.map_or(fallback, |t| t.0), error)
 }
 
index 5da4a540940c24055e44c8a63767c7758d817846..3a3595b04d2876c8d882e7d19e5db826b7c6bcfa 100644 (file)
@@ -40,7 +40,7 @@ pub fn expand_assert<'cx>(
         ))
     });
     let args = P(MacArgs::Delimited(DelimSpan::from_single(sp), MacDelimiter::Parenthesis, tokens));
-    let panic_call = Mac {
+    let panic_call = MacCall {
         path: Path::from_ident(Ident::new(sym::panic, sp)),
         args,
         prior_type_ascription: None,
@@ -48,7 +48,7 @@ pub fn expand_assert<'cx>(
     let if_expr = cx.expr_if(
         sp,
         cx.expr(sp, ExprKind::Unary(UnOp::Not, cond_expr)),
-        cx.expr(sp, ExprKind::Mac(panic_call)),
+        cx.expr(sp, ExprKind::MacCall(panic_call)),
         None,
     );
     MacEager::expr(if_expr)
@@ -80,17 +80,15 @@ fn parse_assert<'a>(
     //     my_function();
     // );
     //
-    // Warn about semicolon and suggest removing it. Eventually, this should be turned into an
-    // error.
+    // Emit an error about semicolon and suggest removing it.
     if parser.token == token::Semi {
-        let mut err = cx.struct_span_warn(sp, "macro requires an expression as an argument");
+        let mut err = cx.struct_span_err(sp, "macro requires an expression as an argument");
         err.span_suggestion(
             parser.token.span,
             "try removing semicolon",
             String::new(),
             Applicability::MaybeIncorrect,
         );
-        err.note("this is going to be an error in the future");
         err.emit();
 
         parser.bump();
@@ -101,11 +99,10 @@ fn parse_assert<'a>(
     //
     // assert!(true "error message");
     //
-    // Parse this as an actual message, and suggest inserting a comma. Eventually, this should be
-    // turned into an error.
+    // Emit an error and suggest inserting a comma.
     let custom_message =
         if let token::Literal(token::Lit { kind: token::Str, .. }) = parser.token.kind {
-            let mut err = cx.struct_span_warn(parser.token.span, "unexpected string literal");
+            let mut err = cx.struct_span_err(parser.token.span, "unexpected string literal");
             let comma_span = parser.prev_token.span.shrink_to_hi();
             err.span_suggestion_short(
                 comma_span,
@@ -113,7 +110,6 @@ fn parse_assert<'a>(
                 ", ".to_string(),
                 Applicability::MaybeIncorrect,
             );
-            err.note("this is going to be an error in the future");
             err.emit();
 
             parse_custom_message(&mut parser)
diff --git a/src/librustc_builtin_macros/cfg_accessible.rs b/src/librustc_builtin_macros/cfg_accessible.rs
new file mode 100644 (file)
index 0000000..3607a4d
--- /dev/null
@@ -0,0 +1,54 @@
+//! Implementation of the `#[cfg_accessible(path)]` attribute macro.
+
+use rustc_ast::ast;
+use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, MultiItemModifier};
+use rustc_feature::AttributeTemplate;
+use rustc_parse::validate_attr;
+use rustc_span::symbol::sym;
+use rustc_span::Span;
+
+crate struct Expander;
+
+fn validate_input<'a>(ecx: &mut ExtCtxt<'_>, mi: &'a ast::MetaItem) -> Option<&'a ast::Path> {
+    match mi.meta_item_list() {
+        None => {}
+        Some([]) => ecx.span_err(mi.span, "`cfg_accessible` path is not specified"),
+        Some([_, .., l]) => ecx.span_err(l.span(), "multiple `cfg_accessible` paths are specified"),
+        Some([nmi]) => match nmi.meta_item() {
+            None => ecx.span_err(nmi.span(), "`cfg_accessible` path cannot be a literal"),
+            Some(mi) => {
+                if !mi.is_word() {
+                    ecx.span_err(mi.span, "`cfg_accessible` path cannot accept arguments");
+                }
+                return Some(&mi.path);
+            }
+        },
+    }
+    None
+}
+
+impl MultiItemModifier for Expander {
+    fn expand(
+        &self,
+        ecx: &mut ExtCtxt<'_>,
+        _span: Span,
+        meta_item: &ast::MetaItem,
+        item: Annotatable,
+    ) -> ExpandResult<Vec<Annotatable>, Annotatable> {
+        let template = AttributeTemplate { list: Some("path"), ..Default::default() };
+        let attr = &ecx.attribute(meta_item.clone());
+        validate_attr::check_builtin_attribute(ecx.parse_sess, attr, sym::cfg_accessible, template);
+
+        let path = match validate_input(ecx, meta_item) {
+            Some(path) => path,
+            None => return ExpandResult::Ready(Vec::new()),
+        };
+
+        let failure_msg = "cannot determine whether the path is accessible or not";
+        match ecx.resolver.cfg_accessible(ecx.current_expansion.id, path) {
+            Ok(true) => ExpandResult::Ready(vec![item]),
+            Ok(false) => ExpandResult::Ready(Vec::new()),
+            Err(_) => ExpandResult::Retry(item, failure_msg.into()),
+        }
+    }
+}
index 311298c0f40832b07dc00f77722a1b0729da34e3..84ed6e96aafc8352c5af419d525b4efa3b164b27 100644 (file)
@@ -360,7 +360,7 @@ fn visit_ty(&mut self, ty: &'a ast::Ty) {
             visit::walk_ty(self, ty)
         }
 
-        fn visit_mac(&mut self, mac: &ast::Mac) {
+        fn visit_mac(&mut self, mac: &ast::MacCall) {
             self.cx.span_err(mac.span(), "`derive` cannot be used on items with type macros");
         }
     }
@@ -482,7 +482,7 @@ pub fn expand_ext(
                         })
                         .cloned(),
                 );
-                push(Annotatable::Item(P(ast::Item { attrs: attrs, ..(*newitem).clone() })))
+                push(Annotatable::Item(P(ast::Item { attrs, ..(*newitem).clone() })))
             }
             _ => {
                 // Non-Item derive is an error, but it should have been
index 5ba9d3800e11838afca90331d12501f3ca7f31fd..b5ad67abf620106daefcee76e66de633e7b77017 100644 (file)
@@ -2,7 +2,7 @@
 
 use rustc_ast::ast::{self, ItemKind, MetaItem};
 use rustc_ast::ptr::P;
-use rustc_expand::base::{Annotatable, ExtCtxt, MultiItemModifier};
+use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, MultiItemModifier};
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
 
@@ -48,13 +48,13 @@ fn expand(
         span: Span,
         meta_item: &MetaItem,
         item: Annotatable,
-    ) -> Vec<Annotatable> {
+    ) -> ExpandResult<Vec<Annotatable>, Annotatable> {
         // FIXME: Built-in derives often forget to give spans contexts,
         // so we are doing it here in a centralized way.
         let span = ecx.with_def_site_ctxt(span);
         let mut items = Vec::new();
         (self.0)(ecx, span, meta_item, &item, &mut |a| items.push(a));
-        items
+        ExpandResult::Ready(items)
     }
 }
 
index 6e2b3ec5fd22259ba67aa1dc3075513addc1fe2f..2883159a9f34ca1af05fb9dd435cfd0aa14368dd 100644 (file)
@@ -156,44 +156,43 @@ fn parse_args<'a>(
         if p.token == token::Eof {
             break;
         } // accept trailing commas
-        if p.token.is_ident() && p.look_ahead(1, |t| *t == token::Eq) {
-            named = true;
-            let name = if let token::Ident(name, _) = p.normalized_token.kind {
+        match p.token.ident() {
+            Some((ident, _)) if p.look_ahead(1, |t| *t == token::Eq) => {
+                named = true;
                 p.bump();
-                name
-            } else {
-                unreachable!();
-            };
+                p.expect(&token::Eq)?;
+                let e = p.parse_expr()?;
+                if let Some(prev) = names.get(&ident.name) {
+                    ecx.struct_span_err(e.span, &format!("duplicate argument named `{}`", ident))
+                        .span_label(args[*prev].span, "previously here")
+                        .span_label(e.span, "duplicate argument")
+                        .emit();
+                    continue;
+                }
 
-            p.expect(&token::Eq)?;
-            let e = p.parse_expr()?;
-            if let Some(prev) = names.get(&name) {
-                ecx.struct_span_err(e.span, &format!("duplicate argument named `{}`", name))
-                    .span_label(args[*prev].span, "previously here")
-                    .span_label(e.span, "duplicate argument")
-                    .emit();
-                continue;
+                // Resolve names into slots early.
+                // Since all the positional args are already seen at this point
+                // if the input is valid, we can simply append to the positional
+                // args. And remember the names.
+                let slot = args.len();
+                names.insert(ident.name, slot);
+                args.push(e);
             }
-
-            // Resolve names into slots early.
-            // Since all the positional args are already seen at this point
-            // if the input is valid, we can simply append to the positional
-            // args. And remember the names.
-            let slot = args.len();
-            names.insert(name, slot);
-            args.push(e);
-        } else {
-            let e = p.parse_expr()?;
-            if named {
-                let mut err = ecx
-                    .struct_span_err(e.span, "positional arguments cannot follow named arguments");
-                err.span_label(e.span, "positional arguments must be before named arguments");
-                for (_, pos) in &names {
-                    err.span_label(args[*pos].span, "named argument");
+            _ => {
+                let e = p.parse_expr()?;
+                if named {
+                    let mut err = ecx.struct_span_err(
+                        e.span,
+                        "positional arguments cannot follow named arguments",
+                    );
+                    err.span_label(e.span, "positional arguments must be before named arguments");
+                    for pos in names.values() {
+                        err.span_label(args[*pos].span, "named argument");
+                    }
+                    err.emit();
                 }
-                err.emit();
+                args.push(e);
             }
-            args.push(e);
         }
     }
     Ok((fmtstr, args, names))
@@ -284,7 +283,7 @@ fn verify_piece(&mut self, p: &parse::Piece<'_>) {
                                 err.tool_only_span_suggestion(
                                     sp,
                                     &format!("use the `{}` trait", name),
-                                    fmt.to_string(),
+                                    (*fmt).to_string(),
                                     Applicability::MaybeIncorrect,
                                 );
                             }
@@ -476,7 +475,7 @@ fn verify_arg_type(&mut self, arg: Position, ty: ArgumentType) {
                 match ty {
                     Placeholder(_) => {
                         // record every (position, type) combination only once
-                        let ref mut seen_ty = self.arg_unique_types[arg];
+                        let seen_ty = &mut self.arg_unique_types[arg];
                         let i = seen_ty.iter().position(|x| *x == ty).unwrap_or_else(|| {
                             let i = seen_ty.len();
                             seen_ty.push(ty);
@@ -526,7 +525,7 @@ fn build_index_map(&mut self) {
 
         // Map the arguments
         for i in 0..args_len {
-            let ref arg_types = self.arg_types[i];
+            let arg_types = &self.arg_types[i];
             let arg_offsets = arg_types.iter().map(|offset| sofar + *offset).collect::<Vec<_>>();
             self.arg_index_map.push(arg_offsets);
             sofar += self.arg_unique_types[i].len();
@@ -597,7 +596,7 @@ fn build_piece(
                             let arg_idx = match arg_index_consumed.get_mut(i) {
                                 None => 0, // error already emitted elsewhere
                                 Some(offset) => {
-                                    let ref idx_map = self.arg_index_map[i];
+                                    let idx_map = &self.arg_index_map[i];
                                     // unwrap_or branch: error already emitted elsewhere
                                     let arg_idx = *idx_map.get(*offset).unwrap_or(&0);
                                     *offset += 1;
@@ -721,7 +720,7 @@ fn into_expr(self) -> P<ast::Expr> {
             let name = names_pos[i];
             let span = self.ecx.with_def_site_ctxt(e.span);
             pats.push(self.ecx.pat_ident(span, name));
-            for ref arg_ty in self.arg_unique_types[i].iter() {
+            for arg_ty in self.arg_unique_types[i].iter() {
                 locals.push(Context::format_arg(self.ecx, self.macsp, e.span, arg_ty, name));
             }
             heads.push(self.ecx.expr_addr_of(e.span, e));
@@ -904,7 +903,7 @@ pub fn expand_preparsed_format_args(
     };
 
     /// Finds the indices of all characters that have been processed and differ between the actual
-    /// written code (code snippet) and the `InternedString` that get's processed in the `Parser`
+    /// written code (code snippet) and the `InternedString` that gets processed in the `Parser`
     /// in order to properly synthethise the intra-string `Span`s for error diagnostics.
     fn find_skips(snippet: &str, is_raw: bool) -> Vec<usize> {
         let mut eat_ws = false;
index 8de7455a09a6472330282e8cf72d9d25f6a90203..5d16be3206aaafe8ae22a116110156e69168c73f 100644 (file)
@@ -57,12 +57,12 @@ impl AllocFnFactory<'_, '_> {
     fn allocator_fn(&self, method: &AllocatorMethod) -> Stmt {
         let mut abi_args = Vec::new();
         let mut i = 0;
-        let ref mut mk = || {
+        let mut mk = || {
             let name = self.cx.ident_of(&format!("arg{}", i), self.span);
             i += 1;
             name
         };
-        let args = method.inputs.iter().map(|ty| self.arg_ty(ty, &mut abi_args, mk)).collect();
+        let args = method.inputs.iter().map(|ty| self.arg_ty(ty, &mut abi_args, &mut mk)).collect();
         let result = self.call_allocator(method.name, args);
         let (output_ty, output_expr) = self.ret_ty(&method.output, result);
         let decl = self.cx.fn_decl(abi_args, ast::FnRetTy::Ty(output_ty));
index 9a8b0a87cb79383cbc7bad60cb6cf7816b5c1b02..26a59c6b1bedb6be72ee9a87741d1360c83be0ca 100644 (file)
@@ -22,6 +22,7 @@
 mod asm;
 mod assert;
 mod cfg;
+mod cfg_accessible;
 mod compile_error;
 mod concat;
 mod concat_idents;
@@ -85,6 +86,7 @@ pub fn register_builtin_macros(resolver: &mut dyn Resolver, edition: Edition) {
 
     register_attr! {
         bench: test::expand_bench,
+        cfg_accessible: cfg_accessible::Expander,
         global_allocator: global_allocator::expand,
         test: test::expand_test,
         test_case: test::expand_test_case,
index 7972466236333739b7317fad10f6e1bb861a0a64..71622a3b7e657b3d6420c3cc0acf4e2df6599362 100644 (file)
@@ -59,7 +59,7 @@ pub fn inject(
     handler: &rustc_errors::Handler,
 ) -> ast::Crate {
     let ecfg = ExpansionConfig::default("proc_macro".to_string());
-    let mut cx = ExtCtxt::new(sess, ecfg, resolver);
+    let mut cx = ExtCtxt::new(sess, ecfg, resolver, None);
 
     let mut collect = CollectProcMacros {
         macros: Vec::new(),
@@ -341,7 +341,7 @@ fn visit_item(&mut self, item: &'a ast::Item) {
         self.in_root = prev_in_root;
     }
 
-    fn visit_mac(&mut self, mac: &'a ast::Mac) {
+    fn visit_mac(&mut self, mac: &'a ast::MacCall) {
         visit::walk_mac(self, mac)
     }
 }
index 5ad72a7443dd2de3fd8960091c26c2ae455839ea..662bbe6a287a36e9399e5d3858fe6596e8e7aa2c 100644 (file)
@@ -5,7 +5,7 @@
 use rustc_ast_pretty::pprust;
 use rustc_expand::base::{self, *};
 use rustc_expand::panictry;
-use rustc_parse::{self, new_sub_parser_from_file, parser::Parser, DirectoryOwnership};
+use rustc_parse::{self, new_sub_parser_from_file, parser::Parser};
 use rustc_session::lint::builtin::INCOMPLETE_INCLUDE;
 use rustc_span::symbol::Symbol;
 use rustc_span::{self, Pos, Span};
@@ -108,8 +108,7 @@ pub fn expand_include<'cx>(
             return DummyResult::any(sp);
         }
     };
-    let directory_ownership = DirectoryOwnership::Owned { relative: None };
-    let p = new_sub_parser_from_file(cx.parse_sess(), &file, directory_ownership, None, sp);
+    let p = new_sub_parser_from_file(cx.parse_sess(), &file, None, sp);
 
     struct ExpandResult<'a> {
         p: Parser<'a>,
index 30403f6dc41c1c1d72da731f8055b19315d5c374..f48fd6df9c98bd4e7d1797cf1a6fff4ee603b4cf 100644 (file)
@@ -39,7 +39,7 @@ pub fn inject(
     let call_site = DUMMY_SP.with_call_site_ctxt(expn_id);
 
     let ecfg = ExpansionConfig::default("std_lib_injection".to_string());
-    let cx = ExtCtxt::new(sess, ecfg, resolver);
+    let cx = ExtCtxt::new(sess, ecfg, resolver, None);
 
     // .rev() to preserve ordering above in combination with insert(0, ...)
     for &name in names.iter().rev() {
index 7fe65f28532d05b85f0e5c76a6c20f9379a1e845..39009ca27f102d46cc050ae5b162f77e8679e6a7 100644 (file)
@@ -86,7 +86,7 @@ pub fn expand_test_or_bench(
             .raise();
     };
 
-    if let ast::ItemKind::Mac(_) = item.kind {
+    if let ast::ItemKind::MacCall(_) = item.kind {
         cx.parse_sess.span_diagnostic.span_warn(
             item.span,
             "`#[test]` attribute should not be used on macros. Use `#[cfg(test)]` instead.",
@@ -313,7 +313,7 @@ fn should_fail(i: &ast::Item) -> bool {
 fn should_panic(cx: &ExtCtxt<'_>, i: &ast::Item) -> ShouldPanic {
     match attr::find_by_name(&i.attrs, sym::should_panic) {
         Some(attr) => {
-            let ref sd = cx.parse_sess.span_diagnostic;
+            let sd = &cx.parse_sess.span_diagnostic;
 
             match attr.meta_item_list() {
                 // Handle #[should_panic(expected = "foo")]
@@ -378,7 +378,7 @@ fn test_type(cx: &ExtCtxt<'_>) -> TestType {
 
 fn has_test_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool {
     let has_should_panic_attr = attr::contains_name(&i.attrs, sym::should_panic);
-    let ref sd = cx.parse_sess.span_diagnostic;
+    let sd = &cx.parse_sess.span_diagnostic;
     if let ast::ItemKind::Fn(_, ref sig, ref generics, _) = i.kind {
         if let ast::Unsafe::Yes(span) = sig.header.unsafety {
             sd.struct_span_err(i.span, "unsafe functions cannot be used for tests")
index 51a2170280559f54b87a88f17f0efb057003590f..b87767f4a4127f650f7037f29833c0b24c42fe77 100644 (file)
@@ -138,7 +138,7 @@ fn visit_crate(&mut self, c: &mut ast::Crate) {
         smallvec![P(item)]
     }
 
-    fn visit_mac(&mut self, _mac: &mut ast::Mac) {
+    fn visit_mac(&mut self, _mac: &mut ast::MacCall) {
         // Do nothing.
     }
 }
@@ -184,7 +184,7 @@ impl MutVisitor for EntryPointCleaner {
         smallvec![item]
     }
 
-    fn visit_mac(&mut self, _mac: &mut ast::Mac) {
+    fn visit_mac(&mut self, _mac: &mut ast::MacCall) {
         // Do nothing.
     }
 }
@@ -202,7 +202,7 @@ fn generate_test_harness(
     let mut econfig = ExpansionConfig::default("test".to_string());
     econfig.features = Some(features);
 
-    let ext_cx = ExtCtxt::new(sess, econfig, resolver);
+    let ext_cx = ExtCtxt::new(sess, econfig, resolver, None);
 
     let expn_id = ext_cx.resolver.expansion_for_ast_pass(
         DUMMY_SP,
@@ -326,7 +326,7 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
 /// &[&test1, &test2]
 fn mk_tests_slice(cx: &TestCtxt<'_>, sp: Span) -> P<ast::Expr> {
     debug!("building test vector from {} tests", cx.test_cases.len());
-    let ref ecx = cx.ext_cx;
+    let ecx = &cx.ext_cx;
 
     ecx.expr_vec_slice(
         sp,
index 8ef76a8657e1eaf9404fd343ea0984141bb7d067..b486eadd1a8bee4fcfff332e61255dfb3777c6c8 100644 (file)
@@ -6,7 +6,7 @@
 
 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::only_word();
+    let template = AttributeTemplate { word: true, ..Default::default() };
     let attr = ecx.attribute(meta_item.clone());
     validate_attr::check_builtin_attribute(ecx.parse_sess, &attr, name, template);
 }
index dda2e5ac18f01ba00f35a1b9a3d8b8d6b3ea567d..97d8f76623e93f52a15369d56d4f0aab0a5cd401 100644 (file)
@@ -2,6 +2,6 @@ The `codegen` crate contains the code to convert from MIR into LLVM IR,
 and then from LLVM IR into machine code. In general it contains code
 that runs towards the end of the compilation process.
 
-For more information about how codegen works, see the [rustc guide].
+For more information about how codegen works, see the [rustc dev guide].
 
-[rustc guide]: https://rust-lang.github.io/rustc-guide/codegen.html
+[rustc dev guide]: https://rustc-dev-guide.rust-lang.org/codegen.html
index c79d9f77e654eb9849642e30f1c8ff55e59e0df7..470a2bb8e1ea5842d145324985ee000fb3f49606 100644 (file)
@@ -148,7 +148,7 @@ fn llvm_type(&self, cx: &CodegenCx<'ll, '_>) -> &'ll Type {
             .prefix
             .iter()
             .flat_map(|option_kind| {
-                option_kind.map(|kind| Reg { kind: kind, size: self.prefix_chunk }.llvm_type(cx))
+                option_kind.map(|kind| Reg { kind, size: self.prefix_chunk }.llvm_type(cx))
             })
             .chain((0..rest_count).map(|_| rest_ll_unit))
             .collect();
index 821377db0ee15645f0f5e2335db0e631fc2f2199..4e7bc9fa0e2aed5fa11796834cbbb2b027cbfd42 100644 (file)
@@ -1,5 +1,3 @@
-use std::ffi::CString;
-
 use crate::attributes;
 use libc::c_uint;
 use rustc::bug;
@@ -50,8 +48,8 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut ModuleLlvm, kind: Alloc
             args.len() as c_uint,
             False,
         );
-        let name = CString::new(format!("__rust_{}", method.name)).unwrap();
-        let llfn = llvm::LLVMRustGetOrInsertFunction(llmod, name.as_ptr(), ty);
+        let name = format!("__rust_{}", method.name);
+        let llfn = llvm::LLVMRustGetOrInsertFunction(llmod, name.as_ptr().cast(), name.len(), ty);
 
         if tcx.sess.target.target.options.default_hidden_visibility {
             llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden);
@@ -60,8 +58,9 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut ModuleLlvm, kind: Alloc
             attributes::emit_uwtable(llfn, true);
         }
 
-        let callee = CString::new(kind.fn_name(method.name)).unwrap();
-        let callee = llvm::LLVMRustGetOrInsertFunction(llmod, callee.as_ptr(), ty);
+        let callee = kind.fn_name(method.name);
+        let callee =
+            llvm::LLVMRustGetOrInsertFunction(llmod, callee.as_ptr().cast(), callee.len(), ty);
         llvm::LLVMRustSetVisibility(callee, llvm::Visibility::Hidden);
 
         let llbb = llvm::LLVMAppendBasicBlockInContext(llcx, llfn, "entry\0".as_ptr().cast());
@@ -73,14 +72,8 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut ModuleLlvm, kind: Alloc
             .enumerate()
             .map(|(i, _)| llvm::LLVMGetParam(llfn, i as c_uint))
             .collect::<Vec<_>>();
-        let ret = llvm::LLVMRustBuildCall(
-            llbuilder,
-            callee,
-            args.as_ptr(),
-            args.len() as c_uint,
-            None,
-            "\0".as_ptr().cast(),
-        );
+        let ret =
+            llvm::LLVMRustBuildCall(llbuilder, callee, args.as_ptr(), args.len() as c_uint, None);
         llvm::LLVMSetTailCall(ret, True);
         if output.is_some() {
             llvm::LLVMBuildRet(llbuilder, ret);
index 8066136c2fe42b83f4f1e3f42a9b90a7e955bf8e..6edc3d5ecd4776b4ee353f806393ea969fbc24a8 100644 (file)
@@ -12,7 +12,6 @@
 
 use libc::{c_char, c_uint};
 use log::debug;
-use std::ffi::{CStr, CString};
 
 impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
     fn codegen_inline_asm(
@@ -29,11 +28,17 @@ fn codegen_inline_asm(
         let mut indirect_outputs = vec![];
         for (i, (out, &place)) in ia.outputs.iter().zip(&outputs).enumerate() {
             if out.is_rw {
-                inputs.push(self.load_operand(place).immediate());
+                let operand = self.load_operand(place);
+                if let OperandValue::Immediate(_) = operand.val {
+                    inputs.push(operand.immediate());
+                }
                 ext_constraints.push(i.to_string());
             }
             if out.is_indirect {
-                indirect_outputs.push(self.load_operand(place).immediate());
+                let operand = self.load_operand(place);
+                if let OperandValue::Immediate(_) = operand.val {
+                    indirect_outputs.push(operand.immediate());
+                }
             } else {
                 output_types.push(place.layout.llvm_type(self.cx()));
             }
@@ -60,7 +65,7 @@ fn codegen_inline_asm(
             .chain(ia.inputs.iter().map(|s| s.to_string()))
             .chain(ext_constraints)
             .chain(clobbers)
-            .chain(arch_clobbers.iter().map(|s| s.to_string()))
+            .chain(arch_clobbers.iter().map(|s| (*s).to_string()))
             .collect::<Vec<String>>()
             .join(",");
 
@@ -74,12 +79,11 @@ fn codegen_inline_asm(
             _ => self.type_struct(&output_types, false),
         };
 
-        let asm = CString::new(ia.asm.as_str().as_bytes()).unwrap();
-        let constraint_cstr = CString::new(all_constraints).unwrap();
+        let asm = ia.asm.as_str();
         let r = inline_asm_call(
             self,
             &asm,
-            &constraint_cstr,
+            &all_constraints,
             &inputs,
             output_type,
             ia.volatile,
@@ -119,17 +123,17 @@ fn codegen_inline_asm(
 
 impl AsmMethods for CodegenCx<'ll, 'tcx> {
     fn codegen_global_asm(&self, ga: &hir::GlobalAsm) {
-        let asm = CString::new(ga.asm.as_str().as_bytes()).unwrap();
+        let asm = ga.asm.as_str();
         unsafe {
-            llvm::LLVMRustAppendModuleInlineAsm(self.llmod, asm.as_ptr());
+            llvm::LLVMRustAppendModuleInlineAsm(self.llmod, asm.as_ptr().cast(), asm.len());
         }
     }
 }
 
 fn inline_asm_call(
     bx: &mut Builder<'a, 'll, 'tcx>,
-    asm: &CStr,
-    cons: &CStr,
+    asm: &str,
+    cons: &str,
     inputs: &[&'ll Value],
     output: &'ll llvm::Type,
     volatile: bool,
@@ -151,13 +155,15 @@ fn inline_asm_call(
     let fty = bx.cx.type_func(&argtys[..], output);
     unsafe {
         // Ask LLVM to verify that the constraints are well-formed.
-        let constraints_ok = llvm::LLVMRustInlineAsmVerify(fty, cons.as_ptr());
+        let constraints_ok = llvm::LLVMRustInlineAsmVerify(fty, cons.as_ptr().cast(), cons.len());
         debug!("constraint verification result: {:?}", constraints_ok);
         if constraints_ok {
             let v = llvm::LLVMRustInlineAsm(
                 fty,
-                asm.as_ptr(),
-                cons.as_ptr(),
+                asm.as_ptr().cast(),
+                asm.len(),
+                cons.as_ptr().cast(),
+                cons.len(),
                 volatile,
                 alignstack,
                 llvm::AsmDialect::from_generic(dia),
index a9e4fdba030366ee60a2d104da1290cdcd68ae14..072607fff85c73cb9f020dfa3f626c7c2db83b91 100644 (file)
@@ -3,8 +3,6 @@
 use std::ffi::CString;
 
 use rustc::middle::codegen_fn_attrs::CodegenFnAttrFlags;
-use rustc::session::config::{OptLevel, Sanitizer};
-use rustc::session::Session;
 use rustc::ty::layout::HasTyCtxt;
 use rustc::ty::query::Providers;
 use rustc::ty::{self, Ty, TyCtxt};
@@ -13,6 +11,8 @@
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::small_c_str::SmallCStr;
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
+use rustc_session::config::{OptLevel, Sanitizer};
+use rustc_session::Session;
 use rustc_target::abi::call::Conv;
 use rustc_target::spec::PanicStrategy;
 
index 455b7086212baf862022695184d64bf824cfc1d9..239ca57ba41434d38b13858dc9157473d00c5bc6 100644 (file)
@@ -9,9 +9,9 @@
 
 use crate::llvm::archive_ro::{ArchiveRO, Child};
 use crate::llvm::{self, ArchiveKind};
-use rustc::session::Session;
 use rustc_codegen_ssa::back::archive::{find_library, ArchiveBuilder};
 use rustc_codegen_ssa::{looks_like_rust_object_file, METADATA_FILENAME, RLIB_BYTECODE_EXTENSION};
+use rustc_session::Session;
 use rustc_span::symbol::Symbol;
 
 struct ArchiveConfig<'a> {
index a39c25f6693c1cb56ed2aa05314b2e07957f2037..1b64750f51febd12f10cb21c8abb0525524951b5 100644 (file)
@@ -9,7 +9,6 @@
 use rustc::bug;
 use rustc::dep_graph::WorkProduct;
 use rustc::middle::exported_symbols::SymbolExportLevel;
-use rustc::session::config::{self, Lto};
 use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule, ThinShared};
 use rustc_codegen_ssa::back::symbol_export;
 use rustc_codegen_ssa::back::write::{CodegenContext, FatLTOInput, ModuleConfig};
@@ -19,6 +18,7 @@
 use rustc_errors::{FatalError, Handler};
 use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_session::cgu_reuse_tracker::CguReuse;
+use rustc_session::config::{self, Lto};
 
 use std::ffi::{CStr, CString};
 use std::fs::File;
@@ -504,7 +504,7 @@ fn thin_lto(
             //
             // This strategy means we can always save the computed imports as
             // canon: when we reuse the post-ThinLTO version, condition (3.)
-            // ensures that the curent import set is the same as the previous
+            // ensures that the current import set is the same as the previous
             // one. (And of course, when we don't reuse the post-ThinLTO
             // version, the current import set *is* the correct one, since we
             // are doing the ThinLTO in this current compilation cycle.)
@@ -538,7 +538,7 @@ fn thin_lto(
             }));
         }
 
-        // Save the curent ThinLTO import information for the next compilation
+        // Save the current ThinLTO import information for the next compilation
         // session, overwriting the previous serialized imports (if any).
         if let Some(path) = import_map_path {
             if let Err(err) = curr_import_map.save_to_file(&path) {
index d56ddac699b09eebed19433ea07c35b15b3fda6c..2741f7d848e79043f676ded67df63ee404578dc9 100644 (file)
@@ -9,8 +9,8 @@ fn llvm_args_to_string_id(profiler: &SelfProfiler, pass_name: &str, ir_name: &st
     let mut components = vec![StringComponent::Ref(pass_name)];
     // handle that LazyCallGraph::SCC is a comma separated list within parentheses
     let parentheses: &[_] = &['(', ')'];
-    let trimed = ir_name.trim_matches(parentheses);
-    for part in trimed.split(", ") {
+    let trimmed = ir_name.trim_matches(parentheses);
+    for part in trimmed.split(", ") {
         let demangled_ir_name = rustc_demangle::demangle(part).to_string();
         let ir_name = profiler.get_or_alloc_cached_string(demangled_ir_name);
         components.push(StringComponent::Value(SEPARATOR_BYTE));
index a215ef81bc9ebe7bc27c220e1bcfc29e1682061f..2327b96e26c36597a125f1bbf945707d493d4771 100644 (file)
@@ -15,8 +15,6 @@
 use crate::ModuleLlvm;
 use log::debug;
 use rustc::bug;
-use rustc::session::config::{self, Lto, OutputType, Passes, Sanitizer, SwitchWithOptPath};
-use rustc::session::Session;
 use rustc::ty::TyCtxt;
 use rustc_codegen_ssa::back::write::{run_assembler, CodegenContext, ModuleConfig};
 use rustc_codegen_ssa::traits::*;
@@ -25,6 +23,8 @@
 use rustc_errors::{FatalError, Handler};
 use rustc_fs_util::{link_or_copy, path_to_c_string};
 use rustc_hir::def_id::LOCAL_CRATE;
+use rustc_session::config::{self, Lto, OutputType, Passes, Sanitizer, SwitchWithOptPath};
+use rustc_session::Session;
 
 use libc::{c_char, c_int, c_uint, c_void, size_t};
 use std::ffi::CString;
@@ -725,7 +725,7 @@ extern "C" fn demangle_callback(
                         Err(_) => return 0,
                     };
 
-                    if let Err(_) = write!(cursor, "{:#}", demangled) {
+                    if write!(cursor, "{:#}", demangled).is_err() {
                         // Possible only if provided buffer is not big enough
                         return 0;
                     }
index 04c084e459eab662f2b441eafcc2ba5715b76ca4..0d063d82c6934ff700ba8fd8476d937abfa776ee 100644 (file)
 use rustc::middle::cstore::EncodedMetadata;
 use rustc::middle::exported_symbols;
 use rustc::mir::mono::{Linkage, Visibility};
-use rustc::session::config::DebugInfo;
 use rustc::ty::TyCtxt;
 use rustc_codegen_ssa::base::maybe_create_entry_wrapper;
 use rustc_codegen_ssa::mono_item::MonoItemExt;
 use rustc_codegen_ssa::traits::*;
 use rustc_codegen_ssa::{ModuleCodegen, ModuleKind};
 use rustc_data_structures::small_c_str::SmallCStr;
+use rustc_session::config::DebugInfo;
 use rustc_span::symbol::Symbol;
 
 use std::ffi::CString;
index 32604d5601d30036ddc5c57c3b0b5e1d78765874..b37d63fce659235a79dbe3db9fa704069579922b 100644 (file)
@@ -7,7 +7,6 @@
 use crate::value::Value;
 use libc::{c_char, c_uint};
 use log::debug;
-use rustc::session::config::{self, Sanitizer};
 use rustc::ty::layout::{self, Align, Size, TyLayout};
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc_codegen_ssa::base::to_immediate;
@@ -19,6 +18,7 @@
 use rustc_data_structures::const_cstr;
 use rustc_data_structures::small_c_str::SmallCStr;
 use rustc_hir::def_id::DefId;
+use rustc_session::config::{self, Sanitizer};
 use rustc_target::spec::{HasTargetSpec, Target};
 use std::borrow::Cow;
 use std::ffi::CStr;
@@ -1016,7 +1016,6 @@ fn call(
                 args.as_ptr() as *const &llvm::Value,
                 args.len() as c_uint,
                 bundle,
-                UNNAMED,
             )
         }
     }
index df38eeec00fce9de052fb6cac83b3becb1a1b664..609ddfc1d3a8075b7ef33456413cc4ba3de6187f 100644 (file)
@@ -259,11 +259,14 @@ fn scalar_to_backend(
                 let base_addr = match alloc_kind {
                     Some(GlobalAlloc::Memory(alloc)) => {
                         let init = const_alloc_to_llvm(self, alloc);
-                        if alloc.mutability == Mutability::Mut {
-                            self.static_addr_of_mut(init, alloc.align, None)
-                        } else {
-                            self.static_addr_of(init, alloc.align, None)
+                        let value = match alloc.mutability {
+                            Mutability::Mut => self.static_addr_of_mut(init, alloc.align, None),
+                            _ => self.static_addr_of(init, alloc.align, None),
+                        };
+                        if !self.sess().fewer_names() {
+                            llvm::set_value_name(value, format!("{:?}", ptr.alloc_id).as_bytes());
                         }
+                        value
                     }
                     Some(GlobalAlloc::Function(fn_instance)) => self.get_fn_addr(fn_instance),
                     Some(GlobalAlloc::Static(def_id)) => {
@@ -320,7 +323,7 @@ fn const_ptrcast(&self, val: &'ll Value, ty: &'ll Type) -> &'ll Value {
     }
 }
 
-pub fn val_ty(v: &'ll Value) -> &'ll Type {
+pub fn val_ty(v: &Value) -> &Type {
     unsafe { llvm::LLVMTypeOf(v) }
 }
 
@@ -342,6 +345,6 @@ 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> {
+fn try_as_const_integral(v: &Value) -> Option<&ConstantInt> {
     unsafe { llvm::LLVMIsAConstantInt(v) }
 }
index 46f461b98c8de0ee7207a78769002305c64978da..7b1526e9da154747ebf41057ca8282fb6bc67f7c 100644 (file)
@@ -1,37 +1,32 @@
-use crate::abi::FnAbi;
 use crate::attributes;
+use crate::callee::get_fn;
 use crate::debuginfo;
 use crate::llvm;
 use crate::llvm_util;
-use crate::value::Value;
-use rustc::dep_graph::DepGraphSafe;
-
 use crate::type_::Type;
-use rustc_codegen_ssa::traits::*;
+use crate::value::Value;
 
-use crate::callee::get_fn;
 use rustc::bug;
+use rustc::dep_graph::DepGraphSafe;
 use rustc::mir::mono::CodegenUnit;
-use rustc::session::config::{self, CFGuard, DebugInfo};
-use rustc::session::Session;
 use rustc::ty::layout::{
-    FnAbiExt, HasParamEnv, LayoutError, LayoutOf, PointeeInfo, Size, TyLayout, VariantIdx,
+    HasParamEnv, LayoutError, LayoutOf, PointeeInfo, Size, TyLayout, VariantIdx,
 };
 use rustc::ty::{self, Instance, Ty, TyCtxt};
 use rustc_codegen_ssa::base::wants_msvc_seh;
+use rustc_codegen_ssa::traits::*;
 use rustc_data_structures::base_n;
 use rustc_data_structures::const_cstr;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::small_c_str::SmallCStr;
-use rustc_hir::Unsafety;
-use rustc_target::spec::{HasTargetSpec, Target};
-
-use crate::abi::Abi;
+use rustc_session::config::{self, CFGuard, DebugInfo};
+use rustc_session::Session;
 use rustc_span::source_map::{Span, DUMMY_SP};
 use rustc_span::symbol::Symbol;
+use rustc_target::spec::{HasTargetSpec, Target};
+
 use std::cell::{Cell, RefCell};
 use std::ffi::CStr;
-use std::iter;
 use std::str;
 use std::sync::Arc;
 
@@ -87,7 +82,6 @@ pub struct CodegenCx<'ll, 'tcx> {
     pub dbg_cx: Option<debuginfo::CrateDebugContext<'ll, 'tcx>>,
 
     eh_personality: Cell<Option<&'ll Value>>,
-    eh_unwind_resume: Cell<Option<&'ll Value>>,
     pub rust_try_fn: Cell<Option<&'ll Value>>,
 
     intrinsics: RefCell<FxHashMap<&'static str, &'ll Value>>,
@@ -174,7 +168,6 @@ pub unsafe fn create_module(
 
         let llvm_data_layout = llvm::LLVMGetDataLayout(llmod);
         let llvm_data_layout = str::from_utf8(CStr::from_ptr(llvm_data_layout).to_bytes())
-            .ok()
             .expect("got a non-UTF8 data-layout from LLVM");
 
         // Unfortunately LLVM target specs change over time, and right now we
@@ -328,7 +321,6 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
             isize_ty,
             dbg_cx,
             eh_personality: Cell::new(None),
-            eh_unwind_resume: Cell::new(None),
             rust_try_fn: Cell::new(None),
             intrinsics: Default::default(),
             local_gen_sym_counter: Cell::new(0),
@@ -406,45 +398,6 @@ fn eh_personality(&self) -> &'ll Value {
         llfn
     }
 
-    // Returns a Value of the "eh_unwind_resume" lang item if one is defined,
-    // otherwise declares it as an external function.
-    fn eh_unwind_resume(&self) -> &'ll Value {
-        let unwresume = &self.eh_unwind_resume;
-        if let Some(llfn) = unwresume.get() {
-            return llfn;
-        }
-
-        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(),
-            );
-            unwresume.set(Some(llfn));
-            return llfn;
-        }
-
-        let sig = ty::Binder::bind(tcx.mk_fn_sig(
-            iter::once(tcx.mk_mut_ptr(tcx.types.u8)),
-            tcx.types.never,
-            false,
-            Unsafety::Unsafe,
-            Abi::C,
-        ));
-
-        let fn_abi = FnAbi::of_fn_ptr(self, sig, &[]);
-        let llfn = self.declare_fn("rust_eh_unwind_resume", &fn_abi);
-        attributes::apply_target_cpu_attr(self, llfn);
-        unwresume.set(Some(llfn));
-        llfn
-    }
-
     fn sess(&self) -> &Session {
         &self.tcx.sess
     }
index cdb9657e1ff3c3b294b1a57068e3ebc59f8ab86b..09422f4ec3768824e92cd9e50f0298b372aa2cb5 100644 (file)
@@ -1,5 +1,5 @@
-use super::metadata::file_metadata;
-use super::utils::{span_start, DIB};
+use super::metadata::{file_metadata, UNKNOWN_COLUMN_NUMBER, UNKNOWN_LINE_NUMBER};
+use super::utils::DIB;
 use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext};
 
 use crate::common::CodegenCx;
@@ -7,10 +7,6 @@
 use crate::llvm::debuginfo::{DIScope, DISubprogram};
 use rustc::mir::{Body, SourceScope};
 
-use libc::c_uint;
-
-use rustc_span::Pos;
-
 use rustc_index::bit_set::BitSet;
 use rustc_index::vec::Idx;
 
@@ -54,7 +50,7 @@ fn make_mir_scope(
         debug_context.scopes[parent]
     } else {
         // The root is the function itself.
-        let loc = span_start(cx, mir.span);
+        let loc = cx.lookup_debug_loc(mir.span.lo());
         debug_context.scopes[scope] = DebugScope {
             scope_metadata: Some(fn_metadata),
             file_start_pos: loc.file.start_pos,
@@ -70,7 +66,7 @@ fn make_mir_scope(
         return;
     }
 
-    let loc = span_start(cx, scope_data.span);
+    let loc = cx.lookup_debug_loc(scope_data.span.lo());
     let file_metadata = file_metadata(cx, &loc.file.name, debug_context.defining_crate);
 
     let scope_metadata = unsafe {
@@ -78,8 +74,8 @@ fn make_mir_scope(
             DIB(cx),
             parent_scope.scope_metadata.unwrap(),
             file_metadata,
-            loc.line as c_uint,
-            loc.col.to_usize() as c_uint,
+            loc.line.unwrap_or(UNKNOWN_LINE_NUMBER),
+            loc.col.unwrap_or(UNKNOWN_COLUMN_NUMBER),
         ))
     };
     debug_context.scopes[scope] = DebugScope {
index 753a4e18faf5e7aa26b719d4d96e4e80747fa0bd..e4cbffb6db3c30704e351dff1988d71c9d545d79 100644 (file)
@@ -6,8 +6,8 @@
 use crate::common::CodegenCx;
 use crate::value::Value;
 use rustc::bug;
-use rustc::session::config::DebugInfo;
 use rustc_codegen_ssa::traits::*;
+use rustc_session::config::DebugInfo;
 
 use rustc_ast::attr;
 use rustc_span::symbol::sym;
index 6ed3153963f9858dda79a5e77bb4e9f704c0a93f..6a7ed4e1dc384266eeefcecc13c58b047cf179dd 100644 (file)
@@ -5,7 +5,7 @@
 use super::namespace::mangled_name_of_instance;
 use super::type_names::compute_debuginfo_type_name;
 use super::utils::{
-    create_DIArray, debug_context, get_namespace_for_item, is_node_local_to_unit, span_start, DIB,
+    create_DIArray, debug_context, get_namespace_for_item, is_node_local_to_unit, DIB,
 };
 use super::CrateDebugContext;
 
@@ -24,7 +24,6 @@
 use rustc::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc::mir::interpret::truncate;
 use rustc::mir::{self, Field, GeneratorLayout};
-use rustc::session::config::{self, DebugInfo};
 use rustc::ty::layout::{
     self, Align, Integer, IntegerExt, LayoutOf, PrimitiveExt, Size, TyLayout, VariantIdx,
 };
 use rustc_data_structures::const_cstr;
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::small_c_str::SmallCStr;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_fs_util::path_to_c_string;
 use rustc_hir::def::CtorKind;
 use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use rustc_index::vec::{Idx, IndexVec};
+use rustc_session::config::{self, DebugInfo};
 use rustc_span::symbol::{Interner, Symbol};
 use rustc_span::{self, FileName, Span};
 use rustc_target::abi::HasDataLayout;
 
 use libc::{c_longlong, c_uint};
 use std::collections::hash_map::Entry;
-use std::ffi::CString;
 use std::fmt::{self, Write};
 use std::hash::{Hash, Hasher};
 use std::iter;
@@ -227,11 +225,11 @@ fn get_unique_type_id_of_enum_variant<'a>(
     /// Gets the unique type ID string for an enum variant part.
     /// Variant parts are not types and shouldn't really have their own ID,
     /// but it makes `set_members_of_composite_type()` simpler.
-    fn get_unique_type_id_str_of_enum_variant_part(&mut self, enum_type_id: UniqueTypeId) -> &str {
-        let variant_part_type_id =
-            format!("{}_variant_part", self.get_unique_type_id_as_string(enum_type_id));
-        let interner_key = self.unique_id_interner.intern(&variant_part_type_id);
-        self.unique_id_interner.get(interner_key)
+    fn get_unique_type_id_str_of_enum_variant_part(
+        &mut self,
+        enum_type_id: UniqueTypeId,
+    ) -> String {
+        format!("{}_variant_part", self.get_unique_type_id_as_string(enum_type_id))
     }
 }
 
@@ -637,12 +635,14 @@ pub fn type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>, usage_site_span: Sp
                 unsafe {
                     // The choice of type here is pretty arbitrary -
                     // anything reading the debuginfo for a recursive
-                    // type is going to see *somthing* weird - the only
+                    // type is going to see *something* weird - the only
                     // question is what exactly it will see.
                     let (size, align) = cx.size_and_align_of(t);
+                    let name = "<recur_type>";
                     llvm::LLVMRustDIBuilderCreateBasicType(
                         DIB(cx),
-                        SmallCStr::new("<recur_type>").as_ptr(),
+                        name.as_ptr().cast(),
+                        name.len(),
                         size.bits(),
                         align.bits() as u32,
                         DW_ATE_unsigned,
@@ -786,16 +786,17 @@ fn file_metadata_raw(
             let (file_name, directory) = v.key();
             debug!("file_metadata: file_name: {:?}, directory: {:?}", file_name, directory);
 
-            let file_name = SmallCStr::new(if let Some(file_name) = file_name {
-                &file_name
-            } else {
-                "<unknown>"
-            });
-            let directory =
-                SmallCStr::new(if let Some(directory) = directory { &directory } else { "" });
+            let file_name = file_name.as_deref().unwrap_or("<unknown>");
+            let directory = directory.as_deref().unwrap_or("");
 
             let file_metadata = unsafe {
-                llvm::LLVMRustDIBuilderCreateFile(DIB(cx), file_name.as_ptr(), directory.as_ptr())
+                llvm::LLVMRustDIBuilderCreateFile(
+                    DIB(cx),
+                    file_name.as_ptr().cast(),
+                    file_name.len(),
+                    directory.as_ptr().cast(),
+                    directory.len(),
+                )
             };
 
             v.insert(file_metadata);
@@ -819,11 +820,11 @@ fn basic_type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType {
     };
 
     let (size, align) = cx.size_and_align_of(t);
-    let name = SmallCStr::new(name);
     let ty_metadata = unsafe {
         llvm::LLVMRustDIBuilderCreateBasicType(
             DIB(cx),
-            name.as_ptr(),
+            name.as_ptr().cast(),
+            name.len(),
             size.bits(),
             align.bits() as u32,
             encoding,
@@ -851,14 +852,15 @@ fn pointer_type_metadata(
 ) -> &'ll DIType {
     let (pointer_size, pointer_align) = cx.size_and_align_of(pointer_type);
     let name = compute_debuginfo_type_name(cx.tcx, pointer_type, false);
-    let name = SmallCStr::new(&name);
     unsafe {
         llvm::LLVMRustDIBuilderCreatePointerType(
             DIB(cx),
             pointee_type_metadata,
             pointer_size.bits(),
             pointer_align.bits() as u32,
-            name.as_ptr(),
+            0, // Ignore DWARF address space.
+            name.as_ptr().cast(),
+            name.len(),
         )
     }
 }
@@ -889,11 +891,9 @@ pub fn compile_unit_metadata(
     let producer = format!("clang LLVM ({})", rustc_producer);
 
     let name_in_debuginfo = name_in_debuginfo.to_string_lossy();
-    let name_in_debuginfo = SmallCStr::new(&name_in_debuginfo);
-    let work_dir = SmallCStr::new(&tcx.sess.working_dir.0.to_string_lossy());
-    let producer = CString::new(producer).unwrap();
+    let work_dir = tcx.sess.working_dir.0.to_string_lossy();
     let flags = "\0";
-    let split_name = "\0";
+    let split_name = "";
 
     // FIXME(#60020):
     //
@@ -916,19 +916,23 @@ pub fn compile_unit_metadata(
     unsafe {
         let file_metadata = llvm::LLVMRustDIBuilderCreateFile(
             debug_context.builder,
-            name_in_debuginfo.as_ptr(),
-            work_dir.as_ptr(),
+            name_in_debuginfo.as_ptr().cast(),
+            name_in_debuginfo.len(),
+            work_dir.as_ptr().cast(),
+            work_dir.len(),
         );
 
         let unit_metadata = llvm::LLVMRustDIBuilderCreateCompileUnit(
             debug_context.builder,
             DW_LANG_RUST,
             file_metadata,
-            producer.as_ptr(),
+            producer.as_ptr().cast(),
+            producer.len(),
             tcx.sess.opts.optimize != config::OptLevel::No,
             flags.as_ptr().cast(),
             0,
             split_name.as_ptr().cast(),
+            split_name.len(),
             kind,
         );
 
@@ -1021,12 +1025,12 @@ fn into_metadata(
         cx: &CodegenCx<'ll, '_>,
         composite_type_metadata: &'ll DIScope,
     ) -> &'ll DIType {
-        let member_name = CString::new(self.name).unwrap();
         unsafe {
             llvm::LLVMRustDIBuilderCreateVariantMemberType(
                 DIB(cx),
                 composite_type_metadata,
-                member_name.as_ptr(),
+                self.name.as_ptr().cast(),
+                self.name.len(),
                 unknown_file_metadata(cx),
                 UNKNOWN_LINE_NUMBER,
                 self.size.bits(),
@@ -1779,13 +1783,20 @@ fn prepare_enum_metadata(
                 .discriminants(cx.tcx)
                 .zip(&def.variants)
                 .map(|((_, discr), v)| {
-                    let name = SmallCStr::new(&v.ident.as_str());
+                    let name = v.ident.as_str();
+                    let is_unsigned = match discr.ty.kind {
+                        ty::Int(_) => false,
+                        ty::Uint(_) => true,
+                        _ => bug!("non integer discriminant"),
+                    };
                     unsafe {
                         Some(llvm::LLVMRustDIBuilderCreateEnumerator(
                             DIB(cx),
-                            name.as_ptr(),
+                            name.as_ptr().cast(),
+                            name.len(),
                             // FIXME: what if enumeration has i128 discriminant?
-                            discr.val as u64,
+                            discr.val as i64,
+                            is_unsigned,
                         ))
                     }
                 })
@@ -1794,13 +1805,15 @@ fn prepare_enum_metadata(
                 .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 = substs.as_generator().variant_name(variant_index);
                     unsafe {
                         Some(llvm::LLVMRustDIBuilderCreateEnumerator(
                             DIB(cx),
-                            name.as_ptr(),
-                            // FIXME: what if enumeration has i128 discriminant?
-                            variant_index.as_usize() as u64,
+                            name.as_ptr().cast(),
+                            name.len(),
+                            // Generators use u32 as discriminant type.
+                            variant_index.as_u32().into(),
+                            true, // IsUnsigned
                         ))
                     }
                 })
@@ -1818,9 +1831,13 @@ fn prepare_enum_metadata(
                 let discriminant_base_type_metadata =
                     type_metadata(cx, discr.to_ty(cx.tcx), rustc_span::DUMMY_SP);
 
+                let item_name;
                 let discriminant_name = match enum_type.kind {
-                    ty::Adt(..) => SmallCStr::new(&cx.tcx.item_name(enum_def_id).as_str()),
-                    ty::Generator(..) => SmallCStr::new(&enum_name),
+                    ty::Adt(..) => {
+                        item_name = cx.tcx.item_name(enum_def_id).as_str();
+                        &*item_name
+                    }
+                    ty::Generator(..) => enum_name.as_str(),
                     _ => bug!(),
                 };
 
@@ -1828,7 +1845,8 @@ fn prepare_enum_metadata(
                     llvm::LLVMRustDIBuilderCreateEnumerationType(
                         DIB(cx),
                         containing_scope,
-                        discriminant_name.as_ptr(),
+                        discriminant_name.as_ptr().cast(),
+                        discriminant_name.len(),
                         file_metadata,
                         UNKNOWN_LINE_NUMBER,
                         discriminant_size.bits(),
@@ -1863,11 +1881,6 @@ fn prepare_enum_metadata(
         _ => {}
     }
 
-    let enum_name = SmallCStr::new(&enum_name);
-    let unique_type_id_str = SmallCStr::new(
-        debug_context(cx).type_map.borrow().get_unique_type_id_as_string(unique_type_id),
-    );
-
     if use_enum_fallback(cx) {
         let discriminant_type_metadata = match layout.variants {
             layout::Variants::Single { .. }
@@ -1882,20 +1895,27 @@ fn prepare_enum_metadata(
             } => Some(discriminant_type_metadata(discr.value)),
         };
 
-        let enum_metadata = unsafe {
-            llvm::LLVMRustDIBuilderCreateUnionType(
-                DIB(cx),
-                containing_scope,
-                enum_name.as_ptr(),
-                file_metadata,
-                UNKNOWN_LINE_NUMBER,
-                layout.size.bits(),
-                layout.align.abi.bits() as u32,
-                DIFlags::FlagZero,
-                None,
-                0, // RuntimeLang
-                unique_type_id_str.as_ptr(),
-            )
+        let enum_metadata = {
+            let type_map = debug_context(cx).type_map.borrow();
+            let unique_type_id_str = type_map.get_unique_type_id_as_string(unique_type_id);
+
+            unsafe {
+                llvm::LLVMRustDIBuilderCreateUnionType(
+                    DIB(cx),
+                    containing_scope,
+                    enum_name.as_ptr().cast(),
+                    enum_name.len(),
+                    file_metadata,
+                    UNKNOWN_LINE_NUMBER,
+                    layout.size.bits(),
+                    layout.align.abi.bits() as u32,
+                    DIFlags::FlagZero,
+                    None,
+                    0, // RuntimeLang
+                    unique_type_id_str.as_ptr().cast(),
+                    unique_type_id_str.len(),
+                )
+            }
         };
 
         return create_and_register_recursive_type_forward_declaration(
@@ -1915,10 +1935,9 @@ fn prepare_enum_metadata(
     }
 
     let discriminator_name = match &enum_type.kind {
-        ty::Generator(..) => Some(SmallCStr::new(&"__state")),
-        _ => None,
+        ty::Generator(..) => "__state",
+        _ => "",
     };
-    let discriminator_name = discriminator_name.map(|n| n.as_ptr()).unwrap_or(ptr::null_mut());
     let discriminator_metadata = match layout.variants {
         // A single-variant enum has no discriminant.
         layout::Variants::Single { .. } => None,
@@ -1946,7 +1965,8 @@ fn prepare_enum_metadata(
                 Some(llvm::LLVMRustDIBuilderCreateMemberType(
                     DIB(cx),
                     containing_scope,
-                    discriminator_name,
+                    discriminator_name.as_ptr().cast(),
+                    discriminator_name.len(),
                     file_metadata,
                     UNKNOWN_LINE_NUMBER,
                     size.bits(),
@@ -1972,7 +1992,8 @@ fn prepare_enum_metadata(
                 Some(llvm::LLVMRustDIBuilderCreateMemberType(
                     DIB(cx),
                     containing_scope,
-                    discriminator_name,
+                    discriminator_name.as_ptr().cast(),
+                    discriminator_name.len(),
                     file_metadata,
                     UNKNOWN_LINE_NUMBER,
                     size.bits(),
@@ -2001,18 +2022,18 @@ fn prepare_enum_metadata(
         }
     };
 
-    let variant_part_unique_type_id_str = SmallCStr::new(
-        debug_context(cx)
-            .type_map
-            .borrow_mut()
-            .get_unique_type_id_str_of_enum_variant_part(unique_type_id),
-    );
+    let variant_part_unique_type_id_str = debug_context(cx)
+        .type_map
+        .borrow_mut()
+        .get_unique_type_id_str_of_enum_variant_part(unique_type_id);
     let empty_array = create_DIArray(DIB(cx), &[]);
+    let name = "";
     let variant_part = unsafe {
         llvm::LLVMRustDIBuilderCreateVariantPart(
             DIB(cx),
             containing_scope,
-            ptr::null_mut(),
+            name.as_ptr().cast(),
+            name.len(),
             file_metadata,
             UNKNOWN_LINE_NUMBER,
             layout.size.bits(),
@@ -2020,29 +2041,38 @@ fn prepare_enum_metadata(
             DIFlags::FlagZero,
             discriminator_metadata,
             empty_array,
-            variant_part_unique_type_id_str.as_ptr(),
+            variant_part_unique_type_id_str.as_ptr().cast(),
+            variant_part_unique_type_id_str.len(),
         )
     };
     outer_fields.push(Some(variant_part));
 
-    // The variant part must be wrapped in a struct according to DWARF.
-    let type_array = create_DIArray(DIB(cx), &outer_fields);
-    let struct_wrapper = unsafe {
-        llvm::LLVMRustDIBuilderCreateStructType(
-            DIB(cx),
-            Some(containing_scope),
-            enum_name.as_ptr(),
-            file_metadata,
-            UNKNOWN_LINE_NUMBER,
-            layout.size.bits(),
-            layout.align.abi.bits() as u32,
-            DIFlags::FlagZero,
-            None,
-            type_array,
-            0,
-            None,
-            unique_type_id_str.as_ptr(),
-        )
+    let struct_wrapper = {
+        // The variant part must be wrapped in a struct according to DWARF.
+        let type_array = create_DIArray(DIB(cx), &outer_fields);
+
+        let type_map = debug_context(cx).type_map.borrow();
+        let unique_type_id_str = type_map.get_unique_type_id_as_string(unique_type_id);
+
+        unsafe {
+            llvm::LLVMRustDIBuilderCreateStructType(
+                DIB(cx),
+                Some(containing_scope),
+                enum_name.as_ptr().cast(),
+                enum_name.len(),
+                file_metadata,
+                UNKNOWN_LINE_NUMBER,
+                layout.size.bits(),
+                layout.align.abi.bits() as u32,
+                DIFlags::FlagZero,
+                None,
+                type_array,
+                0,
+                None,
+                unique_type_id_str.as_ptr().cast(),
+                unique_type_id_str.len(),
+            )
+        }
     };
 
     return create_and_register_recursive_type_forward_declaration(
@@ -2135,7 +2165,7 @@ fn set_members_of_composite_type(
 /// Computes the type parameters for a type, if any, for the given metadata.
 fn compute_type_parameters(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>) -> Option<&'ll DIArray> {
     if let ty::Adt(def, substs) = ty.kind {
-        if !substs.types().next().is_none() {
+        if substs.types().next().is_some() {
             let generics = cx.tcx.generics_of(def.did);
             let names = get_parameter_names(cx, generics);
             let template_params: Vec<_> = substs
@@ -2147,12 +2177,13 @@ fn compute_type_parameters(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>) -> Option<&'
                             cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty);
                         let actual_type_metadata =
                             type_metadata(cx, actual_type, rustc_span::DUMMY_SP);
-                        let name = SmallCStr::new(&name.as_str());
+                        let name = &name.as_str();
                         Some(unsafe {
                             Some(llvm::LLVMRustDIBuilderCreateTemplateTypeParameter(
                                 DIB(cx),
                                 None,
-                                name.as_ptr(),
+                                name.as_ptr().cast(),
+                                name.len(),
                                 actual_type_metadata,
                                 unknown_file_metadata(cx),
                                 0,
@@ -2191,10 +2222,9 @@ fn create_struct_stub(
 ) -> &'ll DICompositeType {
     let (struct_size, struct_align) = cx.size_and_align_of(struct_type);
 
-    let name = SmallCStr::new(struct_type_name);
-    let unique_type_id = SmallCStr::new(
-        debug_context(cx).type_map.borrow().get_unique_type_id_as_string(unique_type_id),
-    );
+    let type_map = debug_context(cx).type_map.borrow();
+    let unique_type_id = type_map.get_unique_type_id_as_string(unique_type_id);
+
     let metadata_stub = unsafe {
         // `LLVMRustDIBuilderCreateStructType()` wants an empty array. A null
         // pointer will lead to hard to trace and debug LLVM assertions
@@ -2204,7 +2234,8 @@ fn create_struct_stub(
         llvm::LLVMRustDIBuilderCreateStructType(
             DIB(cx),
             containing_scope,
-            name.as_ptr(),
+            struct_type_name.as_ptr().cast(),
+            struct_type_name.len(),
             unknown_file_metadata(cx),
             UNKNOWN_LINE_NUMBER,
             struct_size.bits(),
@@ -2214,7 +2245,8 @@ fn create_struct_stub(
             empty_array,
             0,
             None,
-            unique_type_id.as_ptr(),
+            unique_type_id.as_ptr().cast(),
+            unique_type_id.len(),
         )
     };
 
@@ -2230,10 +2262,9 @@ fn create_union_stub(
 ) -> &'ll DICompositeType {
     let (union_size, union_align) = cx.size_and_align_of(union_type);
 
-    let name = SmallCStr::new(union_type_name);
-    let unique_type_id = SmallCStr::new(
-        debug_context(cx).type_map.borrow().get_unique_type_id_as_string(unique_type_id),
-    );
+    let type_map = debug_context(cx).type_map.borrow();
+    let unique_type_id = type_map.get_unique_type_id_as_string(unique_type_id);
+
     let metadata_stub = unsafe {
         // `LLVMRustDIBuilderCreateUnionType()` wants an empty array. A null
         // pointer will lead to hard to trace and debug LLVM assertions
@@ -2243,7 +2274,8 @@ fn create_union_stub(
         llvm::LLVMRustDIBuilderCreateUnionType(
             DIB(cx),
             containing_scope,
-            name.as_ptr(),
+            union_type_name.as_ptr().cast(),
+            union_type_name.len(),
             unknown_file_metadata(cx),
             UNKNOWN_LINE_NUMBER,
             union_size.bits(),
@@ -2251,7 +2283,8 @@ fn create_union_stub(
             DIFlags::FlagZero,
             Some(empty_array),
             0, // RuntimeLang
-            unique_type_id.as_ptr(),
+            unique_type_id.as_ptr().cast(),
+            unique_type_id.len(),
         )
     };
 
@@ -2269,10 +2302,6 @@ pub fn create_global_var_metadata(cx: &CodegenCx<'ll, '_>, def_id: DefId, global
     let tcx = cx.tcx;
     let attrs = tcx.codegen_fn_attrs(def_id);
 
-    if attrs.flags.contains(CodegenFnAttrFlags::NO_DEBUG) {
-        return;
-    }
-
     let no_mangle = attrs.flags.contains(CodegenFnAttrFlags::NO_MANGLE);
     // We may want to remove the namespace scope if we're in an extern block (see
     // https://github.com/rust-lang/rust/pull/46457#issuecomment-351750952).
@@ -2280,22 +2309,24 @@ pub fn create_global_var_metadata(cx: &CodegenCx<'ll, '_>, def_id: DefId, global
     let span = tcx.def_span(def_id);
 
     let (file_metadata, line_number) = if !span.is_dummy() {
-        let loc = span_start(cx, span);
-        (file_metadata(cx, &loc.file.name, LOCAL_CRATE), loc.line as c_uint)
+        let loc = cx.lookup_debug_loc(span.lo());
+        (file_metadata(cx, &loc.file.name, LOCAL_CRATE), loc.line)
     } else {
-        (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER)
+        (unknown_file_metadata(cx), None)
     };
 
     let is_local_to_unit = is_node_local_to_unit(cx, def_id);
     let variable_type = Instance::mono(cx.tcx, def_id).monomorphic_ty(cx.tcx);
     let type_metadata = type_metadata(cx, variable_type, span);
-    let var_name = SmallCStr::new(&tcx.item_name(def_id).as_str());
+    let var_name = tcx.item_name(def_id).as_str();
     let linkage_name = if no_mangle {
         None
     } else {
-        let linkage_name = mangled_name_of_instance(cx, Instance::mono(tcx, def_id));
-        Some(SmallCStr::new(&linkage_name.name.as_str()))
+        Some(mangled_name_of_instance(cx, Instance::mono(tcx, def_id)).name.as_str())
     };
+    // When empty, linkage_name field is omitted,
+    // which is what we want for no_mangle statics
+    let linkage_name = linkage_name.as_deref().unwrap_or("");
 
     let global_align = cx.align_of(variable_type);
 
@@ -2303,12 +2334,12 @@ pub fn create_global_var_metadata(cx: &CodegenCx<'ll, '_>, def_id: DefId, global
         llvm::LLVMRustDIBuilderCreateStaticVariable(
             DIB(cx),
             Some(var_scope),
-            var_name.as_ptr(),
-            // If null, linkage_name field is omitted,
-            // which is what we want for no_mangle statics
-            linkage_name.as_ref().map_or(ptr::null(), |name| name.as_ptr()),
+            var_name.as_ptr().cast(),
+            var_name.len(),
+            linkage_name.as_ptr().cast(),
+            linkage_name.len(),
             file_metadata,
-            line_number,
+            line_number.unwrap_or(UNKNOWN_LINE_NUMBER),
             type_metadata,
             is_local_to_unit,
             global,
@@ -2334,8 +2365,7 @@ pub fn create_vtable_metadata(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>, vtable: &
         // pointer will lead to hard to trace and debug LLVM assertions
         // later on in `llvm/lib/IR/Value.cpp`.
         let empty_array = create_DIArray(DIB(cx), &[]);
-
-        let name = const_cstr!("vtable");
+        let name = "vtable";
 
         // Create a new one each time. We don't want metadata caching
         // here, because each vtable will refer to a unique containing
@@ -2343,7 +2373,8 @@ pub fn create_vtable_metadata(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>, vtable: &
         let vtable_type = llvm::LLVMRustDIBuilderCreateStructType(
             DIB(cx),
             NO_SCOPE_METADATA,
-            name.as_ptr(),
+            name.as_ptr().cast(),
+            name.len(),
             unknown_file_metadata(cx),
             UNKNOWN_LINE_NUMBER,
             Size::ZERO.bits(),
@@ -2353,14 +2384,18 @@ pub fn create_vtable_metadata(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>, vtable: &
             empty_array,
             0,
             Some(type_metadata),
-            name.as_ptr(),
+            name.as_ptr().cast(),
+            name.len(),
         );
 
+        let linkage_name = "";
         llvm::LLVMRustDIBuilderCreateStaticVariable(
             DIB(cx),
             NO_SCOPE_METADATA,
-            name.as_ptr(),
-            ptr::null(),
+            name.as_ptr().cast(),
+            name.len(),
+            linkage_name.as_ptr().cast(),
+            linkage_name.len(),
             unknown_file_metadata(cx),
             UNKNOWN_LINE_NUMBER,
             vtable_type,
index 6515d5e3bec7ff655877dfdad89c2bd4875b4cc7..85decff35b9e054267083b0f9f1629774541516e 100644 (file)
@@ -3,16 +3,15 @@
 
 use rustc_codegen_ssa::mir::debuginfo::VariableKind::*;
 
-use self::metadata::{file_metadata, type_metadata, TypeMap};
+use self::metadata::{file_metadata, type_metadata, TypeMap, UNKNOWN_LINE_NUMBER};
 use self::namespace::mangled_name_of_instance;
 use self::type_names::compute_debuginfo_type_name;
-use self::utils::{create_DIArray, is_node_local_to_unit, span_start, DIB};
+use self::utils::{create_DIArray, is_node_local_to_unit, DIB};
 
 use crate::llvm;
 use crate::llvm::debuginfo::{
     DIArray, DIBuilder, DIFile, DIFlags, DILexicalBlock, DISPFlags, DIScope, DIType, DIVariable,
 };
-use rustc::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc::ty::subst::{GenericArgKind, SubstsRef};
 use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LOCAL_CRATE};
 
 use crate::common::CodegenCx;
 use crate::value::Value;
 use rustc::mir;
-use rustc::session::config::{self, DebugInfo};
-use rustc::ty::{self, Instance, InstanceDef, ParamEnv, Ty};
+use rustc::ty::{self, Instance, ParamEnv, Ty};
 use rustc_codegen_ssa::debuginfo::type_names;
 use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext, VariableKind};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_data_structures::small_c_str::SmallCStr;
 use rustc_index::vec::IndexVec;
+use rustc_session::config::{self, DebugInfo};
 
 use libc::c_uint;
 use log::debug;
 use std::cell::RefCell;
-use std::ffi::CString;
 
 use rustc::ty::layout::{self, HasTyCtxt, LayoutOf, Size};
 use rustc_ast::ast;
@@ -241,12 +238,6 @@ fn create_function_debug_context(
             return None;
         }
 
-        if let InstanceDef::Item(def_id) = instance.def {
-            if self.tcx().codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::NO_DEBUG) {
-                return None;
-            }
-        }
-
         let span = mir.span;
 
         // This can be the case for functions inlined from another crate
@@ -257,7 +248,7 @@ fn create_function_debug_context(
 
         let def_id = instance.def_id();
         let containing_scope = get_containing_scope(self, instance);
-        let loc = span_start(self, span);
+        let loc = self.lookup_debug_loc(span.lo());
         let file_metadata = file_metadata(self, &loc.file.name, def_id.krate);
 
         let function_type_metadata = unsafe {
@@ -280,13 +271,11 @@ fn create_function_debug_context(
 
         // Get the linkage_name, which is just the symbol name
         let linkage_name = mangled_name_of_instance(self, instance);
+        let linkage_name = linkage_name.name.as_str();
 
         // FIXME(eddyb) does this need to be separate from `loc.line` for some reason?
         let scope_line = loc.line;
 
-        let function_name = CString::new(name).unwrap();
-        let linkage_name = SmallCStr::new(&linkage_name.name.as_str());
-
         let mut flags = DIFlags::FlagPrototyped;
 
         if fn_abi.ret.layout.abi.is_uninhabited() {
@@ -310,12 +299,14 @@ fn create_function_debug_context(
             llvm::LLVMRustDIBuilderCreateFunction(
                 DIB(self),
                 containing_scope,
-                function_name.as_ptr(),
-                linkage_name.as_ptr(),
+                name.as_ptr().cast(),
+                name.len(),
+                linkage_name.as_ptr().cast(),
+                linkage_name.len(),
                 file_metadata,
-                loc.line as c_uint,
+                loc.line.unwrap_or(UNKNOWN_LINE_NUMBER),
                 function_type_metadata,
-                scope_line as c_uint,
+                scope_line.unwrap_or(UNKNOWN_LINE_NUMBER),
                 flags,
                 spflags,
                 llfn,
@@ -431,12 +422,13 @@ fn get_template_parameters<'ll, 'tcx>(
                                 cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty);
                             let actual_type_metadata =
                                 type_metadata(cx, actual_type, rustc_span::DUMMY_SP);
-                            let name = SmallCStr::new(&name.as_str());
+                            let name = name.as_str();
                             Some(unsafe {
                                 Some(llvm::LLVMRustDIBuilderCreateTemplateTypeParameter(
                                     DIB(cx),
                                     None,
-                                    name.as_ptr(),
+                                    name.as_ptr().cast(),
+                                    name.len(),
                                     actual_type_metadata,
                                     file_metadata,
                                     0,
@@ -538,7 +530,7 @@ fn create_dbg_var(
         variable_kind: VariableKind,
         span: Span,
     ) -> &'ll DIVariable {
-        let loc = span_start(self, span);
+        let loc = self.lookup_debug_loc(span.lo());
         let file_metadata = file_metadata(self, &loc.file.name, dbg_context.defining_crate);
 
         let type_metadata = type_metadata(self, variable_type, span);
@@ -549,15 +541,16 @@ fn create_dbg_var(
         };
         let align = self.align_of(variable_type);
 
-        let name = SmallCStr::new(&variable_name.as_str());
+        let name = variable_name.as_str();
         unsafe {
             llvm::LLVMRustDIBuilderCreateVariable(
                 DIB(self),
                 dwarf_tag,
                 scope_metadata,
-                name.as_ptr(),
+                name.as_ptr().cast(),
+                name.len(),
                 file_metadata,
-                loc.line as c_uint,
+                loc.line.unwrap_or(UNKNOWN_LINE_NUMBER),
                 type_metadata,
                 true,
                 DIFlags::FlagZero,
index 582f495207455d490dc957d4dad7a21ccbe5c4a9..55a3540809b487a35d924f37d3a11d566ae69b96 100644 (file)
@@ -1,6 +1,5 @@
 // Namespace Handling.
 
-use super::metadata::{unknown_file_metadata, UNKNOWN_LINE_NUMBER};
 use super::utils::{debug_context, DIB};
 use rustc::ty::{self, Instance};
 
@@ -10,8 +9,6 @@
 use rustc::hir::map::DefPathData;
 use rustc_hir::def_id::DefId;
 
-use rustc_data_structures::small_c_str::SmallCStr;
-
 pub fn mangled_name_of_instance<'a, 'tcx>(
     cx: &CodegenCx<'a, 'tcx>,
     instance: Instance<'tcx>,
@@ -34,16 +31,15 @@ pub fn item_namespace(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll DIScope {
         DefPathData::CrateRoot => cx.tcx.crate_name(def_id.krate),
         data => data.as_symbol(),
     };
-
-    let namespace_name = SmallCStr::new(&namespace_name.as_str());
+    let namespace_name = namespace_name.as_str();
 
     let scope = unsafe {
         llvm::LLVMRustDIBuilderCreateNameSpace(
             DIB(cx),
             parent_scope,
-            namespace_name.as_ptr(),
-            unknown_file_metadata(cx),
-            UNKNOWN_LINE_NUMBER,
+            namespace_name.as_ptr().cast(),
+            namespace_name.len(),
+            false, // ExportSymbols (only relevant for C++ anonymous namespaces)
         )
     };
 
index 1f871c7d207a41acc5dd160c9f9086f45b7bddcd..66ae9d72c3e5195fb1d10b462fd1cdfe6f965154 100644 (file)
@@ -1,32 +1,58 @@
-use super::metadata::UNKNOWN_COLUMN_NUMBER;
-use super::utils::{debug_context, span_start};
+use super::metadata::{UNKNOWN_COLUMN_NUMBER, UNKNOWN_LINE_NUMBER};
+use super::utils::debug_context;
 
 use crate::common::CodegenCx;
 use crate::llvm::debuginfo::DIScope;
 use crate::llvm::{self, Value};
 use rustc_codegen_ssa::traits::*;
 
-use libc::c_uint;
-use rustc_span::{Pos, Span};
+use rustc_data_structures::sync::Lrc;
+use rustc_span::{BytePos, Pos, SourceFile, SourceFileAndLine, Span};
+
+/// A source code location used to generate debug information.
+pub struct DebugLoc {
+    /// Information about the original source file.
+    pub file: Lrc<SourceFile>,
+    /// The (1-based) line number.
+    pub line: Option<u32>,
+    /// The (1-based) column number.
+    pub col: Option<u32>,
+}
 
 impl CodegenCx<'ll, '_> {
-    pub fn create_debug_loc(&self, scope: &'ll DIScope, span: Span) -> &'ll Value {
-        let loc = span_start(self, span);
+    /// Looks up debug source information about a `BytePos`.
+    pub fn lookup_debug_loc(&self, pos: BytePos) -> DebugLoc {
+        let (file, line, col) = match self.sess().source_map().lookup_line(pos) {
+            Ok(SourceFileAndLine { sf: file, line }) => {
+                let line_pos = file.line_begin_pos(pos);
+
+                // Use 1-based indexing.
+                let line = (line + 1) as u32;
+                let col = (pos - line_pos).to_u32() + 1;
+
+                (file, Some(line), Some(col))
+            }
+            Err(file) => (file, None, None),
+        };
 
-        // For MSVC, set the column number to zero.
+        // For MSVC, omit the column number.
         // Otherwise, emit it. This mimics clang behaviour.
         // See discussion in https://github.com/rust-lang/rust/issues/42921
-        let col_used = if self.sess().target.target.options.is_like_msvc {
-            UNKNOWN_COLUMN_NUMBER
+        if self.sess().target.target.options.is_like_msvc {
+            DebugLoc { file, line, col: None }
         } else {
-            loc.col.to_usize() as c_uint
-        };
+            DebugLoc { file, line, col }
+        }
+    }
+
+    pub fn create_debug_loc(&self, scope: &'ll DIScope, span: Span) -> &'ll Value {
+        let DebugLoc { line, col, .. } = self.lookup_debug_loc(span.lo());
 
         unsafe {
             llvm::LLVMRustDIBuilderCreateDebugLocation(
                 debug_context(self).llcontext,
-                loc.line as c_uint,
-                col_used,
+                line.unwrap_or(UNKNOWN_LINE_NUMBER),
+                col.unwrap_or(UNKNOWN_COLUMN_NUMBER),
                 scope,
                 None,
             )
index 4e17387e057f9ba85098b9cbc2204b178b16defd..bef40decdf3ab0912258c127cfe2d74d06fffdbf 100644 (file)
@@ -9,9 +9,6 @@
 use crate::common::CodegenCx;
 use crate::llvm;
 use crate::llvm::debuginfo::{DIArray, DIBuilder, DIDescriptor, DIScope};
-use rustc_codegen_ssa::traits::*;
-
-use rustc_span::Span;
 
 pub fn is_node_local_to_unit(cx: &CodegenCx<'_, '_>, def_id: DefId) -> bool {
     // The is_local_to_unit flag indicates whether a function is local to the
@@ -32,11 +29,6 @@ pub fn create_DIArray(builder: &DIBuilder<'ll>, arr: &[Option<&'ll DIDescriptor>
     };
 }
 
-/// Returns rustc_span::Loc corresponding to the beginning of the span
-pub fn span_start(cx: &CodegenCx<'_, '_>, span: Span) -> rustc_span::Loc {
-    cx.sess().source_map().lookup_char_pos(span.lo())
-}
-
 #[inline]
 pub fn debug_context(cx: &'a CodegenCx<'ll, 'tcx>) -> &'a CrateDebugContext<'ll, 'tcx> {
     cx.dbg_cx.as_ref().unwrap()
index 691f32dd85a05b8faee5ebc835fa9960107e7ee7..fab6321186b2c27363a34d60761a0724092f9861 100644 (file)
@@ -21,7 +21,6 @@
 use log::debug;
 use rustc::ty::Ty;
 use rustc_codegen_ssa::traits::*;
-use rustc_data_structures::small_c_str::SmallCStr;
 
 /// Declare a function.
 ///
@@ -34,8 +33,9 @@ fn declare_raw_fn(
     ty: &'ll Type,
 ) -> &'ll Value {
     debug!("declare_raw_fn(name={:?}, ty={:?})", name, ty);
-    let namebuf = SmallCStr::new(name);
-    let llfn = unsafe { llvm::LLVMRustGetOrInsertFunction(cx.llmod, namebuf.as_ptr(), ty) };
+    let llfn = unsafe {
+        llvm::LLVMRustGetOrInsertFunction(cx.llmod, name.as_ptr().cast(), name.len(), ty)
+    };
 
     llvm::SetFunctionCallConv(llfn, callconv);
     // Function addresses in Rust are never significant, allowing functions to
@@ -83,8 +83,7 @@ fn define_private_global(&self, ty: &'ll Type) -> &'ll Value {
 
     fn get_declared_value(&self, name: &str) -> Option<&'ll Value> {
         debug!("get_declared_value(name={:?})", name);
-        let namebuf = SmallCStr::new(name);
-        unsafe { llvm::LLVMRustGetNamedValue(self.llmod, namebuf.as_ptr()) }
+        unsafe { llvm::LLVMRustGetNamedValue(self.llmod, name.as_ptr().cast(), name.len()) }
     }
 
     fn get_defined_value(&self, name: &str) -> Option<&'ll Value> {
index 1ae9d2a6841316e4cd290f848dc68ba5e997ec72..1ddfde526fabde55d0804af63fad2ccde0044fa2 100644 (file)
@@ -195,26 +195,8 @@ fn codegen_intrinsic_call(
                     .unwrap();
                 OperandRef::from_const(self, ty_name, ret_ty).immediate_or_packed_pair(self)
             }
-            "init" => {
-                let ty = substs.type_at(0);
-                if !self.layout_of(ty).is_zst() {
-                    // Just zero out the stack slot.
-                    // If we store a zero constant, LLVM will drown in vreg allocation for large
-                    // data structures, and the generated code will be awful. (A telltale sign of
-                    // this is large quantities of `mov [byte ptr foo],0` in the generated code.)
-                    memset_intrinsic(
-                        self,
-                        false,
-                        ty,
-                        llresult,
-                        self.const_u8(0),
-                        self.const_usize(1),
-                    );
-                }
-                return;
-            }
-            // Effectively no-ops
-            "uninit" | "forget" => {
+            // Effectively no-op
+            "forget" => {
                 return;
             }
             "offset" => {
@@ -851,19 +833,21 @@ fn memset_intrinsic(
 
 fn try_intrinsic(
     bx: &mut Builder<'a, 'll, 'tcx>,
-    func: &'ll Value,
+    try_func: &'ll Value,
     data: &'ll Value,
-    local_ptr: &'ll Value,
+    catch_func: &'ll Value,
     dest: &'ll Value,
 ) {
     if bx.sess().no_landing_pads() {
-        bx.call(func, &[data], None);
-        let ptr_align = bx.tcx().data_layout.pointer_align.abi;
-        bx.store(bx.const_null(bx.type_i8p()), dest, ptr_align);
+        bx.call(try_func, &[data], None);
+        // Return 0 unconditionally from the intrinsic call;
+        // we can never unwind.
+        let ret_align = bx.tcx().data_layout.i32_align.abi;
+        bx.store(bx.const_i32(0), dest, ret_align);
     } else if wants_msvc_seh(bx.sess()) {
-        codegen_msvc_try(bx, func, data, local_ptr, dest);
+        codegen_msvc_try(bx, try_func, data, catch_func, dest);
     } else {
-        codegen_gnu_try(bx, func, data, local_ptr, dest);
+        codegen_gnu_try(bx, try_func, data, catch_func, dest);
     }
 }
 
@@ -876,9 +860,9 @@ fn try_intrinsic(
 // as the old ones are still more optimized.
 fn codegen_msvc_try(
     bx: &mut Builder<'a, 'll, 'tcx>,
-    func: &'ll Value,
+    try_func: &'ll Value,
     data: &'ll Value,
-    local_ptr: &'ll Value,
+    catch_func: &'ll Value,
     dest: &'ll Value,
 ) {
     let llfn = get_rust_try_fn(bx, &mut |mut bx| {
@@ -890,15 +874,15 @@ fn codegen_msvc_try(
         let mut catchpad = bx.build_sibling_block("catchpad");
         let mut caught = bx.build_sibling_block("caught");
 
-        let func = llvm::get_param(bx.llfn(), 0);
+        let try_func = llvm::get_param(bx.llfn(), 0);
         let data = llvm::get_param(bx.llfn(), 1);
-        let local_ptr = llvm::get_param(bx.llfn(), 2);
+        let catch_func = llvm::get_param(bx.llfn(), 2);
 
         // We're generating an IR snippet that looks like:
         //
-        //   declare i32 @rust_try(%func, %data, %ptr) {
-        //      %slot = alloca [2 x i64]
-        //      invoke %func(%data) to label %normal unwind label %catchswitch
+        //   declare i32 @rust_try(%try_func, %data, %catch_func) {
+        //      %slot = alloca u8*
+        //      invoke %try_func(%data) to label %normal unwind label %catchswitch
         //
         //   normal:
         //      ret i32 0
@@ -908,8 +892,8 @@ fn codegen_msvc_try(
         //
         //   catchpad:
         //      %tok = catchpad within %cs [%type_descriptor, 0, %slot]
-        //      %ptr[0] = %slot[0]
-        //      %ptr[1] = %slot[1]
+        //      %ptr = load %slot
+        //      call %catch_func(%data, %ptr)
         //      catchret from %tok to label %caught
         //
         //   caught:
@@ -926,32 +910,57 @@ fn codegen_msvc_try(
         //          ~rust_panic();
         //
         //          uint64_t x[2];
-        //      }
+        //      };
         //
-        //      int bar(void (*foo)(void), uint64_t *ret) {
+        //      int __rust_try(
+        //          void (*try_func)(void*),
+        //          void *data,
+        //          void (*catch_func)(void*, void*) noexcept
+        //      ) {
         //          try {
-        //              foo();
+        //              try_func(data);
         //              return 0;
         //          } catch(rust_panic& a) {
-        //              ret[0] = a.x[0];
-        //              ret[1] = a.x[1];
-        //              a.x[0] = 0;
+        //              catch_func(data, &a);
         //              return 1;
         //          }
         //      }
         //
         // More information can be found in libstd's seh.rs implementation.
-        let i64_2 = bx.type_array(bx.type_i64(), 2);
-        let i64_2_ptr = bx.type_ptr_to(i64_2);
         let ptr_align = bx.tcx().data_layout.pointer_align.abi;
-        let slot = bx.alloca(i64_2_ptr, ptr_align);
-        bx.invoke(func, &[data], normal.llbb(), catchswitch.llbb(), None);
+        let slot = bx.alloca(bx.type_i8p(), ptr_align);
+        bx.invoke(try_func, &[data], normal.llbb(), catchswitch.llbb(), None);
 
         normal.ret(bx.const_i32(0));
 
         let cs = catchswitch.catch_switch(None, None, 1);
         catchswitch.add_handler(cs, catchpad.llbb());
 
+        // We can't use the TypeDescriptor defined in libpanic_unwind because it
+        // might be in another DLL and the SEH encoding only supports specifying
+        // a TypeDescriptor from the current module.
+        //
+        // However this isn't an issue since the MSVC runtime uses string
+        // comparison on the type name to match TypeDescriptors rather than
+        // pointer equality.
+        //
+        // So instead we generate a new TypeDescriptor in each module that uses
+        // `try` and let the linker merge duplicate definitions in the same
+        // module.
+        //
+        // When modifying, make sure that the type_name string exactly matches
+        // the one used in src/libpanic_unwind/seh.rs.
+        let type_info_vtable = bx.declare_global("??_7type_info@@6B@", bx.type_i8p());
+        let type_name = bx.const_bytes(b"rust_panic\0");
+        let type_info =
+            bx.const_struct(&[type_info_vtable, bx.const_null(bx.type_i8p()), type_name], false);
+        let tydesc = bx.declare_global("__rust_panic_type_info", bx.val_ty(type_info));
+        unsafe {
+            llvm::LLVMRustSetLinkage(tydesc, llvm::Linkage::LinkOnceODRLinkage);
+            llvm::SetUniqueComdat(bx.llmod, tydesc);
+            llvm::LLVMSetInitializer(tydesc, type_info);
+        }
+
         // The flag value of 8 indicates that we are catching the exception by
         // reference instead of by value. We can't use catch by value because
         // that requires copying the exception object, which we don't support
@@ -959,23 +968,9 @@ fn codegen_msvc_try(
         //
         // Source: MicrosoftCXXABI::getAddrOfCXXCatchHandlerType in clang
         let flags = bx.const_i32(8);
-        let tydesc = match bx.tcx().lang_items().eh_catch_typeinfo() {
-            Some(did) => bx.get_static(did),
-            None => bug!("eh_catch_typeinfo not defined, but needed for SEH unwinding"),
-        };
         let funclet = catchpad.catch_pad(cs, &[tydesc, flags, slot]);
-
-        let i64_align = bx.tcx().data_layout.i64_align.abi;
-        let payload_ptr = catchpad.load(slot, ptr_align);
-        let payload = catchpad.load(payload_ptr, i64_align);
-        let local_ptr = catchpad.bitcast(local_ptr, bx.type_ptr_to(i64_2));
-        catchpad.store(payload, local_ptr, i64_align);
-
-        // Clear the first word of the exception so avoid double-dropping it.
-        // This will be read by the destructor which is implicitly called at the
-        // end of the catch block by the runtime.
-        let payload_0_ptr = catchpad.inbounds_gep(payload_ptr, &[bx.const_i32(0), bx.const_i32(0)]);
-        catchpad.store(bx.const_u64(0), payload_0_ptr, i64_align);
+        let ptr = catchpad.load(slot, ptr_align);
+        catchpad.call(catch_func, &[data, ptr], Some(&funclet));
 
         catchpad.catch_ret(&funclet, caught.llbb());
 
@@ -984,7 +979,7 @@ fn codegen_msvc_try(
 
     // Note that no invoke is used here because by definition this function
     // can't panic (that's what it's catching).
-    let ret = bx.call(llfn, &[func, data, local_ptr], None);
+    let ret = bx.call(llfn, &[try_func, data, catch_func], None);
     let i32_align = bx.tcx().data_layout.i32_align.abi;
     bx.store(ret, dest, i32_align);
 }
@@ -1002,38 +997,34 @@ fn codegen_msvc_try(
 // the right personality function.
 fn codegen_gnu_try(
     bx: &mut Builder<'a, 'll, 'tcx>,
-    func: &'ll Value,
+    try_func: &'ll Value,
     data: &'ll Value,
-    local_ptr: &'ll Value,
+    catch_func: &'ll Value,
     dest: &'ll Value,
 ) {
     let llfn = get_rust_try_fn(bx, &mut |mut bx| {
         // Codegens the shims described above:
         //
         //   bx:
-        //      invoke %func(%args...) normal %normal unwind %catch
+        //      invoke %try_func(%data) normal %normal unwind %catch
         //
         //   normal:
         //      ret 0
         //
         //   catch:
-        //      (ptr, _) = landingpad
-        //      store ptr, %local_ptr
+        //      (%ptr, _) = landingpad
+        //      call %catch_func(%data, %ptr)
         //      ret 1
-        //
-        // Note that the `local_ptr` data passed into the `try` intrinsic is
-        // 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");
 
-        let func = llvm::get_param(bx.llfn(), 0);
+        let try_func = llvm::get_param(bx.llfn(), 0);
         let data = llvm::get_param(bx.llfn(), 1);
-        let local_ptr = llvm::get_param(bx.llfn(), 2);
-        bx.invoke(func, &[data], then.llbb(), catch.llbb(), None);
+        let catch_func = llvm::get_param(bx.llfn(), 2);
+        bx.invoke(try_func, &[data], then.llbb(), catch.llbb(), None);
         then.ret(bx.const_i32(0));
 
         // Type indicator for the exception being thrown.
@@ -1053,15 +1044,13 @@ fn codegen_gnu_try(
         };
         catch.add_clause(vals, tydesc);
         let ptr = catch.extract_value(vals, 0);
-        let ptr_align = bx.tcx().data_layout.pointer_align.abi;
-        let bitcast = catch.bitcast(local_ptr, bx.type_ptr_to(bx.type_i8p()));
-        catch.store(ptr, bitcast, ptr_align);
+        catch.call(catch_func, &[data, ptr], None);
         catch.ret(bx.const_i32(1));
     });
 
     // Note that no invoke is used here because by definition this function
     // can't panic (that's what it's catching).
-    let ret = bx.call(llfn, &[func, data, local_ptr], None);
+    let ret = bx.call(llfn, &[try_func, data, catch_func], None);
     let i32_align = bx.tcx().data_layout.i32_align.abi;
     bx.store(ret, dest, i32_align);
 }
@@ -1084,6 +1073,8 @@ fn gen_fn<'ll, 'tcx>(
     ));
     let fn_abi = FnAbi::of_fn_ptr(cx, rust_fn_sig, &[]);
     let llfn = cx.declare_fn(name, &fn_abi);
+    cx.set_frame_pointer_elimination(llfn);
+    cx.apply_target_cpu_attr(llfn);
     // FIXME(eddyb) find a nicer way to do this.
     unsafe { llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::InternalLinkage) };
     let bx = Builder::new_block(cx, llfn, "entry-block");
@@ -1106,15 +1097,22 @@ fn get_rust_try_fn<'ll, 'tcx>(
     // Define the type up front for the signature of the rust_try function.
     let tcx = cx.tcx;
     let i8p = tcx.mk_mut_ptr(tcx.types.i8);
-    let fn_ty = tcx.mk_fn_ptr(ty::Binder::bind(tcx.mk_fn_sig(
+    let try_fn_ty = tcx.mk_fn_ptr(ty::Binder::bind(tcx.mk_fn_sig(
         iter::once(i8p),
         tcx.mk_unit(),
         false,
         hir::Unsafety::Unsafe,
         Abi::Rust,
     )));
+    let catch_fn_ty = tcx.mk_fn_ptr(ty::Binder::bind(tcx.mk_fn_sig(
+        [i8p, i8p].iter().cloned(),
+        tcx.mk_unit(),
+        false,
+        hir::Unsafety::Unsafe,
+        Abi::Rust,
+    )));
     let output = tcx.types.i32;
-    let rust_try = gen_fn(cx, "__rust_try", vec![fn_ty, i8p, i8p], output, codegen);
+    let rust_try = gen_fn(cx, "__rust_try", vec![try_fn_ty, i8p, catch_fn_ty], output, codegen);
     cx.rust_try_fn.set(Some(rust_try));
     rust_try
 }
index f32657545745f74554ce2e0295c5f1ec0a34ec63..fa730d289b16bca1dd37c2e3046087a9ec12c4f8 100644 (file)
 #![recursion_limit = "256"]
 
 use back::write::{create_informational_target_machine, create_target_machine};
-use rustc_span::symbol::Symbol;
 
 pub use llvm_util::target_features;
-use rustc::dep_graph::WorkProduct;
+use rustc::dep_graph::{DepGraph, WorkProduct};
+use rustc::middle::cstore::{EncodedMetadata, MetadataLoaderDyn};
+use rustc::ty::{self, TyCtxt};
+use rustc::util::common::ErrorReported;
 use rustc_ast::expand::allocator::AllocatorKind;
 use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule};
 use rustc_codegen_ssa::back::write::{CodegenContext, FatLTOInput, ModuleConfig};
 use rustc_codegen_ssa::traits::*;
+use rustc_codegen_ssa::ModuleCodegen;
 use rustc_codegen_ssa::{CodegenResults, CompiledModule};
+use rustc_codegen_utils::codegen_backend::CodegenBackend;
 use rustc_errors::{FatalError, Handler};
+use rustc_serialize::json;
+use rustc_session::config::{self, OptLevel, OutputFilenames, PrintRequest};
+use rustc_session::Session;
+use rustc_span::symbol::Symbol;
+
 use std::any::Any;
 use std::ffi::CStr;
 use std::fs;
 use std::sync::Arc;
 
-use rustc::dep_graph::DepGraph;
-use rustc::middle::cstore::{EncodedMetadata, MetadataLoaderDyn};
-use rustc::session::config::{self, OptLevel, OutputFilenames, PrintRequest};
-use rustc::session::Session;
-use rustc::ty::{self, TyCtxt};
-use rustc::util::common::ErrorReported;
-use rustc_codegen_ssa::ModuleCodegen;
-use rustc_codegen_utils::codegen_backend::CodegenBackend;
-use rustc_serialize::json;
-
 mod back {
     pub mod archive;
     pub mod bytecode;
index f56647044e08b2b7014f6b50911390eea7949f01..c17c06718f506a3f82dac0c51a8477a64a031883 100644 (file)
@@ -694,8 +694,8 @@ pub enum DebugEmissionKind {
     }
 
     impl DebugEmissionKind {
-        pub fn from_generic(kind: rustc::session::config::DebugInfo) -> Self {
-            use rustc::session::config::DebugInfo;
+        pub fn from_generic(kind: rustc_session::config::DebugInfo) -> Self {
+            use rustc_session::config::DebugInfo;
             match kind {
                 DebugInfo::None => DebugEmissionKind::NoDebug,
                 DebugInfo::Limited => DebugEmissionKind::LineTablesOnly,
@@ -732,7 +732,7 @@ pub fn from_generic(kind: rustc::session::config::DebugInfo) -> Self {
 
     /// See Module::setModuleInlineAsm.
     pub fn LLVMSetModuleInlineAsm(M: &Module, Asm: *const c_char);
-    pub fn LLVMRustAppendModuleInlineAsm(M: &Module, Asm: *const c_char);
+    pub fn LLVMRustAppendModuleInlineAsm(M: &Module, Asm: *const c_char, AsmLen: size_t);
 
     /// See llvm::LLVMTypeKind::getTypeID.
     pub fn LLVMRustGetTypeKind(Ty: &Type) -> TypeKind;
@@ -879,13 +879,18 @@ pub fn LLVMRustGetOrInsertGlobal(
     pub fn LLVMSetThreadLocalMode(GlobalVar: &Value, Mode: ThreadLocalMode);
     pub fn LLVMIsGlobalConstant(GlobalVar: &Value) -> Bool;
     pub fn LLVMSetGlobalConstant(GlobalVar: &Value, IsConstant: Bool);
-    pub fn LLVMRustGetNamedValue(M: &Module, Name: *const c_char) -> Option<&Value>;
+    pub fn LLVMRustGetNamedValue(
+        M: &Module,
+        Name: *const c_char,
+        NameLen: size_t,
+    ) -> Option<&Value>;
     pub fn LLVMSetTailCall(CallInst: &Value, IsTailCall: Bool);
 
     // Operations on functions
     pub fn LLVMRustGetOrInsertFunction(
         M: &'a Module,
         Name: *const c_char,
+        NameLen: size_t,
         FunctionTy: &'a Type,
     ) -> &'a Value;
     pub fn LLVMSetFunctionCallConv(Fn: &Value, CC: c_uint);
@@ -1332,7 +1337,6 @@ pub fn LLVMRustBuildCall(
         Args: *const &'a Value,
         NumArgs: c_uint,
         Bundle: Option<&OperandBundleDef<'a>>,
-        Name: *const c_char,
     ) -> &'a Value;
     pub fn LLVMRustBuildMemCpy(
         B: &Builder<'a>,
@@ -1581,12 +1585,18 @@ pub fn LLVMStructSetBody(
     pub fn LLVMRustInlineAsm(
         Ty: &Type,
         AsmString: *const c_char,
+        AsmStringLen: size_t,
         Constraints: *const c_char,
+        ConstraintsLen: size_t,
         SideEffects: Bool,
         AlignStack: Bool,
         Dialect: AsmDialect,
     ) -> &Value;
-    pub fn LLVMRustInlineAsmVerify(Ty: &Type, Constraints: *const c_char) -> bool;
+    pub fn LLVMRustInlineAsmVerify(
+        Ty: &Type,
+        Constraints: *const c_char,
+        ConstraintsLen: size_t,
+    ) -> bool;
 
     pub fn LLVMRustDebugMetadataVersion() -> u32;
     pub fn LLVMRustVersionMajor() -> u32;
@@ -1607,17 +1617,21 @@ pub fn LLVMRustDIBuilderCreateCompileUnit(
         Lang: c_uint,
         File: &'a DIFile,
         Producer: *const c_char,
+        ProducerLen: size_t,
         isOptimized: bool,
         Flags: *const c_char,
         RuntimeVer: c_uint,
         SplitName: *const c_char,
+        SplitNameLen: size_t,
         kind: DebugEmissionKind,
     ) -> &'a DIDescriptor;
 
     pub fn LLVMRustDIBuilderCreateFile(
         Builder: &DIBuilder<'a>,
         Filename: *const c_char,
+        FilenameLen: size_t,
         Directory: *const c_char,
+        DirectoryLen: size_t,
     ) -> &'a DIFile;
 
     pub fn LLVMRustDIBuilderCreateSubroutineType(
@@ -1630,7 +1644,9 @@ pub fn LLVMRustDIBuilderCreateFunction(
         Builder: &DIBuilder<'a>,
         Scope: &'a DIDescriptor,
         Name: *const c_char,
+        NameLen: size_t,
         LinkageName: *const c_char,
+        LinkageNameLen: size_t,
         File: &'a DIFile,
         LineNo: c_uint,
         Ty: &'a DIType,
@@ -1645,6 +1661,7 @@ pub fn LLVMRustDIBuilderCreateFunction(
     pub fn LLVMRustDIBuilderCreateBasicType(
         Builder: &DIBuilder<'a>,
         Name: *const c_char,
+        NameLen: size_t,
         SizeInBits: u64,
         AlignInBits: u32,
         Encoding: c_uint,
@@ -1655,13 +1672,16 @@ pub fn LLVMRustDIBuilderCreatePointerType(
         PointeeTy: &'a DIType,
         SizeInBits: u64,
         AlignInBits: u32,
+        AddressSpace: c_uint,
         Name: *const c_char,
+        NameLen: size_t,
     ) -> &'a DIDerivedType;
 
     pub fn LLVMRustDIBuilderCreateStructType(
         Builder: &DIBuilder<'a>,
         Scope: Option<&'a DIDescriptor>,
         Name: *const c_char,
+        NameLen: size_t,
         File: &'a DIFile,
         LineNumber: c_uint,
         SizeInBits: u64,
@@ -1672,12 +1692,14 @@ pub fn LLVMRustDIBuilderCreateStructType(
         RunTimeLang: c_uint,
         VTableHolder: Option<&'a DIType>,
         UniqueId: *const c_char,
+        UniqueIdLen: size_t,
     ) -> &'a DICompositeType;
 
     pub fn LLVMRustDIBuilderCreateMemberType(
         Builder: &DIBuilder<'a>,
         Scope: &'a DIDescriptor,
         Name: *const c_char,
+        NameLen: size_t,
         File: &'a DIFile,
         LineNo: c_uint,
         SizeInBits: u64,
@@ -1691,6 +1713,7 @@ pub fn LLVMRustDIBuilderCreateVariantMemberType(
         Builder: &DIBuilder<'a>,
         Scope: &'a DIScope,
         Name: *const c_char,
+        NameLen: size_t,
         File: &'a DIFile,
         LineNumber: c_uint,
         SizeInBits: u64,
@@ -1719,7 +1742,9 @@ pub fn LLVMRustDIBuilderCreateStaticVariable(
         Builder: &DIBuilder<'a>,
         Context: Option<&'a DIScope>,
         Name: *const c_char,
+        NameLen: size_t,
         LinkageName: *const c_char,
+        LinkageNameLen: size_t,
         File: &'a DIFile,
         LineNo: c_uint,
         Ty: &'a DIType,
@@ -1734,6 +1759,7 @@ pub fn LLVMRustDIBuilderCreateVariable(
         Tag: c_uint,
         Scope: &'a DIDescriptor,
         Name: *const c_char,
+        NameLen: size_t,
         File: &'a DIFile,
         LineNo: c_uint,
         Ty: &'a DIType,
@@ -1776,13 +1802,16 @@ pub fn LLVMRustDIBuilderInsertDeclareAtEnd(
     pub fn LLVMRustDIBuilderCreateEnumerator(
         Builder: &DIBuilder<'a>,
         Name: *const c_char,
-        Val: u64,
+        NameLen: size_t,
+        Value: i64,
+        IsUnsigned: bool,
     ) -> &'a DIEnumerator;
 
     pub fn LLVMRustDIBuilderCreateEnumerationType(
         Builder: &DIBuilder<'a>,
         Scope: &'a DIScope,
         Name: *const c_char,
+        NameLen: size_t,
         File: &'a DIFile,
         LineNumber: c_uint,
         SizeInBits: u64,
@@ -1796,6 +1825,7 @@ pub fn LLVMRustDIBuilderCreateUnionType(
         Builder: &DIBuilder<'a>,
         Scope: &'a DIScope,
         Name: *const c_char,
+        NameLen: size_t,
         File: &'a DIFile,
         LineNumber: c_uint,
         SizeInBits: u64,
@@ -1804,12 +1834,14 @@ pub fn LLVMRustDIBuilderCreateUnionType(
         Elements: Option<&'a DIArray>,
         RunTimeLang: c_uint,
         UniqueId: *const c_char,
+        UniqueIdLen: size_t,
     ) -> &'a DIType;
 
     pub fn LLVMRustDIBuilderCreateVariantPart(
         Builder: &DIBuilder<'a>,
         Scope: &'a DIScope,
         Name: *const c_char,
+        NameLen: size_t,
         File: &'a DIFile,
         LineNo: c_uint,
         SizeInBits: u64,
@@ -1818,6 +1850,7 @@ pub fn LLVMRustDIBuilderCreateVariantPart(
         Discriminator: Option<&'a DIDerivedType>,
         Elements: &'a DIArray,
         UniqueId: *const c_char,
+        UniqueIdLen: size_t,
     ) -> &'a DIDerivedType;
 
     pub fn LLVMSetUnnamedAddr(GlobalVar: &Value, UnnamedAddr: Bool);
@@ -1826,6 +1859,7 @@ pub fn LLVMRustDIBuilderCreateTemplateTypeParameter(
         Builder: &DIBuilder<'a>,
         Scope: Option<&'a DIScope>,
         Name: *const c_char,
+        NameLen: size_t,
         Ty: &'a DIType,
         File: &'a DIFile,
         LineNo: c_uint,
@@ -1836,8 +1870,8 @@ pub fn LLVMRustDIBuilderCreateNameSpace(
         Builder: &DIBuilder<'a>,
         Scope: Option<&'a DIScope>,
         Name: *const c_char,
-        File: &'a DIFile,
-        LineNo: c_uint,
+        NameLen: size_t,
+        ExportSymbols: bool,
     ) -> &'a DINameSpace;
 
     pub fn LLVMRustDICompositeTypeReplaceArrays(
index 96014cbee5da1cdc0b288b14b756dfcfaa64a4a3..a083e14979c0b8dc82aad3c506de774f37d02aec 100644 (file)
@@ -185,12 +185,12 @@ fn drop(&mut self) {
     }
 }
 
-pub fn mk_section_iter(llof: &'a ffi::ObjectFile) -> SectionIter<'a> {
+pub fn mk_section_iter(llof: &ffi::ObjectFile) -> SectionIter<'_> {
     unsafe { SectionIter { llsi: LLVMGetSections(llof) } }
 }
 
 /// Safe wrapper around `LLVMGetParam`, because segfaults are no fun.
-pub fn get_param(llfn: &'a Value, index: c_uint) -> &'a Value {
+pub fn get_param(llfn: &Value, index: c_uint) -> &Value {
     unsafe {
         assert!(
             index < LLVMCountParams(llfn),
@@ -203,7 +203,7 @@ pub fn get_param(llfn: &'a Value, index: c_uint) -> &'a Value {
 }
 
 /// Safe wrapper for `LLVMGetValueName2` into a byte slice
-pub fn get_value_name(value: &'a Value) -> &'a [u8] {
+pub fn get_value_name(value: &Value) -> &[u8] {
     unsafe {
         let mut len = 0;
         let data = LLVMGetValueName2(value, &mut len);
index 0081a75a4da11b13b558c939a91f8d94b20fc8a8..5e924c9af8481457d5a9af061676ac8844494e10 100644 (file)
@@ -2,10 +2,10 @@
 use crate::llvm;
 use libc::c_int;
 use rustc::bug;
-use rustc::session::config::PrintRequest;
-use rustc::session::Session;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_feature::UnstableFeatures;
+use rustc_session::config::PrintRequest;
+use rustc_session::Session;
 use rustc_span::symbol::sym;
 use rustc_span::symbol::Symbol;
 use rustc_target::spec::{MergeFunctions, PanicStrategy};
index aacaf130f9aa98bb89093163dbb225ea6319e6e9..5bc1475df23a7ff89a5a08a24e3dd5785d3667b8 100644 (file)
@@ -240,7 +240,7 @@ pub fn ix_llcx(llcx: &llvm::Context, num_bits: u64) -> &Type {
         unsafe { llvm::LLVMIntTypeInContext(llcx, num_bits as c_uint) }
     }
 
-    pub fn i8p_llcx(llcx: &'ll llvm::Context) -> &'ll Type {
+    pub fn i8p_llcx(llcx: &llvm::Context) -> &Type {
         Type::i8_llcx(llcx).ptr_to()
     }
 
index 9bc3eec60ae044702770bc6642e7a68b173c2b26..a552f2cdb78aaf268a4d11bdfc0f909dc9632e67 100644 (file)
@@ -117,8 +117,7 @@ pub(super) fn emit_va_arg(
         // Windows x86_64
         ("x86_64", true) => {
             let target_ty_size = bx.cx.size_of(target_ty).bytes();
-            let indirect =
-                if target_ty_size > 8 || !target_ty_size.is_power_of_two() { true } else { false };
+            let indirect: bool = target_ty_size > 8 || !target_ty_size.is_power_of_two();
             emit_ptr_va_arg(bx, addr, target_ty, indirect, Align::from_bytes(8).unwrap(), false)
         }
         // For all other architecture/OS combinations fall back to using
index 2a3a4fcc5fca4452c77504831765b11739591e33..90d991a3a4b25d7a11468546024a89ec84b37afb 100644 (file)
@@ -1,3 +1,3 @@
-Please read the rustc-guide chapter on [Backend Agnostic Codegen][bac].
+Please read the rustc-dev-guide chapter on [Backend Agnostic Codegen][bac].
 
-[bac]: https://rust-lang.github.io/rustc-guide/codegen/backend-agnostic.html
+[bac]: https://rustc-dev-guide.rust-lang.org/codegen/backend-agnostic.html
index a357c350287fbc1ae19b4e72247e75b4f6c805d9..f83b4b2b0c025adb24d3c9c76fb45b42ae1a9020 100644 (file)
@@ -1,4 +1,4 @@
-use rustc::session::Session;
+use rustc_session::Session;
 use rustc_span::symbol::Symbol;
 
 use std::io;
index 90601521b19f1f65f2ddd83096879082b1816bd1..af413d3cdfe6862ec25013ae7f902500101b4098 100644 (file)
@@ -1,15 +1,15 @@
 use rustc::middle::cstore::{EncodedMetadata, LibSource, NativeLibrary, NativeLibraryKind};
 use rustc::middle::dependency_format::Linkage;
-use rustc::session::config::{
+use rustc_data_structures::fx::FxHashSet;
+use rustc_fs_util::fix_windows_verbatim_for_gcc;
+use rustc_hir::def_id::CrateNum;
+use rustc_session::config::{
     self, CFGuard, DebugInfo, OutputFilenames, OutputType, PrintRequest, Sanitizer,
 };
-use rustc::session::search_paths::PathKind;
+use rustc_session::search_paths::PathKind;
 /// For all the linkers we support, and information they might
 /// need out of the shared crate context before we get rid of it.
-use rustc::session::{filesearch, Session};
-use rustc_data_structures::fx::FxHashSet;
-use rustc_fs_util::fix_windows_verbatim_for_gcc;
-use rustc_hir::def_id::CrateNum;
+use rustc_session::{filesearch, Session};
 use rustc_span::symbol::Symbol;
 use rustc_target::spec::{LinkerFlavor, PanicStrategy, RelroLevel};
 
@@ -186,7 +186,7 @@ pub fn get_linker(sess: &Session, linker: &Path, flavor: LinkerFlavor) -> (PathB
     if flavor == LinkerFlavor::Msvc && t.target_vendor == "uwp" {
         if let Some(ref tool) = msvc_tool {
             let original_path = tool.path();
-            if let Some(ref root_lib_path) = original_path.ancestors().skip(4).next() {
+            if let Some(ref root_lib_path) = original_path.ancestors().nth(4) {
                 let arch = match t.arch.as_str() {
                     "x86_64" => Some("x64".to_string()),
                     "x86" => Some("x86".to_string()),
@@ -490,6 +490,11 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>(
     info!("preparing {:?} to {:?}", crate_type, out_filename);
     let (linker, flavor) = linker_and_flavor(sess);
 
+    let any_dynamic_crate = crate_type == config::CrateType::Dylib
+        || codegen_results.crate_info.dependency_formats.iter().any(|(ty, list)| {
+            *ty == crate_type && list.iter().any(|&linkage| linkage == Linkage::Dynamic)
+        });
+
     // The invocations of cc share some flags across platforms
     let (pname, mut cmd) = get_linker(sess, &linker, flavor);
 
@@ -497,7 +502,7 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>(
         cmd.args(args);
     }
     if let Some(args) = sess.target.target.options.pre_link_args_crt.get(&flavor) {
-        if sess.crt_static() {
+        if sess.crt_static(Some(crate_type)) {
             cmd.args(args);
         }
     }
@@ -523,7 +528,7 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>(
         cmd.arg(get_file_path(sess, obj));
     }
 
-    if crate_type == config::CrateType::Executable && sess.crt_static() {
+    if crate_type == config::CrateType::Executable && sess.crt_static(Some(crate_type)) {
         for obj in &sess.target.target.options.pre_link_objects_exe_crt {
             cmd.arg(get_file_path(sess, obj));
         }
@@ -555,10 +560,19 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>(
     if let Some(args) = sess.target.target.options.late_link_args.get(&flavor) {
         cmd.args(args);
     }
+    if any_dynamic_crate {
+        if let Some(args) = sess.target.target.options.late_link_args_dynamic.get(&flavor) {
+            cmd.args(args);
+        }
+    } else {
+        if let Some(args) = sess.target.target.options.late_link_args_static.get(&flavor) {
+            cmd.args(args);
+        }
+    }
     for obj in &sess.target.target.options.post_link_objects {
         cmd.arg(get_file_path(sess, obj));
     }
-    if sess.crt_static() {
+    if sess.crt_static(Some(crate_type)) {
         for obj in &sess.target.target.options.post_link_objects_crt {
             cmd.arg(get_file_path(sess, obj));
         }
@@ -1288,7 +1302,8 @@ fn link_args<'a, B: ArchiveBuilder<'a>>(
             let more_args = &sess.opts.cg.link_arg;
             let mut args = args.iter().chain(more_args.iter()).chain(used_link_args.iter());
 
-            if is_pic(sess) && !sess.crt_static() && !args.any(|x| *x == "-static") {
+            if is_pic(sess) && !sess.crt_static(Some(crate_type)) && !args.any(|x| *x == "-static")
+            {
                 position_independent_executable = true;
             }
         }
@@ -1373,7 +1388,7 @@ fn link_args<'a, B: ArchiveBuilder<'a>>(
     if crate_type != config::CrateType::Executable {
         cmd.build_dylib(out_filename);
     }
-    if crate_type == config::CrateType::Executable && sess.crt_static() {
+    if crate_type == config::CrateType::Executable && sess.crt_static(Some(crate_type)) {
         cmd.build_static_executable();
     }
 
@@ -1519,17 +1534,25 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(
     // for the current implementation of the standard library.
     let mut group_end = None;
     let mut group_start = None;
-    let mut end_with = FxHashSet::default();
+    // Crates available for linking thus far.
+    let mut available = FxHashSet::default();
+    // Crates required to satisfy dependencies discovered so far.
+    let mut required = FxHashSet::default();
+
     let info = &codegen_results.crate_info;
     for &(cnum, _) in deps.iter().rev() {
         if let Some(missing) = info.missing_lang_items.get(&cnum) {
-            end_with.extend(missing.iter().cloned());
-            if !end_with.is_empty() && group_end.is_none() {
-                group_end = Some(cnum);
-            }
+            let missing_crates = missing.iter().map(|i| info.lang_item_to_crate.get(i).copied());
+            required.extend(missing_crates);
+        }
+
+        required.insert(Some(cnum));
+        available.insert(Some(cnum));
+
+        if required.len() > available.len() && group_end.is_none() {
+            group_end = Some(cnum);
         }
-        end_with.retain(|item| info.lang_item_to_crate.get(item) != Some(&cnum));
-        if end_with.is_empty() && group_end.is_some() {
+        if required.len() == available.len() && group_end.is_some() {
             group_start = Some(cnum);
             break;
         }
index 5aafb8a12d74b261d4ba0eeeb92d7b85f4cfa4f0..6b30ae8559db9e146d95f1587b7126a4eae6521a 100644 (file)
@@ -2,7 +2,6 @@
 use super::command::Command;
 use super::symbol_export;
 
-use rustc_data_structures::fx::FxHashMap;
 use std::ffi::{OsStr, OsString};
 use std::fs::{self, File};
 use std::io::prelude::*;
 use std::path::{Path, PathBuf};
 
 use rustc::middle::dependency_format::Linkage;
-use rustc::session::config::{self, CrateType, DebugInfo, LinkerPluginLto, Lto, OptLevel};
-use rustc::session::Session;
 use rustc::ty::TyCtxt;
+use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
 use rustc_serialize::{json, Encoder};
+use rustc_session::config::{self, CrateType, DebugInfo, LinkerPluginLto, Lto, OptLevel};
+use rustc_session::Session;
 use rustc_span::symbol::Symbol;
 use rustc_target::spec::{LinkerFlavor, LldFlavor};
 
index 3fe256ce25b964a505aad1fc4f58392efc868b2c..8368d98884a5d5dfccde1621dec110fc42c7584c 100644 (file)
@@ -3,7 +3,6 @@
 
 use rustc::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc::middle::exported_symbols::{metadata_symbol_name, ExportedSymbol, SymbolExportLevel};
-use rustc::session::config::{self, Sanitizer};
 use rustc::ty::query::Providers;
 use rustc::ty::subst::{GenericArgKind, SubstsRef};
 use rustc::ty::Instance;
@@ -16,6 +15,7 @@
 use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_hir::Node;
 use rustc_index::vec::IndexVec;
+use rustc_session::config::{self, Sanitizer};
 
 pub fn threshold(tcx: TyCtxt<'_>) -> SymbolExportLevel {
     crates_export_threshold(&tcx.sess.crate_types.borrow())
@@ -88,7 +88,7 @@ fn reachable_non_generics_provider(
                 // Only consider nodes that actually have exported symbols.
                 Node::Item(&hir::Item { kind: hir::ItemKind::Static(..), .. })
                 | Node::Item(&hir::Item { kind: hir::ItemKind::Fn(..), .. })
-                | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Method(..), .. }) => {
+                | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }) => {
                     let def_id = tcx.hir().local_def_id(hir_id);
                     let generics = tcx.generics_of(def_id);
                     if !generics.requires_monomorphization(tcx) &&
index 76728e9840616364334f61682ffcf5381efdef9b..303ee385658480c4063ddf151306afe028db85bd 100644 (file)
 use rustc::dep_graph::{WorkProduct, WorkProductFileKind, WorkProductId};
 use rustc::middle::cstore::EncodedMetadata;
 use rustc::middle::exported_symbols::SymbolExportLevel;
-use rustc::session::config::{
-    self, Lto, OutputFilenames, OutputType, Passes, Sanitizer, SwitchWithOptPath,
-};
-use rustc::session::Session;
 use rustc::ty::TyCtxt;
 use rustc_ast::attr;
 use rustc_data_structures::fx::FxHashMap;
     copy_cgu_workproducts_to_incr_comp_cache_dir, in_incr_comp_dir, in_incr_comp_dir_sess,
 };
 use rustc_session::cgu_reuse_tracker::CguReuseTracker;
+use rustc_session::config::{
+    self, Lto, OutputFilenames, OutputType, Passes, Sanitizer, SwitchWithOptPath,
+};
+use rustc_session::Session;
 use rustc_span::hygiene::ExpnId;
 use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::{sym, Symbol};
@@ -341,9 +341,9 @@ pub fn start_async_codegen<B: ExtraBackendMethods>(
 
     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);
+    let no_builtins = attr::contains_name(&tcx.hir().krate().item.attrs, sym::no_builtins);
     let subsystem =
-        attr::first_attr_value_str_by_name(&tcx.hir().krate().attrs, sym::windows_subsystem);
+        attr::first_attr_value_str_by_name(&tcx.hir().krate().item.attrs, sym::windows_subsystem);
     let windows_subsystem = subsystem.map(|subsystem| {
         if subsystem != sym::windows && subsystem != sym::console {
             tcx.sess.fatal(&format!(
@@ -736,7 +736,7 @@ fn execute_work_item<B: ExtraBackendMethods>(
     }
 }
 
-// Actual LTO type we end up chosing based on multiple factors.
+// Actual LTO type we end up choosing based on multiple factors.
 enum ComputedLtoType {
     No,
     Thin,
@@ -1257,7 +1257,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
                 if main_thread_worker_state == MainThreadWorkerState::Idle {
                     if !queue_full_enough(work_items.len(), running, max_workers) {
                         // The queue is not full enough, codegen more items:
-                        if let Err(_) = codegen_worker_send.send(Message::CodegenItem) {
+                        if codegen_worker_send.send(Message::CodegenItem).is_err() {
                             panic!("Could not send Message::CodegenItem to main thread")
                         }
                         main_thread_worker_state = MainThreadWorkerState::Codegenning;
index d6e1ab8909c5956e80d5723ca821eca6d6f628ca..e57cae30b7795446777e956f0157dd74002b30bf 100644 (file)
@@ -31,8 +31,6 @@
 use rustc::middle::lang_items;
 use rustc::middle::lang_items::StartFnLangItem;
 use rustc::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem};
-use rustc::session::config::{self, EntryFnType, Lto};
-use rustc::session::Session;
 use rustc::ty::layout::{self, Align, HasTyCtxt, LayoutOf, TyLayout, VariantIdx};
 use rustc::ty::layout::{FAT_PTR_ADDR, FAT_PTR_EXTRA};
 use rustc::ty::query::Providers;
@@ -46,6 +44,8 @@
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_index::vec::Idx;
 use rustc_session::cgu_reuse_tracker::CguReuse;
+use rustc_session::config::{self, EntryFnType, Lto};
+use rustc_session::Session;
 use rustc_span::Span;
 
 use std::cmp;
index 28b61e0b36d64d08c3a4c33aa0825cac16e99a36..147b23995023f04585159205f1a6bcb2d27360ae 100644 (file)
@@ -1,8 +1,8 @@
 #![allow(non_camel_case_types, non_snake_case)]
 
-use rustc::session::Session;
 use rustc::ty::{Ty, TyCtxt};
 use rustc_errors::struct_span_err;
+use rustc_session::Session;
 use rustc_span::Span;
 
 use crate::base;
index a2bb39b9e401935d222c16bd79d66ba8bce67777..d2afbdc23e1fdd586e3518c47fefb0ca9b314a57 100644 (file)
 use rustc::middle::cstore::{CrateSource, LibSource, NativeLibrary};
 use rustc::middle::dependency_format::Dependencies;
 use rustc::middle::lang_items::LangItem;
-use rustc::session::config::{OutputFilenames, OutputType, RUST_CGU_EXT};
 use rustc::ty::query::Providers;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::svh::Svh;
 use rustc_data_structures::sync::Lrc;
 use rustc_hir::def_id::CrateNum;
+use rustc_session::config::{OutputFilenames, OutputType, RUST_CGU_EXT};
 use rustc_span::symbol::Symbol;
 use std::path::{Path, PathBuf};
 
index 7bf222f4701b7ea70a8d1a52b44b929df7a7782b..04680a1751734de8e296a1acb51f05b252f6517f 100644 (file)
@@ -97,7 +97,7 @@ fn assign(&mut self, local: mir::Local, location: Location) {
 
     fn process_place(
         &mut self,
-        place_ref: &mir::PlaceRef<'_, 'tcx>,
+        place_ref: &mir::PlaceRef<'tcx>,
         context: PlaceContext,
         location: Location,
     ) {
@@ -203,7 +203,7 @@ fn process_place(
             }
 
             self.visit_place_base(&place_ref.local, context, location);
-            self.visit_projection(&place_ref.local, place_ref.projection, context, location);
+            self.visit_projection(place_ref.local, place_ref.projection, context, location);
         }
     }
 }
index a1b54607b809e02b855482dfb854834ac0160150..8433f793020774962e1fbb0318997007ca13b7a4 100644 (file)
@@ -178,15 +178,10 @@ fn codegen_resume_terminator(&mut self, helper: TerminatorCodegenHelper<'tcx>, m
             let lp1 = bx.load_operand(lp1).immediate();
             slot.storage_dead(&mut bx);
 
-            if !bx.sess().target.target.options.custom_unwind_resume {
-                let mut lp = bx.const_undef(self.landing_pad_type());
-                lp = bx.insert_value(lp, lp0, 0);
-                lp = bx.insert_value(lp, lp1, 1);
-                bx.resume(lp);
-            } else {
-                bx.call(bx.eh_unwind_resume(), &[lp0], helper.funclet(self));
-                bx.unreachable();
-            }
+            let mut lp = bx.const_undef(self.landing_pad_type());
+            lp = bx.insert_value(lp, lp0, 0);
+            lp = bx.insert_value(lp, lp1, 1);
+            bx.resume(lp);
         }
     }
 
@@ -415,11 +410,15 @@ fn codegen_assert_terminator(
             AssertKind::BoundsCheck { ref len, ref index } => {
                 let len = self.codegen_operand(&mut bx, len).immediate();
                 let index = self.codegen_operand(&mut bx, index).immediate();
-                (lang_items::PanicBoundsCheckFnLangItem, vec![location, index, len])
+                // It's `fn panic_bounds_check(index: usize, len: usize)`,
+                // and `#[track_caller]` adds an implicit third argument.
+                (lang_items::PanicBoundsCheckFnLangItem, vec![index, len, location])
             }
             _ => {
                 let msg_str = Symbol::intern(msg.description());
                 let msg = bx.const_str(msg_str);
+                // It's `pub fn panic(expr: &str)`, with the wide reference being passed
+                // as two arguments, and `#[track_caller]` adds an implicit third argument.
                 (lang_items::PanicFnLangItem, vec![msg.0, msg.1, location])
             }
         };
@@ -434,6 +433,89 @@ fn codegen_assert_terminator(
         helper.do_call(self, &mut bx, fn_abi, llfn, &args, None, cleanup);
     }
 
+    /// Returns `true` if this is indeed a panic intrinsic and codegen is done.
+    fn codegen_panic_intrinsic(
+        &mut self,
+        helper: &TerminatorCodegenHelper<'tcx>,
+        bx: &mut Bx,
+        intrinsic: Option<&str>,
+        instance: Option<Instance<'tcx>>,
+        span: Span,
+        destination: &Option<(mir::Place<'tcx>, mir::BasicBlock)>,
+        cleanup: Option<mir::BasicBlock>,
+    ) -> bool {
+        // Emit a panic or a no-op for `assert_*` intrinsics.
+        // These are intrinsics that compile to panics so that we can get a message
+        // which mentions the offending type, even from a const context.
+        #[derive(Debug, PartialEq)]
+        enum AssertIntrinsic {
+            Inhabited,
+            ZeroValid,
+            UninitValid,
+        };
+        let panic_intrinsic = intrinsic.and_then(|i| match i {
+            // FIXME: Move to symbols instead of strings.
+            "assert_inhabited" => Some(AssertIntrinsic::Inhabited),
+            "assert_zero_valid" => Some(AssertIntrinsic::ZeroValid),
+            "assert_uninit_valid" => Some(AssertIntrinsic::UninitValid),
+            _ => None,
+        });
+        if let Some(intrinsic) = panic_intrinsic {
+            use AssertIntrinsic::*;
+            let ty = instance.unwrap().substs.type_at(0);
+            let layout = bx.layout_of(ty);
+            let do_panic = match intrinsic {
+                Inhabited => layout.abi.is_uninhabited(),
+                // We unwrap as the error type is `!`.
+                ZeroValid => !layout.might_permit_raw_init(bx, /*zero:*/ true).unwrap(),
+                // We unwrap as the error type is `!`.
+                UninitValid => !layout.might_permit_raw_init(bx, /*zero:*/ false).unwrap(),
+            };
+            if do_panic {
+                let msg_str = if layout.abi.is_uninhabited() {
+                    // Use this error even for the other intrinsics as it is more precise.
+                    format!("attempted to instantiate uninhabited type `{}`", ty)
+                } else if intrinsic == ZeroValid {
+                    format!("attempted to zero-initialize type `{}`, which is invalid", ty)
+                } else {
+                    format!("attempted to leave type `{}` uninitialized, which is invalid", ty)
+                };
+                let msg = bx.const_str(Symbol::intern(&msg_str));
+                let location = self.get_caller_location(bx, span).immediate();
+
+                // Obtain the panic entry point.
+                // FIXME: dedup this with `codegen_assert_terminator` above.
+                let def_id =
+                    common::langcall(bx.tcx(), Some(span), "", lang_items::PanicFnLangItem);
+                let instance = ty::Instance::mono(bx.tcx(), def_id);
+                let fn_abi = FnAbi::of_instance(bx, instance, &[]);
+                let llfn = bx.get_fn_addr(instance);
+
+                if let Some((_, target)) = destination.as_ref() {
+                    helper.maybe_sideeffect(self.mir, bx, &[*target]);
+                }
+                // Codegen the actual panic invoke/call.
+                helper.do_call(
+                    self,
+                    bx,
+                    fn_abi,
+                    llfn,
+                    &[msg.0, msg.1, location],
+                    destination.as_ref().map(|(_, bb)| (ReturnDest::Nothing, *bb)),
+                    cleanup,
+                );
+            } else {
+                // a NOP
+                let target = destination.as_ref().unwrap().1;
+                helper.maybe_sideeffect(self.mir, bx, &[target]);
+                helper.funclet_br(self, bx, target)
+            }
+            true
+        } else {
+            false
+        }
+    }
+
     fn codegen_call_terminator(
         &mut self,
         helper: TerminatorCodegenHelper<'tcx>,
@@ -520,41 +602,15 @@ fn codegen_call_terminator(
             bug!("`miri_start_panic` should never end up in compiled code");
         }
 
-        // Emit a panic or a no-op for `panic_if_uninhabited`.
-        if intrinsic == Some("panic_if_uninhabited") {
-            let ty = instance.unwrap().substs.type_at(0);
-            let layout = bx.layout_of(ty);
-            if layout.abi.is_uninhabited() {
-                let msg_str = format!("Attempted to instantiate uninhabited type {}", ty);
-                let msg = bx.const_str(Symbol::intern(&msg_str));
-                let location = self.get_caller_location(&mut bx, span).immediate();
-
-                // Obtain the panic entry point.
-                let def_id =
-                    common::langcall(bx.tcx(), Some(span), "", lang_items::PanicFnLangItem);
-                let instance = ty::Instance::mono(bx.tcx(), def_id);
-                let fn_abi = FnAbi::of_instance(&bx, instance, &[]);
-                let llfn = bx.get_fn_addr(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,
-                    &mut bx,
-                    fn_abi,
-                    llfn,
-                    &[msg.0, msg.1, location],
-                    destination.as_ref().map(|(_, bb)| (ReturnDest::Nothing, *bb)),
-                    cleanup,
-                );
-            } 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)
-            }
+        if self.codegen_panic_intrinsic(
+            &helper,
+            &mut bx,
+            intrinsic,
+            instance,
+            span,
+            destination,
+            cleanup,
+        ) {
             return;
         }
 
index e5f21013ce3e32a487c0edd88bafab024c6f65c3..cbe5f51115246c02ca27492f06b4626fc35cee1b 100644 (file)
@@ -1,10 +1,10 @@
 use crate::traits::*;
 use rustc::mir;
-use rustc::session::config::DebugInfo;
 use rustc::ty;
 use rustc::ty::layout::{LayoutOf, Size};
 use rustc_hir::def_id::CrateNum;
 use rustc_index::vec::IndexVec;
+use rustc_session::config::DebugInfo;
 
 use rustc_span::symbol::{kw, Symbol};
 use rustc_span::{BytePos, Span};
@@ -48,7 +48,7 @@ pub struct DebugScope<D> {
 
 impl<D> DebugScope<D> {
     pub fn is_valid(&self) -> bool {
-        !self.scope_metadata.is_none()
+        self.scope_metadata.is_some()
     }
 }
 
@@ -304,7 +304,7 @@ pub fn compute_per_local_var_debug_info(
     ) -> Option<IndexVec<mir::Local, Vec<PerLocalVarDebugInfo<'tcx, Bx::DIVariable>>>> {
         let full_debug_info = self.cx.sess().opts.debuginfo == DebugInfo::Full;
 
-        if !(full_debug_info || !self.cx.sess().fewer_names()) {
+        if !full_debug_info && self.cx.sess().fewer_names() {
             return None;
         }
 
index 64ead19b358697501b8a57fd22b59dcba72eec58..000db0155ada38b05667e5a396abf7b1995ebd4d 100644 (file)
@@ -86,13 +86,18 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
 impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
     pub fn monomorphize<T>(&self, value: &T) -> T
     where
-        T: TypeFoldable<'tcx>,
+        T: Copy + TypeFoldable<'tcx>,
     {
-        self.cx.tcx().subst_and_normalize_erasing_regions(
-            self.instance.substs,
-            ty::ParamEnv::reveal_all(),
-            value,
-        )
+        debug!("monomorphize: self.instance={:?}", self.instance);
+        if let Some(substs) = self.instance.substs_for_mir_body() {
+            self.cx.tcx().subst_and_normalize_erasing_regions(
+                substs,
+                ty::ParamEnv::reveal_all(),
+                &value,
+            )
+        } else {
+            self.cx.tcx().normalize_erasing_regions(ty::ParamEnv::reveal_all(), *value)
+        }
     }
 }
 
index af95450935caa7441b1dc826a8552f2e77ab589d..1e1fede2588df54c22c353239294e033913cb614 100644 (file)
@@ -364,7 +364,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
     fn maybe_codegen_consume_direct(
         &mut self,
         bx: &mut Bx,
-        place_ref: mir::PlaceRef<'_, 'tcx>,
+        place_ref: mir::PlaceRef<'tcx>,
     ) -> Option<OperandRef<'tcx, Bx::Value>> {
         debug!("maybe_codegen_consume_direct(place_ref={:?})", place_ref);
 
@@ -408,7 +408,7 @@ fn maybe_codegen_consume_direct(
     pub fn codegen_consume(
         &mut self,
         bx: &mut Bx,
-        place_ref: mir::PlaceRef<'_, 'tcx>,
+        place_ref: mir::PlaceRef<'tcx>,
     ) -> OperandRef<'tcx, Bx::Value> {
         debug!("codegen_consume(place_ref={:?})", place_ref);
 
index fa82daa0f7d526addf04a56654a049af6c280d45..2eba88c6b5f3108a8fddaf0cc557e1805b48037d 100644 (file)
@@ -408,7 +408,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
     pub fn codegen_place(
         &mut self,
         bx: &mut Bx,
-        place_ref: mir::PlaceRef<'_, 'tcx>,
+        place_ref: mir::PlaceRef<'tcx>,
     ) -> PlaceRef<'tcx, Bx::Value> {
         debug!("codegen_place(place_ref={:?})", place_ref);
         let cx = self.cx;
@@ -497,7 +497,7 @@ pub fn codegen_place(
         result
     }
 
-    pub fn monomorphized_place_ty(&self, place_ref: mir::PlaceRef<'_, 'tcx>) -> Ty<'tcx> {
+    pub fn monomorphized_place_ty(&self, place_ref: mir::PlaceRef<'tcx>) -> Ty<'tcx> {
         let tcx = self.cx.tcx();
         let place_ty = mir::Place::ty_from(place_ref.local, place_ref.projection, *self.mir, tcx);
         self.monomorphize(&place_ty.ty)
index 5535841156acd24d4d8a4ff5ed442540a53807fa..7acae300a2f0276a7dca59695443e36f7a3a90c4 100644 (file)
@@ -3,12 +3,12 @@
 use crate::ModuleCodegen;
 
 use rustc::middle::cstore::EncodedMetadata;
-use rustc::session::{config, Session};
 use rustc::ty::layout::{HasTyCtxt, LayoutOf, TyLayout};
 use rustc::ty::Ty;
 use rustc::ty::TyCtxt;
 use rustc_ast::expand::allocator::AllocatorKind;
 use rustc_codegen_utils::codegen_backend::CodegenBackend;
+use rustc_session::{config, Session};
 use rustc_span::symbol::Symbol;
 
 use std::sync::Arc;
index 691b94c2f9d485309ff1ef9995b4ce228f069d5c..6863b474cb6de95923105b5b55cc4e6531f9d454 100644 (file)
@@ -1,8 +1,8 @@
 use super::BackendTypes;
 use rustc::mir::mono::CodegenUnit;
-use rustc::session::Session;
 use rustc::ty::{self, Instance, Ty};
 use rustc_data_structures::fx::FxHashMap;
+use rustc_session::Session;
 use std::cell::RefCell;
 use std::sync::Arc;
 
@@ -14,7 +14,6 @@ fn vtables(
     fn get_fn(&self, instance: Instance<'tcx>) -> Self::Function;
     fn get_fn_addr(&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<CodegenUnit<'tcx>>;
     fn used_statics(&self) -> &RefCell<Vec<Self::Value>>;
index b8afadaadef38b163a2e5a6445bb9879a1bf2826..d03ff8d4d37d8b7cf4aef1c6900a1fae0f867f40 100644 (file)
@@ -8,7 +8,7 @@
 //! actual codegen, while the builder stores the information about the function during codegen and
 //! is used to produce the instructions of the backend IR.
 //!
-//! Finaly, a third `Backend` structure has to implement methods related to how codegen information
+//! Finally, a third `Backend` structure has to implement methods related to how codegen information
 //! is passed to the backend, especially for asynchronous compilation.
 //!
 //! The traits contain associated types that are backend-specific, such as the backend's value or
index b5533a8307c3dc501886749c52d1a5c4e68617d4..7ab59029bc8a9fbf9676a726a367a263469ad54e 100644 (file)
@@ -21,3 +21,4 @@ rustc_hir = { path = "../librustc_hir" }
 rustc_target = { path = "../librustc_target" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_metadata = { path = "../librustc_metadata" }
+rustc_session = { path = "../librustc_session" }
index 96166e04c2e3c89d6d47db3686c809206e52a4f4..561692e70669aaa0ad54c3f4a9a7da62adf7f1a9 100644 (file)
 
 use rustc::dep_graph::DepGraph;
 use rustc::middle::cstore::{EncodedMetadata, MetadataLoaderDyn};
-use rustc::session::config::{OutputFilenames, PrintRequest};
-use rustc::session::Session;
 use rustc::ty::query::Providers;
 use rustc::ty::TyCtxt;
 use rustc::util::common::ErrorReported;
+use rustc_session::config::{OutputFilenames, PrintRequest};
+use rustc_session::Session;
 use rustc_span::symbol::Symbol;
 
 pub use rustc_data_structures::sync::MetadataRef;
index 524fb0a59c2f19712d655b581b137495b13b80b6..1f53eec514bbf682f36c0fcd60b1cf517460a5e6 100644 (file)
@@ -1,6 +1,6 @@
-use rustc::session::config::{self, Input, OutputFilenames, OutputType};
-use rustc::session::Session;
 use rustc_ast::{ast, attr};
+use rustc_session::config::{self, Input, OutputFilenames, OutputType};
+use rustc_session::Session;
 use rustc_span::symbol::sym;
 use rustc_span::Span;
 use std::path::{Path, PathBuf};
@@ -167,7 +167,9 @@ pub fn invalid_output_for_target(sess: &Session, crate_type: config::CrateType)
             if !sess.target.target.options.dynamic_linking {
                 return true;
             }
-            if sess.crt_static() && !sess.target.target.options.crt_static_allows_dylibs {
+            if sess.crt_static(Some(crate_type))
+                && !sess.target.target.options.crt_static_allows_dylibs
+            {
                 return true;
             }
         }
index 6713459f627ef726823ee4f247a025392112c560..eb3fe49a5e9cc6f1d46b05d76ae0b2a92e94ad29 100644 (file)
 
 use rustc::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc::mir::mono::{InstantiationMode, MonoItem};
-use rustc::session::config::SymbolManglingVersion;
 use rustc::ty::query::Providers;
 use rustc::ty::subst::SubstsRef;
 use rustc::ty::{self, Instance, TyCtxt};
 use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
 use rustc_hir::Node;
+use rustc_session::config::SymbolManglingVersion;
 
 use rustc_span::symbol::Symbol;
 
@@ -185,7 +185,7 @@ fn compute_symbol_name(
     //
     // * On the wasm32 targets there is a bug (or feature) in LLD [1] where the
     //   same-named symbol when imported from different wasm modules will get
-    //   hooked up incorectly. As a result foreign symbols, on the wasm target,
+    //   hooked up incorrectly. As a result foreign symbols, on the wasm target,
     //   with a wasm import module, get mangled. Additionally our codegen will
     //   deduplicate symbols based purely on the symbol name, but for wasm this
     //   isn't quite right because the same-named symbol on wasm can come from
index dbc54291f4087c25858d77cbefdaf5931d3b0813..edeb4f83c7d7e6f1bbf0fb388be057f81d7f211f 100644 (file)
@@ -25,22 +25,6 @@ pub struct PinnedGenerator<I, A, R> {
 }
 
 impl<I, A, R> PinnedGenerator<I, A, R> {
-    #[cfg(bootstrap)]
-    pub fn new<T: Generator<Yield = YieldType<I, A>, Return = R> + 'static>(
-        generator: T,
-    ) -> (I, Self) {
-        let mut result = PinnedGenerator { generator: Box::pin(generator) };
-
-        // Run it to the first yield to set it up
-        let init = match Pin::new(&mut result.generator).resume() {
-            GeneratorState::Yielded(YieldType::Initial(y)) => y,
-            _ => panic!(),
-        };
-
-        (init, result)
-    }
-
-    #[cfg(not(bootstrap))]
     pub fn new<T: Generator<Yield = YieldType<I, A>, Return = R> + 'static>(
         generator: T,
     ) -> (I, Self) {
@@ -55,19 +39,6 @@ pub fn new<T: Generator<Yield = YieldType<I, A>, Return = R> + 'static>(
         (init, result)
     }
 
-    #[cfg(bootstrap)]
-    pub unsafe fn access(&mut self, closure: *mut dyn FnMut()) {
-        BOX_REGION_ARG.with(|i| {
-            i.set(Action::Access(AccessAction(closure)));
-        });
-
-        // Call the generator, which in turn will call the closure in BOX_REGION_ARG
-        if let GeneratorState::Complete(_) = Pin::new(&mut self.generator).resume() {
-            panic!()
-        }
-    }
-
-    #[cfg(not(bootstrap))]
     pub unsafe fn access(&mut self, closure: *mut dyn FnMut()) {
         BOX_REGION_ARG.with(|i| {
             i.set(Action::Access(AccessAction(closure)));
@@ -79,16 +50,6 @@ pub unsafe fn access(&mut self, closure: *mut dyn FnMut()) {
         }
     }
 
-    #[cfg(bootstrap)]
-    pub fn complete(&mut self) -> R {
-        // Tell the generator we want it to complete, consuming it and yielding a result
-        BOX_REGION_ARG.with(|i| i.set(Action::Complete));
-
-        let result = Pin::new(&mut self.generator).resume();
-        if let GeneratorState::Complete(r) = result { r } else { panic!() }
-    }
-
-    #[cfg(not(bootstrap))]
     pub fn complete(&mut self) -> R {
         // Tell the generator we want it to complete, consuming it and yielding a result
         BOX_REGION_ARG.with(|i| i.set(Action::Complete));
diff --git a/src/librustc_data_structures/frozen.rs b/src/librustc_data_structures/frozen.rs
new file mode 100644 (file)
index 0000000..2daf5b0
--- /dev/null
@@ -0,0 +1,63 @@
+//! An immutable, owned value (except for interior mutability).
+//!
+//! The purpose of `Frozen` is to make a value immutable for the sake of defensive programming. For example,
+//! suppose we have the following:
+//!
+//! ```rust
+//! struct Bar { /* some data */ }
+//!
+//! struct Foo {
+//!     /// Some computed data that should never change after construction.
+//!     pub computed: Bar,
+//!
+//!     /* some other fields */
+//! }
+//!
+//! impl Bar {
+//!     /// Mutate the `Bar`.
+//!     pub fn mutate(&mut self) { }
+//! }
+//! ```
+//!
+//! Now suppose we want to pass around a mutable `Foo` instance but, we want to make sure that
+//! `computed` does not change accidentally (e.g. somebody might accidentally call
+//! `foo.computed.mutate()`). This is what `Frozen` is for. We can do the following:
+//!
+//! ```rust
+//! use rustc_data_structures::frozen::Frozen;
+//!
+//! struct Foo {
+//!     /// Some computed data that should never change after construction.
+//!     pub computed: Frozen<Bar>,
+//!
+//!     /* some other fields */
+//! }
+//! ```
+//!
+//! `Frozen` impls `Deref`, so we can ergonomically call methods on `Bar`, but it doesn't `impl
+//! DerefMut`.  Now calling `foo.compute.mutate()` will result in a compile-time error stating that
+//! `mutate` requires a mutable reference but we don't have one.
+//!
+//! # Caveats
+//!
+//! - `Frozen` doesn't try to defend against interior mutability (e.g. `Frozen<RefCell<Bar>>`).
+//! - `Frozen` doesn't pin it's contents (e.g. one could still do `foo.computed =
+//!    Frozen::freeze(new_bar)`).
+
+/// An owned immutable value.
+#[derive(Debug)]
+pub struct Frozen<T>(T);
+
+impl<T> Frozen<T> {
+    pub fn freeze(val: T) -> Self {
+        Frozen(val)
+    }
+}
+
+impl<T> std::ops::Deref for Frozen<T> {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        &self.0
+    }
+}
index 70fc2d7dad9eecd619a25e1354c58b3d8beb7030..7ecf3e3cb8d5dbfc23b8cac2e62fdf091775d863 100644 (file)
@@ -97,7 +97,7 @@ impl<N: Idx, S: Idx> GraphSuccessors<'graph> for Sccs<N, S> {
 }
 
 impl<N: Idx, S: Idx> WithSuccessors for Sccs<N, S> {
-    fn successors<'graph>(&'graph self, node: S) -> <Self as GraphSuccessors<'graph>>::Iter {
+    fn successors(&self, node: S) -> <Self as GraphSuccessors<'_>>::Iter {
         self.successors(node).iter().cloned()
     }
 }
index 22c50afe6d0b4439b799913805f0864b5f265331..064467174cae22f9b91812d6b9304e1d29a2d35d 100644 (file)
@@ -101,7 +101,7 @@ impl<N: Idx> GraphSuccessors<'graph> for VecGraph<N> {
 }
 
 impl<N: Idx> WithSuccessors for VecGraph<N> {
-    fn successors<'graph>(&'graph self, node: N) -> <Self as GraphSuccessors<'graph>>::Iter {
+    fn successors(&self, node: N) -> <Self as GraphSuccessors<'_>>::Iter {
         self.successors(node).iter().cloned()
     }
 }
index 1db8bd4b102bfdad325893fef075ebb61f785a79..c8f979267170f8227377130b9b5309e73b0b21b2 100644 (file)
@@ -23,7 +23,7 @@ fn num_nodes() {
 }
 
 #[test]
-fn succesors() {
+fn successors() {
     let graph = create_graph();
     assert_eq!(graph.successors(0), &[1]);
     assert_eq!(graph.successors(1), &[2, 3]);
index 13792a0c890c4bc8e6587b429d353f98cc38ff23..f9f8ff5303e10d61dbc776a1e73f9e8a68f16893 100644 (file)
@@ -94,6 +94,7 @@ macro_rules! unlikely {
 pub mod vec_linked_list;
 pub mod work_queue;
 pub use atomic_ref::AtomicRef;
+pub mod frozen;
 
 pub struct OnDrop<F: Fn()>(pub F);
 
index 15d1e2dd0b644c08086e60a9c8b82586fda0589d..d08d46a7414d060c0ba89fa33ae54fc3dd82f9e3 100644 (file)
@@ -13,7 +13,7 @@
 #[cfg(parallel_compiler)]
 // 32 shards is sufficient to reduce contention on an 8-core Ryzen 7 1700,
 // but this should be tested on higher core count CPUs. How the `Sharded` type gets used
-// may also affect the ideal nunber of shards.
+// may also affect the ideal number of shards.
 const SHARD_BITS: usize = 5;
 
 #[cfg(not(parallel_compiler))]
@@ -41,7 +41,7 @@ pub fn new(mut value: impl FnMut() -> T) -> Self {
         let mut values: SmallVec<[_; SHARDS]> =
             (0..SHARDS).map(|_| CacheAligned(Lock::new(value()))).collect();
 
-        // Create an unintialized array
+        // Create an uninitialized array
         let mut shards: mem::MaybeUninit<[CacheAligned<Lock<T>>; SHARDS]> =
             mem::MaybeUninit::uninit();
 
index 26f1741153c8c310747460bc14252e62de187e32..3e6449582319fedf36ef8bbb6d88d7b9c1114631 100644 (file)
@@ -33,6 +33,7 @@ rustc_interface = { path = "../librustc_interface" }
 rustc_serialize = { path = "../libserialize", package = "serialize" }
 rustc_ast = { path = "../librustc_ast" }
 rustc_span = { path = "../librustc_span" }
+rustc_session = { path = "../librustc_session" }
 
 [target.'cfg(windows)'.dependencies]
 winapi = { version = "0.3", features = ["consoleapi", "debugapi", "processenv"] }
index c4d73953e9b2e0bac3582173a24aaf12025feb29..37dc7f6ba5fe4b06d1654ee4e686ecb7ce60e577 100644 (file)
@@ -5,6 +5,6 @@ not contain any of the "main logic" of the compiler (though it does
 have some code related to pretty printing or other minor compiler
 options).
 
-For more information about how the driver works, see the [rustc guide].
+For more information about how the driver works, see the [rustc dev guide].
 
-[rustc guide]: https://rust-lang.github.io/rustc-guide/rustc-driver.html
+[rustc dev guide]: https://rustc-dev-guide.rust-lang.org/rustc-driver.html
index 9a94349e5fde44c52f6cee6032e63e19fb2ec8c6..34f0c182499dbc410a3f63c5be42030635122f8d 100644 (file)
 
 pub extern crate rustc_plugin_impl as plugin;
 
-use rustc::lint::{Lint, LintId};
 use rustc::middle::cstore::MetadataLoader;
-use rustc::session::config::nightly_options;
-use rustc::session::config::{ErrorOutputType, Input, OutputType, PrintRequest};
-use rustc::session::{config, DiagnosticOutput, Session};
-use rustc::session::{early_error, early_warn};
 use rustc::ty::TyCtxt;
 use rustc::util::common::ErrorReported;
 use rustc_codegen_ssa::CodegenResults;
 use rustc_codegen_utils::codegen_backend::CodegenBackend;
 use rustc_data_structures::profiling::print_time_passes_entry;
 use rustc_data_structures::sync::SeqCst;
-use rustc_errors::{registry::Registry, PResult};
+use rustc_errors::{
+    registry::{InvalidErrorCode, Registry},
+    PResult,
+};
 use rustc_feature::{find_gated_cfg, UnstableFeatures};
 use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_interface::util::{collect_crate_types, get_builtin_codegen_backend};
 use rustc_save_analysis as save;
 use rustc_save_analysis::DumpHandler;
 use rustc_serialize::json::{self, ToJson};
+use rustc_session::config::nightly_options;
+use rustc_session::config::{ErrorOutputType, Input, OutputType, PrintRequest};
+use rustc_session::lint::{Lint, LintId};
+use rustc_session::{config, DiagnosticOutput, Session};
+use rustc_session::{early_error, early_warn};
 
 use std::borrow::Cow;
 use std::cmp::max;
@@ -522,11 +525,10 @@ fn stdout_isatty() -> bool {
 fn handle_explain(registry: Registry, code: &str, output: ErrorOutputType) {
     let normalised =
         if code.starts_with('E') { code.to_string() } else { format!("E{0:0>4}", code) };
-    match registry.find_description(&normalised) {
-        Some(ref description) => {
+    match registry.try_find_description(&normalised) {
+        Ok(Some(description)) => {
             let mut is_in_code_block = false;
             let mut text = String::new();
-
             // Slice off the leading newline and print.
             for line in description.lines() {
                 let indent_level =
@@ -542,16 +544,18 @@ fn handle_explain(registry: Registry, code: &str, output: ErrorOutputType) {
                 }
                 text.push('\n');
             }
-
             if stdout_isatty() {
                 show_content_with_pager(&text);
             } else {
                 print!("{}", text);
             }
         }
-        None => {
+        Ok(None) => {
             early_error(output, &format!("no extended information for {}", code));
         }
+        Err(InvalidErrorCode) => {
+            early_error(output, &format!("{} is not a valid error code", code));
+        }
     }
 }
 
@@ -648,7 +652,7 @@ fn print_crate_info(
         odir: &Option<PathBuf>,
         ofile: &Option<PathBuf>,
     ) -> Compilation {
-        use rustc::session::config::PrintRequest::*;
+        use rustc_session::config::PrintRequest::*;
         // PrintRequest::NativeStaticLibs is special - printed during linking
         // (empty iterator returns true)
         if sess.opts.prints.iter().all(|&p| p == PrintRequest::NativeStaticLibs) {
@@ -676,6 +680,10 @@ fn print_crate_info(
                     println!("{}", targets.join("\n"));
                 }
                 Sysroot => println!("{}", sess.sysroot.display()),
+                TargetLibdir => println!(
+                    "{}",
+                    sess.target_tlib_path.as_ref().unwrap_or(&sess.host_tlib_path).dir.display()
+                ),
                 TargetSpec => println!("{}", sess.target.target.to_json().pretty()),
                 FileNames | CrateName => {
                     let input = input.unwrap_or_else(|| {
@@ -1116,12 +1124,7 @@ fn extra_compiler_flags() -> Option<(Vec<String>, bool)> {
         return None;
     }
 
-    let matches = if let Some(matches) = handle_options(&args) {
-        matches
-    } else {
-        return None;
-    };
-
+    let matches = handle_options(&args)?;
     let mut result = Vec::new();
     let mut excluded_cargo_defaults = false;
     for flag in ICE_REPORT_COMPILER_FLAGS {
index ca129ac59849a2798cadc8fa70dbdb06a9ba12ad..1e5cc55a82853058dee3fd7ae236b4ed56adbda5 100644 (file)
@@ -1,8 +1,6 @@
 //! The various pretty-printing routines.
 
 use rustc::hir::map as hir_map;
-use rustc::session::config::{Input, PpMode, PpSourceMode};
-use rustc::session::Session;
 use rustc::ty::{self, TyCtxt};
 use rustc::util::common::ErrorReported;
 use rustc_ast::ast;
@@ -11,6 +9,8 @@
 use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_hir::print as pprust_hir;
 use rustc_mir::util::{write_mir_graphviz, write_mir_pretty};
+use rustc_session::config::{Input, PpMode, PpSourceMode};
+use rustc_session::Session;
 use rustc_span::FileName;
 
 use std::cell::Cell;
@@ -96,7 +96,7 @@ trait PrinterSupport: pprust::PpAnn {
     ///
     /// (Rust does not yet support upcasting from a trait object to
     /// an object for one of its super-traits.)
-    fn pp_ann<'a>(&'a self) -> &'a dyn pprust::PpAnn;
+    fn pp_ann(&self) -> &dyn pprust::PpAnn;
 }
 
 trait HirPrinterSupport<'hir>: pprust_hir::PpAnn {
@@ -106,13 +106,13 @@ trait HirPrinterSupport<'hir>: pprust_hir::PpAnn {
 
     /// Provides a uniform interface for re-extracting a reference to an
     /// `hir_map::Map` from a value that now owns it.
-    fn hir_map<'a>(&'a self) -> Option<&'a hir_map::Map<'hir>>;
+    fn hir_map(&self) -> Option<hir_map::Map<'hir>>;
 
     /// Produces the pretty-print annotation object.
     ///
     /// (Rust does not yet support upcasting from a trait object to
     /// an object for one of its super-traits.)
-    fn pp_ann<'a>(&'a self) -> &'a dyn pprust_hir::PpAnn;
+    fn pp_ann(&self) -> &dyn pprust_hir::PpAnn;
 
     /// Computes an user-readable representation of a path, if possible.
     fn node_path(&self, id: hir::HirId) -> Option<String> {
@@ -132,7 +132,7 @@ fn sess(&self) -> &Session {
         self.sess
     }
 
-    fn pp_ann<'a>(&'a self) -> &'a dyn pprust::PpAnn {
+    fn pp_ann(&self) -> &dyn pprust::PpAnn {
         self
     }
 }
@@ -142,11 +142,11 @@ fn sess(&self) -> &Session {
         self.sess
     }
 
-    fn hir_map<'a>(&'a self) -> Option<&'a hir_map::Map<'hir>> {
-        self.tcx.map(|tcx| *tcx.hir())
+    fn hir_map(&self) -> Option<hir_map::Map<'hir>> {
+        self.tcx.map(|tcx| tcx.hir())
     }
 
-    fn pp_ann<'a>(&'a self) -> &'a dyn pprust_hir::PpAnn {
+    fn pp_ann(&self) -> &dyn pprust_hir::PpAnn {
         self
     }
 }
@@ -155,7 +155,7 @@ impl<'hir> pprust::PpAnn for NoAnn<'hir> {}
 impl<'hir> pprust_hir::PpAnn for NoAnn<'hir> {
     fn nested(&self, state: &mut pprust_hir::State<'_>, nested: pprust_hir::Nested) {
         if let Some(tcx) = self.tcx {
-            pprust_hir::PpAnn::nested(*tcx.hir(), state, nested)
+            pprust_hir::PpAnn::nested(&tcx.hir(), state, nested)
         }
     }
 }
@@ -170,7 +170,7 @@ fn sess(&self) -> &Session {
         self.sess
     }
 
-    fn pp_ann<'a>(&'a self) -> &'a dyn pprust::PpAnn {
+    fn pp_ann(&self) -> &dyn pprust::PpAnn {
         self
     }
 }
@@ -216,11 +216,11 @@ fn sess(&self) -> &Session {
         self.sess
     }
 
-    fn hir_map<'a>(&'a self) -> Option<&'a hir_map::Map<'hir>> {
-        self.tcx.map(|tcx| *tcx.hir())
+    fn hir_map(&self) -> Option<hir_map::Map<'hir>> {
+        self.tcx.map(|tcx| tcx.hir())
     }
 
-    fn pp_ann<'a>(&'a self) -> &'a dyn pprust_hir::PpAnn {
+    fn pp_ann(&self) -> &dyn pprust_hir::PpAnn {
         self
     }
 }
@@ -228,7 +228,7 @@ fn pp_ann<'a>(&'a self) -> &'a dyn pprust_hir::PpAnn {
 impl<'hir> pprust_hir::PpAnn for IdentifiedAnnotation<'hir> {
     fn nested(&self, state: &mut pprust_hir::State<'_>, nested: pprust_hir::Nested) {
         if let Some(ref tcx) = self.tcx {
-            pprust_hir::PpAnn::nested(*tcx.hir(), state, nested)
+            pprust_hir::PpAnn::nested(&tcx.hir(), state, nested)
         }
     }
     fn pre(&self, s: &mut pprust_hir::State<'_>, node: pprust_hir::AnnNode<'_>) {
@@ -315,11 +315,11 @@ fn sess(&self) -> &Session {
         &self.tcx.sess
     }
 
-    fn hir_map<'a>(&'a self) -> Option<&'a hir_map::Map<'tcx>> {
-        Some(&self.tcx.hir())
+    fn hir_map(&self) -> Option<hir_map::Map<'tcx>> {
+        Some(self.tcx.hir())
     }
 
-    fn pp_ann<'a>(&'a self) -> &'a dyn pprust_hir::PpAnn {
+    fn pp_ann(&self) -> &dyn pprust_hir::PpAnn {
         self
     }
 
@@ -334,7 +334,7 @@ fn nested(&self, state: &mut pprust_hir::State<'_>, nested: pprust_hir::Nested)
         if let pprust_hir::Nested::Body(id) = nested {
             self.tables.set(self.tcx.body_tables(id));
         }
-        pprust_hir::PpAnn::nested(*self.tcx.hir(), state, nested);
+        pprust_hir::PpAnn::nested(&self.tcx.hir(), state, nested);
         self.tables.set(old_tables);
     }
     fn pre(&self, s: &mut pprust_hir::State<'_>, node: pprust_hir::AnnNode<'_>) {
index 89359bb1bfdff40a4678067c27bce645f3fc5578..85339ab9aa15badd581582ba388c3e2e0200601a 100644 (file)
 E0624: include_str!("./error_codes/E0624.md"),
 E0626: include_str!("./error_codes/E0626.md"),
 E0627: include_str!("./error_codes/E0627.md"),
+E0628: include_str!("./error_codes/E0628.md"),
 E0631: include_str!("./error_codes/E0631.md"),
 E0633: include_str!("./error_codes/E0633.md"),
+E0634: include_str!("./error_codes/E0634.md"),
 E0635: include_str!("./error_codes/E0635.md"),
 E0636: include_str!("./error_codes/E0636.md"),
 E0637: include_str!("./error_codes/E0637.md"),
 E0690: include_str!("./error_codes/E0690.md"),
 E0691: include_str!("./error_codes/E0691.md"),
 E0692: include_str!("./error_codes/E0692.md"),
+E0693: include_str!("./error_codes/E0693.md"),
 E0695: include_str!("./error_codes/E0695.md"),
 E0697: include_str!("./error_codes/E0697.md"),
 E0698: include_str!("./error_codes/E0698.md"),
 E0715: include_str!("./error_codes/E0715.md"),
 E0716: include_str!("./error_codes/E0716.md"),
 E0718: include_str!("./error_codes/E0718.md"),
+E0719: include_str!("./error_codes/E0719.md"),
 E0720: include_str!("./error_codes/E0720.md"),
 E0723: include_str!("./error_codes/E0723.md"),
 E0725: include_str!("./error_codes/E0725.md"),
 E0736: include_str!("./error_codes/E0736.md"),
 E0737: include_str!("./error_codes/E0737.md"),
 E0738: include_str!("./error_codes/E0738.md"),
+E0739: include_str!("./error_codes/E0739.md"),
 E0740: include_str!("./error_codes/E0740.md"),
 E0741: include_str!("./error_codes/E0741.md"),
 E0742: include_str!("./error_codes/E0742.md"),
 //  E0612, // merged into E0609
 //  E0613, // Removed (merged with E0609)
     E0625, // thread-local statics cannot be accessed at compile-time
-    E0628, // generators cannot have explicit parameters
     E0629, // missing 'feature' (rustc_const_unstable)
     // rustc_const_unstable attribute must be paired with stable/unstable
     // attribute
     E0630,
     E0632, // cannot provide explicit generic arguments when `impl Trait` is
            // used in argument position
-    E0634, // type has conflicting packed representaton hints
     E0640, // infer outlives requirements
 //  E0645, // trait aliases not finished
     E0657, // `impl Trait` can only capture lifetimes bound at the fn level
     E0667, // `impl Trait` in projections
     E0687, // in-band lifetimes cannot be used in `fn`/`Fn` syntax
     E0688, // in-band lifetimes cannot be mixed with explicit lifetime binders
-    E0693, // incorrect `repr(align)` attribute format
 //  E0694, // an unknown tool name found in scoped attributes
     E0696, // `continue` pointing to a labeled block
 //  E0702, // replaced with a generic attribute input check
     E0710, // an unknown tool name found in scoped lint
     E0711, // a feature has been declared with conflicting stability attributes
     E0717, // rustc_promotable without stability attribute
-    E0719, // duplicate values for associated type binding
 //  E0721, // `await` keyword
     E0722, // Malformed `#[optimize]` attribute
     E0724, // `#[ffi_returns_twice]` is only allowed in foreign functions
     E0726, // non-explicit (not `'_`) elided lifetime in unsupported position
-    E0739, // invalid track_caller application/syntax
 }
index 7fa211d4a27d422390db0be84cf7904026477973..0544667cccaea520190599467a214d9e9100e715 100644 (file)
@@ -1,4 +1,4 @@
-The `Drop` trait was implemented on a non-struct type.
+Only traits defined in the current crate can be implemented for arbitrary types.
 
 Erroneous code example:
 
index a907ca272970e0a3f72ee29cd3f8810f7e36e3ee..7d87d54194e9b7a5e195a2d9e5a7067b9d66affe 100644 (file)
@@ -1,10 +1,6 @@
-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.
+Expected type did not match the received type.
 
-For example:
+Erroneous code example:
 
 ```compile_fail,E0308
 let x: i32 = "I am not a number!";
@@ -15,3 +11,9 @@ let x: i32 = "I am not a number!";
 //      |
 //    type `i32` assigned to variable `x`
 ```
+
+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.
index 3d357819c7f91ca9418f3c0b8aec50a688e341f8..bc522e9cf4085cb6eac5f359361a63caa5feddf3 100644 (file)
@@ -1,4 +1,4 @@
-An implementation of a trait doesn't match the type contraint.
+An implementation of a trait doesn't match the type constraint.
 
 Erroneous code example:
 
index 0e1a4bf8099a047b9c91dd933919c1a8a1955be0..6d7dc88823c9926fb7dce082397d4995ab6059af 100644 (file)
@@ -1,9 +1,5 @@
-A struct without a field containing an unsized type cannot implement
-`CoerceUnsized`. An [unsized type][1] is any type that the compiler
-doesn't know the length or alignment of at compile time. Any struct
-containing an unsized type is also unsized.
-
-[1]: https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait
+`CoerceUnsized` was implemented on a struct which does not contain a field with
+an unsized type.
 
 Example of erroneous code:
 
@@ -20,6 +16,12 @@ impl<T, U> CoerceUnsized<Foo<U>> for Foo<T>
     where T: CoerceUnsized<U> {}
 ```
 
+An [unsized type][1] is any type where the compiler does not know the length or
+alignment of at compile time. Any struct containing an unsized type is also
+unsized.
+
+[1]: https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait
+
 `CoerceUnsized` is used to coerce one struct containing an unsized type
 into another struct containing a different unsized type. If the struct
 doesn't have any fields of unsized types then you don't need explicit
index 31fcd85cb079f6d60e23a523f933e52b83130557..71e530571650b53357047ff647ec0337e7327315 100644 (file)
@@ -1,12 +1,7 @@
-A struct with more than one field containing an unsized type cannot implement
-`CoerceUnsized`. This only occurs when you are trying to coerce one of the
-types in your struct to another type in the struct. In this case we try to
-impl `CoerceUnsized` from `T` to `U` which are both types that the struct
-takes. An [unsized type][1] is any type that the compiler doesn't know the
-length or alignment of at compile time. Any struct containing an unsized type
-is also unsized.
+`CoerceUnsized` was implemented on a struct which contains more than one field
+with an unsized type.
 
-Example of erroneous code:
+Erroneous code example:
 
 ```compile_fail,E0375
 #![feature(coerce_unsized)]
@@ -22,6 +17,14 @@ struct Foo<T: ?Sized, U: ?Sized> {
 impl<T, U> CoerceUnsized<Foo<U, T>> for Foo<T, U> {}
 ```
 
+A struct with more than one field containing an unsized type cannot implement
+`CoerceUnsized`. This only occurs when you are trying to coerce one of the
+types in your struct to another type in the struct. In this case we try to
+impl `CoerceUnsized` from `T` to `U` which are both types that the struct
+takes. An [unsized type][1] is any type that the compiler doesn't know the
+length or alignment of at compile time. Any struct containing an unsized type
+is also unsized.
+
 `CoerceUnsized` only allows for coercion from a structure with a single
 unsized type field to another struct with a single unsized type field.
 In fact Rust only allows for a struct to have one unsized type in a struct
index b028aab45831f7612b12923ab28e0ffc9f834b8c..50de15bd30f09ac87544ec01d2ce362af83b0439 100644 (file)
@@ -1,14 +1,6 @@
-The type you are trying to impl `CoerceUnsized` for is not a struct.
-`CoerceUnsized` can only be implemented for a struct. Unsized types are
-already able to be coerced without an implementation of `CoerceUnsized`
-whereas a struct containing an unsized type needs to know the unsized type
-field it's containing is able to be coerced. An [unsized type][1]
-is any type that the compiler doesn't know the length or alignment of at
-compile time. Any struct containing an unsized type is also unsized.
-
-[1]: https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait
+`CoerceUnsized` was implemented on something that isn't a struct.
 
-Example of erroneous code:
+Erroneous code example:
 
 ```compile_fail,E0376
 #![feature(coerce_unsized)]
@@ -22,6 +14,15 @@ struct Foo<T: ?Sized> {
 impl<T, U> CoerceUnsized<U> for Foo<T> {}
 ```
 
+`CoerceUnsized` can only be implemented for a struct. Unsized types are
+already able to be coerced without an implementation of `CoerceUnsized`
+whereas a struct containing an unsized type needs to know the unsized type
+field it's containing is able to be coerced. An [unsized type][1]
+is any type that the compiler doesn't know the length or alignment of at
+compile time. Any struct containing an unsized type is also unsized.
+
+[1]: https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait
+
 The `CoerceUnsized` trait takes a struct type. Make sure the type you are
 providing to `CoerceUnsized` is a struct with only the last field containing an
 unsized type.
index 311483c8900beaf3fb8652aa759af94e1db74d35..7f4374738de28ec4341247a93f3b1cd7c0edb298 100644 (file)
@@ -1,10 +1,28 @@
+The `DispatchFromDyn` trait was implemented on something which is not a pointer
+or a newtype wrapper around a pointer.
+
+Erroneous code example:
+
+```compile-fail,E0378
+#![feature(dispatch_from_dyn)]
+use std::ops::DispatchFromDyn;
+
+struct WrapperExtraField<T> {
+    ptr: T,
+    extra_stuff: i32,
+}
+
+impl<T, U> DispatchFromDyn<WrapperExtraField<U>> for WrapperExtraField<T>
+where
+    T: DispatchFromDyn<U>,
+{}
+```
+
 The `DispatchFromDyn` trait currently can only be implemented for
 builtin pointer types and structs that are newtype wrappers around them
 — that is, the struct must have only one field (except for`PhantomData`),
 and that field must itself implement `DispatchFromDyn`.
 
-Examples:
-
 ```
 #![feature(dispatch_from_dyn, unsize)]
 use std::{
@@ -20,6 +38,8 @@ where
 {}
 ```
 
+Another example:
+
 ```
 #![feature(dispatch_from_dyn)]
 use std::{
@@ -37,21 +57,3 @@ where
     T: DispatchFromDyn<U>,
 {}
 ```
-
-Example of illegal `DispatchFromDyn` implementation
-(illegal because of extra field)
-
-```compile-fail,E0378
-#![feature(dispatch_from_dyn)]
-use std::ops::DispatchFromDyn;
-
-struct WrapperExtraField<T> {
-    ptr: T,
-    extra_stuff: i32,
-}
-
-impl<T, U> DispatchFromDyn<WrapperExtraField<U>> for WrapperExtraField<T>
-where
-    T: DispatchFromDyn<U>,
-{}
-```
index 3503da6ac2f7893958f957878da3d43f1d8e3f83..930204847ecd872347c7d34077848ebf52f70288 100644 (file)
@@ -1,3 +1,15 @@
+A trait method was declared const.
+
+Erroneous code example:
+
+```compile_fail,E0379
+#![feature(const_fn)]
+
+trait Foo {
+    const fn bar() -> u32; // error!
+}
+```
+
 Trait methods cannot be declared `const` by design. For more information, see
 [RFC 911].
 
index fe5de56933963183276a7b03aa5a2fdc95744e28..638f0c8ecc65f3260be6e80ab5c2eb30ea8e9e97 100644 (file)
@@ -1,4 +1,14 @@
-Auto traits cannot have methods or associated items.
-For more information see the [opt-in builtin traits RFC][RFC 19].
+An auto trait was declared with a method or an associated item.
+
+Erroneous code example:
+
+```compile_fail,E0380
+unsafe auto trait Trait {
+    type Output; // error!
+}
+```
+
+Auto traits cannot have methods or associated items. For more information see
+the [opt-in builtin traits RFC][RFC 19].
 
 [RFC 19]: https://github.com/rust-lang/rfcs/blob/master/text/0019-opt-in-builtin-traits.md
index f2356583cce1ce820bf13b780a58548179a4be0c..d1408a062963023e02a351e3797e34e9b912f6f5 100644 (file)
@@ -1,5 +1,4 @@
-This error occurs when an attempt is made to use a variable after its contents
-have been moved elsewhere.
+A variable was used after its contents have been moved elsewhere.
 
 Erroneous code example:
 
index 7c7ee744a8c89c692e4ac148af44a356566e1b23..e21fac0797cb98e25aaa2cf71bd6485ed0e8c8d6 100644 (file)
@@ -1,4 +1,4 @@
-This error occurs when an attempt is made to reassign an immutable variable.
+An immutable variable was reassigned.
 
 Erroneous code example:
 
index 9d05740d6f5ab1be7a8720580c32c9f296c4f157..ecc5b5568ada15c41384d90e84dcf83840cbd8f5 100644 (file)
@@ -1,4 +1,6 @@
-You tried to implement methods for a primitive type. Erroneous code example:
+A method was implemented on a primitive type.
+
+Erroneous code example:
 
 ```compile_fail,E0390
 struct Foo {
index 5db9ad16d08f700f5e590c2d6938fd1dcbbc820b..dff50ccaa0b773bb36ae256315d73e2c67f707af 100644 (file)
@@ -1,7 +1,6 @@
-This error indicates that some types or traits depend on each other
-and therefore cannot be constructed.
+A type dependency cycle has been encountered.
 
-The following example contains a circular dependency between two traits:
+Erroneous code example:
 
 ```compile_fail,E0391
 trait FirstTrait : SecondTrait {
@@ -12,3 +11,6 @@ trait SecondTrait : FirstTrait {
 
 }
 ```
+
+The previous example contains a circular dependency between two traits:
+`FirstTrait` depends on `SecondTrait` which itself depends on `FirstTrait`.
index 1d93e904e37fc8b694d08f3e64d5085bc9d2c460..f373d89456dd4f6434ce9525080d60f84dfecddb 100644 (file)
@@ -1,5 +1,6 @@
-This error indicates that a type or lifetime parameter has been declared
-but not actually used. Here is an example that demonstrates the error:
+A type or lifetime parameter has been declared but is not actually used.
+
+Erroneous code example:
 
 ```compile_fail,E0392
 enum Foo<T> {
index 7cce99401cf0c13144681e0b2a40bb3cf9ecb409..3e853cf1b8a360f7e94d858d30e63470f6683225 100644 (file)
@@ -1,5 +1,6 @@
 A type parameter which references `Self` in its default value was not specified.
-Example of erroneous code:
+
+Erroneous code example:
 
 ```compile_fail,E0393
 trait A<T=Self> {}
index 60a09610d86f6bb639d705032f2df9b72f888d99..d9ebc852bbab7465d37cf2e03f61e6bc76dc3a0a 100644 (file)
@@ -1,4 +1,4 @@
-The type name used is not in scope.
+A used type name is not in scope.
 
 Erroneous code examples:
 
index a91ea6a9e22f607ca58e6314ab5a6ad54743260f..828a52e73411469ca949d0acdeec406773a5a6d1 100644 (file)
@@ -1,4 +1,5 @@
-You are trying to use an identifier that is either undefined or not a struct.
+An identifier that is neither defined nor a struct was used.
+
 Erroneous code example:
 
 ```compile_fail,E0422
index 6a7c31f5e0d43095622831a26c18e24dcec4827d..a98ada17a469c7801c8e0d27854f98ad1366bd08 100644 (file)
@@ -1,8 +1,7 @@
 An identifier was used like a function name or a value was expected and the
 identifier exists but it belongs to a different namespace.
 
-For (an erroneous) example, here a `struct` variant name were used as a
-function:
+Erroneous code example:
 
 ```compile_fail,E0423
 struct Foo { a: bool };
index e093f0796da5e6aae062b1fe926e4a1ed6099365..8fd60412baf01d9cc05611932f9b1712cb5ff064 100644 (file)
@@ -1,6 +1,4 @@
-This error indicates that a variable usage inside an inner function is invalid
-because the variable comes from a dynamic environment. Inner functions do not
-have access to their containing environment.
+A variable used inside an inner function comes from a dynamic environment.
 
 Erroneous code example:
 
@@ -14,8 +12,8 @@ fn foo() {
 }
 ```
 
-Functions do not capture local variables. To fix this error, you can replace the
-function with a closure:
+Inner functions do not have access to their containing environment. To fix this
+error, you can replace the function with a closure:
 
 ```
 fn foo() {
@@ -26,7 +24,7 @@ fn foo() {
 }
 ```
 
-or replace the captured variable with a constant or a static item:
+Or replace the captured variable with a constant or a static item:
 
 ```
 fn foo() {
index 834cf33dbc7f0790b53bac15456d8a898ae4664e..0f924ba69206421bc68cd8ad0bdf74b0ce62ef20 100644 (file)
@@ -1,7 +1,5 @@
-Trait implementations can only implement associated types that are members of
-the trait in question. This error indicates that you attempted to implement
-an associated type whose name does not match the name of any associated type
-in the trait.
+An associated type whose name does not match any of the associated types
+in the trait was used when implementing the trait.
 
 Erroneous code example:
 
@@ -13,6 +11,9 @@ impl Foo for i32 {
 }
 ```
 
+Trait implementations can only implement associated types that are members of
+the trait in question.
+
 The solution to this problem is to remove the extraneous associated type:
 
 ```
index cb141a5d24aeddda718ea69528e7c4dd4393008e..13723bc30090e6a4f66a24ea626ecbdffe1b2d45 100644 (file)
@@ -1,7 +1,5 @@
-Trait implementations can only implement associated constants that are
-members of the trait in question. This error indicates that you
-attempted to implement an associated constant whose name does not
-match the name of any associated constant in the trait.
+An associated constant whose name does not match any of the associated constants
+in the trait was used when implementing the trait.
 
 Erroneous code example:
 
@@ -13,6 +11,9 @@ impl Foo for i32 {
 }
 ```
 
+Trait implementations can only implement associated constants that are
+members of the trait in question.
+
 The solution to this problem is to remove the extraneous associated constant:
 
 ```
index 782d4cf29c32c16a70ffdb5416662aa5101760ea..7f68815b1c21b7b2dfcf821d000fef367fa1d4ed 100644 (file)
@@ -54,7 +54,7 @@ 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:
+- cast the fn item of a fn pointer before calling transmute, as shown here:
 
     ```
     # extern "C" fn foo(_: Box<i32>) {}
diff --git a/src/librustc_error_codes/error_codes/E0628.md b/src/librustc_error_codes/error_codes/E0628.md
new file mode 100644 (file)
index 0000000..40040c9
--- /dev/null
@@ -0,0 +1,30 @@
+More than one parameter was used for a generator.
+
+Erroneous code example:
+
+```compile_fail,E0628
+#![feature(generators, generator_trait)]
+
+fn main() {
+    let generator = |a: i32, b: i32| {
+        // error: too many parameters for a generator
+        // Allowed only 0 or 1 parameter
+        yield a;
+    };
+}
+```
+
+At present, it is not permitted to pass more than one explicit
+parameter for a generator.This can be fixed by using
+at most 1 parameter for the generator. For example, we might resolve
+the previous example by passing only one parameter.
+
+```
+#![feature(generators, generator_trait)]
+
+fn main() {
+    let generator = |a: i32| {
+        yield a;
+    };
+}
+```
diff --git a/src/librustc_error_codes/error_codes/E0634.md b/src/librustc_error_codes/error_codes/E0634.md
new file mode 100644 (file)
index 0000000..0c4ed25
--- /dev/null
@@ -0,0 +1,20 @@
+A type has conflicting `packed` representation hints.
+
+Erroneous code examples:
+
+```compile_fail,E0634
+#[repr(packed, packed(2))] // error!
+struct Company(i32);
+
+#[repr(packed(2))] // error!
+#[repr(packed)]
+struct Company(i32);
+```
+
+You cannot use conflicting `packed` hints on a same type. If you want to pack a
+type to a given size, you should provide a size to packed:
+
+```
+#[repr(packed)] // ok!
+struct Company(i32);
+```
diff --git a/src/librustc_error_codes/error_codes/E0693.md b/src/librustc_error_codes/error_codes/E0693.md
new file mode 100644 (file)
index 0000000..43e9d17
--- /dev/null
@@ -0,0 +1,19 @@
+`align` representation hint was incorrectly declared.
+
+Erroneous code examples:
+
+```compile_fail,E0693
+#[repr(align=8)] // error!
+struct Align8(i8);
+
+#[repr(align="8")] // error!
+struct Align8(i8);
+```
+
+This is a syntax error at the level of attribute declarations. The proper
+syntax for `align` representation hint is the following:
+
+```
+#[repr(align(8))] // ok!
+struct Align8(i8);
+```
diff --git a/src/librustc_error_codes/error_codes/E0719.md b/src/librustc_error_codes/error_codes/E0719.md
new file mode 100644 (file)
index 0000000..38bc635
--- /dev/null
@@ -0,0 +1,35 @@
+The value for an associated type has already been specified.
+
+Erroneous code example:
+
+```compile_fail,E0719
+#![feature(associated_type_bounds)]
+
+trait FooTrait {}
+trait BarTrait {}
+
+// error: associated type `Item` in trait `Iterator` is specified twice
+struct Foo<T: Iterator<Item: FooTrait, Item: BarTrait>> { f: T }
+```
+
+`Item` in trait `Iterator` cannot be specified multiple times for struct `Foo`.
+To fix this, create a new trait that is a combination of the desired traits and
+specify the associated type with the new trait.
+
+Corrected example:
+
+```
+#![feature(associated_type_bounds)]
+
+trait FooTrait {}
+trait BarTrait {}
+trait FooBarTrait: FooTrait + BarTrait {}
+
+struct Foo<T: Iterator<Item: FooBarTrait>> { f: T }
+```
+
+For more information about associated types, see [the book][bk-at]. For more
+information on associated type bounds, see [RFC 2289][rfc-2289].
+
+[bk-at]: https://doc.rust-lang.org/book/ch19-03-advanced-traits.html#specifying-placeholder-types-in-trait-definitions-with-associated-types
+[rfc-2289]: https://rust-lang.github.io/rfcs/2289-associated-type-bounds.html
diff --git a/src/librustc_error_codes/error_codes/E0739.md b/src/librustc_error_codes/error_codes/E0739.md
new file mode 100644 (file)
index 0000000..7077510
--- /dev/null
@@ -0,0 +1,13 @@
+`#[track_caller]` can not be applied on struct.
+
+Erroneous code example:
+
+```compile_fail,E0739
+#![feature(track_caller)]
+#[track_caller]
+struct Bar {
+    a: u8,
+}
+```
+
+[RFC 2091]: https://github.com/rust-lang/rfcs/blob/master/text/2091-inline-semantic.md
index f051fdd11b807584ec8bb5742444c1c2e3c7432b..4353a294cc31db9f11c53b8f3499a155c5ea790e 100644 (file)
@@ -3,8 +3,9 @@
 
 macro_rules! register_diagnostics {
     ($($ecode:ident: $message:expr,)* ; $($code:ident,)*) => (
-        pub static DIAGNOSTICS: &[(&str, &str)] = &[
-            $( (stringify!($ecode), $message), )*
+        pub static DIAGNOSTICS: &[(&str, Option<&str>)] = &[
+            $( (stringify!($ecode), Some($message)), )*
+            $( (stringify!($code), None), )*
         ];
     )
 }
index 39f585231eea433c5e737871dae38c0e331001a8..008d2e92418f9b89f38cf83e74c3808a48d69a5a 100644 (file)
@@ -136,12 +136,11 @@ pub fn into_diagnostic(mut self) -> Option<(Diagnostic, &'a Handler)> {
 
         let handler = self.0.handler;
 
-        // We need to use `ptr::read` because `DiagnosticBuilder` implements `Drop`.
-        let diagnostic;
-        unsafe {
-            diagnostic = std::ptr::read(&self.0.diagnostic);
-            std::mem::forget(self);
-        };
+        // We must use `Level::Cancelled` for `dummy` to avoid an ICE about an
+        // unused diagnostic.
+        let dummy = Diagnostic::new(Level::Cancelled, "");
+        let diagnostic = std::mem::replace(&mut self.0.diagnostic, dummy);
+
         // Logging here is useful to help track down where in logs an error was
         // actually emitted.
         debug!("buffer: diagnostic={:?}", diagnostic);
index 2d7ff191c77a5a40127d4a999d9d49e05f875ce4..26f1fa267f9b5e828877dd1101c17c5ac652d94d 100644 (file)
@@ -5,7 +5,7 @@
 //! There are various `Emitter` implementations that generate different output formats such as
 //! JSON and human readable output.
 //!
-//! The output types are defined in `librustc::session::config::ErrorOutputType`.
+//! The output types are defined in `rustc_session::config::ErrorOutputType`.
 
 use Destination::*;
 
@@ -414,22 +414,24 @@ fn render_multispan_macro_backtrace(&self, span: &mut MultiSpan, always_backtrac
     }
 
     // This does a small "fix" for multispans by looking to see if it can find any that
-    // point directly at <*macros>. Since these are often difficult to read, this
-    // will change the span to point at the use site.
+    // point directly at external macros. Since these are often difficult to read,
+    // this will change the span to point at the use site.
     fn fix_multispans_in_extern_macros(
         &self,
         source_map: &Option<Lrc<SourceMap>>,
         span: &mut MultiSpan,
         children: &mut Vec<SubDiagnostic>,
     ) {
-        for span in iter::once(span).chain(children.iter_mut().map(|child| &mut child.span)) {
+        debug!("fix_multispans_in_extern_macros: before: span={:?} children={:?}", span, children);
+        for span in iter::once(&mut *span).chain(children.iter_mut().map(|child| &mut child.span)) {
             self.fix_multispan_in_extern_macros(source_map, span);
         }
+        debug!("fix_multispans_in_extern_macros: after: span={:?} children={:?}", span, children);
     }
 
-    // This "fixes" MultiSpans that contain Spans that are pointing to locations inside of
-    // <*macros>. Since these locations are often difficult to read, we move these Spans from
-    // <*macros> to their corresponding use site.
+    // This "fixes" MultiSpans that contain `Span`s pointing to locations inside of external macros.
+    // Since these locations are often difficult to read,
+    // we move these spans from the external macros to their corresponding use site.
     fn fix_multispan_in_extern_macros(
         &self,
         source_map: &Option<Lrc<SourceMap>>,
@@ -440,14 +442,14 @@ fn fix_multispan_in_extern_macros(
             None => return,
         };
 
-        // First, find all the spans in <*macros> and point instead at their use site
+        // First, find all the spans in external macros and point instead at their use site.
         let replacements: Vec<(Span, Span)> = span
             .primary_spans()
             .iter()
             .copied()
             .chain(span.span_labels().iter().map(|sp_label| sp_label.span))
             .filter_map(|sp| {
-                if !sp.is_dummy() && sm.span_to_filename(sp).is_macros() {
+                if !sp.is_dummy() && sm.is_imported(sp) {
                     let maybe_callsite = sp.source_callsite();
                     if sp != maybe_callsite {
                         return Some((sp, maybe_callsite));
@@ -457,7 +459,7 @@ fn fix_multispan_in_extern_macros(
             })
             .collect();
 
-        // After we have them, make sure we replace these 'bad' def sites with their use sites
+        // After we have them, make sure we replace these 'bad' def sites with their use sites.
         for (from, to) in replacements {
             span.replace(from, to);
         }
@@ -472,6 +474,7 @@ fn source_map(&self) -> Option<&Lrc<SourceMap>> {
     fn emit_diagnostic(&mut self, diag: &Diagnostic) {
         let mut children = diag.children.clone();
         let (mut primary_span, suggestions) = self.primary_span_formatted(&diag);
+        debug!("emit_diagnostic: suggestions={:?}", suggestions);
 
         self.fix_multispans_in_extern_macros_and_render_macro_backtrace(
             &self.sm,
@@ -1533,6 +1536,7 @@ fn emit_suggestion_default(
 
         // Render the replacements for each suggestion
         let suggestions = suggestion.splice_lines(&**sm);
+        debug!("emit_suggestion_default: suggestions={:?}", suggestions);
 
         if suggestions.is_empty() {
             // Suggestions coming from macros can have malformed spans. This is a heavy handed
@@ -1574,9 +1578,9 @@ fn emit_suggestion_default(
 
             let line_start = sm.lookup_char_pos(parts[0].span.lo()).line;
             draw_col_separator_no_space(&mut buffer, 1, max_line_num_len + 1);
-            let mut line_pos = 0;
             let mut lines = complete.lines();
-            for line in lines.by_ref().take(MAX_SUGGESTION_HIGHLIGHT_LINES) {
+            for (line_pos, line) in lines.by_ref().take(MAX_SUGGESTION_HIGHLIGHT_LINES).enumerate()
+            {
                 // Print the span column to avoid confusion
                 buffer.puts(
                     row_num,
@@ -1587,7 +1591,6 @@ fn emit_suggestion_default(
                 // print the suggestion
                 draw_col_separator(&mut buffer, row_num, max_line_num_len + 1);
                 buffer.append(row_num, line, Style::NoStyle);
-                line_pos += 1;
                 row_num += 1;
             }
 
index df73785b8f63596166da562991bdaef6d74c0af2..1382825922b0edff9bc5526337fc70d5c5ec4bfd 100644 (file)
@@ -394,6 +394,11 @@ fn from_span(span: Span, je: &JsonEmitter) -> Vec<DiagnosticSpanLine> {
         je.sm
             .span_to_lines(span)
             .map(|lines| {
+                // We can't get any lines if the source is unavailable.
+                if !je.sm.ensure_source_file_source_present(lines.file.clone()) {
+                    return vec![];
+                }
+
                 let sf = &*lines.file;
                 lines
                     .lines
@@ -419,10 +424,10 @@ fn map_opt_string(s: Option<DiagnosticId>, je: &JsonEmitter) -> Option<Diagnosti
                 DiagnosticId::Error(s) => s,
                 DiagnosticId::Lint(s) => s,
             };
-            let explanation =
-                je.registry.as_ref().and_then(|registry| registry.find_description(&s));
+            let je_result =
+                je.registry.as_ref().map(|registry| registry.try_find_description(&s)).unwrap();
 
-            DiagnosticCode { code: s, explanation }
+            DiagnosticCode { code: s, explanation: je_result.unwrap_or(None) }
         })
     }
 }
index 1a0fe3435213000aa14b28b55f426860b6b5a245..bed26c3736b83978dd485f1796f26a9bccef00d2 100644 (file)
@@ -163,7 +163,7 @@ fn push_trailing(
                         None => buf.push_str(&line[lo..]),
                     }
                 }
-                if let None = hi_opt {
+                if hi_opt.is_none() {
                     buf.push('\n');
                 }
             }
@@ -196,6 +196,11 @@ fn push_trailing(
                 let lines = sm.span_to_lines(bounding_span).ok()?;
                 assert!(!lines.lines.is_empty());
 
+                // We can't splice anything if the source is unavailable.
+                if !sm.ensure_source_file_source_present(lines.file.clone()) {
+                    return None;
+                }
+
                 // To build up the result, we do this for each span:
                 // - push the line segment trailing the previous span
                 //   (at the beginning a "phantom" span pointing at the start of the line)
@@ -444,22 +449,12 @@ pub fn reset_err_count(&self) {
     }
 
     /// Stash a given diagnostic with the given `Span` and `StashKey` as the key for later stealing.
-    /// If the diagnostic with this `(span, key)` already exists, this will result in an ICE.
     pub fn stash_diagnostic(&self, span: Span, key: StashKey, diag: Diagnostic) {
         let mut inner = self.inner.borrow_mut();
-        if let Some(mut old_diag) = inner.stashed_diagnostics.insert((span, key), diag) {
-            // We are removing a previously stashed diagnostic which should not happen.
-            old_diag.level = Bug;
-            old_diag.note(&format!(
-                "{}:{}: already existing stashed diagnostic with (span = {:?}, key = {:?})",
-                file!(),
-                line!(),
-                span,
-                key
-            ));
-            inner.emit_diag_at_span(old_diag, span);
-            panic!(ExplicitBug);
-        }
+        // FIXME(Centril, #69537): Consider reintroducing panic on overwriting a stashed diagnostic
+        // if/when we have a more robust macro-friendly replacement for `(span, key)` as a key.
+        // See the PR for a discussion.
+        inner.stashed_diagnostics.insert((span, key), diag);
     }
 
     /// Steal a previously stashed diagnostic with the given `Span` and `StashKey` as the key.
@@ -786,8 +781,12 @@ fn print_error_count(&mut self, registry: &Registry) {
                 .emitted_diagnostic_codes
                 .iter()
                 .filter_map(|x| match &x {
-                    DiagnosticId::Error(s) if registry.find_description(s).is_some() => {
-                        Some(s.clone())
+                    DiagnosticId::Error(s) => {
+                        if let Ok(Some(_explanation)) = registry.try_find_description(s) {
+                            Some(s.clone())
+                        } else {
+                            None
+                        }
                     }
                     _ => None,
                 })
index 771542cb06fa6808ea450bbe803947638f0c06dc..32700c6500bc86619a05fd1d09a546c7d64c6885 100644 (file)
@@ -1,16 +1,32 @@
 use rustc_data_structures::fx::FxHashMap;
 
+#[derive(Debug)]
+pub struct InvalidErrorCode;
+
 #[derive(Clone)]
 pub struct Registry {
-    descriptions: FxHashMap<&'static str, &'static str>,
+    long_descriptions: FxHashMap<&'static str, Option<&'static str>>,
 }
 
 impl Registry {
-    pub fn new(descriptions: &[(&'static str, &'static str)]) -> Registry {
-        Registry { descriptions: descriptions.iter().cloned().collect() }
+    pub fn new(long_descriptions: &[(&'static str, Option<&'static str>)]) -> Registry {
+        Registry { long_descriptions: long_descriptions.iter().cloned().collect() }
     }
 
+    /// This will panic if an invalid error code is passed in
     pub fn find_description(&self, code: &str) -> Option<&'static str> {
-        self.descriptions.get(code).cloned()
+        self.try_find_description(code).unwrap()
+    }
+    /// Returns `InvalidErrorCode` if the code requested does not exist in the
+    /// registry. Otherwise, returns an `Option` where `None` means the error
+    /// code is valid but has no extended information.
+    pub fn try_find_description(
+        &self,
+        code: &str,
+    ) -> Result<Option<&'static str>, InvalidErrorCode> {
+        if !self.long_descriptions.contains_key(code) {
+            return Err(InvalidErrorCode);
+        }
+        Ok(*self.long_descriptions.get(code).unwrap())
     }
 }
index 9258b59f79be85b75ec1d4ee4202550d889e6ee5..74c304c96b9a45490d82dd6969abdc801c6580da 100644 (file)
@@ -1,16 +1,17 @@
 use crate::expand::{self, AstFragment, Invocation};
+use crate::module::DirectoryOwnership;
 
 use rustc_ast::ast::{self, Attribute, Name, NodeId, PatKind};
 use rustc_ast::mut_visit::{self, MutVisitor};
 use rustc_ast::ptr::P;
 use rustc_ast::token;
-use rustc_ast::tokenstream::{self, TokenStream};
+use rustc_ast::tokenstream::{self, TokenStream, TokenTree};
 use rustc_ast::visit::{AssocCtxt, Visitor};
 use rustc_attr::{self as attr, Deprecation, HasAttrs, Stability};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::{self, Lrc};
 use rustc_errors::{DiagnosticBuilder, DiagnosticId};
-use rustc_parse::{self, parser, DirectoryOwnership, MACRO_ARGUMENTS};
+use rustc_parse::{self, parser, MACRO_ARGUMENTS};
 use rustc_session::parse::ParseSess;
 use rustc_span::edition::Edition;
 use rustc_span::hygiene::{AstPass, ExpnData, ExpnId, ExpnKind};
@@ -118,6 +119,31 @@ pub fn visit_with<'a, V: Visitor<'a>>(&'a self, visitor: &mut V) {
         }
     }
 
+    crate fn into_tokens(self) -> TokenStream {
+        // `Annotatable` can be converted into tokens directly, but we
+        // are packing it into a nonterminal as a piece of AST to make
+        // the produced token stream look nicer in pretty-printed form.
+        let nt = match self {
+            Annotatable::Item(item) => token::NtItem(item),
+            Annotatable::TraitItem(item) | Annotatable::ImplItem(item) => {
+                token::NtItem(P(item.and_then(ast::AssocItem::into_item)))
+            }
+            Annotatable::ForeignItem(item) => {
+                token::NtItem(P(item.and_then(ast::ForeignItem::into_item)))
+            }
+            Annotatable::Stmt(stmt) => token::NtStmt(stmt.into_inner()),
+            Annotatable::Expr(expr) => token::NtExpr(expr),
+            Annotatable::Arm(..)
+            | Annotatable::Field(..)
+            | Annotatable::FieldPat(..)
+            | Annotatable::GenericParam(..)
+            | Annotatable::Param(..)
+            | Annotatable::StructField(..)
+            | Annotatable::Variant(..) => panic!("unexpected annotatable"),
+        };
+        TokenTree::token(token::Interpolated(Lrc::new(nt)), DUMMY_SP).into()
+    }
+
     pub fn expect_item(self) -> P<ast::Item> {
         match self {
             Annotatable::Item(i) => i,
@@ -233,8 +259,17 @@ pub fn derive_allowed(&self) -> bool {
     }
 }
 
-// `meta_item` is the annotation, and `item` is the item being modified.
-// FIXME Decorators should follow the same pattern too.
+/// Result of an expansion that may need to be retried.
+/// Consider using this for non-`MultiItemModifier` expanders as well.
+pub enum ExpandResult<T, U> {
+    /// Expansion produced a result (possibly dummy).
+    Ready(T),
+    /// Expansion could not produce a result and needs to be retried.
+    /// The string is an explanation that will be printed if we are stuck in an infinite retry loop.
+    Retry(U, String),
+}
+
+// `meta_item` is the attribute, and `item` is the item being modified.
 pub trait MultiItemModifier {
     fn expand(
         &self,
@@ -242,13 +277,12 @@ fn expand(
         span: Span,
         meta_item: &ast::MetaItem,
         item: Annotatable,
-    ) -> Vec<Annotatable>;
+    ) -> ExpandResult<Vec<Annotatable>, Annotatable>;
 }
 
-impl<F, T> MultiItemModifier for F
+impl<F> MultiItemModifier for F
 where
-    F: Fn(&mut ExtCtxt<'_>, Span, &ast::MetaItem, Annotatable) -> T,
-    T: Into<Vec<Annotatable>>,
+    F: Fn(&mut ExtCtxt<'_>, Span, &ast::MetaItem, Annotatable) -> Vec<Annotatable>,
 {
     fn expand(
         &self,
@@ -256,14 +290,8 @@ fn expand(
         span: Span,
         meta_item: &ast::MetaItem,
         item: Annotatable,
-    ) -> Vec<Annotatable> {
-        (*self)(ecx, span, meta_item, item).into()
-    }
-}
-
-impl Into<Vec<Annotatable>> for Annotatable {
-    fn into(self) -> Vec<Annotatable> {
-        vec![self]
+    ) -> ExpandResult<Vec<Annotatable>, Annotatable> {
+        ExpandResult::Ready(self(ecx, span, meta_item, item))
     }
 }
 
@@ -347,7 +375,7 @@ fn visit_tt(&mut self, tt: &mut tokenstream::TokenTree) {
                 mut_visit::noop_visit_tt(tt, self)
             }
 
-            fn visit_mac(&mut self, mac: &mut ast::Mac) {
+            fn visit_mac(&mut self, mac: &mut ast::MacCall) {
                 mut_visit::noop_visit_mac(mac, self)
             }
         }
@@ -870,6 +898,7 @@ fn resolve_macro_invocation(
 
     fn has_derive_copy(&self, expn_id: ExpnId) -> bool;
     fn add_derive_copy(&mut self, expn_id: ExpnId);
+    fn cfg_accessible(&mut self, expn_id: ExpnId, path: &ast::Path) -> Result<bool, Indeterminate>;
 }
 
 #[derive(Clone)]
@@ -897,6 +926,8 @@ pub struct ExtCtxt<'a> {
     pub resolver: &'a mut dyn Resolver,
     pub current_expansion: ExpansionData,
     pub expansions: FxHashMap<Span, Vec<String>>,
+    /// Called directly after having parsed an external `mod foo;` in expansion.
+    pub(super) extern_mod_loaded: Option<&'a dyn Fn(&ast::Crate)>,
 }
 
 impl<'a> ExtCtxt<'a> {
@@ -904,12 +935,14 @@ pub fn new(
         parse_sess: &'a ParseSess,
         ecfg: expand::ExpansionConfig<'a>,
         resolver: &'a mut dyn Resolver,
+        extern_mod_loaded: Option<&'a dyn Fn(&ast::Crate)>,
     ) -> ExtCtxt<'a> {
         ExtCtxt {
             parse_sess,
             ecfg,
-            root_path: PathBuf::new(),
             resolver,
+            extern_mod_loaded,
+            root_path: PathBuf::new(),
             current_expansion: ExpansionData {
                 id: ExpnId::root(),
                 depth: 0,
diff --git a/src/librustc_expand/config.rs b/src/librustc_expand/config.rs
new file mode 100644 (file)
index 0000000..72c09f3
--- /dev/null
@@ -0,0 +1,532 @@
+//! Conditional compilation stripping.
+
+use rustc_ast::ast::{self, AttrItem, Attribute, MetaItem};
+use rustc_ast::attr::HasAttrs;
+use rustc_ast::mut_visit::*;
+use rustc_ast::ptr::P;
+use rustc_ast::util::map_in_place::MapInPlace;
+use rustc_attr as attr;
+use rustc_data_structures::fx::FxHashMap;
+use rustc_errors::{error_code, struct_span_err, Applicability, Handler};
+use rustc_feature::{Feature, Features, State as FeatureState};
+use rustc_feature::{
+    ACCEPTED_FEATURES, ACTIVE_FEATURES, REMOVED_FEATURES, STABLE_REMOVED_FEATURES,
+};
+use rustc_parse::{parse_in, validate_attr};
+use rustc_session::parse::{feature_err, ParseSess};
+use rustc_span::edition::{Edition, ALL_EDITIONS};
+use rustc_span::symbol::{sym, Symbol};
+use rustc_span::{Span, DUMMY_SP};
+
+use smallvec::SmallVec;
+
+/// A folder that strips out items that do not belong in the current configuration.
+pub struct StripUnconfigured<'a> {
+    pub sess: &'a ParseSess,
+    pub features: Option<&'a Features>,
+}
+
+fn get_features(
+    span_handler: &Handler,
+    krate_attrs: &[ast::Attribute],
+    crate_edition: Edition,
+    allow_features: &Option<Vec<String>>,
+) -> Features {
+    fn feature_removed(span_handler: &Handler, span: Span, reason: Option<&str>) {
+        let mut err = struct_span_err!(span_handler, span, E0557, "feature has been removed");
+        err.span_label(span, "feature has been removed");
+        if let Some(reason) = reason {
+            err.note(reason);
+        }
+        err.emit();
+    }
+
+    fn active_features_up_to(edition: Edition) -> impl Iterator<Item = &'static Feature> {
+        ACTIVE_FEATURES.iter().filter(move |feature| {
+            if let Some(feature_edition) = feature.edition {
+                feature_edition <= edition
+            } else {
+                false
+            }
+        })
+    }
+
+    let mut features = Features::default();
+    let mut edition_enabled_features = FxHashMap::default();
+
+    for &edition in ALL_EDITIONS {
+        if edition <= crate_edition {
+            // The `crate_edition` implies its respective umbrella feature-gate
+            // (i.e., `#![feature(rust_20XX_preview)]` isn't needed on edition 20XX).
+            edition_enabled_features.insert(edition.feature_name(), edition);
+        }
+    }
+
+    for feature in active_features_up_to(crate_edition) {
+        feature.set(&mut features, DUMMY_SP);
+        edition_enabled_features.insert(feature.name, crate_edition);
+    }
+
+    // Process the edition umbrella feature-gates first, to ensure
+    // `edition_enabled_features` is completed before it's queried.
+    for attr in krate_attrs {
+        if !attr.check_name(sym::feature) {
+            continue;
+        }
+
+        let list = match attr.meta_item_list() {
+            Some(list) => list,
+            None => continue,
+        };
+
+        for mi in list {
+            if !mi.is_word() {
+                continue;
+            }
+
+            let name = mi.name_or_empty();
+
+            let edition = ALL_EDITIONS.iter().find(|e| name == e.feature_name()).copied();
+            if let Some(edition) = edition {
+                if edition <= crate_edition {
+                    continue;
+                }
+
+                for feature in active_features_up_to(edition) {
+                    // FIXME(Manishearth) there is currently no way to set
+                    // lib features by edition
+                    feature.set(&mut features, DUMMY_SP);
+                    edition_enabled_features.insert(feature.name, edition);
+                }
+            }
+        }
+    }
+
+    for attr in krate_attrs {
+        if !attr.check_name(sym::feature) {
+            continue;
+        }
+
+        let list = match attr.meta_item_list() {
+            Some(list) => list,
+            None => continue,
+        };
+
+        let bad_input = |span| {
+            struct_span_err!(span_handler, span, E0556, "malformed `feature` attribute input")
+        };
+
+        for mi in list {
+            let name = match mi.ident() {
+                Some(ident) if mi.is_word() => ident.name,
+                Some(ident) => {
+                    bad_input(mi.span())
+                        .span_suggestion(
+                            mi.span(),
+                            "expected just one word",
+                            format!("{}", ident.name),
+                            Applicability::MaybeIncorrect,
+                        )
+                        .emit();
+                    continue;
+                }
+                None => {
+                    bad_input(mi.span()).span_label(mi.span(), "expected just one word").emit();
+                    continue;
+                }
+            };
+
+            if let Some(edition) = edition_enabled_features.get(&name) {
+                let msg =
+                    &format!("the feature `{}` is included in the Rust {} edition", name, edition);
+                span_handler.struct_span_warn_with_code(mi.span(), msg, error_code!(E0705)).emit();
+                continue;
+            }
+
+            if ALL_EDITIONS.iter().any(|e| name == e.feature_name()) {
+                // Handled in the separate loop above.
+                continue;
+            }
+
+            let removed = REMOVED_FEATURES.iter().find(|f| name == f.name);
+            let stable_removed = STABLE_REMOVED_FEATURES.iter().find(|f| name == f.name);
+            if let Some(Feature { state, .. }) = removed.or(stable_removed) {
+                if let FeatureState::Removed { reason } | FeatureState::Stabilized { reason } =
+                    state
+                {
+                    feature_removed(span_handler, mi.span(), *reason);
+                    continue;
+                }
+            }
+
+            if let Some(Feature { since, .. }) = ACCEPTED_FEATURES.iter().find(|f| name == f.name) {
+                let since = Some(Symbol::intern(since));
+                features.declared_lang_features.push((name, mi.span(), since));
+                continue;
+            }
+
+            if let Some(allowed) = allow_features.as_ref() {
+                if allowed.iter().find(|&f| name.as_str() == *f).is_none() {
+                    struct_span_err!(
+                        span_handler,
+                        mi.span(),
+                        E0725,
+                        "the feature `{}` is not in the list of allowed features",
+                        name
+                    )
+                    .emit();
+                    continue;
+                }
+            }
+
+            if let Some(f) = ACTIVE_FEATURES.iter().find(|f| name == f.name) {
+                f.set(&mut features, mi.span());
+                features.declared_lang_features.push((name, mi.span(), None));
+                continue;
+            }
+
+            features.declared_lib_features.push((name, mi.span()));
+        }
+    }
+
+    features
+}
+
+// `cfg_attr`-process the crate's attributes and compute the crate's features.
+pub fn features(
+    mut krate: ast::Crate,
+    sess: &ParseSess,
+    edition: Edition,
+    allow_features: &Option<Vec<String>>,
+) -> (ast::Crate, Features) {
+    let mut strip_unconfigured = StripUnconfigured { sess, features: None };
+
+    let unconfigured_attrs = krate.attrs.clone();
+    let diag = &sess.span_diagnostic;
+    let err_count = diag.err_count();
+    let features = match strip_unconfigured.configure(krate.attrs) {
+        None => {
+            // The entire crate is unconfigured.
+            krate.attrs = Vec::new();
+            krate.module.items = Vec::new();
+            Features::default()
+        }
+        Some(attrs) => {
+            krate.attrs = attrs;
+            let features = get_features(diag, &krate.attrs, edition, allow_features);
+            if err_count == diag.err_count() {
+                // Avoid reconfiguring malformed `cfg_attr`s.
+                strip_unconfigured.features = Some(&features);
+                strip_unconfigured.configure(unconfigured_attrs);
+            }
+            features
+        }
+    };
+    (krate, features)
+}
+
+#[macro_export]
+macro_rules! configure {
+    ($this:ident, $node:ident) => {
+        match $this.configure($node) {
+            Some(node) => node,
+            None => return Default::default(),
+        }
+    };
+}
+
+const CFG_ATTR_GRAMMAR_HELP: &str = "#[cfg_attr(condition, attribute, other_attribute, ...)]";
+const CFG_ATTR_NOTE_REF: &str = "for more information, visit \
+    <https://doc.rust-lang.org/reference/conditional-compilation.html\
+    #the-cfg_attr-attribute>";
+
+impl<'a> StripUnconfigured<'a> {
+    pub fn configure<T: HasAttrs>(&mut self, mut node: T) -> Option<T> {
+        self.process_cfg_attrs(&mut node);
+        self.in_cfg(node.attrs()).then_some(node)
+    }
+
+    /// Parse and expand all `cfg_attr` attributes into a list of attributes
+    /// that are within each `cfg_attr` that has a true configuration predicate.
+    ///
+    /// Gives compiler warnings if any `cfg_attr` does not contain any
+    /// attributes and is in the original source code. Gives compiler errors if
+    /// the syntax of any `cfg_attr` is incorrect.
+    pub fn process_cfg_attrs<T: HasAttrs>(&mut self, node: &mut T) {
+        node.visit_attrs(|attrs| {
+            attrs.flat_map_in_place(|attr| self.process_cfg_attr(attr));
+        });
+    }
+
+    /// Parse and expand a single `cfg_attr` attribute into a list of attributes
+    /// when the configuration predicate is true, or otherwise expand into an
+    /// empty list of attributes.
+    ///
+    /// Gives a compiler warning when the `cfg_attr` contains no attributes and
+    /// is in the original source file. Gives a compiler error if the syntax of
+    /// the attribute is incorrect.
+    fn process_cfg_attr(&mut self, attr: Attribute) -> Vec<Attribute> {
+        if !attr.has_name(sym::cfg_attr) {
+            return vec![attr];
+        }
+
+        let (cfg_predicate, expanded_attrs) = match self.parse_cfg_attr(&attr) {
+            None => return vec![],
+            Some(r) => r,
+        };
+
+        // Lint on zero attributes in source.
+        if expanded_attrs.is_empty() {
+            return vec![attr];
+        }
+
+        // At this point we know the attribute is considered used.
+        attr::mark_used(&attr);
+
+        if !attr::cfg_matches(&cfg_predicate, self.sess, self.features) {
+            return vec![];
+        }
+
+        // We call `process_cfg_attr` recursively in case there's 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)| {
+                let attr = attr::mk_attr_from_item(attr.style, item, span);
+                self.process_cfg_attr(attr)
+            })
+            .collect()
+    }
+
+    fn parse_cfg_attr(&self, attr: &Attribute) -> Option<(MetaItem, Vec<(AttrItem, Span)>)> {
+        match attr.get_normal_item().args {
+            ast::MacArgs::Delimited(dspan, delim, ref tts) if !tts.is_empty() => {
+                let msg = "wrong `cfg_attr` delimiters";
+                validate_attr::check_meta_bad_delim(self.sess, dspan, delim, msg);
+                match parse_in(self.sess, tts.clone(), "`cfg_attr` input", |p| p.parse_cfg_attr()) {
+                    Ok(r) => return Some(r),
+                    Err(mut e) => {
+                        e.help(&format!("the valid syntax is `{}`", CFG_ATTR_GRAMMAR_HELP))
+                            .note(CFG_ATTR_NOTE_REF)
+                            .emit();
+                    }
+                }
+            }
+            _ => self.error_malformed_cfg_attr_missing(attr.span),
+        }
+        None
+    }
+
+    fn error_malformed_cfg_attr_missing(&self, span: Span) {
+        self.sess
+            .span_diagnostic
+            .struct_span_err(span, "malformed `cfg_attr` attribute input")
+            .span_suggestion(
+                span,
+                "missing condition and attribute",
+                CFG_ATTR_GRAMMAR_HELP.to_string(),
+                Applicability::HasPlaceholders,
+            )
+            .note(CFG_ATTR_NOTE_REF)
+            .emit();
+    }
+
+    /// Determines if a node with the given attributes should be included in this configuration.
+    pub fn in_cfg(&self, attrs: &[Attribute]) -> bool {
+        attrs.iter().all(|attr| {
+            if !is_cfg(attr) {
+                return true;
+            }
+            let meta_item = match validate_attr::parse_meta(self.sess, attr) {
+                Ok(meta_item) => meta_item,
+                Err(mut err) => {
+                    err.emit();
+                    return true;
+                }
+            };
+            let error = |span, msg, suggestion: &str| {
+                let mut err = self.sess.span_diagnostic.struct_span_err(span, msg);
+                if !suggestion.is_empty() {
+                    err.span_suggestion(
+                        span,
+                        "expected syntax is",
+                        suggestion.into(),
+                        Applicability::MaybeIncorrect,
+                    );
+                }
+                err.emit();
+                true
+            };
+            let span = meta_item.span;
+            match meta_item.meta_item_list() {
+                None => error(span, "`cfg` is not followed by parentheses", "cfg(/* predicate */)"),
+                Some([]) => error(span, "`cfg` predicate is not specified", ""),
+                Some([_, .., l]) => error(l.span(), "multiple `cfg` predicates are specified", ""),
+                Some([single]) => match single.meta_item() {
+                    Some(meta_item) => attr::cfg_matches(meta_item, self.sess, self.features),
+                    None => error(single.span(), "`cfg` predicate key cannot be a literal", ""),
+                },
+            }
+        })
+    }
+
+    /// Visit attributes on expression and statements (but not attributes on items in blocks).
+    fn visit_expr_attrs(&mut self, attrs: &[Attribute]) {
+        // flag the offending attributes
+        for attr in attrs.iter() {
+            self.maybe_emit_expr_attr_err(attr);
+        }
+    }
+
+    /// If attributes are not allowed on expressions, emit an error for `attr`
+    pub fn maybe_emit_expr_attr_err(&self, attr: &Attribute) {
+        if !self.features.map(|features| features.stmt_expr_attributes).unwrap_or(true) {
+            let mut err = feature_err(
+                self.sess,
+                sym::stmt_expr_attributes,
+                attr.span,
+                "attributes on expressions are experimental",
+            );
+
+            if attr.is_doc_comment() {
+                err.help("`///` is for documentation comments. For a plain comment, use `//`.");
+            }
+
+            err.emit();
+        }
+    }
+
+    pub fn configure_foreign_mod(&mut self, foreign_mod: &mut ast::ForeignMod) {
+        let ast::ForeignMod { abi: _, items } = foreign_mod;
+        items.flat_map_in_place(|item| self.configure(item));
+    }
+
+    pub fn configure_generic_params(&mut self, params: &mut Vec<ast::GenericParam>) {
+        params.flat_map_in_place(|param| self.configure(param));
+    }
+
+    fn configure_variant_data(&mut self, vdata: &mut ast::VariantData) {
+        match vdata {
+            ast::VariantData::Struct(fields, ..) | ast::VariantData::Tuple(fields, _) => {
+                fields.flat_map_in_place(|field| self.configure(field))
+            }
+            ast::VariantData::Unit(_) => {}
+        }
+    }
+
+    pub fn configure_item_kind(&mut self, item: &mut ast::ItemKind) {
+        match item {
+            ast::ItemKind::Struct(def, _generics) | ast::ItemKind::Union(def, _generics) => {
+                self.configure_variant_data(def)
+            }
+            ast::ItemKind::Enum(ast::EnumDef { variants }, _generics) => {
+                variants.flat_map_in_place(|variant| self.configure(variant));
+                for variant in variants {
+                    self.configure_variant_data(&mut variant.data);
+                }
+            }
+            _ => {}
+        }
+    }
+
+    pub fn configure_expr_kind(&mut self, expr_kind: &mut ast::ExprKind) {
+        match expr_kind {
+            ast::ExprKind::Match(_m, arms) => {
+                arms.flat_map_in_place(|arm| self.configure(arm));
+            }
+            ast::ExprKind::Struct(_path, fields, _base) => {
+                fields.flat_map_in_place(|field| self.configure(field));
+            }
+            _ => {}
+        }
+    }
+
+    pub fn configure_expr(&mut self, expr: &mut P<ast::Expr>) {
+        self.visit_expr_attrs(expr.attrs());
+
+        // If an expr is valid to cfg away it will have been removed by the
+        // outer stmt or expression folder before descending in here.
+        // Anything else is always required, and thus has to error out
+        // in case of a cfg attr.
+        //
+        // N.B., this is intentionally not part of the visit_expr() function
+        //     in order for filter_map_expr() to be able to avoid this check
+        if let Some(attr) = expr.attrs().iter().find(|a| is_cfg(a)) {
+            let msg = "removing an expression is not supported in this position";
+            self.sess.span_diagnostic.span_err(attr.span, msg);
+        }
+
+        self.process_cfg_attrs(expr)
+    }
+
+    pub fn configure_pat(&mut self, pat: &mut P<ast::Pat>) {
+        if let ast::PatKind::Struct(_path, fields, _etc) = &mut pat.kind {
+            fields.flat_map_in_place(|field| self.configure(field));
+        }
+    }
+
+    pub fn configure_fn_decl(&mut self, fn_decl: &mut ast::FnDecl) {
+        fn_decl.inputs.flat_map_in_place(|arg| self.configure(arg));
+    }
+}
+
+impl<'a> MutVisitor for StripUnconfigured<'a> {
+    fn visit_foreign_mod(&mut self, foreign_mod: &mut ast::ForeignMod) {
+        self.configure_foreign_mod(foreign_mod);
+        noop_visit_foreign_mod(foreign_mod, self);
+    }
+
+    fn visit_item_kind(&mut self, item: &mut ast::ItemKind) {
+        self.configure_item_kind(item);
+        noop_visit_item_kind(item, self);
+    }
+
+    fn visit_expr(&mut self, expr: &mut P<ast::Expr>) {
+        self.configure_expr(expr);
+        self.configure_expr_kind(&mut expr.kind);
+        noop_visit_expr(expr, self);
+    }
+
+    fn filter_map_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
+        let mut expr = configure!(self, expr);
+        self.configure_expr_kind(&mut expr.kind);
+        noop_visit_expr(&mut expr, self);
+        Some(expr)
+    }
+
+    fn flat_map_stmt(&mut self, stmt: ast::Stmt) -> SmallVec<[ast::Stmt; 1]> {
+        noop_flat_map_stmt(configure!(self, stmt), self)
+    }
+
+    fn flat_map_item(&mut self, item: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
+        noop_flat_map_item(configure!(self, item), self)
+    }
+
+    fn flat_map_impl_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
+        noop_flat_map_assoc_item(configure!(self, item), self)
+    }
+
+    fn flat_map_trait_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
+        noop_flat_map_assoc_item(configure!(self, item), self)
+    }
+
+    fn visit_mac(&mut self, _mac: &mut ast::MacCall) {
+        // Don't configure interpolated AST (cf. issue #34171).
+        // Interpolated AST will get configured once the surrounding tokens are parsed.
+    }
+
+    fn visit_pat(&mut self, pat: &mut P<ast::Pat>) {
+        self.configure_pat(pat);
+        noop_visit_pat(pat, self)
+    }
+
+    fn visit_fn_decl(&mut self, mut fn_decl: &mut P<ast::FnDecl>) {
+        self.configure_fn_decl(&mut fn_decl);
+        noop_visit_fn_decl(fn_decl, self);
+    }
+}
+
+fn is_cfg(attr: &Attribute) -> bool {
+    attr.check_name(sym::cfg)
+}
index a2c512fda91ba686037f116959777338ab4ece1a..b6cc192cc33d6c6b86d64e4816aa8757b12252d3 100644 (file)
@@ -1,7 +1,9 @@
 use crate::base::*;
 use crate::config::StripUnconfigured;
+use crate::configure;
 use crate::hygiene::{ExpnData, ExpnId, ExpnKind, SyntaxContext};
 use crate::mbe::macro_rules::annotate_err_with_kind;
+use crate::module::{parse_external_mod, push_directory, Directory, DirectoryOwnership};
 use crate::placeholders::{placeholder, PlaceholderExpander};
 use crate::proc_macro::collect_derives;
 
 use rustc_ast::mut_visit::*;
 use rustc_ast::ptr::P;
 use rustc_ast::token;
-use rustc_ast::tokenstream::{TokenStream, TokenTree};
+use rustc_ast::tokenstream::TokenStream;
 use rustc_ast::util::map_in_place::MapInPlace;
 use rustc_ast::visit::{self, AssocCtxt, Visitor};
 use rustc_ast_pretty::pprust;
 use rustc_attr::{self as attr, is_builtin_attr, HasAttrs};
-use rustc_data_structures::sync::Lrc;
 use rustc_errors::{Applicability, FatalError, PResult};
 use rustc_feature::Features;
-use rustc_parse::configure;
 use rustc_parse::parser::Parser;
 use rustc_parse::validate_attr;
-use rustc_parse::DirectoryOwnership;
 use rustc_session::lint::builtin::UNUSED_DOC_COMMENTS;
 use rustc_session::lint::BuiltinLintDiagnostics;
 use rustc_session::parse::{feature_err, ParseSess};
@@ -272,7 +271,7 @@ pub struct Invocation {
 
 pub enum InvocationKind {
     Bang {
-        mac: ast::Mac,
+        mac: ast::MacCall,
         span: Span,
     },
     Attr {
@@ -409,7 +408,7 @@ pub fn fully_expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragm
         let mut undetermined_invocations = Vec::new();
         let (mut progress, mut force) = (false, !self.monotonic);
         loop {
-            let invoc = if let Some(invoc) = invocations.pop() {
+            let (invoc, res) = if let Some(invoc) = invocations.pop() {
                 invoc
             } else {
                 self.resolve_imports();
@@ -421,30 +420,51 @@ pub fn fully_expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragm
                 continue;
             };
 
-            let eager_expansion_root =
-                if self.monotonic { invoc.expansion_data.id } else { orig_expansion_data.id };
-            let res = match self.cx.resolver.resolve_macro_invocation(
-                &invoc,
-                eager_expansion_root,
-                force,
-            ) {
-                Ok(res) => res,
-                Err(Indeterminate) => {
-                    undetermined_invocations.push(invoc);
-                    continue;
+            let res = match res {
+                Some(res) => res,
+                None => {
+                    let eager_expansion_root = if self.monotonic {
+                        invoc.expansion_data.id
+                    } else {
+                        orig_expansion_data.id
+                    };
+                    match self.cx.resolver.resolve_macro_invocation(
+                        &invoc,
+                        eager_expansion_root,
+                        force,
+                    ) {
+                        Ok(res) => res,
+                        Err(Indeterminate) => {
+                            // Cannot resolve, will retry this invocation later.
+                            undetermined_invocations.push((invoc, None));
+                            continue;
+                        }
+                    }
                 }
             };
 
-            progress = true;
             let ExpansionData { depth, id: expn_id, .. } = invoc.expansion_data;
             self.cx.current_expansion = invoc.expansion_data.clone();
 
             // FIXME(jseyfried): Refactor out the following logic
             let (expanded_fragment, new_invocations) = match res {
-                InvocationRes::Single(ext) => {
-                    let fragment = self.expand_invoc(invoc, &ext.kind);
-                    self.collect_invocations(fragment, &[])
-                }
+                InvocationRes::Single(ext) => match self.expand_invoc(invoc, &ext.kind) {
+                    ExpandResult::Ready(fragment) => self.collect_invocations(fragment, &[]),
+                    ExpandResult::Retry(invoc, explanation) => {
+                        if force {
+                            // We are stuck, stop retrying and produce a dummy fragment.
+                            let span = invoc.span();
+                            self.cx.span_err(span, &explanation);
+                            let fragment = invoc.fragment_kind.dummy(span);
+                            self.collect_invocations(fragment, &[])
+                        } else {
+                            // Cannot expand, will retry this invocation later.
+                            undetermined_invocations
+                                .push((invoc, Some(InvocationRes::Single(ext))));
+                            continue;
+                        }
+                    }
+                },
                 InvocationRes::DeriveContainer(_exts) => {
                     // FIXME: Consider using the derive resolutions (`_exts`) immediately,
                     // instead of enqueuing the derives to be resolved again later.
@@ -464,14 +484,17 @@ pub fn fully_expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragm
                     for path in derives {
                         let expn_id = ExpnId::fresh(None);
                         derive_placeholders.push(NodeId::placeholder_from_expn_id(expn_id));
-                        invocations.push(Invocation {
-                            kind: InvocationKind::Derive { path, item: item.clone() },
-                            fragment_kind: invoc.fragment_kind,
-                            expansion_data: ExpansionData {
-                                id: expn_id,
-                                ..invoc.expansion_data.clone()
+                        invocations.push((
+                            Invocation {
+                                kind: InvocationKind::Derive { path, item: item.clone() },
+                                fragment_kind: invoc.fragment_kind,
+                                expansion_data: ExpansionData {
+                                    id: expn_id,
+                                    ..invoc.expansion_data.clone()
+                                },
                             },
-                        });
+                            None,
+                        ));
                     }
                     let fragment =
                         invoc.fragment_kind.expect_from_annotatables(::std::iter::once(item));
@@ -479,6 +502,7 @@ pub fn fully_expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragm
                 }
             };
 
+            progress = true;
             if expanded_fragments.len() < depth {
                 expanded_fragments.push(Vec::new());
             }
@@ -536,7 +560,7 @@ fn collect_invocations(
         &mut self,
         mut fragment: AstFragment,
         extra_placeholders: &[NodeId],
-    ) -> (AstFragment, Vec<Invocation>) {
+    ) -> (AstFragment, Vec<(Invocation, Option<InvocationRes>)>) {
         // Resolve `$crate`s in the fragment for pretty-printing.
         self.cx.resolver.resolve_dollar_crates();
 
@@ -626,7 +650,7 @@ fn error_recursion_limit_reached(&mut self) {
 
     /// A macro's expansion does not fit in this fragment kind.
     /// For example, a non-type macro in a type position.
-    fn error_wrong_fragment_kind(&mut self, kind: AstFragmentKind, mac: &ast::Mac, span: Span) {
+    fn error_wrong_fragment_kind(&mut self, kind: AstFragmentKind, mac: &ast::MacCall, span: Span) {
         let msg = format!(
             "non-{kind} macro in {kind} position: {path}",
             kind = kind.name(),
@@ -636,13 +660,17 @@ fn error_wrong_fragment_kind(&mut self, kind: AstFragmentKind, mac: &ast::Mac, s
         self.cx.trace_macros_diag();
     }
 
-    fn expand_invoc(&mut self, invoc: Invocation, ext: &SyntaxExtensionKind) -> AstFragment {
+    fn expand_invoc(
+        &mut self,
+        invoc: Invocation,
+        ext: &SyntaxExtensionKind,
+    ) -> ExpandResult<AstFragment, Invocation> {
         if self.cx.current_expansion.depth > self.cx.ecfg.recursion_limit {
             self.error_recursion_limit_reached();
         }
 
         let (fragment_kind, span) = (invoc.fragment_kind, invoc.span());
-        match invoc.kind {
+        ExpandResult::Ready(match invoc.kind {
             InvocationKind::Bang { mac, .. } => match ext {
                 SyntaxExtensionKind::Bang(expander) => {
                     self.gate_proc_macro_expansion_kind(span, fragment_kind);
@@ -664,47 +692,41 @@ fn expand_invoc(&mut self, invoc: Invocation, ext: &SyntaxExtensionKind) -> AstF
                 }
                 _ => unreachable!(),
             },
-            InvocationKind::Attr { attr, mut item, .. } => match ext {
+            InvocationKind::Attr { attr, mut item, derives, after_derive } => match ext {
                 SyntaxExtensionKind::Attr(expander) => {
                     self.gate_proc_macro_input(&item);
                     self.gate_proc_macro_attr_item(span, &item);
-                    // `Annotatable` can be converted into tokens directly, but we are packing it
-                    // into a nonterminal as a piece of AST to make the produced token stream
-                    // look nicer in pretty-printed form. This may be no longer necessary.
-                    let item_tok = TokenTree::token(
-                        token::Interpolated(Lrc::new(match item {
-                            Annotatable::Item(item) => token::NtItem(item),
-                            Annotatable::TraitItem(item)
-                            | Annotatable::ImplItem(item)
-                            | Annotatable::ForeignItem(item) => {
-                                token::NtItem(P(item.and_then(ast::AssocItem::into_item)))
-                            }
-                            Annotatable::Stmt(stmt) => token::NtStmt(stmt.into_inner()),
-                            Annotatable::Expr(expr) => token::NtExpr(expr),
-                            Annotatable::Arm(..)
-                            | Annotatable::Field(..)
-                            | Annotatable::FieldPat(..)
-                            | Annotatable::GenericParam(..)
-                            | Annotatable::Param(..)
-                            | Annotatable::StructField(..)
-                            | Annotatable::Variant(..) => panic!("unexpected annotatable"),
-                        })),
-                        DUMMY_SP,
-                    )
-                    .into();
-                    let item = attr.unwrap_normal_item();
-                    if let MacArgs::Eq(..) = item.args {
+                    let tokens = item.into_tokens();
+                    let attr_item = attr.unwrap_normal_item();
+                    if let MacArgs::Eq(..) = attr_item.args {
                         self.cx.span_err(span, "key-value macro attributes are not supported");
                     }
                     let tok_result =
-                        expander.expand(self.cx, span, item.args.inner_tokens(), item_tok);
-                    self.parse_ast_fragment(tok_result, fragment_kind, &item.path, span)
+                        expander.expand(self.cx, span, attr_item.args.inner_tokens(), tokens);
+                    self.parse_ast_fragment(tok_result, fragment_kind, &attr_item.path, span)
                 }
                 SyntaxExtensionKind::LegacyAttr(expander) => {
                     match validate_attr::parse_meta(self.cx.parse_sess, &attr) {
                         Ok(meta) => {
-                            let item = expander.expand(self.cx, span, &meta, item);
-                            fragment_kind.expect_from_annotatables(item)
+                            let items = match expander.expand(self.cx, span, &meta, item) {
+                                ExpandResult::Ready(items) => items,
+                                ExpandResult::Retry(item, explanation) => {
+                                    // Reassemble the original invocation for retrying.
+                                    return ExpandResult::Retry(
+                                        Invocation {
+                                            kind: InvocationKind::Attr {
+                                                attr,
+                                                item,
+                                                derives,
+                                                after_derive,
+                                            },
+                                            ..invoc
+                                        },
+                                        explanation,
+                                    );
+                                }
+                            };
+                            fragment_kind.expect_from_annotatables(items)
                         }
                         Err(mut err) => {
                             err.emit();
@@ -726,19 +748,31 @@ fn expand_invoc(&mut self, invoc: Invocation, ext: &SyntaxExtensionKind) -> AstF
                 SyntaxExtensionKind::Derive(expander)
                 | SyntaxExtensionKind::LegacyDerive(expander) => {
                     if !item.derive_allowed() {
-                        return fragment_kind.dummy(span);
+                        return ExpandResult::Ready(fragment_kind.dummy(span));
                     }
                     if let SyntaxExtensionKind::Derive(..) = ext {
                         self.gate_proc_macro_input(&item);
                     }
                     let meta = ast::MetaItem { kind: ast::MetaItemKind::Word, span, path };
-                    let items = expander.expand(self.cx, span, &meta, item);
+                    let items = match expander.expand(self.cx, span, &meta, item) {
+                        ExpandResult::Ready(items) => items,
+                        ExpandResult::Retry(item, explanation) => {
+                            // Reassemble the original invocation for retrying.
+                            return ExpandResult::Retry(
+                                Invocation {
+                                    kind: InvocationKind::Derive { path: meta.path, item },
+                                    ..invoc
+                                },
+                                explanation,
+                            );
+                        }
+                    };
                     fragment_kind.expect_from_annotatables(items)
                 }
                 _ => unreachable!(),
             },
             InvocationKind::DeriveContainer { .. } => unreachable!(),
-        }
+        })
     }
 
     fn gate_proc_macro_attr_item(&self, span: Span, item: &Annotatable) {
@@ -792,7 +826,7 @@ fn visit_item(&mut self, item: &'ast ast::Item) {
                 visit::walk_item(self, item);
             }
 
-            fn visit_mac(&mut self, _: &'ast ast::Mac) {}
+            fn visit_mac(&mut self, _: &'ast ast::MacCall) {}
         }
 
         if !self.cx.ecfg.proc_macro_hygiene() {
@@ -957,7 +991,7 @@ pub fn ensure_complete_parse<'a>(
 struct InvocationCollector<'a, 'b> {
     cx: &'a mut ExtCtxt<'b>,
     cfg: StripUnconfigured<'a>,
-    invocations: Vec<Invocation>,
+    invocations: Vec<(Invocation, Option<InvocationRes>)>,
     monotonic: bool,
 }
 
@@ -979,19 +1013,27 @@ fn collect(&mut self, fragment_kind: AstFragmentKind, kind: InvocationKind) -> A
         };
         let expn_id = ExpnId::fresh(expn_data);
         let vis = kind.placeholder_visibility();
-        self.invocations.push(Invocation {
-            kind,
-            fragment_kind,
-            expansion_data: ExpansionData {
-                id: expn_id,
-                depth: self.cx.current_expansion.depth + 1,
-                ..self.cx.current_expansion.clone()
+        self.invocations.push((
+            Invocation {
+                kind,
+                fragment_kind,
+                expansion_data: ExpansionData {
+                    id: expn_id,
+                    depth: self.cx.current_expansion.depth + 1,
+                    ..self.cx.current_expansion.clone()
+                },
             },
-        });
+            None,
+        ));
         placeholder(fragment_kind, NodeId::placeholder_from_expn_id(expn_id), vis)
     }
 
-    fn collect_bang(&mut self, mac: ast::Mac, span: Span, kind: AstFragmentKind) -> AstFragment {
+    fn collect_bang(
+        &mut self,
+        mac: ast::MacCall,
+        span: Span,
+        kind: AstFragmentKind,
+    ) -> AstFragment {
         self.collect(kind, InvocationKind::Bang { mac, span })
     }
 
@@ -1134,7 +1176,7 @@ fn visit_expr(&mut self, expr: &mut P<ast::Expr>) {
                     .into_inner();
             }
 
-            if let ast::ExprKind::Mac(mac) = expr.kind {
+            if let ast::ExprKind::MacCall(mac) = expr.kind {
                 self.check_attributes(&expr.attrs);
                 self.collect_bang(mac, expr.span, AstFragmentKind::Expr).make_expr().into_inner()
             } else {
@@ -1281,7 +1323,7 @@ fn filter_map_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
                     .map(|expr| expr.into_inner());
             }
 
-            if let ast::ExprKind::Mac(mac) = expr.kind {
+            if let ast::ExprKind::MacCall(mac) = expr.kind {
                 self.check_attributes(&expr.attrs);
                 self.collect_bang(mac, expr.span, AstFragmentKind::OptExpr)
                     .make_opt_expr()
@@ -1298,12 +1340,14 @@ fn filter_map_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
     fn visit_pat(&mut self, pat: &mut P<ast::Pat>) {
         self.cfg.configure_pat(pat);
         match pat.kind {
-            PatKind::Mac(_) => {}
+            PatKind::MacCall(_) => {}
             _ => return noop_visit_pat(pat, self),
         }
 
         visit_clobber(pat, |mut pat| match mem::replace(&mut pat.kind, PatKind::Wild) {
-            PatKind::Mac(mac) => self.collect_bang(mac, pat.span, AstFragmentKind::Pat).make_pat(),
+            PatKind::MacCall(mac) => {
+                self.collect_bang(mac, pat.span, AstFragmentKind::Pat).make_pat()
+            }
             _ => unreachable!(),
         });
     }
@@ -1335,7 +1379,7 @@ fn visit_pat(&mut self, pat: &mut P<ast::Pat>) {
             }
         }
 
-        if let StmtKind::Mac(mac) = stmt.kind {
+        if let StmtKind::MacCall(mac) = stmt.kind {
             let (mac, style, attrs) = mac.into_inner();
             self.check_attributes(&attrs);
             let mut placeholder =
@@ -1383,59 +1427,83 @@ fn visit_block(&mut self, block: &mut P<Block>) {
                 .make_items();
         }
 
+        let mut attrs = mem::take(&mut item.attrs); // We do this to please borrowck.
+        let ident = item.ident;
+        let span = item.span;
+
         match item.kind {
-            ast::ItemKind::Mac(..) => {
+            ast::ItemKind::MacCall(..) => {
+                item.attrs = attrs;
                 self.check_attributes(&item.attrs);
                 item.and_then(|item| match item.kind {
-                    ItemKind::Mac(mac) => self
-                        .collect(
-                            AstFragmentKind::Items,
-                            InvocationKind::Bang { mac, span: item.span },
-                        )
+                    ItemKind::MacCall(mac) => self
+                        .collect(AstFragmentKind::Items, InvocationKind::Bang { mac, span })
                         .make_items(),
                     _ => unreachable!(),
                 })
             }
-            ast::ItemKind::Mod(ast::Mod { inner, inline, .. })
-                if item.ident != Ident::invalid() =>
-            {
-                let orig_directory_ownership = self.cx.current_expansion.directory_ownership;
+            ast::ItemKind::Mod(ref mut old_mod @ ast::Mod { .. }) if ident != Ident::invalid() => {
+                let sess = self.cx.parse_sess;
+                let orig_ownership = self.cx.current_expansion.directory_ownership;
                 let mut module = (*self.cx.current_expansion.module).clone();
-                module.mod_path.push(item.ident);
 
-                if inline {
-                    if let Some(path) = attr::first_attr_value_str_by_name(&item.attrs, sym::path) {
-                        self.cx.current_expansion.directory_ownership =
-                            DirectoryOwnership::Owned { relative: None };
-                        module.directory.push(&*path.as_str());
-                    } else {
-                        module.directory.push(&*item.ident.as_str());
-                    }
+                let pushed = &mut false; // Record `parse_external_mod` pushing so we can pop.
+                let dir = Directory { ownership: orig_ownership, path: module.directory };
+                let Directory { ownership, path } = if old_mod.inline {
+                    // Inline `mod foo { ... }`, but we still need to push directories.
+                    item.attrs = attrs;
+                    push_directory(ident, &item.attrs, dir)
                 } else {
-                    let path = self.cx.parse_sess.source_map().span_to_unmapped_path(inner);
-                    let mut path = match path {
-                        FileName::Real(path) => path,
-                        other => PathBuf::from(other.to_string()),
+                    // We have an outline `mod foo;` so we need to parse the file.
+                    let (new_mod, dir) =
+                        parse_external_mod(sess, ident, span, dir, &mut attrs, pushed);
+
+                    let krate = ast::Crate {
+                        span: new_mod.inner,
+                        module: new_mod,
+                        attrs,
+                        proc_macros: vec![],
                     };
-                    let directory_ownership = match path.file_name().unwrap().to_str() {
-                        Some("mod.rs") => DirectoryOwnership::Owned { relative: None },
-                        Some(_) => DirectoryOwnership::Owned { relative: Some(item.ident) },
-                        None => DirectoryOwnership::UnownedViaMod,
+                    if let Some(extern_mod_loaded) = self.cx.extern_mod_loaded {
+                        extern_mod_loaded(&krate);
+                    }
+
+                    *old_mod = krate.module;
+                    item.attrs = krate.attrs;
+                    // File can have inline attributes, e.g., `#![cfg(...)]` & co. => Reconfigure.
+                    item = match self.configure(item) {
+                        Some(node) => node,
+                        None => {
+                            if *pushed {
+                                sess.included_mod_stack.borrow_mut().pop();
+                            }
+                            return Default::default();
+                        }
                     };
-                    path.pop();
-                    module.directory = path;
-                    self.cx.current_expansion.directory_ownership = directory_ownership;
-                }
+                    dir
+                };
 
+                // Set the module info before we flat map.
+                self.cx.current_expansion.directory_ownership = ownership;
+                module.directory = path;
+                module.mod_path.push(ident);
                 let orig_module =
                     mem::replace(&mut self.cx.current_expansion.module, Rc::new(module));
+
                 let result = noop_flat_map_item(item, self);
+
+                // Restore the module info.
                 self.cx.current_expansion.module = orig_module;
-                self.cx.current_expansion.directory_ownership = orig_directory_ownership;
+                self.cx.current_expansion.directory_ownership = orig_ownership;
+                if *pushed {
+                    sess.included_mod_stack.borrow_mut().pop();
+                }
                 result
             }
-
-            _ => noop_flat_map_item(item, self),
+            _ => {
+                item.attrs = attrs;
+                noop_flat_map_item(item, self)
+            }
         }
     }
 
@@ -1456,10 +1524,10 @@ fn visit_block(&mut self, block: &mut P<Block>) {
         }
 
         match item.kind {
-            ast::AssocItemKind::Macro(..) => {
+            ast::AssocItemKind::MacCall(..) => {
                 self.check_attributes(&item.attrs);
                 item.and_then(|item| match item.kind {
-                    ast::AssocItemKind::Macro(mac) => self
+                    ast::AssocItemKind::MacCall(mac) => self
                         .collect_bang(mac, item.span, AstFragmentKind::TraitItems)
                         .make_trait_items(),
                     _ => unreachable!(),
@@ -1486,10 +1554,10 @@ fn visit_block(&mut self, block: &mut P<Block>) {
         }
 
         match item.kind {
-            ast::AssocItemKind::Macro(..) => {
+            ast::AssocItemKind::MacCall(..) => {
                 self.check_attributes(&item.attrs);
                 item.and_then(|item| match item.kind {
-                    ast::AssocItemKind::Macro(mac) => self
+                    ast::AssocItemKind::MacCall(mac) => self
                         .collect_bang(mac, item.span, AstFragmentKind::ImplItems)
                         .make_impl_items(),
                     _ => unreachable!(),
@@ -1501,12 +1569,14 @@ fn visit_block(&mut self, block: &mut P<Block>) {
 
     fn visit_ty(&mut self, ty: &mut P<ast::Ty>) {
         match ty.kind {
-            ast::TyKind::Mac(_) => {}
+            ast::TyKind::MacCall(_) => {}
             _ => return noop_visit_ty(ty, self),
         };
 
         visit_clobber(ty, |mut ty| match mem::replace(&mut ty.kind, ast::TyKind::Err) {
-            ast::TyKind::Mac(mac) => self.collect_bang(mac, ty.span, AstFragmentKind::Ty).make_ty(),
+            ast::TyKind::MacCall(mac) => {
+                self.collect_bang(mac, ty.span, AstFragmentKind::Ty).make_ty()
+            }
             _ => unreachable!(),
         });
     }
@@ -1535,10 +1605,10 @@ fn flat_map_foreign_item(
         }
 
         match foreign_item.kind {
-            ast::ForeignItemKind::Macro(..) => {
+            ast::ForeignItemKind::MacCall(..) => {
                 self.check_attributes(&foreign_item.attrs);
                 foreign_item.and_then(|item| match item.kind {
-                    ast::ForeignItemKind::Macro(mac) => self
+                    ast::ForeignItemKind::MacCall(mac) => self
                         .collect_bang(mac, item.span, AstFragmentKind::ForeignItems)
                         .make_foreign_items(),
                     _ => unreachable!(),
index f119c956ced04e078bef2d823b97041276eb4f71..0320a275e5d20de35c773dd602a57768785551c4 100644 (file)
@@ -1,9 +1,11 @@
+#![feature(bool_to_option)]
 #![feature(cow_is_borrowed)]
 #![feature(crate_visibility_modifier)]
 #![feature(decl_macro)]
 #![feature(proc_macro_diagnostic)]
 #![feature(proc_macro_internals)]
 #![feature(proc_macro_span)]
+#![feature(try_blocks)]
 
 extern crate proc_macro as pm;
 
@@ -33,8 +35,10 @@ macro_rules! panictry {
 crate use rustc_span::hygiene;
 pub mod base;
 pub mod build;
+#[macro_use]
+pub mod config;
 pub mod expand;
-pub use rustc_parse::config;
+pub mod module;
 pub mod proc_macro;
 
 crate mod mbe;
index 6eb834beac6522f77aa00950a6ae1b29561ac73a..582c26162ed6d29e2cfb72cef169c71f7c7a5073 100644 (file)
 use rustc_session::lint::builtin::META_VARIABLE_MISUSE;
 use rustc_session::parse::ParseSess;
 use rustc_span::symbol::kw;
-use rustc_span::{symbol::Ident, MultiSpan, Span};
+use rustc_span::{symbol::MacroRulesNormalizedIdent, MultiSpan, Span};
 
 use smallvec::SmallVec;
 
@@ -179,7 +179,7 @@ struct BinderInfo {
 }
 
 /// An environment of meta-variables to their binder information.
-type Binders = FxHashMap<Ident, BinderInfo>;
+type Binders = FxHashMap<MacroRulesNormalizedIdent, BinderInfo>;
 
 /// The state at which we entered a macro definition in the RHS of another macro definition.
 struct MacroState<'a> {
@@ -245,6 +245,7 @@ fn check_binders(
             if macros.is_empty() {
                 sess.span_diagnostic.span_bug(span, "unexpected MetaVar in lhs");
             }
+            let name = MacroRulesNormalizedIdent::new(name);
             // There are 3 possibilities:
             if let Some(prev_info) = binders.get(&name) {
                 // 1. The meta-variable is already bound in the current LHS: This is an error.
@@ -264,6 +265,7 @@ fn check_binders(
             if !macros.is_empty() {
                 sess.span_diagnostic.span_bug(span, "unexpected MetaVarDecl in nested lhs");
             }
+            let name = MacroRulesNormalizedIdent::new(name);
             if let Some(prev_info) = get_binder_info(macros, binders, name) {
                 // Duplicate binders at the top-level macro definition are errors. The lint is only
                 // for nested macro definitions.
@@ -300,7 +302,7 @@ fn check_binders(
 fn get_binder_info<'a>(
     mut macros: &'a Stack<'a, MacroState<'a>>,
     binders: &'a Binders,
-    name: Ident,
+    name: MacroRulesNormalizedIdent,
 ) -> Option<&'a BinderInfo> {
     binders.get(&name).or_else(|| macros.find_map(|state| state.binders.get(&name)))
 }
@@ -331,6 +333,7 @@ fn check_occurrences(
             sess.span_diagnostic.span_bug(span, "unexpected MetaVarDecl in rhs")
         }
         TokenTree::MetaVar(span, name) => {
+            let name = MacroRulesNormalizedIdent::new(name);
             check_ops_is_prefix(sess, node_id, macros, binders, ops, span, name);
         }
         TokenTree::Delimited(_, ref del) => {
@@ -419,10 +422,10 @@ fn check_nested_occurrences(
             | (NestedMacroState::MacroName, &TokenTree::Delimited(_, ref del))
                 if del.delim == DelimToken::Brace =>
             {
-                let legacy = state == NestedMacroState::MacroRulesNotName;
+                let macro_rules = state == NestedMacroState::MacroRulesNotName;
                 state = NestedMacroState::Empty;
                 let rest =
-                    check_nested_macro(sess, node_id, legacy, &del.tts, &nested_macros, valid);
+                    check_nested_macro(sess, node_id, macro_rules, &del.tts, &nested_macros, valid);
                 // If we did not check the whole macro definition, then check the rest as if outside
                 // the macro definition.
                 check_nested_occurrences(
@@ -493,21 +496,21 @@ fn check_nested_occurrences(
 /// Arguments:
 /// - `sess` is used to emit diagnostics and lints
 /// - `node_id` is used to emit lints
-/// - `legacy` specifies whether the macro is legacy
+/// - `macro_rules` specifies whether the macro is `macro_rules`
 /// - `tts` is checked as a list of (LHS) => {RHS}
 /// - `macros` is the stack of outer macros
 /// - `valid` is set in case of errors
 fn check_nested_macro(
     sess: &ParseSess,
     node_id: NodeId,
-    legacy: bool,
+    macro_rules: bool,
     tts: &[TokenTree],
     macros: &Stack<'_, MacroState<'_>>,
     valid: &mut bool,
 ) -> usize {
     let n = tts.len();
     let mut i = 0;
-    let separator = if legacy { TokenKind::Semi } else { TokenKind::Comma };
+    let separator = if macro_rules { TokenKind::Semi } else { TokenKind::Comma };
     loop {
         // We expect 3 token trees: `(LHS) => {RHS}`. The separator is checked after.
         if i + 2 >= n
@@ -522,7 +525,7 @@ fn check_nested_macro(
         let mut binders = Binders::default();
         check_binders(sess, node_id, lhs, macros, &mut binders, &Stack::Empty, valid);
         check_occurrences(sess, node_id, rhs, macros, &binders, &Stack::Empty, valid);
-        // Since the last semicolon is optional for legacy macros and decl_macro are not terminated,
+        // Since the last semicolon is optional for `macro_rules` macros and decl_macro are not terminated,
         // we increment our checked position by how many token trees we already checked (the 3
         // above) before checking for the separator.
         i += 3;
@@ -552,7 +555,7 @@ fn check_ops_is_prefix(
     binders: &Binders,
     ops: &Stack<'_, KleeneToken>,
     span: Span,
-    name: Ident,
+    name: MacroRulesNormalizedIdent,
 ) {
     let macros = macros.push(MacroState { binders, ops: ops.into() });
     // Accumulates the stacks the operators of each state until (and including when) the
@@ -598,7 +601,7 @@ fn ops_is_prefix(
     sess: &ParseSess,
     node_id: NodeId,
     span: Span,
-    name: Ident,
+    name: MacroRulesNormalizedIdent,
     binder_ops: &[KleeneToken],
     occurrence_ops: &[KleeneToken],
 ) {
index d2a5c54aae49063437a3ef9e88f1b0e53f35a92c..3b9158f444519f1cc64c80244b9c874789242444 100644 (file)
 
 use crate::mbe::{self, TokenTree};
 
-use rustc_ast::ast::{Ident, Name};
+use rustc_ast::ast::Name;
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, DocComment, Nonterminal, Token};
 use rustc_ast_pretty::pprust;
 use rustc_parse::parser::{FollowedByType, Parser, PathStyle};
 use rustc_session::parse::ParseSess;
-use rustc_span::symbol::{kw, sym, Symbol};
+use rustc_span::symbol::{kw, sym, Ident, MacroRulesNormalizedIdent, Symbol};
 
 use rustc_errors::{FatalError, PResult};
 use rustc_span::Span;
@@ -273,9 +273,10 @@ fn deref_mut(&mut self) -> &mut MatcherPos<'root, 'tt> {
     Error(rustc_span::Span, String),
 }
 
-/// A `ParseResult` where the `Success` variant contains a mapping of `Ident`s to `NamedMatch`es.
-/// This represents the mapping of metavars to the token trees they bind to.
-crate type NamedParseResult = ParseResult<FxHashMap<Ident, NamedMatch>>;
+/// A `ParseResult` where the `Success` variant contains a mapping of
+/// `MacroRulesNormalizedIdent`s to `NamedMatch`es. This represents the mapping
+/// of metavars to the token trees they bind to.
+crate type NamedParseResult = ParseResult<FxHashMap<MacroRulesNormalizedIdent, NamedMatch>>;
 
 /// Count how many metavars are named in the given matcher `ms`.
 pub(super) fn count_names(ms: &[TokenTree]) -> usize {
@@ -368,7 +369,7 @@ fn n_rec<I: Iterator<Item = NamedMatch>>(
         sess: &ParseSess,
         m: &TokenTree,
         res: &mut I,
-        ret_val: &mut FxHashMap<Ident, NamedMatch>,
+        ret_val: &mut FxHashMap<MacroRulesNormalizedIdent, NamedMatch>,
     ) -> Result<(), (rustc_span::Span, String)> {
         match *m {
             TokenTree::Sequence(_, ref seq) => {
@@ -386,7 +387,9 @@ fn n_rec<I: Iterator<Item = NamedMatch>>(
                     return Err((span, "missing fragment specifier".to_string()));
                 }
             }
-            TokenTree::MetaVarDecl(sp, bind_name, _) => match ret_val.entry(bind_name) {
+            TokenTree::MetaVarDecl(sp, bind_name, _) => match ret_val
+                .entry(MacroRulesNormalizedIdent::new(bind_name))
+            {
                 Vacant(spot) => {
                     spot.insert(res.next().unwrap());
                 }
@@ -750,17 +753,8 @@ pub(super) fn parse_tt(parser: &mut Cow<'_, Parser<'_>>, ms: &[TokenTree]) -> Na
 
 /// The token is an identifier, but not `_`.
 /// We prohibit passing `_` to macros expecting `ident` for now.
-fn get_macro_name(token: &Token) -> Option<(Name, bool)> {
-    match token.kind {
-        token::Ident(name, is_raw) if name != kw::Underscore => Some((name, is_raw)),
-        token::Interpolated(ref nt) => match **nt {
-            token::NtIdent(ident, is_raw) if ident.name != kw::Underscore => {
-                Some((ident.name, is_raw))
-            }
-            _ => None,
-        },
-        _ => None,
-    }
+fn get_macro_ident(token: &Token) -> Option<(Ident, bool)> {
+    token.ident().filter(|(ident, _)| ident.name != kw::Underscore)
 }
 
 /// Checks whether a non-terminal may begin with a particular token.
@@ -783,7 +777,7 @@ fn may_be_ident(nt: &token::Nonterminal) -> bool {
             && !token.is_keyword(kw::Let)
         }
         sym::ty => token.can_begin_type(),
-        sym::ident => get_macro_name(token).is_some(),
+        sym::ident => get_macro_ident(token).is_some(),
         sym::literal => token.can_begin_literal_or_bool(),
         sym::vis => match token.kind {
             // The follow-set of :vis + "priv" keyword + interpolated
@@ -888,9 +882,9 @@ fn parse_nt_inner<'a>(p: &mut Parser<'a>, sp: Span, name: Symbol) -> PResult<'a,
         sym::ty => token::NtTy(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) {
+            if let Some((ident, is_raw)) = get_macro_ident(&p.token) {
                 p.bump();
-                token::NtIdent(Ident::new(name, p.normalized_prev_token.span), is_raw)
+                token::NtIdent(ident, is_raw)
             } else {
                 let token_str = pprust::token_to_string(&p.token);
                 let msg = &format!("expected ident, found {}", &token_str);
index b02c935039512239909c33b0e89e88e69464de27..3de2169f1142e41560a76cdee472263724fbd08a 100644 (file)
@@ -1,4 +1,4 @@
-use crate::base::{DummyResult, ExpansionData, ExtCtxt, MacResult, TTMacroExpander};
+use crate::base::{DummyResult, ExtCtxt, MacResult, TTMacroExpander};
 use crate::base::{SyntaxExtension, SyntaxExtensionKind};
 use crate::expand::{ensure_complete_parse, parse_ast_fragment, AstFragment, AstFragmentKind};
 use crate::mbe;
 use rustc_errors::{Applicability, DiagnosticBuilder, FatalError};
 use rustc_feature::Features;
 use rustc_parse::parser::Parser;
-use rustc_parse::Directory;
 use rustc_session::parse::ParseSess;
 use rustc_span::edition::Edition;
 use rustc_span::hygiene::Transparency;
-use rustc_span::symbol::{kw, sym, Symbol};
+use rustc_span::symbol::{kw, sym, MacroRulesNormalizedIdent, Symbol};
 use rustc_span::Span;
 
 use log::debug;
@@ -105,10 +104,10 @@ impl<'a> ParserAnyMacro<'a> {
             if e.span.is_dummy() {
                 // Get around lack of span in error (#30128)
                 e.replace_span_with(site_span);
-                if parser.sess.source_map().span_to_filename(arm_span).is_real() {
+                if !parser.sess.source_map().is_imported(arm_span) {
                     e.span_label(arm_span, "in this macro arm");
                 }
-            } else if !parser.sess.source_map().span_to_filename(parser.token.span).is_real() {
+            } else if parser.sess.source_map().is_imported(parser.token.span) {
                 e.span_label(site_span, "in this macro invocation");
             }
             match kind {
@@ -182,6 +181,8 @@ fn generic_extension<'cx>(
     lhses: &[mbe::TokenTree],
     rhses: &[mbe::TokenTree],
 ) -> Box<dyn MacResult + 'cx> {
+    let sess = cx.parse_sess;
+
     if cx.trace_macros() {
         let msg = format!("expanding `{}! {{ {} }}`", name, pprust::tts_to_string(arg.clone()));
         trace_macros_note(&mut cx.expansions, sp, msg);
@@ -209,7 +210,7 @@ fn generic_extension<'cx>(
     // hacky, but speeds up the `html5ever` benchmark significantly. (Issue
     // 68836 suggests a more comprehensive but more complex change to deal with
     // this situation.)
-    let parser = parser_from_cx(&cx.current_expansion, &cx.parse_sess, arg.clone());
+    let parser = parser_from_cx(sess, arg.clone());
 
     for (i, lhs) in lhses.iter().enumerate() {
         // try each arm's matchers
@@ -222,14 +223,13 @@ fn generic_extension<'cx>(
         // This is used so that if a matcher is not `Success(..)`ful,
         // then the spans which became gated when parsing the unsuccessful matcher
         // are not recorded. On the first `Success(..)`ful matcher, the spans are merged.
-        let mut gated_spans_snapshot =
-            mem::take(&mut *cx.parse_sess.gated_spans.spans.borrow_mut());
+        let mut gated_spans_snapshot = mem::take(&mut *sess.gated_spans.spans.borrow_mut());
 
         match parse_tt(&mut Cow::Borrowed(&parser), lhs_tt) {
             Success(named_matches) => {
                 // The matcher was `Success(..)`ful.
                 // Merge the gated spans from parsing the matcher with the pre-existing ones.
-                cx.parse_sess.gated_spans.merge(gated_spans_snapshot);
+                sess.gated_spans.merge(gated_spans_snapshot);
 
                 let rhs = match rhses[i] {
                     // ignore delimiters
@@ -258,11 +258,7 @@ fn generic_extension<'cx>(
                     trace_macros_note(&mut cx.expansions, sp, msg);
                 }
 
-                let directory = Directory {
-                    path: cx.current_expansion.module.directory.clone(),
-                    ownership: cx.current_expansion.directory_ownership,
-                };
-                let mut p = Parser::new(cx.parse_sess(), tts, Some(directory), true, false, None);
+                let mut p = Parser::new(sess, tts, false, None);
                 p.root_module_name =
                     cx.current_expansion.module.mod_path.last().map(|id| id.to_string());
                 p.last_type_ascription = cx.current_expansion.prior_type_ascription;
@@ -289,7 +285,7 @@ fn generic_extension<'cx>(
 
         // The matcher was not `Success(..)`ful.
         // Restore to the state before snapshotting and maybe try again.
-        mem::swap(&mut gated_spans_snapshot, &mut cx.parse_sess.gated_spans.spans.borrow_mut());
+        mem::swap(&mut gated_spans_snapshot, &mut sess.gated_spans.spans.borrow_mut());
     }
     drop(parser);
 
@@ -297,7 +293,7 @@ fn generic_extension<'cx>(
     let span = token.span.substitute_dummy(sp);
     let mut err = cx.struct_span_err(span, &parse_failure_msg(&token));
     err.span_label(span, label);
-    if !def_span.is_dummy() && cx.source_map().span_to_filename(def_span).is_real() {
+    if !def_span.is_dummy() && !cx.source_map().is_imported(def_span) {
         err.span_label(cx.source_map().def_span(def_span), "when calling this macro");
     }
 
@@ -309,8 +305,7 @@ fn generic_extension<'cx>(
                 mbe::TokenTree::Delimited(_, ref delim) => &delim.tts[..],
                 _ => continue,
             };
-            let parser = parser_from_cx(&cx.current_expansion, &cx.parse_sess, arg.clone());
-            match parse_tt(&mut Cow::Borrowed(&parser), lhs_tt) {
+            match parse_tt(&mut Cow::Borrowed(&parser_from_cx(sess, arg.clone())), lhs_tt) {
                 Success(_) => {
                     if comma_span.is_dummy() {
                         err.note("you might be missing a comma");
@@ -350,8 +345,8 @@ pub fn compile_declarative_macro(
     let tt_spec = ast::Ident::new(sym::tt, def.span);
 
     // Parse the macro_rules! invocation
-    let (is_legacy, body) = match &def.kind {
-        ast::ItemKind::MacroDef(macro_def) => (macro_def.legacy, macro_def.body.inner_tokens()),
+    let (macro_rules, body) = match &def.kind {
+        ast::ItemKind::MacroDef(def) => (def.macro_rules, def.body.inner_tokens()),
         _ => unreachable!(),
     };
 
@@ -370,7 +365,7 @@ pub fn compile_declarative_macro(
                     mbe::TokenTree::MetaVarDecl(def.span, rhs_nm, tt_spec),
                 ],
                 separator: Some(Token::new(
-                    if is_legacy { token::Semi } else { token::Comma },
+                    if macro_rules { token::Semi } else { token::Comma },
                     def.span,
                 )),
                 kleene: mbe::KleeneToken::new(mbe::KleeneOp::OneOrMore, def.span),
@@ -382,7 +377,7 @@ pub fn compile_declarative_macro(
             DelimSpan::dummy(),
             Lrc::new(mbe::SequenceRepetition {
                 tts: vec![mbe::TokenTree::token(
-                    if is_legacy { token::Semi } else { token::Comma },
+                    if macro_rules { token::Semi } else { token::Comma },
                     def.span,
                 )],
                 separator: None,
@@ -392,7 +387,7 @@ pub fn compile_declarative_macro(
         ),
     ];
 
-    let parser = Parser::new(sess, body, None, true, true, rustc_parse::MACRO_ARGUMENTS);
+    let parser = Parser::new(sess, body, true, rustc_parse::MACRO_ARGUMENTS);
     let argument_map = match parse_tt(&mut Cow::Borrowed(&parser), &argument_gram) {
         Success(m) => m,
         Failure(token, msg) => {
@@ -411,7 +406,7 @@ pub fn compile_declarative_macro(
     let mut valid = true;
 
     // Extract the arguments:
-    let lhses = match argument_map[&lhs_nm] {
+    let lhses = match argument_map[&MacroRulesNormalizedIdent::new(lhs_nm)] {
         MatchedSeq(ref s) => s
             .iter()
             .map(|m| {
@@ -428,7 +423,7 @@ pub fn compile_declarative_macro(
         _ => sess.span_diagnostic.span_bug(def.span, "wrong-structured lhs"),
     };
 
-    let rhses = match argument_map[&rhs_nm] {
+    let rhses = match argument_map[&MacroRulesNormalizedIdent::new(rhs_nm)] {
         MatchedSeq(ref s) => s
             .iter()
             .map(|m| {
@@ -456,7 +451,7 @@ pub fn compile_declarative_macro(
     // that is not lint-checked and trigger the "failed to process buffered lint here" bug.
     valid &= macro_check::check_meta_variables(sess, ast::CRATE_NODE_ID, def.span, &lhses, &rhses);
 
-    let (transparency, transparency_error) = attr::find_transparency(&def.attrs, is_legacy);
+    let (transparency, transparency_error) = attr::find_transparency(&def.attrs, macro_rules);
     match transparency_error {
         Some(TransparencyError::UnknownTransparency(value, span)) => {
             diag.span_err(span, &format!("unknown macro transparency: `{}`", value))
@@ -991,7 +986,7 @@ fn token_can_be_followed_by_any(tok: &mbe::TokenTree) -> bool {
     if let mbe::TokenTree::MetaVarDecl(_, _, frag_spec) = *tok {
         frag_can_be_followed_by_any(frag_spec.name)
     } else {
-        // (Non NT's can always be followed by anthing in matchers.)
+        // (Non NT's can always be followed by anything in matchers.)
         true
     }
 }
@@ -1209,16 +1204,8 @@ fn quoted_tt_to_string(tt: &mbe::TokenTree) -> String {
     }
 }
 
-fn parser_from_cx<'cx>(
-    current_expansion: &'cx ExpansionData,
-    sess: &'cx ParseSess,
-    tts: TokenStream,
-) -> Parser<'cx> {
-    let directory = Directory {
-        path: current_expansion.module.directory.clone(),
-        ownership: current_expansion.directory_ownership,
-    };
-    Parser::new(sess, tts, Some(directory), true, true, rustc_parse::MACRO_ARGUMENTS)
+fn parser_from_cx(sess: &ParseSess, tts: TokenStream) -> Parser<'_> {
+    Parser::new(sess, tts, true, rustc_parse::MACRO_ARGUMENTS)
 }
 
 /// Generates an appropriate parsing failure message. For EOF, this is "unexpected end...". For
index 80bf02b1366e0e86077ad32fbc74c3bc0e5ca496..1b1093c9529f4813a3b0b5997c49a4153e2a2fe0 100644 (file)
@@ -2,7 +2,7 @@
 use crate::mbe;
 use crate::mbe::macro_parser::{MatchedNonterminal, MatchedSeq, NamedMatch};
 
-use rustc_ast::ast::{Ident, Mac};
+use rustc_ast::ast::MacCall;
 use rustc_ast::mut_visit::{self, MutVisitor};
 use rustc_ast::token::{self, NtTT, Token};
 use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree, TreeAndJoint};
@@ -10,6 +10,7 @@
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::pluralize;
 use rustc_span::hygiene::{ExpnId, Transparency};
+use rustc_span::symbol::MacroRulesNormalizedIdent;
 use rustc_span::Span;
 
 use smallvec::{smallvec, SmallVec};
@@ -23,7 +24,7 @@ fn visit_span(&mut self, span: &mut Span) {
         *span = span.apply_mark(self.0, self.1)
     }
 
-    fn visit_mac(&mut self, mac: &mut Mac) {
+    fn visit_mac(&mut self, mac: &mut MacCall) {
         mut_visit::noop_visit_mac(mac, self)
     }
 }
@@ -81,7 +82,7 @@ fn next(&mut self) -> Option<mbe::TokenTree> {
 /// Along the way, we do some additional error checking.
 pub(super) fn transcribe(
     cx: &ExtCtxt<'_>,
-    interp: &FxHashMap<Ident, NamedMatch>,
+    interp: &FxHashMap<MacroRulesNormalizedIdent, NamedMatch>,
     src: Vec<mbe::TokenTree>,
     transparency: Transparency,
 ) -> TokenStream {
@@ -119,9 +120,9 @@ pub(super) fn transcribe(
         let tree = if let Some(tree) = stack.last_mut().unwrap().next() {
             // If it still has a TokenTree we have not looked at yet, use that tree.
             tree
-        }
-        // The else-case never produces a value for `tree` (it `continue`s or `return`s).
-        else {
+        } else {
+            // This else-case never produces a value for `tree` (it `continue`s or `return`s).
+
             // Otherwise, if we have just reached the end of a sequence and we can keep repeating,
             // go back to the beginning of the sequence.
             if let Frame::Sequence { idx, sep, .. } = stack.last_mut().unwrap() {
@@ -223,9 +224,10 @@ pub(super) fn transcribe(
             }
 
             // Replace the meta-var with the matched token tree from the invocation.
-            mbe::TokenTree::MetaVar(mut sp, mut ident) => {
+            mbe::TokenTree::MetaVar(mut sp, mut orignal_ident) => {
                 // Find the matched nonterminal from the macro invocation, and use it to replace
                 // the meta-var.
+                let ident = MacroRulesNormalizedIdent::new(orignal_ident);
                 if let Some(cur_matched) = lookup_cur_matched(ident, interp, &repeats) {
                     if let MatchedNonterminal(ref nt) = cur_matched {
                         // FIXME #2887: why do we apply a mark when matching a token tree meta-var
@@ -249,9 +251,9 @@ pub(super) fn transcribe(
                     // If we aren't able to match the meta-var, we push it back into the result but
                     // with modified syntax context. (I believe this supports nested macros).
                     marker.visit_span(&mut sp);
-                    marker.visit_ident(&mut ident);
+                    marker.visit_ident(&mut orignal_ident);
                     result.push(TokenTree::token(token::Dollar, sp).into());
-                    result.push(TokenTree::Token(Token::from_ast_ident(ident)).into());
+                    result.push(TokenTree::Token(Token::from_ast_ident(orignal_ident)).into());
                 }
             }
 
@@ -287,8 +289,8 @@ pub(super) fn transcribe(
 /// into the right place in nested matchers. If we attempt to descend too far, the macro writer has
 /// made a mistake, and we return `None`.
 fn lookup_cur_matched<'a>(
-    ident: Ident,
-    interpolations: &'a FxHashMap<Ident, NamedMatch>,
+    ident: MacroRulesNormalizedIdent,
+    interpolations: &'a FxHashMap<MacroRulesNormalizedIdent, NamedMatch>,
     repeats: &[(usize, usize)],
 ) -> Option<&'a NamedMatch> {
     interpolations.get(&ident).map(|matched| {
@@ -316,7 +318,7 @@ enum LockstepIterSize {
 
     /// A `MetaVar` with an actual `MatchedSeq`. The length of the match and the name of the
     /// meta-var are returned.
-    Constraint(usize, Ident),
+    Constraint(usize, MacroRulesNormalizedIdent),
 
     /// Two `Constraint`s on the same sequence had different lengths. This is an error.
     Contradiction(String),
@@ -360,7 +362,7 @@ fn with(self, other: LockstepIterSize) -> LockstepIterSize {
 /// multiple nested matcher sequences.
 fn lockstep_iter_size(
     tree: &mbe::TokenTree,
-    interpolations: &FxHashMap<Ident, NamedMatch>,
+    interpolations: &FxHashMap<MacroRulesNormalizedIdent, NamedMatch>,
     repeats: &[(usize, usize)],
 ) -> LockstepIterSize {
     use mbe::TokenTree;
@@ -376,6 +378,7 @@ fn lockstep_iter_size(
             })
         }
         TokenTree::MetaVar(_, name) | TokenTree::MetaVarDecl(_, name, _) => {
+            let name = MacroRulesNormalizedIdent::new(name);
             match lookup_cur_matched(name, interpolations, repeats) {
                 Some(matched) => match matched {
                     MatchedNonterminal(_) => LockstepIterSize::Unconstrained,
diff --git a/src/librustc_expand/module.rs b/src/librustc_expand/module.rs
new file mode 100644 (file)
index 0000000..2d5e4d4
--- /dev/null
@@ -0,0 +1,306 @@
+use rustc_ast::ast::{self, Attribute, Ident, Mod};
+use rustc_ast::{attr, token};
+use rustc_errors::{struct_span_err, PResult};
+use rustc_parse::new_sub_parser_from_file;
+use rustc_session::parse::ParseSess;
+use rustc_span::source_map::{FileName, Span};
+use rustc_span::symbol::sym;
+
+use std::path::{self, Path, PathBuf};
+
+#[derive(Clone)]
+pub struct Directory {
+    pub path: PathBuf,
+    pub ownership: DirectoryOwnership,
+}
+
+#[derive(Copy, Clone)]
+pub enum DirectoryOwnership {
+    Owned {
+        // None if `mod.rs`, `Some("foo")` if we're in `foo.rs`.
+        relative: Option<ast::Ident>,
+    },
+    UnownedViaBlock,
+    UnownedViaMod,
+}
+
+/// Information about the path to a module.
+// Public for rustfmt usage.
+pub struct ModulePath<'a> {
+    name: String,
+    path_exists: bool,
+    pub result: PResult<'a, ModulePathSuccess>,
+}
+
+// Public for rustfmt usage.
+pub struct ModulePathSuccess {
+    pub path: PathBuf,
+    pub ownership: DirectoryOwnership,
+}
+
+crate fn parse_external_mod(
+    sess: &ParseSess,
+    id: ast::Ident,
+    span: Span, // The span to blame on errors.
+    Directory { mut ownership, path }: Directory,
+    attrs: &mut Vec<Attribute>,
+    pop_mod_stack: &mut bool,
+) -> (Mod, Directory) {
+    // We bail on the first error, but that error does not cause a fatal error... (1)
+    let result: PResult<'_, _> = try {
+        // Extract the file path and the new ownership.
+        let mp = submod_path(sess, id, span, &attrs, ownership, &path)?;
+        ownership = mp.ownership;
+
+        // Ensure file paths are acyclic.
+        let mut included_mod_stack = sess.included_mod_stack.borrow_mut();
+        error_on_circular_module(sess, span, &mp.path, &included_mod_stack)?;
+        included_mod_stack.push(mp.path.clone());
+        *pop_mod_stack = true; // We have pushed, so notify caller.
+        drop(included_mod_stack);
+
+        // Actually parse the external file as amodule.
+        let mut p0 = new_sub_parser_from_file(sess, &mp.path, Some(id.to_string()), span);
+        let mut module = p0.parse_mod(&token::Eof)?;
+        module.0.inline = false;
+        module
+    };
+    // (1) ...instead, we return a dummy module.
+    let (module, mut new_attrs) = result.map_err(|mut err| err.emit()).unwrap_or_default();
+    attrs.append(&mut new_attrs);
+
+    // Extract the directory path for submodules of `module`.
+    let path = sess.source_map().span_to_unmapped_path(module.inner);
+    let mut path = match path {
+        FileName::Real(path) => path,
+        other => PathBuf::from(other.to_string()),
+    };
+    path.pop();
+
+    (module, Directory { ownership, path })
+}
+
+fn error_on_circular_module<'a>(
+    sess: &'a ParseSess,
+    span: Span,
+    path: &Path,
+    included_mod_stack: &[PathBuf],
+) -> PResult<'a, ()> {
+    if let Some(i) = included_mod_stack.iter().position(|p| *p == path) {
+        let mut err = String::from("circular modules: ");
+        for p in &included_mod_stack[i..] {
+            err.push_str(&p.to_string_lossy());
+            err.push_str(" -> ");
+        }
+        err.push_str(&path.to_string_lossy());
+        return Err(sess.span_diagnostic.struct_span_err(span, &err[..]));
+    }
+    Ok(())
+}
+
+crate fn push_directory(
+    id: Ident,
+    attrs: &[Attribute],
+    Directory { mut ownership, mut path }: Directory,
+) -> Directory {
+    if let Some(filename) = attr::first_attr_value_str_by_name(attrs, sym::path) {
+        path.push(&*filename.as_str());
+        ownership = DirectoryOwnership::Owned { relative: None };
+    } else {
+        // We have to push on the current module name in the case of relative
+        // paths in order to ensure that any additional module paths from inline
+        // `mod x { ... }` come after the relative extension.
+        //
+        // For example, a `mod z { ... }` inside `x/y.rs` should set the current
+        // directory path to `/x/y/z`, not `/x/z` with a relative offset of `y`.
+        if let DirectoryOwnership::Owned { relative } = &mut ownership {
+            if let Some(ident) = relative.take() {
+                // Remove the relative offset.
+                path.push(&*ident.as_str());
+            }
+        }
+        path.push(&*id.as_str());
+    }
+    Directory { ownership, path }
+}
+
+fn submod_path<'a>(
+    sess: &'a ParseSess,
+    id: ast::Ident,
+    span: Span,
+    attrs: &[Attribute],
+    ownership: DirectoryOwnership,
+    dir_path: &Path,
+) -> PResult<'a, ModulePathSuccess> {
+    if let Some(path) = submod_path_from_attr(attrs, dir_path) {
+        let ownership = match path.file_name().and_then(|s| s.to_str()) {
+            // All `#[path]` files are treated as though they are a `mod.rs` file.
+            // This means that `mod foo;` declarations inside `#[path]`-included
+            // files are siblings,
+            //
+            // Note that this will produce weirdness when a file named `foo.rs` is
+            // `#[path]` included and contains a `mod foo;` declaration.
+            // If you encounter this, it's your own darn fault :P
+            Some(_) => DirectoryOwnership::Owned { relative: None },
+            _ => DirectoryOwnership::UnownedViaMod,
+        };
+        return Ok(ModulePathSuccess { ownership, path });
+    }
+
+    let relative = match ownership {
+        DirectoryOwnership::Owned { relative } => relative,
+        DirectoryOwnership::UnownedViaBlock | DirectoryOwnership::UnownedViaMod => None,
+    };
+    let ModulePath { path_exists, name, result } =
+        default_submod_path(sess, id, span, relative, dir_path);
+    match ownership {
+        DirectoryOwnership::Owned { .. } => Ok(result?),
+        DirectoryOwnership::UnownedViaBlock => {
+            let _ = result.map_err(|mut err| err.cancel());
+            error_decl_mod_in_block(sess, span, path_exists, &name)
+        }
+        DirectoryOwnership::UnownedViaMod => {
+            let _ = result.map_err(|mut err| err.cancel());
+            error_cannot_declare_mod_here(sess, span, path_exists, &name)
+        }
+    }
+}
+
+fn error_decl_mod_in_block<'a, T>(
+    sess: &'a ParseSess,
+    span: Span,
+    path_exists: bool,
+    name: &str,
+) -> PResult<'a, T> {
+    let msg = "Cannot declare a non-inline module inside a block unless it has a path attribute";
+    let mut err = sess.span_diagnostic.struct_span_err(span, msg);
+    if path_exists {
+        let msg = format!("Maybe `use` the module `{}` instead of redeclaring it", name);
+        err.span_note(span, &msg);
+    }
+    Err(err)
+}
+
+fn error_cannot_declare_mod_here<'a, T>(
+    sess: &'a ParseSess,
+    span: Span,
+    path_exists: bool,
+    name: &str,
+) -> PResult<'a, T> {
+    let mut err =
+        sess.span_diagnostic.struct_span_err(span, "cannot declare a new module at this location");
+    if !span.is_dummy() {
+        if let FileName::Real(src_path) = sess.source_map().span_to_filename(span) {
+            if let Some(stem) = src_path.file_stem() {
+                let mut dest_path = src_path.clone();
+                dest_path.set_file_name(stem);
+                dest_path.push("mod.rs");
+                err.span_note(
+                    span,
+                    &format!(
+                        "maybe move this module `{}` to its own directory via `{}`",
+                        src_path.display(),
+                        dest_path.display()
+                    ),
+                );
+            }
+        }
+    }
+    if path_exists {
+        err.span_note(
+            span,
+            &format!("... or maybe `use` the module `{}` instead of possibly redeclaring it", name),
+        );
+    }
+    Err(err)
+}
+
+/// Derive a submodule path from the first found `#[path = "path_string"]`.
+/// The provided `dir_path` is joined with the `path_string`.
+// Public for rustfmt usage.
+pub fn submod_path_from_attr(attrs: &[Attribute], dir_path: &Path) -> Option<PathBuf> {
+    // Extract path string from first `#[path = "path_string"]` attribute.
+    let path_string = attr::first_attr_value_str_by_name(attrs, sym::path)?;
+    let path_string = path_string.as_str();
+
+    // On windows, the base path might have the form
+    // `\\?\foo\bar` in which case it does not tolerate
+    // mixed `/` and `\` separators, so canonicalize
+    // `/` to `\`.
+    #[cfg(windows)]
+    let path_string = path_string.replace("/", "\\");
+
+    Some(dir_path.join(&*path_string))
+}
+
+/// Returns a path to a module.
+// Public for rustfmt usage.
+pub fn default_submod_path<'a>(
+    sess: &'a ParseSess,
+    id: ast::Ident,
+    span: Span,
+    relative: Option<ast::Ident>,
+    dir_path: &Path,
+) -> ModulePath<'a> {
+    // If we're in a foo.rs file instead of a mod.rs file,
+    // we need to look for submodules in
+    // `./foo/<id>.rs` and `./foo/<id>/mod.rs` rather than
+    // `./<id>.rs` and `./<id>/mod.rs`.
+    let relative_prefix_string;
+    let relative_prefix = if let Some(ident) = relative {
+        relative_prefix_string = format!("{}{}", ident.name, path::MAIN_SEPARATOR);
+        &relative_prefix_string
+    } else {
+        ""
+    };
+
+    let mod_name = id.name.to_string();
+    let default_path_str = format!("{}{}.rs", relative_prefix, mod_name);
+    let secondary_path_str =
+        format!("{}{}{}mod.rs", relative_prefix, mod_name, path::MAIN_SEPARATOR);
+    let default_path = dir_path.join(&default_path_str);
+    let secondary_path = dir_path.join(&secondary_path_str);
+    let default_exists = sess.source_map().file_exists(&default_path);
+    let secondary_exists = sess.source_map().file_exists(&secondary_path);
+
+    let result = match (default_exists, secondary_exists) {
+        (true, false) => Ok(ModulePathSuccess {
+            path: default_path,
+            ownership: DirectoryOwnership::Owned { relative: Some(id) },
+        }),
+        (false, true) => Ok(ModulePathSuccess {
+            path: secondary_path,
+            ownership: DirectoryOwnership::Owned { relative: None },
+        }),
+        (false, false) => {
+            let mut err = struct_span_err!(
+                sess.span_diagnostic,
+                span,
+                E0583,
+                "file not found for module `{}`",
+                mod_name,
+            );
+            err.help(&format!(
+                "to create the module `{}`, create file \"{}\"",
+                mod_name,
+                default_path.display(),
+            ));
+            Err(err)
+        }
+        (true, true) => {
+            let mut err = struct_span_err!(
+                sess.span_diagnostic,
+                span,
+                E0584,
+                "file for module `{}` found at both {} and {}",
+                mod_name,
+                default_path_str,
+                secondary_path_str,
+            );
+            err.help("delete or rename one of them to remove the ambiguity");
+            Err(err)
+        }
+    };
+
+    ModulePath { name: mod_name, path_exists: default_exists || secondary_exists, result }
+}
index 4c947d8fa2b4e7d90e87f04f5aa7a9990adc3856..70fb8975d4d085ca167bf2ee537de100bd87bae1 100644 (file)
@@ -17,7 +17,7 @@ impl MutVisitor for ToZzIdentMutVisitor {
     fn visit_ident(&mut self, ident: &mut ast::Ident) {
         *ident = Ident::from_str("zz");
     }
-    fn visit_mac(&mut self, mac: &mut ast::Mac) {
+    fn visit_mac(&mut self, mac: &mut ast::MacCall) {
         mut_visit::noop_visit_mac(mac, self)
     }
 }
index 55e815bd4a4e0a597fa515685d89fa593baab3db..4add896258fa8e10ef95ec7e70f8f4517511f005 100644 (file)
@@ -281,7 +281,7 @@ fn parse_expr_from_source_str(
         .unwrap();
 
         let tts: Vec<_> = match expr.kind {
-            ast::ExprKind::Mac(ref mac) => mac.args.inner_tokens().trees().collect(),
+            ast::ExprKind::MacCall(ref mac) => mac.args.inner_tokens().trees().collect(),
             _ => panic!("not a macro"),
         };
 
index cd4f0a61d424a48a9c32bd98a659a23b45600a2d..e1781f8636e5830dd6e894a8e3ae0e776b134ee5 100644 (file)
@@ -15,8 +15,8 @@ pub fn placeholder(
     id: ast::NodeId,
     vis: Option<ast::Visibility>,
 ) -> AstFragment {
-    fn mac_placeholder() -> ast::Mac {
-        ast::Mac {
+    fn mac_placeholder() -> ast::MacCall {
+        ast::MacCall {
             path: ast::Path { span: DUMMY_SP, segments: Vec::new() },
             args: P(ast::MacArgs::Empty),
             prior_type_ascription: None,
@@ -32,11 +32,11 @@ fn mac_placeholder() -> ast::Mac {
             id,
             span,
             attrs: ast::AttrVec::new(),
-            kind: ast::ExprKind::Mac(mac_placeholder()),
+            kind: ast::ExprKind::MacCall(mac_placeholder()),
         })
     };
-    let ty = || P(ast::Ty { id, kind: ast::TyKind::Mac(mac_placeholder()), span });
-    let pat = || P(ast::Pat { id, kind: ast::PatKind::Mac(mac_placeholder()), span });
+    let ty = || P(ast::Ty { id, kind: ast::TyKind::MacCall(mac_placeholder()), span });
+    let pat = || P(ast::Pat { id, kind: ast::PatKind::MacCall(mac_placeholder()), span });
 
     match kind {
         AstFragmentKind::Expr => AstFragment::Expr(expr_placeholder()),
@@ -47,7 +47,7 @@ fn mac_placeholder() -> ast::Mac {
             ident,
             vis,
             attrs,
-            kind: ast::ItemKind::Mac(mac_placeholder()),
+            kind: ast::ItemKind::MacCall(mac_placeholder()),
             tokens: None,
         })]),
         AstFragmentKind::TraitItems => AstFragment::TraitItems(smallvec![P(ast::AssocItem {
@@ -56,7 +56,7 @@ fn mac_placeholder() -> ast::Mac {
             ident,
             vis,
             attrs,
-            kind: ast::AssocItemKind::Macro(mac_placeholder()),
+            kind: ast::AssocItemKind::MacCall(mac_placeholder()),
             tokens: None,
         })]),
         AstFragmentKind::ImplItems => AstFragment::ImplItems(smallvec![P(ast::AssocItem {
@@ -65,7 +65,7 @@ fn mac_placeholder() -> ast::Mac {
             ident,
             vis,
             attrs,
-            kind: ast::AssocItemKind::Macro(mac_placeholder()),
+            kind: ast::AssocItemKind::MacCall(mac_placeholder()),
             tokens: None,
         })]),
         AstFragmentKind::ForeignItems => {
@@ -75,19 +75,21 @@ fn mac_placeholder() -> ast::Mac {
                 ident,
                 vis,
                 attrs,
-                kind: ast::ForeignItemKind::Macro(mac_placeholder()),
+                kind: ast::ForeignItemKind::MacCall(mac_placeholder()),
                 tokens: None,
             })])
         }
-        AstFragmentKind::Pat => {
-            AstFragment::Pat(P(ast::Pat { id, span, kind: ast::PatKind::Mac(mac_placeholder()) }))
-        }
+        AstFragmentKind::Pat => AstFragment::Pat(P(ast::Pat {
+            id,
+            span,
+            kind: ast::PatKind::MacCall(mac_placeholder()),
+        })),
         AstFragmentKind::Ty => {
-            AstFragment::Ty(P(ast::Ty { id, span, kind: ast::TyKind::Mac(mac_placeholder()) }))
+            AstFragment::Ty(P(ast::Ty { id, span, kind: ast::TyKind::MacCall(mac_placeholder()) }))
         }
         AstFragmentKind::Stmts => AstFragment::Stmts(smallvec![{
             let mac = P((mac_placeholder(), ast::MacStmtStyle::Braces, ast::AttrVec::new()));
-            ast::Stmt { id, span, kind: ast::StmtKind::Mac(mac) }
+            ast::Stmt { id, span, kind: ast::StmtKind::MacCall(mac) }
         }]),
         AstFragmentKind::Arms => AstFragment::Arms(smallvec![ast::Arm {
             attrs: Default::default(),
@@ -239,7 +241,7 @@ fn flat_map_generic_param(
 
     fn flat_map_item(&mut self, item: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
         match item.kind {
-            ast::ItemKind::Mac(_) => return self.remove(item.id).make_items(),
+            ast::ItemKind::MacCall(_) => return self.remove(item.id).make_items(),
             ast::ItemKind::MacroDef(_) => return smallvec![item],
             _ => {}
         }
@@ -249,14 +251,14 @@ fn flat_map_generic_param(
 
     fn flat_map_trait_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
         match item.kind {
-            ast::AssocItemKind::Macro(_) => self.remove(item.id).make_trait_items(),
+            ast::AssocItemKind::MacCall(_) => self.remove(item.id).make_trait_items(),
             _ => noop_flat_map_assoc_item(item, self),
         }
     }
 
     fn flat_map_impl_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
         match item.kind {
-            ast::AssocItemKind::Macro(_) => self.remove(item.id).make_impl_items(),
+            ast::AssocItemKind::MacCall(_) => self.remove(item.id).make_impl_items(),
             _ => noop_flat_map_assoc_item(item, self),
         }
     }
@@ -266,28 +268,28 @@ fn flat_map_foreign_item(
         item: P<ast::ForeignItem>,
     ) -> SmallVec<[P<ast::ForeignItem>; 1]> {
         match item.kind {
-            ast::ForeignItemKind::Macro(_) => self.remove(item.id).make_foreign_items(),
+            ast::ForeignItemKind::MacCall(_) => self.remove(item.id).make_foreign_items(),
             _ => noop_flat_map_foreign_item(item, self),
         }
     }
 
     fn visit_expr(&mut self, expr: &mut P<ast::Expr>) {
         match expr.kind {
-            ast::ExprKind::Mac(_) => *expr = self.remove(expr.id).make_expr(),
+            ast::ExprKind::MacCall(_) => *expr = self.remove(expr.id).make_expr(),
             _ => noop_visit_expr(expr, self),
         }
     }
 
     fn filter_map_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
         match expr.kind {
-            ast::ExprKind::Mac(_) => self.remove(expr.id).make_opt_expr(),
+            ast::ExprKind::MacCall(_) => self.remove(expr.id).make_opt_expr(),
             _ => noop_filter_map_expr(expr, self),
         }
     }
 
     fn flat_map_stmt(&mut self, stmt: ast::Stmt) -> SmallVec<[ast::Stmt; 1]> {
         let (style, mut stmts) = match stmt.kind {
-            ast::StmtKind::Mac(mac) => (mac.1, self.remove(stmt.id).make_stmts()),
+            ast::StmtKind::MacCall(mac) => (mac.1, self.remove(stmt.id).make_stmts()),
             _ => return noop_flat_map_stmt(stmt, self),
         };
 
@@ -302,14 +304,14 @@ fn filter_map_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
 
     fn visit_pat(&mut self, pat: &mut P<ast::Pat>) {
         match pat.kind {
-            ast::PatKind::Mac(_) => *pat = self.remove(pat.id).make_pat(),
+            ast::PatKind::MacCall(_) => *pat = self.remove(pat.id).make_pat(),
             _ => noop_visit_pat(pat, self),
         }
     }
 
     fn visit_ty(&mut self, ty: &mut P<ast::Ty>) {
         match ty.kind {
-            ast::TyKind::Mac(_) => *ty = self.remove(ty.id).make_ty(),
+            ast::TyKind::MacCall(_) => *ty = self.remove(ty.id).make_ty(),
             _ => noop_visit_ty(ty, self),
         }
     }
@@ -328,12 +330,12 @@ fn visit_block(&mut self, block: &mut P<ast::Block>) {
     fn visit_mod(&mut self, module: &mut ast::Mod) {
         noop_visit_mod(module, self);
         module.items.retain(|item| match item.kind {
-            ast::ItemKind::Mac(_) if !self.cx.ecfg.keep_macs => false, // remove macro definitions
+            ast::ItemKind::MacCall(_) if !self.cx.ecfg.keep_macs => false, // remove macro definitions
             _ => true,
         });
     }
 
-    fn visit_mac(&mut self, _mac: &mut ast::Mac) {
+    fn visit_mac(&mut self, _mac: &mut ast::MacCall) {
         // Do nothing.
     }
 }
index 84a546345bb285971da67a99ba4af1124ae9c6a1..cb9afa4cd4f0287c324cc0129d9476e66873c233 100644 (file)
@@ -79,7 +79,7 @@ fn expand(
         span: Span,
         _meta_item: &ast::MetaItem,
         item: Annotatable,
-    ) -> Vec<Annotatable> {
+    ) -> ExpandResult<Vec<Annotatable>, Annotatable> {
         let item = match item {
             Annotatable::Arm(..)
             | Annotatable::Field(..)
@@ -99,7 +99,7 @@ fn expand(
                     "proc-macro derives may only be \
                                     applied to a struct, enum, or union",
                 );
-                return Vec::new();
+                return ExpandResult::Ready(Vec::new());
             }
         };
         match item.kind {
@@ -110,7 +110,7 @@ fn expand(
                     "proc-macro derives may only be \
                                     applied to a struct, enum, or union",
                 );
-                return Vec::new();
+                return ExpandResult::Ready(Vec::new());
             }
         }
 
@@ -158,7 +158,7 @@ fn expand(
             FatalError.raise();
         }
 
-        items
+        ExpandResult::Ready(items)
     }
 }
 
index 0082f4f1a6e8985e647b7797c71120d1e96cee95..9f1fee8fc09d8f31c9a57e7e54d7c17fc5fac63b 100644 (file)
@@ -99,6 +99,9 @@ pub fn set(&self, features: &mut Features, span: Span) {
 
     // no-tracking-issue-start
 
+    /// Allows using `rustc_*` attributes (RFC 572).
+    (active, rustc_attrs, "1.0.0", None, None),
+
     /// Allows using compiler's own crates.
     (active, rustc_private, "1.0.0", Some(27812), None),
 
@@ -128,9 +131,6 @@ pub fn set(&self, features: &mut Features, span: Span) {
     /// Allows using `#[link_name="llvm.*"]`.
     (active, link_llvm_intrinsics, "1.0.0", Some(29602), None),
 
-    /// Allows using `rustc_*` attributes (RFC 572).
-    (active, rustc_attrs, "1.0.0", Some(29642), None),
-
     /// Allows using the `box $expr` syntax.
     (active, box_syntax, "1.0.0", Some(49733), None),
 
@@ -289,9 +289,6 @@ pub fn set(&self, features: &mut Features, span: Span) {
     /// Permits specifying whether a function should permit unwinding or abort on unwind.
     (active, unwind_attributes, "1.4.0", Some(58760), None),
 
-    /// Allows `#[no_debug]`.
-    (active, no_debug, "1.5.0", Some(29721), None),
-
     /// Allows attributes on expressions and non-item statements.
     (active, stmt_expr_attributes, "1.6.0", Some(15701), None),
 
@@ -304,6 +301,11 @@ pub fn set(&self, features: &mut Features, span: Span) {
     /// Allows specialization of implementations (RFC 1210).
     (active, specialization, "1.7.0", Some(31844), None),
 
+    /// A minimal, sound subset of specialization intended to be used by the
+    /// standard library until the soundness issues with specialization
+    /// are fixed.
+    (active, min_specialization, "1.7.0", Some(31844), None),
+
     /// Allows using `#[naked]` on functions.
     (active, naked_functions, "1.9.0", Some(32408), None),
 
@@ -363,9 +365,6 @@ pub fn set(&self, features: &mut Features, span: Span) {
     /// Allows `#[doc(masked)]`.
     (active, doc_masked, "1.21.0", Some(44027), None),
 
-    /// Allows `#[doc(spotlight)]`.
-    (active, doc_spotlight, "1.22.0", Some(45040), None),
-
     /// Allows `#[doc(include = "some-file")]`.
     (active, external_doc, "1.22.0", Some(44732), None),
 
@@ -387,7 +386,7 @@ pub fn set(&self, features: &mut Features, span: Span) {
     /// Allows defining `trait X = A + B;` alias items.
     (active, trait_alias, "1.24.0", Some(41517), None),
 
-    /// Allows infering `'static` outlives requirements (RFC 2093).
+    /// Allows inferring `'static` outlives requirements (RFC 2093).
     (active, infer_static_outlives_requirements, "1.26.0", Some(54185), None),
 
     /// Allows accessing fields of unions inside `const` functions.
@@ -552,6 +551,9 @@ pub fn set(&self, features: &mut Features, span: Span) {
     /// Allows the use of `no_sanitize` attribute.
     (active, no_sanitize, "1.42.0", Some(39699), None),
 
+    // Allows limiting the evaluation steps of const expressions
+    (active, const_eval_limit, "1.43.0", Some(67217), None),
+
     // -------------------------------------------------------------------------
     // feature-group-end: actual feature gates
     // -------------------------------------------------------------------------
index e2e061c185c03f58adfa29f42f02d94b0da9ac1b..eaebdd9fb95a25f77f299cafc586ca463c415905 100644 (file)
@@ -85,19 +85,13 @@ fn is_deprecated(&self) -> bool {
 
 /// A template that the attribute input must match.
 /// Only top-level shape (`#[attr]` vs `#[attr(...)]` vs `#[attr = ...]`) is considered now.
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Default)]
 pub struct AttributeTemplate {
     pub word: bool,
     pub list: Option<&'static str>,
     pub name_value_str: Option<&'static str>,
 }
 
-impl AttributeTemplate {
-    pub fn only_word() -> Self {
-        Self { word: true, list: None, name_value_str: None }
-    }
-}
-
 /// A convenience macro for constructing attribute templates.
 /// E.g., `template!(Word, List: "description")` means that the attribute
 /// supports forms `#[attr]` and `#[attr(description)]`.
@@ -175,7 +169,7 @@ macro_rules! experimental {
     // Stable attributes:
     // ==========================================================================
 
-    // Condtional compilation:
+    // Conditional compilation:
     ungated!(cfg, Normal, template!(List: "predicate")),
     ungated!(cfg_attr, Normal, template!(List: "predicate, attr1, attr2, ...")),
 
@@ -239,6 +233,10 @@ macro_rules! experimental {
     // Limits:
     ungated!(recursion_limit, CrateLevel, template!(NameValueStr: "N")),
     ungated!(type_length_limit, CrateLevel, template!(NameValueStr: "N")),
+    gated!(
+        const_eval_limit, CrateLevel, template!(NameValueStr: "N"), const_eval_limit,
+        experimental!(const_eval_limit)
+    ),
 
     // Entry point:
     ungated!(main, Normal, template!(Word)),
@@ -503,16 +501,6 @@ macro_rules! experimental {
             cfg_fn!(rustc_attrs),
         ),
     ),
-    (
-        sym::no_debug, Whitelisted, template!(Word),
-        Gated(
-            Stability::Deprecated("https://github.com/rust-lang/rust/issues/29721", None),
-            sym::no_debug,
-            "the `#[no_debug]` attribute was an experimental feature that has been \
-            deprecated due to lack of demand",
-            cfg_fn!(no_debug)
-        )
-    ),
     gated!(
         // Used in resolve:
         prelude_import, Whitelisted, template!(Word),
@@ -536,6 +524,14 @@ macro_rules! experimental {
         rustc_test_marker, Normal, template!(Word),
         "the `#[rustc_test_marker]` attribute is used internally to track tests",
     ),
+    rustc_attr!(
+        rustc_unsafe_specialization_marker, Normal, template!(Word),
+        "the `#[rustc_unsafe_specialization_marker]` attribute is used to check specializations"
+    ),
+    rustc_attr!(
+        rustc_specialization_trait, Normal, template!(Word),
+        "the `#[rustc_specialization_trait]` attribute is used to check specializations"
+    ),
 
     // ==========================================================================
     // Internal attributes, Testing:
index e6ea093fe89c73a31025a1d43e75fe93ab7a063e..4e348054fbd4b1eea17226fc15275bd120f85cfe 100644 (file)
@@ -111,6 +111,8 @@ macro_rules! declare_features {
     /// Allows overlapping impls of marker traits.
     (removed, overlapping_marker_traits, "1.42.0", Some(29864), None,
      Some("removed in favor of `#![feature(marker_trait_attr)]`")),
+    /// Allows `#[no_debug]`.
+    (removed, no_debug, "1.43.0", Some(29721), None, Some("removed due to lack of demand")),
     // -------------------------------------------------------------------------
     // feature-group-end: removed features
     // -------------------------------------------------------------------------
index 595543eaf535fd8f34ce25833e4daa2c622142b2..696aa5c6f7dfeee850f2b4449731976e25de928e 100644 (file)
@@ -72,7 +72,7 @@ pub enum DefKind {
     Static,
     /// Refers to the struct or enum variant's constructor.
     Ctor(CtorOf, CtorKind),
-    Method,
+    AssocFn,
     AssocConst,
 
     // Macro namespace
@@ -107,7 +107,7 @@ pub fn descr(self, def_id: DefId) -> &'static str {
             DefKind::Union => "union",
             DefKind::Trait => "trait",
             DefKind::ForeignTy => "foreign type",
-            DefKind::Method => "method",
+            DefKind::AssocFn => "associated function",
             DefKind::Const => "constant",
             DefKind::AssocConst => "associated constant",
             DefKind::TyParam => "type parameter",
@@ -122,6 +122,7 @@ pub fn article(&self) -> &'static str {
             DefKind::AssocTy
             | DefKind::AssocConst
             | DefKind::AssocOpaqueTy
+            | DefKind::AssocFn
             | DefKind::Enum
             | DefKind::OpaqueTy => "an",
             DefKind::Macro(macro_kind) => macro_kind.article(),
@@ -150,7 +151,7 @@ pub fn matches_ns(&self, ns: Namespace) -> bool {
             | DefKind::ConstParam
             | DefKind::Static
             | DefKind::Ctor(..)
-            | DefKind::Method
+            | DefKind::AssocFn
             | DefKind::AssocConst => ns == Namespace::ValueNS,
 
             DefKind::Macro(..) => ns == Namespace::MacroNS,
index 1a74b50b57e7f869ae6a697a1cfebf940dd26434..0ef35b184e17f3f3cde776a46be9e3fb6c1a59e2 100644 (file)
@@ -13,7 +13,6 @@
 pub use rustc_ast::ast::{BorrowKind, ImplPolarity, IsAuto};
 pub use rustc_ast::ast::{CaptureBy, Movability, Mutability};
 use rustc_ast::node_id::NodeMap;
-use rustc_ast::tokenstream::TokenStream;
 use rustc_ast::util::parser::ExprPrecedence;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::sync::{par_for_each_in, Send, Sync};
@@ -80,9 +79,9 @@ pub fn ident(&self) -> Ident {
         }
     }
 
-    pub fn modern(&self) -> ParamName {
+    pub fn normalize_to_macros_2_0(&self) -> ParamName {
         match *self {
-            ParamName::Plain(ident) => ParamName::Plain(ident.modern()),
+            ParamName::Plain(ident) => ParamName::Plain(ident.normalize_to_macros_2_0()),
             param_name => param_name,
         }
     }
@@ -152,9 +151,11 @@ fn is_static(&self) -> bool {
         self == &LifetimeName::Static
     }
 
-    pub fn modern(&self) -> LifetimeName {
+    pub fn normalize_to_macros_2_0(&self) -> LifetimeName {
         match *self {
-            LifetimeName::Param(param_name) => LifetimeName::Param(param_name.modern()),
+            LifetimeName::Param(param_name) => {
+                LifetimeName::Param(param_name.normalize_to_macros_2_0())
+            }
             lifetime_name => lifetime_name,
         }
     }
@@ -597,7 +598,7 @@ pub struct WhereEqPredicate<'hir> {
     pub rhs_ty: &'hir Ty<'hir>,
 }
 
-#[derive(RustcEncodable, RustcDecodable, Debug)]
+#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
 pub struct ModuleItems {
     // Use BTreeSets here so items are in the same order as in the
     // list of all items in Crate
@@ -606,17 +607,23 @@ pub struct ModuleItems {
     pub impl_items: BTreeSet<ImplItemId>,
 }
 
+/// A type representing only the top-level module.
+#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+pub struct CrateItem<'hir> {
+    pub module: Mod<'hir>,
+    pub attrs: &'hir [Attribute],
+    pub span: Span,
+}
+
 /// The top-level data structure that stores the entire contents of
 /// the crate currently being compiled.
 ///
-/// For more details, see the [rustc guide].
+/// For more details, see the [rustc dev guide].
 ///
-/// [rustc guide]: https://rust-lang.github.io/rustc-guide/hir.html
+/// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/hir.html
 #[derive(RustcEncodable, RustcDecodable, Debug)]
 pub struct Crate<'hir> {
-    pub module: Mod<'hir>,
-    pub attrs: &'hir [Attribute],
-    pub span: Span,
+    pub item: CrateItem<'hir>,
     pub exported_macros: &'hir [MacroDef<'hir>],
     // Attributes from non-exported macros, kept only for collecting the library feature list.
     pub non_exported_macro_attrs: &'hir [Attribute],
@@ -679,15 +686,15 @@ pub fn visit_all_item_likes<'hir, V>(&'hir self, visitor: &mut V)
     where
         V: itemlikevisit::ItemLikeVisitor<'hir>,
     {
-        for (_, item) in &self.items {
+        for item in self.items.values() {
             visitor.visit_item(item);
         }
 
-        for (_, trait_item) in &self.trait_items {
+        for trait_item in self.trait_items.values() {
             visitor.visit_trait_item(trait_item);
         }
 
-        for (_, impl_item) in &self.impl_items {
+        for impl_item in self.impl_items.values() {
             visitor.visit_impl_item(impl_item);
         }
     }
@@ -722,13 +729,12 @@ pub fn par_visit_all_item_likes<'hir, V>(&'hir self, visitor: &V)
 /// Not parsed directly, but created on macro import or `macro_rules!` expansion.
 #[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
 pub struct MacroDef<'hir> {
-    pub name: Name,
+    pub ident: Ident,
     pub vis: Visibility<'hir>,
     pub attrs: &'hir [Attribute],
     pub hir_id: HirId,
     pub span: Span,
-    pub body: TokenStream,
-    pub legacy: bool,
+    pub ast: ast::MacroDef,
 }
 
 /// A block of statements `{ .. }`, which may have a label (in this case the
@@ -1850,7 +1856,7 @@ pub struct TraitItem<'hir> {
 
 /// Represents a trait method's body (or just argument names).
 #[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
-pub enum TraitMethod<'hir> {
+pub enum TraitFn<'hir> {
     /// No default body in the trait, just a signature.
     Required(&'hir [Ident]),
 
@@ -1863,8 +1869,8 @@ pub enum TraitMethod<'hir> {
 pub enum TraitItemKind<'hir> {
     /// An associated constant with an optional value (otherwise `impl`s must contain a value).
     Const(&'hir Ty<'hir>, Option<BodyId>),
-    /// A method with an optional body.
-    Method(FnSig<'hir>, TraitMethod<'hir>),
+    /// An associated function with an optional body.
+    Fn(FnSig<'hir>, TraitFn<'hir>),
     /// An associated type with (possibly empty) bounds and optional concrete
     /// type.
     Type(GenericBounds<'hir>, Option<&'hir Ty<'hir>>),
@@ -1897,8 +1903,8 @@ pub enum ImplItemKind<'hir> {
     /// An associated constant of the given type, set to the constant result
     /// of the expression.
     Const(&'hir Ty<'hir>, BodyId),
-    /// A method implementation with the given signature and body.
-    Method(FnSig<'hir>, BodyId),
+    /// An associated function implementation with the given signature and body.
+    Fn(FnSig<'hir>, BodyId),
     /// An associated type.
     TyAlias(&'hir Ty<'hir>),
     /// An associated `type = impl Trait`.
@@ -1909,7 +1915,7 @@ impl ImplItemKind<'_> {
     pub fn namespace(&self) -> Namespace {
         match self {
             ImplItemKind::OpaqueTy(..) | ImplItemKind::TyAlias(..) => Namespace::TypeNS,
-            ImplItemKind::Const(..) | ImplItemKind::Method(..) => Namespace::ValueNS,
+            ImplItemKind::Const(..) | ImplItemKind::Fn(..) => Namespace::ValueNS,
         }
     }
 }
@@ -2653,7 +2659,7 @@ pub fn map_import_ids<F, T>(self, f: F) -> TraitCandidate<T>
 // imported.
 pub type GlobMap = NodeMap<FxHashSet<Name>>;
 
-#[derive(Copy, Clone, Debug)]
+#[derive(Copy, Clone, Debug, HashStable_Generic)]
 pub enum Node<'hir> {
     Param(&'hir Param<'hir>),
     Item(&'hir Item<'hir>),
@@ -2683,7 +2689,7 @@ pub enum Node<'hir> {
     GenericParam(&'hir GenericParam<'hir>),
     Visibility(&'hir Visibility<'hir>),
 
-    Crate,
+    Crate(&'hir CrateItem<'hir>),
 }
 
 impl Node<'_> {
@@ -2699,8 +2705,8 @@ pub fn ident(&self) -> Option<Ident> {
 
     pub fn fn_decl(&self) -> Option<&FnDecl<'_>> {
         match self {
-            Node::TraitItem(TraitItem { kind: TraitItemKind::Method(fn_sig, _), .. })
-            | Node::ImplItem(ImplItem { kind: ImplItemKind::Method(fn_sig, _), .. })
+            Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. })
+            | Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. })
             | Node::Item(Item { kind: ItemKind::Fn(fn_sig, _, _), .. }) => Some(fn_sig.decl),
             Node::ForeignItem(ForeignItem { kind: ForeignItemKind::Fn(fn_decl, _, _), .. }) => {
                 Some(fn_decl)
index 6d2ec445763539d0dfed252681b6cb53ae61d437..1c7987e965f8506ee92bf315badbb5dff17b9fd6 100644 (file)
@@ -1,9 +1,8 @@
-use crate::def_id::{DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX};
-use rustc_serialize::{self, Decodable, Decoder, Encodable, Encoder};
+use crate::def_id::{LocalDefId, CRATE_DEF_INDEX};
 use std::fmt;
 
 /// Uniquely identifies a node in the HIR of the current crate. It is
-/// composed of the `owner`, which is the `DefIndex` of the directly enclosing
+/// composed of the `owner`, which is the `LocalDefId` of the directly enclosing
 /// `hir::Item`, `hir::TraitItem`, or `hir::ImplItem` (i.e., the closest "item-like"),
 /// and the `local_id` which is unique within the given owner.
 ///
 /// the `local_id` part of the `HirId` changing, which is a very useful property in
 /// incremental compilation where we have to persist things through changes to
 /// the code base.
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, PartialOrd, Ord, RustcEncodable, RustcDecodable)]
 pub struct HirId {
-    pub owner: DefIndex,
+    pub owner: LocalDefId,
     pub local_id: ItemLocalId,
 }
 
-impl HirId {
-    pub fn owner_def_id(self) -> DefId {
-        DefId::local(self.owner)
-    }
-
-    pub fn owner_local_def_id(self) -> LocalDefId {
-        LocalDefId::from_def_id(DefId::local(self.owner))
-    }
-}
-
-impl rustc_serialize::UseSpecializedEncodable for HirId {
-    fn default_encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
-        let HirId { owner, local_id } = *self;
-
-        owner.encode(s)?;
-        local_id.encode(s)?;
-        Ok(())
-    }
-}
-
-impl rustc_serialize::UseSpecializedDecodable for HirId {
-    fn default_decode<D: Decoder>(d: &mut D) -> Result<HirId, D::Error> {
-        let owner = DefIndex::decode(d)?;
-        let local_id = ItemLocalId::decode(d)?;
-
-        Ok(HirId { owner, local_id })
-    }
-}
-
 impl fmt::Display for HirId {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(f, "{:?}", self)
@@ -70,9 +40,12 @@ pub struct ItemLocalId { .. }
 rustc_data_structures::impl_stable_hash_via_hash!(ItemLocalId);
 
 /// The `HirId` corresponding to `CRATE_NODE_ID` and `CRATE_DEF_INDEX`.
-pub const CRATE_HIR_ID: HirId =
-    HirId { owner: CRATE_DEF_INDEX, local_id: ItemLocalId::from_u32_const(0) };
+pub const CRATE_HIR_ID: HirId = HirId {
+    owner: LocalDefId { local_def_index: CRATE_DEF_INDEX },
+    local_id: ItemLocalId::from_u32(0),
+};
 
-pub const DUMMY_HIR_ID: HirId = HirId { owner: CRATE_DEF_INDEX, local_id: DUMMY_ITEM_LOCAL_ID };
+pub const DUMMY_HIR_ID: HirId =
+    HirId { owner: LocalDefId { local_def_index: CRATE_DEF_INDEX }, local_id: DUMMY_ITEM_LOCAL_ID };
 
 pub const DUMMY_ITEM_LOCAL_ID: ItemLocalId = ItemLocalId::MAX;
index 45257b04d79076cc15b35050c997f7f27523667d..316b31f069855e8ae69a98dbb9d04fbe4f516949 100644 (file)
@@ -127,6 +127,25 @@ pub trait Map<'hir> {
     fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem<'hir>;
 }
 
+/// An erased version of `Map<'hir>`, using dynamic dispatch.
+/// NOTE: This type is effectively only usable with `NestedVisitorMap::None`.
+pub struct ErasedMap<'hir>(&'hir dyn Map<'hir>);
+
+impl<'hir> Map<'hir> for ErasedMap<'hir> {
+    fn body(&self, id: BodyId) -> &'hir Body<'hir> {
+        self.0.body(id)
+    }
+    fn item(&self, id: HirId) -> &'hir Item<'hir> {
+        self.0.item(id)
+    }
+    fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem<'hir> {
+        self.0.trait_item(id)
+    }
+    fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem<'hir> {
+        self.0.impl_item(id)
+    }
+}
+
 /// Specifies what nested things a visitor wants to visit. The most
 /// common choice is `OnlyBodies`, which will cause the visitor to
 /// visit fn bodies for fns that it encounters, but skip over nested
@@ -134,7 +153,7 @@ pub trait Map<'hir> {
 ///
 /// See the comments on `ItemLikeVisitor` for more details on the overall
 /// visit strategy.
-pub enum NestedVisitorMap<'this, M> {
+pub enum NestedVisitorMap<M> {
     /// Do not visit any nested things. When you add a new
     /// "non-nested" thing, you will want to audit such uses to see if
     /// they remain valid.
@@ -151,20 +170,20 @@ pub enum NestedVisitorMap<'this, M> {
     /// to use `visit_all_item_likes()` as an outer loop,
     /// and to have the visitor that visits the contents of each item
     /// using this setting.
-    OnlyBodies(&'this M),
+    OnlyBodies(M),
 
     /// Visits all nested things, including item-likes.
     ///
     /// **This is an unusual choice.** It is used when you want to
     /// process everything within their lexical context. Typically you
     /// kick off the visit by doing `walk_krate()`.
-    All(&'this M),
+    All(M),
 }
 
-impl<'this, M> NestedVisitorMap<'this, M> {
+impl<M> NestedVisitorMap<M> {
     /// Returns the map to use for an "intra item-like" thing (if any).
     /// E.g., function body.
-    fn intra(self) -> Option<&'this M> {
+    fn intra(self) -> Option<M> {
         match self {
             NestedVisitorMap::None => None,
             NestedVisitorMap::OnlyBodies(map) => Some(map),
@@ -174,7 +193,7 @@ fn intra(self) -> Option<&'this M> {
 
     /// Returns the map to use for an "item-like" thing (if any).
     /// E.g., item, impl-item.
-    fn inter(self) -> Option<&'this M> {
+    fn inter(self) -> Option<M> {
         match self {
             NestedVisitorMap::None => None,
             NestedVisitorMap::OnlyBodies(_) => None,
@@ -221,7 +240,7 @@ pub trait Visitor<'v>: Sized {
     /// `panic!()`. This way, if a new `visit_nested_XXX` variant is
     /// added in the future, we will see the panic in your code and
     /// fix it appropriately.
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map>;
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map>;
 
     /// Invoked when a nested item is encountered. By default does
     /// nothing unless you override `nested_visit_map` to return other than
@@ -284,7 +303,7 @@ fn visit_body(&mut self, b: &'v Body<'v>) {
     /// If you use this, you probably don't want to process the
     /// contents of nested item-like things, since the outer loop will
     /// visit them as well.
-    fn as_deep_visitor<'s>(&'s mut self) -> DeepVisitor<'s, Self> {
+    fn as_deep_visitor(&mut self) -> DeepVisitor<'_, Self> {
         DeepVisitor::new(self)
     }
 
@@ -438,14 +457,14 @@ fn visit_defaultness(&mut self, defaultness: &'v Defaultness) {
 
 /// Walks the contents of a crate. See also `Crate::visit_all_items`.
 pub fn walk_crate<'v, V: Visitor<'v>>(visitor: &mut V, krate: &'v Crate<'v>) {
-    visitor.visit_mod(&krate.module, krate.span, CRATE_HIR_ID);
-    walk_list!(visitor, visit_attribute, krate.attrs);
+    visitor.visit_mod(&krate.item.module, krate.item.span, CRATE_HIR_ID);
+    walk_list!(visitor, visit_attribute, krate.item.attrs);
     walk_list!(visitor, visit_macro_def, krate.exported_macros);
 }
 
 pub fn walk_macro_def<'v, V: Visitor<'v>>(visitor: &mut V, macro_def: &'v MacroDef<'v>) {
     visitor.visit_id(macro_def.hir_id);
-    visitor.visit_name(macro_def.span, macro_def.name);
+    visitor.visit_ident(macro_def.ident);
     walk_list!(visitor, visit_attribute, macro_def.attrs);
 }
 
@@ -911,14 +930,14 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v Trai
             visitor.visit_ty(ty);
             walk_list!(visitor, visit_nested_body, default);
         }
-        TraitItemKind::Method(ref sig, TraitMethod::Required(param_names)) => {
+        TraitItemKind::Fn(ref sig, TraitFn::Required(param_names)) => {
             visitor.visit_id(trait_item.hir_id);
             visitor.visit_fn_decl(&sig.decl);
             for &param_name in param_names {
                 visitor.visit_ident(param_name);
             }
         }
-        TraitItemKind::Method(ref sig, TraitMethod::Provided(body_id)) => {
+        TraitItemKind::Fn(ref sig, TraitFn::Provided(body_id)) => {
             visitor.visit_fn(
                 FnKind::Method(trait_item.ident, sig, None, &trait_item.attrs),
                 &sig.decl,
@@ -968,7 +987,7 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplIt
             visitor.visit_ty(ty);
             visitor.visit_nested_body(body);
         }
-        ImplItemKind::Method(ref sig, body_id) => {
+        ImplItemKind::Fn(ref sig, body_id) => {
             visitor.visit_fn(
                 FnKind::Method(impl_item.ident, sig, Some(&impl_item.vis), &impl_item.attrs),
                 &sig.decl,
index fc91b68e3ea444d9ec09ff30a675cd143768134a..89457009a8bfa4d32dbe533e91b99e44947a1a7d 100644 (file)
@@ -240,7 +240,6 @@ pub fn extract(attrs: &[ast::Attribute]) -> Option<(Symbol, Span)> {
     StartFnLangItem,             "start",              start_fn,                Target::Fn;
 
     EhPersonalityLangItem,       "eh_personality",     eh_personality,          Target::Fn;
-    EhUnwindResumeLangItem,      "eh_unwind_resume",   eh_unwind_resume,        Target::Fn;
     EhCatchTypeinfoLangItem,     "eh_catch_typeinfo",  eh_catch_typeinfo,       Target::Static;
 
     OwnedBoxLangItem,            "owned_box",          owned_box,               Target::Struct;
index d958dfc681b00fe0703c2770dbf5ef78807a3033..fa5c72b060dcfe59e886f987d98fb69647e47f8a 100644 (file)
@@ -1,9 +1,11 @@
-//! HIR datatypes. See the [rustc guide] for more info.
+//! HIR datatypes. See the [rustc dev guide] for more info.
 //!
-//! [rustc guide]: https://rust-lang.github.io/rustc-guide/hir.html
+//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/hir.html
 
 #![feature(crate_visibility_modifier)]
+#![feature(const_if_match)]
 #![feature(const_fn)] // For the unsizing cast on `&[]`
+#![feature(const_panic)]
 #![feature(in_band_lifetimes)]
 #![feature(specialization)]
 #![recursion_limit = "256"]
index 8cbbef959ce75ca4d40f26e4c8c49749cc59120b..4e9618b7676e8dcdb03a1cdacf97c62ee999af02 100644 (file)
@@ -102,7 +102,7 @@ pub fn print_node(&mut self, node: Node<'_>) {
             Node::Ctor(..) => panic!("cannot print isolated Ctor"),
             Node::Local(a) => self.print_local_decl(&a),
             Node::MacroDef(_) => panic!("cannot print MacroDef"),
-            Node::Crate => panic!("cannot print Crate"),
+            Node::Crate(..) => panic!("cannot print Crate"),
         }
     }
 }
@@ -151,7 +151,7 @@ pub fn print_crate<'a>(
     // When printing the AST, we sometimes need to inject `#[no_std]` here.
     // Since you can't compile the HIR, it's not necessary.
 
-    s.print_mod(&krate.module, &krate.attrs);
+    s.print_mod(&krate.item.module, &krate.item.attrs);
     s.print_remaining_comments();
     s.s.eof()
 }
@@ -652,7 +652,7 @@ pub fn print_item(&mut self, item: &hir::Item<'_>) {
                     self.word_nbsp("const");
                 }
 
-                if let hir::ImplPolarity::Negative = polarity {
+                if let hir::ImplPolarity::Negative(_) = polarity {
                     self.s.word("!");
                 }
 
@@ -886,13 +886,13 @@ pub fn print_trait_item(&mut self, ti: &hir::TraitItem<'_>) {
                     Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Inherited };
                 self.print_associated_const(ti.ident, &ty, default, &vis);
             }
-            hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Required(ref arg_names)) => {
+            hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(ref arg_names)) => {
                 let vis =
                     Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Inherited };
                 self.print_method_sig(ti.ident, sig, &ti.generics, &vis, arg_names, None);
                 self.s.word(";");
             }
-            hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body)) => {
+            hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => {
                 let vis =
                     Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Inherited };
                 self.head("");
@@ -925,7 +925,7 @@ pub fn print_impl_item(&mut self, ii: &hir::ImplItem<'_>) {
             hir::ImplItemKind::Const(ref ty, expr) => {
                 self.print_associated_const(ii.ident, &ty, Some(expr), &ii.vis);
             }
-            hir::ImplItemKind::Method(ref sig, body) => {
+            hir::ImplItemKind::Fn(ref sig, body) => {
                 self.head("");
                 self.print_method_sig(ii.ident, sig, &ii.generics, &ii.vis, &[], Some(body));
                 self.nbsp();
index 3938a0369b924cb8ae19c3b7c425ea0a85447b98..996b310896904221a96028f83899f2aee0998b05 100644 (file)
@@ -1,7 +1,11 @@
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
 
-use crate::hir::{BodyId, Expr, ImplItemId, ItemId, Mod, TraitItemId, Ty, VisibilityKind};
-use crate::hir_id::HirId;
+use crate::hir::{
+    BodyId, Expr, ImplItem, ImplItemId, Item, ItemId, Mod, TraitItem, TraitItemId, Ty,
+    VisibilityKind,
+};
+use crate::hir_id::{HirId, ItemLocalId};
+use rustc_span::def_id::{DefPathHash, LocalDefId};
 
 /// Requirements for a `StableHashingContext` to be used in this crate.
 /// This is a hack to allow using the `HashStable_Generic` derive macro
@@ -16,6 +20,36 @@ pub trait HashStableContext:
     fn hash_hir_expr(&mut self, _: &Expr<'_>, hasher: &mut StableHasher);
     fn hash_hir_ty(&mut self, _: &Ty<'_>, hasher: &mut StableHasher);
     fn hash_hir_visibility_kind(&mut self, _: &VisibilityKind<'_>, hasher: &mut StableHasher);
+    fn hash_hir_item_like<F: FnOnce(&mut Self)>(&mut self, f: F);
+    fn local_def_path_hash(&self, def_id: LocalDefId) -> DefPathHash;
+}
+
+impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for HirId {
+    type KeyType = (DefPathHash, ItemLocalId);
+
+    #[inline]
+    fn to_stable_hash_key(&self, hcx: &HirCtx) -> (DefPathHash, ItemLocalId) {
+        let def_path_hash = hcx.local_def_path_hash(self.owner);
+        (def_path_hash, self.local_id)
+    }
+}
+
+impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for TraitItemId {
+    type KeyType = (DefPathHash, ItemLocalId);
+
+    #[inline]
+    fn to_stable_hash_key(&self, hcx: &HirCtx) -> (DefPathHash, ItemLocalId) {
+        self.hir_id.to_stable_hash_key(hcx)
+    }
+}
+
+impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for ImplItemId {
+    type KeyType = (DefPathHash, ItemLocalId);
+
+    #[inline]
+    fn to_stable_hash_key(&self, hcx: &HirCtx) -> (DefPathHash, ItemLocalId) {
+        self.hir_id.to_stable_hash_key(hcx)
+    }
 }
 
 impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for HirId {
@@ -78,3 +112,56 @@ fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
         hcx.hash_hir_visibility_kind(self, hasher)
     }
 }
+
+impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for TraitItem<'_> {
+    fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
+        let TraitItem { hir_id: _, ident, ref attrs, ref generics, ref kind, span } = *self;
+
+        hcx.hash_hir_item_like(|hcx| {
+            ident.name.hash_stable(hcx, hasher);
+            attrs.hash_stable(hcx, hasher);
+            generics.hash_stable(hcx, hasher);
+            kind.hash_stable(hcx, hasher);
+            span.hash_stable(hcx, hasher);
+        });
+    }
+}
+
+impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for ImplItem<'_> {
+    fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
+        let ImplItem {
+            hir_id: _,
+            ident,
+            ref vis,
+            defaultness,
+            ref attrs,
+            ref generics,
+            ref kind,
+            span,
+        } = *self;
+
+        hcx.hash_hir_item_like(|hcx| {
+            ident.name.hash_stable(hcx, hasher);
+            vis.hash_stable(hcx, hasher);
+            defaultness.hash_stable(hcx, hasher);
+            attrs.hash_stable(hcx, hasher);
+            generics.hash_stable(hcx, hasher);
+            kind.hash_stable(hcx, hasher);
+            span.hash_stable(hcx, hasher);
+        });
+    }
+}
+
+impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for Item<'_> {
+    fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
+        let Item { ident, ref attrs, hir_id: _, ref kind, ref vis, span } = *self;
+
+        hcx.hash_hir_item_like(|hcx| {
+            ident.name.hash_stable(hcx, hasher);
+            attrs.hash_stable(hcx, hasher);
+            kind.hash_stable(hcx, hasher);
+            vis.hash_stable(hcx, hasher);
+            span.hash_stable(hcx, hasher);
+        });
+    }
+}
index 501976fc3cb39cb020f9bbb49c5c343309abaf8e..3a4485a1b17fd38ed43b7f431b9d1da7d72377a6 100644 (file)
@@ -105,10 +105,10 @@ pub fn from_item(item: &Item<'_>) -> Target {
     pub fn from_trait_item(trait_item: &TraitItem<'_>) -> Target {
         match trait_item.kind {
             TraitItemKind::Const(..) => Target::AssocConst,
-            TraitItemKind::Method(_, hir::TraitMethod::Required(_)) => {
+            TraitItemKind::Fn(_, hir::TraitFn::Required(_)) => {
                 Target::Method(MethodKind::Trait { body: false })
             }
-            TraitItemKind::Method(_, hir::TraitMethod::Provided(_)) => {
+            TraitItemKind::Fn(_, hir::TraitFn::Provided(_)) => {
                 Target::Method(MethodKind::Trait { body: true })
             }
             TraitItemKind::Type(..) => Target::AssocTy,
index 405a31d5a69adc1d779416c735c63d6b42d354be..c0560eb8d455a9deee694c607e0404b9d843688d 100644 (file)
@@ -43,6 +43,5 @@ pub fn is_weak_lang_item(&self, item_def_id: DefId) -> bool {
 weak_lang_items! {
     panic_impl,         PanicImplLangItem,          rust_begin_unwind;
     eh_personality,     EhPersonalityLangItem,      rust_eh_personality;
-    eh_unwind_resume,   EhUnwindResumeLangItem,     rust_eh_unwind_resume;
     oom,                OomLangItem,                rust_oom;
 }
index c82ed0c2c49702ce6fe2359596dba82c3ad79c62..a7dccaf974b8240146a6c8cd8e1dd7ab37bb5ccb 100644 (file)
@@ -68,7 +68,7 @@ pub fn assert_dep_graph(tcx: TyCtxt<'_>) {
         let (if_this_changed, then_this_would_need) = {
             let mut visitor =
                 IfThisChanged { tcx, if_this_changed: vec![], then_this_would_need: vec![] };
-            visitor.process_attrs(hir::CRATE_HIR_ID, &tcx.hir().krate().attrs);
+            visitor.process_attrs(hir::CRATE_HIR_ID, &tcx.hir().krate().item.attrs);
             tcx.hir().krate().visit_all_item_likes(&mut visitor.as_deep_visitor());
             (visitor.if_this_changed, visitor.then_this_would_need)
         };
@@ -120,7 +120,7 @@ fn process_attrs(&mut self, hir_id: hir::HirId, attrs: &[ast::Attribute]) {
             if attr.check_name(sym::rustc_if_this_changed) {
                 let dep_node_interned = self.argument(attr);
                 let dep_node = match dep_node_interned {
-                    None => def_path_hash.to_dep_node(DepKind::Hir),
+                    None => DepNode::from_def_path_hash(def_path_hash, DepKind::hir_owner),
                     Some(n) => match DepNode::from_label_string(&n.as_str(), def_path_hash) {
                         Ok(n) => n,
                         Err(()) => {
@@ -162,8 +162,8 @@ fn process_attrs(&mut self, hir_id: hir::HirId, attrs: &[ast::Attribute]) {
 impl Visitor<'tcx> for IfThisChanged<'tcx> {
     type Map = Map<'tcx>;
 
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, Self::Map> {
-        NestedVisitorMap::OnlyBodies(&self.tcx.hir())
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::OnlyBodies(self.tcx.hir())
     }
 
     fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
index 261540abcad5d85d1fe7bb5cf5a56a0a61070164..54d7e0ece503185dfcd241023521c5d556e2c56c 100644 (file)
@@ -44,7 +44,7 @@ pub fn assert_module_sources(tcx: TyCtxt<'_>) {
 
         let ams = AssertModuleSource { tcx, available_cgus };
 
-        for attr in tcx.hir().krate().attrs {
+        for attr in tcx.hir().krate().item.attrs {
             ams.check_attr(attr);
         }
     })
index 8131d2840b49d3eed0afddc38966a83d2bd3038a..b01fe219e1e11bb180c5934c3a40f727bf7f87ac 100644 (file)
@@ -1,3 +1,3 @@
-For info on how the incremental compilation works, see the [rustc guide].
+For info on how the incremental compilation works, see the [rustc dev guide].
 
-[rustc guide]: https://rust-lang.github.io/rustc-guide/query.html
+[rustc dev guide]: https://rustc-dev-guide.rust-lang.org/query.html
index f304292d922e5612bfed7ac6a21eb8b21ea61093..df5fd110db9b691a83ca3d4b0cc8e047bbc8159a 100644 (file)
@@ -53,9 +53,9 @@
 
 /// DepNodes for Hir, which is pretty much everything
 const BASE_HIR: &[&str] = &[
-    // Hir and HirBody should be computed for all nodes
-    label_strs::Hir,
-    label_strs::HirBody,
+    // hir_owner and hir_owner_items should be computed for all nodes
+    label_strs::hir_owner,
+    label_strs::hir_owner_items,
 ];
 
 /// `impl` implementation of struct/trait
@@ -328,12 +328,12 @@ fn auto_labels(&mut self, item_id: hir::HirId, attr: &Attribute) -> (&'static st
                 }
             }
             HirNode::TraitItem(item) => match item.kind {
-                TraitItemKind::Method(..) => ("Node::TraitItem", LABELS_FN_IN_TRAIT),
+                TraitItemKind::Fn(..) => ("Node::TraitItem", LABELS_FN_IN_TRAIT),
                 TraitItemKind::Const(..) => ("NodeTraitConst", LABELS_CONST_IN_TRAIT),
                 TraitItemKind::Type(..) => ("NodeTraitType", LABELS_CONST_IN_TRAIT),
             },
             HirNode::ImplItem(item) => match item.kind {
-                ImplItemKind::Method(..) => ("Node::ImplItem", LABELS_FN_IN_IMPL),
+                ImplItemKind::Fn(..) => ("Node::ImplItem", LABELS_FN_IN_IMPL),
                 ImplItemKind::Const(..) => ("NodeImplConst", LABELS_CONST_IN_IMPL),
                 ImplItemKind::TyAlias(..) => ("NodeImplType", LABELS_CONST_IN_IMPL),
                 ImplItemKind::OpaqueTy(..) => ("NodeImplType", LABELS_CONST_IN_IMPL),
@@ -343,7 +343,8 @@ fn auto_labels(&mut self, item_id: hir::HirId, attr: &Attribute) -> (&'static st
                 &format!("clean/dirty auto-assertions not yet defined for {:?}", node),
             ),
         };
-        let labels = Labels::from_iter(labels.iter().flat_map(|s| s.iter().map(|l| l.to_string())));
+        let labels =
+            Labels::from_iter(labels.iter().flat_map(|s| s.iter().map(|l| (*l).to_string())));
         (name, labels)
     }
 
@@ -547,8 +548,8 @@ fn report_unchecked_attrs(&self, checked_attrs: &FxHashSet<ast::AttrId>) {
 impl intravisit::Visitor<'tcx> for FindAllAttrs<'tcx> {
     type Map = Map<'tcx>;
 
-    fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, Self::Map> {
-        intravisit::NestedVisitorMap::All(&self.tcx.hir())
+    fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
+        intravisit::NestedVisitorMap::All(self.tcx.hir())
     }
 
     fn visit_attribute(&mut self, attr: &'tcx Attribute) {
index 5c72b049d97e98647e56efe307c7433eb0085b85..048a81b81bab3879f19c1be80f51dafe0ca21c13 100644 (file)
@@ -14,8 +14,8 @@
 use std::io::{self, Read};
 use std::path::Path;
 
-use rustc::session::config::nightly_options;
 use rustc_serialize::opaque::Encoder;
+use rustc_session::config::nightly_options;
 
 /// The first few bytes of files generated by incremental compilation.
 const FILE_MAGIC: &[u8] = b"RSIC";
index 8548ad392d2dd3b84ac1cb058fb3b95e473c9e6d..4926f726f35935779407db28373def3eeaf241f4 100644 (file)
 //! unsupported file system and emit a warning in that case. This is not yet
 //! implemented.
 
-use rustc::session::{CrateDisambiguator, Session};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::svh::Svh;
 use rustc_data_structures::{base_n, flock};
 use rustc_fs_util::{link_or_copy, LinkOrCopy};
+use rustc_session::{CrateDisambiguator, Session};
 
 use std::fs as std_fs;
 use std::io;
index 6c57f79e1a7fb911e03edc5ce52a1ce7a249a2e4..8a11586250dec543d49909ba45584509b32b20ae 100644 (file)
@@ -1,12 +1,12 @@
 //! Code to save/load the dep-graph from files.
 
 use rustc::dep_graph::{PreviousDepGraph, SerializedDepGraph, WorkProduct, WorkProductId};
-use rustc::session::Session;
 use rustc::ty::query::OnDiskCache;
 use rustc::ty::TyCtxt;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_serialize::opaque::Decoder;
 use rustc_serialize::Decodable as RustcDecodable;
+use rustc_session::Session;
 use std::path::Path;
 
 use super::data::*;
index 87f39dedd02734331310758d29aab7753f81d091..b465a11c99c069bdbe3c97b9088f02d05d812278 100644 (file)
@@ -1,10 +1,10 @@
 use rustc::dep_graph::{DepGraph, DepKind, WorkProduct, WorkProductId};
-use rustc::session::Session;
 use rustc::ty::TyCtxt;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::join;
 use rustc_serialize::opaque::Encoder;
 use rustc_serialize::Encodable as RustcEncodable;
+use rustc_session::Session;
 use std::fs;
 use std::path::PathBuf;
 
index 65a742a202dddd0a6e6a1a7fbe76a4de52b0e882..aa3588b284b2812455f5dd3d18195e82fc78f09d 100644 (file)
@@ -2,8 +2,8 @@
 
 use crate::persist::fs::*;
 use rustc::dep_graph::{WorkProduct, WorkProductFileKind, WorkProductId};
-use rustc::session::Session;
 use rustc_fs_util::link_or_copy;
+use rustc_session::Session;
 use std::fs as std_fs;
 use std::path::PathBuf;
 
@@ -13,9 +13,7 @@ pub fn copy_cgu_workproducts_to_incr_comp_cache_dir(
     files: &[(WorkProductFileKind, PathBuf)],
 ) -> Option<(WorkProductId, WorkProduct)> {
     debug!("copy_cgu_workproducts_to_incr_comp_cache_dir({:?},{:?})", cgu_name, files);
-    if sess.opts.incremental.is_none() {
-        return None;
-    }
+    sess.opts.incremental.as_ref()?;
 
     let saved_files = files
         .iter()
index 86dd1a29d0ce3a23f318abc7b9c8f3200895775b..e8aa1a209e9299812dff923723ae6e751366bf88 100644 (file)
@@ -1,4 +1,7 @@
 #![feature(allow_internal_unstable)]
+#![feature(const_if_match)]
+#![feature(const_fn)]
+#![feature(const_panic)]
 #![feature(unboxed_closures)]
 #![feature(test)]
 #![feature(fn_traits)]
index 1dfe97238a3df8b7f6235f08b0383733d7e86992..d8c67f6210c7500d5c1ed399fae5a91edec373e1 100644 (file)
@@ -120,10 +120,10 @@ fn clone(&self) -> Self {
         impl $type {
             $v const MAX_AS_U32: u32 = $max;
 
-            $v const MAX: Self = Self::from_u32_const($max);
+            $v const MAX: Self = Self::from_u32($max);
 
             #[inline]
-            $v fn from_usize(value: usize) -> Self {
+            $v const fn from_usize(value: usize) -> Self {
                 assert!(value <= ($max as usize));
                 unsafe {
                     Self::from_u32_unchecked(value as u32)
@@ -131,31 +131,13 @@ impl $type {
             }
 
             #[inline]
-            $v fn from_u32(value: u32) -> Self {
+            $v const fn from_u32(value: u32) -> Self {
                 assert!(value <= $max);
                 unsafe {
                     Self::from_u32_unchecked(value)
                 }
             }
 
-            /// Hacky variant of `from_u32` for use in constants.
-            /// This version checks the "max" constraint by using an
-            /// invalid array dereference.
-            #[inline]
-            $v const fn from_u32_const(value: u32) -> Self {
-                // This will fail at const eval time unless `value <=
-                // max` is true (in which case we get the index 0).
-                // It will also fail at runtime, of course, but in a
-                // kind of wacky way.
-                let _ = ["out of range value used"][
-                    !(value <= $max) as usize
-                ];
-
-                unsafe {
-                    Self { private: value }
-                }
-            }
-
             #[inline]
             $v const unsafe fn from_u32_unchecked(value: u32) -> Self {
                 Self { private: value }
@@ -163,19 +145,19 @@ impl $type {
 
             /// Extracts the value of this index as an integer.
             #[inline]
-            $v fn index(self) -> usize {
+            $v const fn index(self) -> usize {
                 self.as_usize()
             }
 
             /// Extracts the value of this index as a `u32`.
             #[inline]
-            $v fn as_u32(self) -> u32 {
+            $v const fn as_u32(self) -> u32 {
                 self.private
             }
 
             /// Extracts the value of this index as a `usize`.
             #[inline]
-            $v fn as_usize(self) -> usize {
+            $v const fn as_usize(self) -> usize {
                 self.as_u32() as usize
             }
         }
@@ -196,7 +178,7 @@ fn new(value: usize) -> Self {
 
             #[inline]
             fn index(self) -> usize {
-                usize::from(self)
+                self.as_usize()
             }
         }
 
@@ -500,7 +482,7 @@ fn decode<D: ::rustc_serialize::Decoder>(d: &mut D) -> Result<Self, D::Error> {
                    const $name:ident = $constant:expr,
                    $($tokens:tt)*) => (
         $(#[doc = $doc])*
-        $v const $name: $type = $type::from_u32_const($constant);
+        $v const $name: $type = $type::from_u32($constant);
         $crate::newtype_index!(
             @derives      [$($derives,)*]
             @attrs        [$(#[$attrs])*]
index de99214901d9b71b55ebb59dc69549e3f38dadcc..9ecd056430c204b571120e7b3e37d019410501bc 100644 (file)
@@ -10,14 +10,11 @@ path = "lib.rs"
 doctest = false
 
 [dependencies]
-fmt_macros = { path = "../libfmt_macros" }
 graphviz = { path = "../libgraphviz" }
 log = { version = "0.4", features = ["release_max_level_info", "std"] }
-rustc_attr = { path = "../librustc_attr" }
 rustc = { path = "../librustc" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_errors = { path = "../librustc_errors" }
-rustc_error_codes = { path = "../librustc_error_codes" }
 rustc_hir = { path = "../librustc_hir" }
 rustc_index = { path = "../librustc_index" }
 rustc_macros = { path = "../librustc_macros" }
index 156b5a8b0b50bd593e4c581c3b6175b206d1f4ee..04f5b03c0e15cb26eae880e99d5ac5b5e7fe10d1 100644 (file)
@@ -179,7 +179,7 @@ pub fn trace_exp<T>(self, a_is_expected: bool, a: T, b: T) -> Trace<'a, 'tcx>
         T: ToTrace<'tcx>,
     {
         let trace = ToTrace::to_trace(self.cause, a_is_expected, a, b);
-        Trace { at: self, trace: trace, a_is_expected }
+        Trace { at: self, trace, a_is_expected }
     }
 }
 
index 26f855b177e8161a64b970091f6bb32e448ba675..964e378f7abc8abe495a8793206c2b6e643ac64b 100644 (file)
@@ -1,9 +1,9 @@
 //! This module contains the "canonicalizer" itself.
 //!
 //! For an overview of what canonicalization is and how it fits into
-//! rustc, check out the [chapter in the rustc guide][c].
+//! rustc, check out the [chapter in the rustc dev guide][c].
 //!
-//! [c]: https://rust-lang.github.io/rustc-guide/traits/canonicalization.html
+//! [c]: https://rustc-dev-guide.rust-lang.org/traits/canonicalization.html
 
 use crate::infer::canonical::{
     Canonical, CanonicalTyVarKind, CanonicalVarInfo, CanonicalVarKind, Canonicalized,
@@ -33,9 +33,9 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
     /// with a mapping M that maps `'?0` to `'static`.
     ///
     /// To get a good understanding of what is happening here, check
-    /// out the [chapter in the rustc guide][c].
+    /// out the [chapter in the rustc dev guide][c].
     ///
-    /// [c]: https://rust-lang.github.io/rustc-guide/traits/canonicalization.html#canonicalizing-the-query
+    /// [c]: https://rustc-dev-guide.rust-lang.org/traits/canonicalization.html#canonicalizing-the-query
     pub fn canonicalize_query<V>(
         &self,
         value: &V,
@@ -77,9 +77,9 @@ pub fn canonicalize_query<V>(
     /// reference to `'static` alone.
     ///
     /// To get a good understanding of what is happening here, check
-    /// out the [chapter in the rustc guide][c].
+    /// out the [chapter in the rustc dev guide][c].
     ///
-    /// [c]: https://rust-lang.github.io/rustc-guide/traits/canonicalization.html#canonicalizing-the-query-result
+    /// [c]: https://rustc-dev-guide.rust-lang.org/traits/canonicalization.html#canonicalizing-the-query-result
     pub fn canonicalize_response<V>(&self, value: &V) -> Canonicalized<'tcx, V>
     where
         V: TypeFoldable<'tcx>,
@@ -357,10 +357,8 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
                     // `TyVar(vid)` is unresolved, track its universe index in the canonicalized
                     // result.
                     Err(mut ui) => {
-                        if !self.infcx.unwrap().tcx.sess.opts.debugging_opts.chalk {
-                            // FIXME: perf problem described in #55921.
-                            ui = ty::UniverseIndex::ROOT;
-                        }
+                        // FIXME: perf problem described in #55921.
+                        ui = ty::UniverseIndex::ROOT;
                         self.canonicalize_ty_var(
                             CanonicalVarInfo {
                                 kind: CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)),
@@ -447,10 +445,8 @@ fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
                     // `ConstVar(vid)` is unresolved, track its universe index in the
                     // canonicalized result
                     Err(mut ui) => {
-                        if !self.infcx.unwrap().tcx.sess.opts.debugging_opts.chalk {
-                            // FIXME: perf problem described in #55921.
-                            ui = ty::UniverseIndex::ROOT;
-                        }
+                        // FIXME: perf problem described in #55921.
+                        ui = ty::UniverseIndex::ROOT;
                         return self.canonicalize_const_var(
                             CanonicalVarInfo { kind: CanonicalVarKind::Const(ui) },
                             ct,
index ba019a8cf0369a67e49b4c8de12559bde2193af3..0e9593e8ea6b0de92ffcd691b4654978416d57a6 100644 (file)
@@ -17,9 +17,9 @@
 //! `instantiate_query_result` method.
 //!
 //! For a more detailed look at what is happening here, check
-//! out the [chapter in the rustc guide][c].
+//! out the [chapter in the rustc dev guide][c].
 //!
-//! [c]: https://rust-lang.github.io/rustc-guide/traits/canonicalization.html
+//! [c]: https://rustc-dev-guide.rust-lang.org/traits/canonicalization.html
 
 use crate::infer::{ConstVariableOrigin, ConstVariableOriginKind};
 use crate::infer::{InferCtxt, RegionVariableOrigin, TypeVariableOrigin, TypeVariableOriginKind};
index 77f1c6bf28109fcc8675330f423d5a4b821f0fe7..9322df48235113a0ff1aa039ce3adc17cf2ebc1c 100644 (file)
@@ -3,74 +3,31 @@
 //! encode them therein.
 //!
 //! For an overview of what canonicaliation is and how it fits into
-//! rustc, check out the [chapter in the rustc guide][c].
+//! rustc, check out the [chapter in the rustc dev guide][c].
 //!
-//! [c]: https://rust-lang.github.io/rustc-guide/traits/canonicalization.html
+//! [c]: https://rustc-dev-guide.rust-lang.org/traits/canonicalization.html
 
 use crate::infer::canonical::substitute::{substitute_value, CanonicalExt};
 use crate::infer::canonical::{
     Canonical, CanonicalVarValues, CanonicalizedQueryResponse, Certainty, OriginalQueryValues,
     QueryOutlivesConstraint, QueryRegionConstraints, QueryResponse,
 };
+use crate::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRelatingDelegate};
 use crate::infer::region_constraints::{Constraint, RegionConstraintData};
-use crate::infer::InferCtxtBuilder;
-use crate::infer::{InferCtxt, InferOk, InferResult};
+use crate::infer::{InferCtxt, InferOk, InferResult, NLLRegionVariableOrigin};
 use crate::traits::query::{Fallible, NoSolution};
-use crate::traits::TraitEngine;
+use crate::traits::{DomainGoal, TraitEngine};
 use crate::traits::{Obligation, ObligationCause, PredicateObligation};
 use rustc::arena::ArenaAllocatable;
 use rustc::ty::fold::TypeFoldable;
+use rustc::ty::relate::TypeRelation;
 use rustc::ty::subst::{GenericArg, GenericArgKind};
 use rustc::ty::{self, BoundVar, Ty, TyCtxt};
 use rustc_data_structures::captures::Captures;
 use rustc_index::vec::Idx;
 use rustc_index::vec::IndexVec;
-use rustc_span::DUMMY_SP;
 use std::fmt::Debug;
 
-impl<'tcx> InferCtxtBuilder<'tcx> {
-    /// The "main method" for a canonicalized trait query. Given the
-    /// canonical key `canonical_key`, this method will create a new
-    /// inference context, instantiate the key, and run your operation
-    /// `op`. The operation should yield up a result (of type `R`) as
-    /// well as a set of trait obligations that must be fully
-    /// satisfied. These obligations will be processed and the
-    /// canonical result created.
-    ///
-    /// Returns `NoSolution` in the event of any error.
-    ///
-    /// (It might be mildly nicer to implement this on `TyCtxt`, and
-    /// not `InferCtxtBuilder`, but that is a bit tricky right now.
-    /// In part because we would need a `for<'tcx>` sort of
-    /// bound for the closure and in part because it is convenient to
-    /// have `'tcx` be free on this function so that we can talk about
-    /// `K: TypeFoldable<'tcx>`.)
-    pub fn enter_canonical_trait_query<K, R>(
-        &mut self,
-        canonical_key: &Canonical<'tcx, K>,
-        operation: impl FnOnce(&InferCtxt<'_, 'tcx>, &mut dyn TraitEngine<'tcx>, K) -> Fallible<R>,
-    ) -> Fallible<CanonicalizedQueryResponse<'tcx, R>>
-    where
-        K: TypeFoldable<'tcx>,
-        R: Debug + TypeFoldable<'tcx>,
-        Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable,
-    {
-        self.enter_with_canonical(
-            DUMMY_SP,
-            canonical_key,
-            |ref infcx, key, canonical_inference_vars| {
-                let mut fulfill_cx = TraitEngine::new(infcx.tcx);
-                let value = operation(infcx, &mut *fulfill_cx, key)?;
-                infcx.make_canonicalized_query_response(
-                    canonical_inference_vars,
-                    value,
-                    &mut *fulfill_cx,
-                )
-            },
-        )
-    }
-}
-
 impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
     /// This method is meant to be invoked as the final step of a canonical query
     /// implementation. It is given:
@@ -195,9 +152,9 @@ fn make_query_response<T>(
     /// the query before applying this function.)
     ///
     /// To get a good understanding of what is happening here, check
-    /// out the [chapter in the rustc guide][c].
+    /// out the [chapter in the rustc dev guide][c].
     ///
-    /// [c]: https://rust-lang.github.io/rustc-guide/traits/canonicalization.html#processing-the-canonicalized-query-result
+    /// [c]: https://rustc-dev-guide.rust-lang.org/traits/canonicalization.html#processing-the-canonicalized-query-result
     pub fn instantiate_query_response_and_region_obligations<R>(
         &self,
         cause: &ObligationCause<'tcx>,
@@ -304,13 +261,31 @@ pub fn instantiate_nll_query_response_and_region_obligations<R>(
                 }
 
                 (GenericArgKind::Type(v1), GenericArgKind::Type(v2)) => {
-                    let ok = self.at(cause, param_env).eq(v1, v2)?;
-                    obligations.extend(ok.into_obligations());
+                    TypeRelating::new(
+                        self,
+                        QueryTypeRelatingDelegate {
+                            infcx: self,
+                            param_env,
+                            cause,
+                            obligations: &mut obligations,
+                        },
+                        ty::Variance::Invariant,
+                    )
+                    .relate(&v1, &v2)?;
                 }
 
                 (GenericArgKind::Const(v1), GenericArgKind::Const(v2)) => {
-                    let ok = self.at(cause, param_env).eq(v1, v2)?;
-                    obligations.extend(ok.into_obligations());
+                    TypeRelating::new(
+                        self,
+                        QueryTypeRelatingDelegate {
+                            infcx: self,
+                            param_env,
+                            cause,
+                            obligations: &mut obligations,
+                        },
+                        ty::Variance::Invariant,
+                    )
+                    .relate(&v1, &v2)?;
                 }
 
                 _ => {
@@ -656,3 +631,55 @@ pub fn make_query_region_constraints<'tcx>(
 
     QueryRegionConstraints { outlives, member_constraints: member_constraints.clone() }
 }
+
+struct QueryTypeRelatingDelegate<'a, 'tcx> {
+    infcx: &'a InferCtxt<'a, 'tcx>,
+    obligations: &'a mut Vec<PredicateObligation<'tcx>>,
+    param_env: ty::ParamEnv<'tcx>,
+    cause: &'a ObligationCause<'tcx>,
+}
+
+impl<'tcx> TypeRelatingDelegate<'tcx> for QueryTypeRelatingDelegate<'_, 'tcx> {
+    fn create_next_universe(&mut self) -> ty::UniverseIndex {
+        self.infcx.create_next_universe()
+    }
+
+    fn next_existential_region_var(&mut self, from_forall: bool) -> ty::Region<'tcx> {
+        let origin = NLLRegionVariableOrigin::Existential { from_forall };
+        self.infcx.next_nll_region_var(origin)
+    }
+
+    fn next_placeholder_region(&mut self, placeholder: ty::PlaceholderRegion) -> ty::Region<'tcx> {
+        self.infcx.tcx.mk_region(ty::RePlaceholder(placeholder))
+    }
+
+    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,
+        )
+    }
+
+    fn push_outlives(&mut self, sup: ty::Region<'tcx>, sub: ty::Region<'tcx>) {
+        self.obligations.push(Obligation {
+            cause: self.cause.clone(),
+            param_env: self.param_env,
+            predicate: ty::Predicate::RegionOutlives(ty::Binder::dummy(ty::OutlivesPredicate(
+                sup, sub,
+            ))),
+            recursion_depth: 0,
+        });
+    }
+
+    fn push_domain_goal(&mut self, _: DomainGoal<'tcx>) {
+        bug!("should never be invoked with eager normalization")
+    }
+
+    fn normalization() -> NormalizationStrategy {
+        NormalizationStrategy::Eager
+    }
+
+    fn forbid_inference_vars() -> bool {
+        true
+    }
+}
index 99ddedfe8815ba50941c10fb3da78b4e6822835f..afef32c1ffebb9d06f837029a555b948a0766253 100644 (file)
@@ -2,9 +2,9 @@
 //! `Canonical<'tcx, T>`.
 //!
 //! For an overview of what canonicalization is and how it fits into
-//! rustc, check out the [chapter in the rustc guide][c].
+//! rustc, check out the [chapter in the rustc dev guide][c].
 //!
-//! [c]: https://rust-lang.github.io/rustc-guide/traits/canonicalization.html
+//! [c]: https://rustc-dev-guide.rust-lang.org/traits/canonicalization.html
 
 use crate::infer::canonical::{Canonical, CanonicalVarValues};
 use rustc::ty::fold::TypeFoldable;
index c1eec6832b82663593cedf1f8628979de07ebb57..bb0c124a1892dffe39120a82e68a4a44c6b7aaf6 100644 (file)
@@ -19,7 +19,7 @@ pub fn new(
         fields: &'combine mut CombineFields<'infcx, 'tcx>,
         a_is_expected: bool,
     ) -> Equate<'combine, 'infcx, 'tcx> {
-        Equate { fields: fields, a_is_expected: a_is_expected }
+        Equate { fields, a_is_expected }
     }
 }
 
index bd133738db7ab153a49ab8202d492dffcad6ee45..ebbfcb28db2f533244821293bf8f538c69f581c6 100644 (file)
@@ -49,8 +49,7 @@
 use super::region_constraints::GenericKind;
 use super::{InferCtxt, RegionVariableOrigin, SubregionOrigin, TypeTrace, ValuePairs};
 
-use crate::infer::opaque_types;
-use crate::infer::{self, SuppressRegionErrors};
+use crate::infer;
 use crate::traits::error_reporting::report_object_safety_error;
 use crate::traits::{
     IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode,
@@ -269,14 +268,14 @@ fn item_scope_tag(item: &hir::Item<'_>) -> &'static str {
 
 fn trait_item_scope_tag(item: &hir::TraitItem<'_>) -> &'static str {
     match item.kind {
-        hir::TraitItemKind::Method(..) => "method body",
+        hir::TraitItemKind::Fn(..) => "method body",
         hir::TraitItemKind::Const(..) | hir::TraitItemKind::Type(..) => "associated item",
     }
 }
 
 fn impl_item_scope_tag(item: &hir::ImplItem<'_>) -> &'static str {
     match item.kind {
-        hir::ImplItemKind::Method(..) => "method body",
+        hir::ImplItemKind::Fn(..) => "method body",
         hir::ImplItemKind::Const(..)
         | hir::ImplItemKind::OpaqueTy(..)
         | hir::ImplItemKind::TyAlias(..) => "associated item",
@@ -288,22 +287,93 @@ fn explain_span(tcx: TyCtxt<'tcx>, heading: &str, span: Span) -> (String, Option
     (format!("the {} at {}:{}", heading, lo.line, lo.col.to_usize() + 1), Some(span))
 }
 
+pub fn unexpected_hidden_region_diagnostic(
+    tcx: TyCtxt<'tcx>,
+    region_scope_tree: Option<&region::ScopeTree>,
+    span: Span,
+    hidden_ty: Ty<'tcx>,
+    hidden_region: ty::Region<'tcx>,
+) -> DiagnosticBuilder<'tcx> {
+    let mut err = struct_span_err!(
+        tcx.sess,
+        span,
+        E0700,
+        "hidden type for `impl Trait` captures lifetime that does not appear in bounds",
+    );
+
+    // Explain the region we are capturing.
+    if let ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReStatic | ty::ReEmpty(_) = hidden_region {
+        // Assuming regionck succeeded (*), we ought to always be
+        // capturing *some* region from the fn header, and hence it
+        // ought to be free. So under normal circumstances, we will go
+        // down this path which gives a decent human readable
+        // explanation.
+        //
+        // (*) if not, the `tainted_by_errors` flag would be set to
+        // true in any case, so we wouldn't be here at all.
+        note_and_explain_free_region(
+            tcx,
+            &mut err,
+            &format!("hidden type `{}` captures ", hidden_ty),
+            hidden_region,
+            "",
+        );
+    } else {
+        // Ugh. This is a painful case: the hidden region is not one
+        // that we can easily summarize or explain. This can happen
+        // in a case like
+        // `src/test/ui/multiple-lifetimes/ordinary-bounds-unsuited.rs`:
+        //
+        // ```
+        // fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> {
+        //   if condition() { a } else { b }
+        // }
+        // ```
+        //
+        // Here the captured lifetime is the intersection of `'a` and
+        // `'b`, which we can't quite express.
+
+        if let Some(region_scope_tree) = region_scope_tree {
+            // If the `region_scope_tree` is available, this is being
+            // invoked from the "region inferencer error". We can at
+            // least report a really cryptic error for now.
+            note_and_explain_region(
+                tcx,
+                region_scope_tree,
+                &mut err,
+                &format!("hidden type `{}` captures ", hidden_ty),
+                hidden_region,
+                "",
+            );
+        } else {
+            // If the `region_scope_tree` is *unavailable*, this is
+            // being invoked by the code that comes *after* region
+            // inferencing. This is a bug, as the region inferencer
+            // ought to have noticed the failed constraint and invoked
+            // error reporting, which in turn should have prevented us
+            // from getting trying to infer the hidden type
+            // completely.
+            tcx.sess.delay_span_bug(
+                span,
+                &format!(
+                    "hidden type captures unexpected lifetime `{:?}` \
+                     but no region inference failure",
+                    hidden_region,
+                ),
+            );
+        }
+    }
+
+    err
+}
+
 impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     pub fn report_region_errors(
         &self,
         region_scope_tree: &region::ScopeTree,
         errors: &Vec<RegionResolutionError<'tcx>>,
-        suppress: SuppressRegionErrors,
     ) {
-        debug!(
-            "report_region_errors(): {} errors to start, suppress = {:?}",
-            errors.len(),
-            suppress
-        );
-
-        if suppress.suppressed() {
-            return;
-        }
+        debug!("report_region_errors(): {} errors to start", errors.len());
 
         // try to pre-process the errors, which will group some of them
         // together into a `ProcessedErrors` group:
@@ -410,7 +480,7 @@ pub fn report_region_errors(
                         span,
                     } => {
                         let hidden_ty = self.resolve_vars_if_possible(&hidden_ty);
-                        opaque_types::unexpected_hidden_region_diagnostic(
+                        unexpected_hidden_region_diagnostic(
                             self.tcx,
                             Some(region_scope_tree),
                             span,
@@ -1819,7 +1889,7 @@ fn binding_suggestion<'tcx, S: fmt::Display>(
                     "{} may not live long enough",
                     labeled_user_string
                 );
-                // Explicitely use the name instead of `sub`'s `Display` impl. The `Display` impl
+                // Explicitly use the name instead of `sub`'s `Display` impl. The `Display` impl
                 // for the bound is not suitable for suggestions when `-Zverbose` is set because it
                 // uses `Debug` output, so we handle it specially here so that suggestions are
                 // always correct.
@@ -2077,7 +2147,7 @@ fn as_requirement_str(&self) -> &'static str {
 /// This is a bare signal of what kind of type we're dealing with. `ty::TyKind` tracks
 /// extra information about each type, but we only care about the category.
 #[derive(Clone, Copy, PartialEq, Eq, Hash)]
-crate enum TyCategory {
+pub enum TyCategory {
     Closure,
     Opaque,
     Generator,
index a1e6a0a325ada94a6467dcbb4f7e6b7ffe8d4982..0eda4555e25656f671c9d6f8c88dbf739c85dd4a 100644 (file)
@@ -16,7 +16,7 @@
 struct FindLocalByTypeVisitor<'a, 'tcx> {
     infcx: &'a InferCtxt<'a, 'tcx>,
     target_ty: Ty<'tcx>,
-    hir_map: &'a Map<'tcx>,
+    hir_map: Map<'tcx>,
     found_local_pattern: Option<&'tcx Pat<'tcx>>,
     found_arg_pattern: Option<&'tcx Pat<'tcx>>,
     found_ty: Option<Ty<'tcx>>,
@@ -25,7 +25,7 @@ struct FindLocalByTypeVisitor<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> FindLocalByTypeVisitor<'a, 'tcx> {
-    fn new(infcx: &'a InferCtxt<'a, 'tcx>, target_ty: Ty<'tcx>, hir_map: &'a Map<'tcx>) -> Self {
+    fn new(infcx: &'a InferCtxt<'a, 'tcx>, target_ty: Ty<'tcx>, hir_map: Map<'tcx>) -> Self {
         Self {
             infcx,
             target_ty,
@@ -69,8 +69,8 @@ fn node_matches_type(&mut self, hir_id: HirId) -> Option<Ty<'tcx>> {
 impl<'a, 'tcx> Visitor<'tcx> for FindLocalByTypeVisitor<'a, 'tcx> {
     type Map = Map<'tcx>;
 
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, Self::Map> {
-        NestedVisitorMap::OnlyBodies(&self.hir_map)
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::OnlyBodies(self.hir_map)
     }
 
     fn visit_local(&mut self, local: &'tcx Local<'tcx>) {
@@ -223,7 +223,7 @@ pub fn need_type_info_err(
         let ty = self.resolve_vars_if_possible(&ty);
         let (name, name_sp, descr, parent_name, parent_descr) = self.extract_type_name(&ty, None);
 
-        let mut local_visitor = FindLocalByTypeVisitor::new(&self, ty, &self.tcx.hir());
+        let mut local_visitor = FindLocalByTypeVisitor::new(&self, ty, self.tcx.hir());
         let ty_to_string = |ty: Ty<'tcx>| -> String {
             let mut s = String::new();
             let mut printer = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS);
@@ -391,7 +391,7 @@ pub fn need_type_info_err(
             err.span_label(pattern.span, msg);
         } else if let Some(e) = local_visitor.found_method_call {
             if let ExprKind::MethodCall(segment, ..) = &e.kind {
-                // Suggest specifiying type params or point out the return type of the call:
+                // Suggest specifying type params or point out the return type of the call:
                 //
                 // error[E0282]: type annotations needed
                 //   --> $DIR/type-annotations-needed-expr.rs:2:39
@@ -468,7 +468,7 @@ fn annotate_method_call(
             &segment.args,
         ) {
             let borrow = tables.borrow();
-            if let Some((DefKind::Method, did)) = borrow.type_dependent_def(e.hir_id) {
+            if let Some((DefKind::AssocFn, did)) = borrow.type_dependent_def(e.hir_id) {
                 let generics = self.tcx.generics_of(did);
                 if !generics.params.is_empty() {
                     err.span_suggestion(
index 1a09729ef6443dde38b1e979c93e79004a01f0c4..50b324c72278e1fa83d9a67671962e900221a6e6 100644 (file)
@@ -3,6 +3,8 @@
 
 use crate::infer::error_reporting::nice_region_error::util::AnonymousParamInfo;
 use crate::infer::error_reporting::nice_region_error::NiceRegionError;
+use crate::infer::lexical_region_resolve::RegionResolutionError;
+use crate::infer::SubregionOrigin;
 use rustc::util::common::ErrorReported;
 
 use rustc_errors::struct_span_err;
@@ -47,6 +49,15 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
     pub(super) fn try_report_anon_anon_conflict(&self) -> Option<ErrorReported> {
         let (span, sub, sup) = self.regions()?;
 
+        if let Some(RegionResolutionError::ConcreteFailure(
+            SubregionOrigin::ReferenceOutlivesReferent(..),
+            ..,
+        )) = self.error
+        {
+            // This error doesn't make much sense in this case.
+            return None;
+        }
+
         // Determine whether the sub and sup consist of both anonymous (elided) regions.
         let anon_reg_sup = self.tcx().is_suitable_region(sup)?;
 
index 2ae7f4cc04f981611aa6220dc7cf96d280a7fba5..15acf632b2c9829efab5382a4c753f74d6877966 100644 (file)
@@ -33,11 +33,11 @@ pub(super) fn find_anon_type(
                 let fndecl = match self.tcx().hir().get(hir_id) {
                     Node::Item(&hir::Item { kind: hir::ItemKind::Fn(ref m, ..), .. })
                     | Node::TraitItem(&hir::TraitItem {
-                        kind: hir::TraitItemKind::Method(ref m, ..),
+                        kind: hir::TraitItemKind::Fn(ref m, ..),
                         ..
                     })
                     | Node::ImplItem(&hir::ImplItem {
-                        kind: hir::ImplItemKind::Method(ref m, ..),
+                        kind: hir::ImplItemKind::Fn(ref m, ..),
                         ..
                     }) => &m.decl,
                     _ => return None,
@@ -93,8 +93,8 @@ struct FindNestedTypeVisitor<'tcx> {
 impl Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
     type Map = Map<'tcx>;
 
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, Self::Map> {
-        NestedVisitorMap::OnlyBodies(&self.tcx.hir())
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::OnlyBodies(self.tcx.hir())
     }
 
     fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx>) {
@@ -212,8 +212,8 @@ struct TyPathVisitor<'tcx> {
 impl Visitor<'tcx> for TyPathVisitor<'tcx> {
     type Map = Map<'tcx>;
 
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, Map<'tcx>> {
-        NestedVisitorMap::OnlyBodies(&self.tcx.hir())
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Map<'tcx>> {
+        NestedVisitorMap::OnlyBodies(self.tcx.hir())
     }
 
     fn visit_lifetime(&mut self, lifetime: &hir::Lifetime) {
index d8c314a0d2f1f67867f6786498dae06d1d0a1d43..2357ee689d59e700a5d2c034b6f1d4a828bcbca3 100644 (file)
 
 impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
     pub fn try_report_nice_region_error(&self, error: &RegionResolutionError<'tcx>) -> bool {
-        if let Some(tables) = self.in_progress_tables {
-            let tables = tables.borrow();
-            NiceRegionError::new(self, error.clone(), Some(&tables)).try_report().is_some()
-        } else {
-            NiceRegionError::new(self, error.clone(), None).try_report().is_some()
-        }
+        NiceRegionError::new(self, error.clone()).try_report().is_some()
     }
 }
 
@@ -30,16 +25,11 @@ pub struct NiceRegionError<'cx, 'tcx> {
     infcx: &'cx InferCtxt<'cx, 'tcx>,
     error: Option<RegionResolutionError<'tcx>>,
     regions: Option<(Span, ty::Region<'tcx>, ty::Region<'tcx>)>,
-    tables: Option<&'cx ty::TypeckTables<'tcx>>,
 }
 
 impl<'cx, 'tcx> NiceRegionError<'cx, 'tcx> {
-    pub fn new(
-        infcx: &'cx InferCtxt<'cx, 'tcx>,
-        error: RegionResolutionError<'tcx>,
-        tables: Option<&'cx ty::TypeckTables<'tcx>>,
-    ) -> Self {
-        Self { infcx, error: Some(error), regions: None, tables }
+    pub fn new(infcx: &'cx InferCtxt<'cx, 'tcx>, error: RegionResolutionError<'tcx>) -> Self {
+        Self { infcx, error: Some(error), regions: None }
     }
 
     pub fn new_from_span(
@@ -47,9 +37,8 @@ pub fn new_from_span(
         span: Span,
         sub: ty::Region<'tcx>,
         sup: ty::Region<'tcx>,
-        tables: Option<&'cx ty::TypeckTables<'tcx>>,
     ) -> Self {
-        Self { infcx, error: None, regions: Some((span, sub, sup)), tables }
+        Self { infcx, error: None, regions: Some((span, sub, sup)) }
     }
 
     fn tcx(&self) -> TyCtxt<'tcx> {
index 4dc9096533b843f71de8835ee557f789392993a1..de72c276595f769dc5b887a087e17615498b39d3 100644 (file)
@@ -51,52 +51,44 @@ pub(super) fn find_param_with_region(
         };
 
         let hir = &self.tcx().hir();
-        if let Some(hir_id) = hir.as_local_hir_id(id) {
-            if let Some(body_id) = hir.maybe_body_owned_by(hir_id) {
-                let body = hir.body(body_id);
-                let owner_id = hir.body_owner(body_id);
-                let fn_decl = hir.fn_decl_by_hir_id(owner_id).unwrap();
-                if let Some(tables) = self.tables {
-                    body.params
-                        .iter()
-                        .enumerate()
-                        .filter_map(|(index, param)| {
-                            // May return None; sometimes the tables are not yet populated.
-                            let ty_hir_id = fn_decl.inputs[index].hir_id;
-                            let param_ty_span = hir.span(ty_hir_id);
-                            let ty = tables.node_type_opt(param.hir_id)?;
-                            let mut found_anon_region = false;
-                            let new_param_ty = self.tcx().fold_regions(&ty, &mut false, |r, _| {
-                                if *r == *anon_region {
-                                    found_anon_region = true;
-                                    replace_region
-                                } else {
-                                    r
-                                }
-                            });
-                            if found_anon_region {
-                                let is_first = index == 0;
-                                Some(AnonymousParamInfo {
-                                    param: param,
-                                    param_ty: new_param_ty,
-                                    param_ty_span: param_ty_span,
-                                    bound_region: bound_region,
-                                    is_first: is_first,
-                                })
-                            } else {
-                                None
-                            }
-                        })
-                        .next()
+        let hir_id = hir.as_local_hir_id(id)?;
+        let body_id = hir.maybe_body_owned_by(hir_id)?;
+        let body = hir.body(body_id);
+        let owner_id = hir.body_owner(body_id);
+        let fn_decl = hir.fn_decl_by_hir_id(owner_id).unwrap();
+        let poly_fn_sig = self.tcx().fn_sig(id);
+        let fn_sig = self.tcx().liberate_late_bound_regions(id, &poly_fn_sig);
+        body.params
+            .iter()
+            .enumerate()
+            .filter_map(|(index, param)| {
+                // May return None; sometimes the tables are not yet populated.
+                let ty = fn_sig.inputs()[index];
+                let mut found_anon_region = false;
+                let new_param_ty = self.tcx().fold_regions(&ty, &mut false, |r, _| {
+                    if *r == *anon_region {
+                        found_anon_region = true;
+                        replace_region
+                    } else {
+                        r
+                    }
+                });
+                if found_anon_region {
+                    let ty_hir_id = fn_decl.inputs[index].hir_id;
+                    let param_ty_span = hir.span(ty_hir_id);
+                    let is_first = index == 0;
+                    Some(AnonymousParamInfo {
+                        param,
+                        param_ty: new_param_ty,
+                        param_ty_span,
+                        bound_region,
+                        is_first,
+                    })
                 } else {
                     None
                 }
-            } else {
-                None
-            }
-        } else {
-            None
-        }
+            })
+            .next()
     }
 
     // Here, we check for the case where the anonymous region
index 63dded3b43d10941c933fd5222f85980ffccbaa2..a454feea36b70d6dad0bcbe877ed841e92207ec5 100644 (file)
@@ -143,10 +143,7 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
     }
 
     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
-        if !t.needs_infer()
-            && !t.has_erasable_regions()
-            && !(t.has_closure_types() && self.infcx.in_progress_tables.is_some())
-        {
+        if !t.needs_infer() && !t.has_erasable_regions() {
             return t;
         }
 
index 2634d9cac3e99a6bdbb27f775198aabe4b78d32d..8b26bcef5730459786740e0f52f2f9ebefbade33 100644 (file)
@@ -18,7 +18,7 @@ pub fn new(
         fields: &'combine mut CombineFields<'infcx, 'tcx>,
         a_is_expected: bool,
     ) -> Glb<'combine, 'infcx, 'tcx> {
-        Glb { fields: fields, a_is_expected: a_is_expected }
+        Glb { fields, a_is_expected }
     }
 }
 
index e7afaa5beb0a75adcc35dca489ddbfe834cc0419..533d0ef7e6c4b0c60f2b2c8f8a11dff710d85568 100644 (file)
@@ -1,8 +1,8 @@
 To learn more about how Higher-ranked trait bounds work in the _old_ trait
-solver, see [this chapter][oldhrtb] of the rustc-guide.
+solver, see [this chapter][oldhrtb] of the rustc-dev-guide.
 
 To learn more about how they work in the _new_ trait solver, see [this
 chapter][newhrtb].
 
-[oldhrtb]: https://rust-lang.github.io/rustc-guide/traits/hrtb.html
-[newhrtb]: https://rust-lang.github.io/rustc-guide/borrow_check/region_inference.html#placeholders-and-universes
+[oldhrtb]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html
+[newhrtb]: https://rustc-dev-guide.rust-lang.org/borrow_check/region_inference.html#placeholders-and-universes
index 33781188a95509bd4d7b81eae080fa80ed9756e6..105b987f85e96272f36328f81b0da378cd485786 100644 (file)
@@ -71,9 +71,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     /// needed (but is also permitted).
     ///
     /// For more information about how placeholders and HRTBs work, see
-    /// the [rustc guide].
+    /// the [rustc dev guide].
     ///
-    /// [rustc guide]: https://rust-lang.github.io/rustc-guide/traits/hrtb.html
+    /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html
     pub fn replace_bound_vars_with_placeholders<T>(
         &self,
         binder: &ty::Binder<T>,
index c26b5625a90b636082a3c31001c0460cd040cd11..e0b2c0bffeeb36b398c26054067235afa9176afb 100644 (file)
@@ -2,6 +2,6 @@
 Lexical Region Resolution was removed in https://github.com/rust-lang/rust/pull/64790.
 
 Rust now uses Non-lexical lifetimes. For more info, please see the [borrowck
-chapter][bc] in the rustc-guide.
+chapter][bc] in the rustc-dev-guide.
 
-[bc]: https://rust-lang.github.io/rustc-guide/borrow_check/region_inference.html
+[bc]: https://rustc-dev-guide.rust-lang.org/borrow_check/region_inference.html
index fc9f3bb076745a6f076a8783d11e7aa0b7682cf6..3af10e850d534fe2c3112c58339f7075672fdfbb 100644 (file)
@@ -7,6 +7,7 @@
 use crate::infer::region_constraints::VarInfos;
 use crate::infer::region_constraints::VerifyBound;
 use crate::infer::RegionVariableOrigin;
+use crate::infer::RegionckMode;
 use crate::infer::SubregionOrigin;
 use rustc::middle::free_region::RegionRelations;
 use rustc::ty::fold::TypeFoldable;
@@ -33,12 +34,29 @@ pub fn resolve<'tcx>(
     region_rels: &RegionRelations<'_, 'tcx>,
     var_infos: VarInfos,
     data: RegionConstraintData<'tcx>,
+    mode: RegionckMode,
 ) -> (LexicalRegionResolutions<'tcx>, Vec<RegionResolutionError<'tcx>>) {
     debug!("RegionConstraintData: resolve_regions()");
     let mut errors = vec![];
     let mut resolver = LexicalResolver { region_rels, var_infos, data };
-    let values = resolver.infer_variable_values(&mut errors);
-    (values, errors)
+    match mode {
+        RegionckMode::Solve => {
+            let values = resolver.infer_variable_values(&mut errors);
+            (values, errors)
+        }
+        RegionckMode::Erase { suppress_errors: false } => {
+            // Do real inference to get errors, then erase the results.
+            let mut values = resolver.infer_variable_values(&mut errors);
+            let re_erased = region_rels.tcx.lifetimes.re_erased;
+
+            values.values.iter_mut().for_each(|v| *v = VarValue::Value(re_erased));
+            (values, errors)
+        }
+        RegionckMode::Erase { suppress_errors: true } => {
+            // Skip region inference entirely.
+            (resolver.erased_data(region_rels.tcx), Vec::new())
+        }
+    }
 }
 
 /// Contains the result of lexical region resolution. Offers methods
@@ -163,6 +181,19 @@ fn construct_var_data(&self, tcx: TyCtxt<'tcx>) -> LexicalRegionResolutions<'tcx
         }
     }
 
+    /// An erased version of the lexical region resolutions. Used when we're
+    /// erasing regions and suppressing errors: in item bodies with
+    /// `-Zborrowck=mir`.
+    fn erased_data(&self, tcx: TyCtxt<'tcx>) -> LexicalRegionResolutions<'tcx> {
+        LexicalRegionResolutions {
+            error_region: tcx.lifetimes.re_static,
+            values: IndexVec::from_elem_n(
+                VarValue::Value(tcx.lifetimes.re_erased),
+                self.num_vars(),
+            ),
+        }
+    }
+
     fn dump_constraints(&self, free_regions: &RegionRelations<'_, 'tcx>) {
         debug!("----() Start constraint listing (context={:?}) ()----", free_regions.context);
         for (idx, (constraint, _)) in self.data.constraints.iter().enumerate() {
@@ -751,7 +782,7 @@ fn construct_graph(&self) -> RegionGraph<'tcx> {
         let dummy_source = graph.add_node(());
         let dummy_sink = graph.add_node(());
 
-        for (constraint, _) in &self.data.constraints {
+        for constraint in self.data.constraints.keys() {
             match *constraint {
                 Constraint::VarSubVar(a_id, b_id) => {
                     graph.add_edge(
index b6d20ba1f3f12f3f736e8870a16fcb7ba54d916f..20ddeec68503aa9f9a6ab57fd3a03d2f7240bb56 100644 (file)
@@ -18,7 +18,7 @@ pub fn new(
         fields: &'combine mut CombineFields<'infcx, 'tcx>,
         a_is_expected: bool,
     ) -> Lub<'combine, 'infcx, 'tcx> {
-        Lub { fields: fields, a_is_expected: a_is_expected }
+        Lub { fields, a_is_expected }
     }
 }
 
index 11b08d468b1b919ed0ce04dac7fe720e14e8edc2..391fce946bf43b37fa9b0bddedeb0d39f7213ff5 100644 (file)
@@ -5,7 +5,6 @@
 pub use self::RegionVariableOrigin::*;
 pub use self::SubregionOrigin::*;
 pub use self::ValuePairs::*;
-pub use rustc::ty::IntVarValue;
 
 use crate::traits::{self, ObligationCause, PredicateObligations, TraitEngine};
 
 use rustc::infer::unify_key::{ConstVarValue, ConstVariableValue};
 use rustc::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind, ToType};
 use rustc::middle::free_region::RegionRelations;
-use rustc::middle::lang_items;
 use rustc::middle::region;
 use rustc::mir;
 use rustc::mir::interpret::ConstEvalResult;
-use rustc::session::config::BorrowckMode;
+use rustc::traits::select;
 use rustc::ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric};
 use rustc::ty::fold::{TypeFoldable, TypeFolder};
 use rustc::ty::relate::RelateResult;
 use rustc::ty::subst::{GenericArg, InternalSubsts, SubstsRef};
+pub use rustc::ty::IntVarValue;
 use rustc::ty::{self, GenericParamDefKind, InferConst, Ty, TyCtxt};
 use rustc::ty::{ConstVid, FloatVid, IntVid, TyVid};
-
 use rustc_ast::ast;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::DiagnosticBuilder;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
+use rustc_session::config::BorrowckMode;
 use rustc_span::symbol::Symbol;
 use rustc_span::Span;
+
 use std::cell::{Cell, Ref, RefCell};
 use std::collections::BTreeMap;
 use std::fmt;
@@ -58,7 +58,6 @@
 mod lexical_region_resolve;
 mod lub;
 pub mod nll_relate;
-pub mod opaque_types;
 pub mod outlives;
 pub mod region_constraints;
 pub mod resolve;
@@ -80,31 +79,50 @@ pub struct InferOk<'tcx, T> {
 pub type UnitResult<'tcx> = RelateResult<'tcx, ()>; // "unify result"
 pub type FixupResult<'tcx, T> = Result<T, FixupError<'tcx>>; // "fixup result"
 
-/// A flag that is used to suppress region errors. This is normally
-/// false, but sometimes -- when we are doing region checks that the
-/// NLL borrow checker will also do -- it might be set to true.
-#[derive(Copy, Clone, Default, Debug)]
-pub struct SuppressRegionErrors {
-    suppressed: bool,
+/// How we should handle region solving.
+///
+/// This is used so that the region values inferred by HIR region solving are
+/// not exposed, and so that we can avoid doing work in HIR typeck that MIR
+/// typeck will also do.
+#[derive(Copy, Clone, Debug)]
+pub enum RegionckMode {
+    /// The default mode: report region errors, don't erase regions.
+    Solve,
+    /// Erase the results of region after solving.
+    Erase {
+        /// A flag that is used to suppress region errors, when we are doing
+        /// region checks that the NLL borrow checker will also do -- it might
+        /// be set to true.
+        suppress_errors: bool,
+    },
+}
+
+impl Default for RegionckMode {
+    fn default() -> Self {
+        RegionckMode::Solve
+    }
 }
 
-impl SuppressRegionErrors {
+impl RegionckMode {
     pub fn suppressed(self) -> bool {
-        self.suppressed
+        match self {
+            Self::Solve => false,
+            Self::Erase { suppress_errors } => suppress_errors,
+        }
     }
 
     /// Indicates that the MIR borrowck will repeat these region
     /// checks, so we should ignore errors if NLL is (unconditionally)
     /// enabled.
-    pub fn when_nll_is_enabled(tcx: TyCtxt<'_>) -> Self {
+    pub fn for_item_body(tcx: TyCtxt<'_>) -> Self {
         // FIXME(Centril): Once we actually remove `::Migrate` also make
         // this always `true` and then proceed to eliminate the dead code.
         match tcx.borrowck_mode() {
             // If we're on Migrate mode, report AST region errors
-            BorrowckMode::Migrate => SuppressRegionErrors { suppressed: false },
+            BorrowckMode::Migrate => RegionckMode::Erase { suppress_errors: false },
 
             // If we're on MIR, don't report AST region errors as they should be reported by NLL
-            BorrowckMode::Mir => SuppressRegionErrors { suppressed: true },
+            BorrowckMode::Mir => RegionckMode::Erase { suppress_errors: true },
         }
     }
 }
@@ -215,10 +233,10 @@ pub struct InferCtxt<'a, 'tcx> {
 
     /// Caches the results of trait selection. This cache is used
     /// for things that have to do with the parameters in scope.
-    pub selection_cache: traits::SelectionCache<'tcx>,
+    pub selection_cache: select::SelectionCache<'tcx>,
 
     /// Caches the results of trait evaluation.
-    pub evaluation_cache: traits::EvaluationCache<'tcx>,
+    pub evaluation_cache: select::EvaluationCache<'tcx>,
 
     /// the set of predicates on which errors have been reported, to
     /// avoid reporting the same error twice.
@@ -1208,20 +1226,13 @@ pub fn resolve_regions_and_report_errors(
         region_context: DefId,
         region_map: &region::ScopeTree,
         outlives_env: &OutlivesEnvironment<'tcx>,
-        suppress: SuppressRegionErrors,
+        mode: RegionckMode,
     ) {
         assert!(
             self.is_tainted_by_errors() || self.inner.borrow().region_obligations.is_empty(),
             "region_obligations not empty: {:#?}",
             self.inner.borrow().region_obligations
         );
-
-        let region_rels = &RegionRelations::new(
-            self.tcx,
-            region_context,
-            region_map,
-            outlives_env.free_region_map(),
-        );
         let (var_infos, data) = self
             .inner
             .borrow_mut()
@@ -1229,8 +1240,16 @@ pub fn resolve_regions_and_report_errors(
             .take()
             .expect("regions already resolved")
             .into_infos_and_data();
+
+        let region_rels = &RegionRelations::new(
+            self.tcx,
+            region_context,
+            region_map,
+            outlives_env.free_region_map(),
+        );
+
         let (lexical_region_resolutions, errors) =
-            lexical_region_resolve::resolve(region_rels, var_infos, data);
+            lexical_region_resolve::resolve(region_rels, var_infos, data, mode);
 
         let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions));
         assert!(old_value.is_none());
@@ -1241,7 +1260,7 @@ pub fn resolve_regions_and_report_errors(
             // this infcx was in use.  This is totally hokey but
             // otherwise we have a hard time separating legit region
             // errors from silly ones.
-            self.report_region_errors(region_map, &errors, suppress);
+            self.report_region_errors(region_map, &errors);
         }
     }
 
@@ -1474,31 +1493,6 @@ pub fn verify_generic_bound(
             .verify_generic_bound(origin, kind, a, bound);
     }
 
-    pub fn type_is_copy_modulo_regions(
-        &self,
-        param_env: ty::ParamEnv<'tcx>,
-        ty: Ty<'tcx>,
-        span: Span,
-    ) -> bool {
-        let ty = self.resolve_vars_if_possible(&ty);
-
-        // Even if the type may have no inference variables, during
-        // type-checking closure types are in local tables only.
-        if !self.in_progress_tables.is_some() || !ty.has_closure_types() {
-            if !(param_env, ty).has_local_value() {
-                return ty.is_copy_modulo_regions(self.tcx, param_env, span);
-            }
-        }
-
-        let copy_def_id = self.tcx.require_lang_item(lang_items::CopyTraitLangItem, None);
-
-        // This can get called from typeck (by euv), and `moves_by_default`
-        // rightly refuses to work with inference variables, but
-        // moves_by_default has a cache, which we want to use in other
-        // cases.
-        traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, copy_def_id, span)
-    }
-
     /// Obtains the latest type of the given closure; this may be a
     /// closure in the current function, in which case its
     /// `ClosureKind` may not yet be known.
@@ -1522,30 +1516,6 @@ pub fn closure_sig(&self, def_id: DefId, substs: SubstsRef<'tcx>) -> ty::PolyFnS
         closure_sig_ty.fn_sig(self.tcx)
     }
 
-    /// Normalizes associated types in `value`, potentially returning
-    /// new obligations that must further be processed.
-    pub fn partially_normalize_associated_types_in<T>(
-        &self,
-        span: Span,
-        body_id: hir::HirId,
-        param_env: ty::ParamEnv<'tcx>,
-        value: &T,
-    ) -> InferOk<'tcx, T>
-    where
-        T: TypeFoldable<'tcx>,
-    {
-        debug!("partially_normalize_associated_types_in(value={:?})", value);
-        let mut selcx = traits::SelectionContext::new(self);
-        let cause = ObligationCause::misc(span, body_id);
-        let traits::Normalized { value, obligations } =
-            traits::normalize(&mut selcx, param_env, cause, value);
-        debug!(
-            "partially_normalize_associated_types_in: result={:?} predicates={:?}",
-            value, obligations
-        );
-        InferOk { value, obligations }
-    }
-
     /// Clears the selection, evaluation, and projection caches. This is useful when
     /// repeatedly attempting to select an `Obligation` while changing only
     /// its `ParamEnv`, since `FulfillmentContext` doesn't use probing.
@@ -1671,14 +1641,14 @@ pub fn shallow_resolve_changed(&self, infer: ty::InferTy) -> bool {
 
             ty::IntVar(v) => {
                 // If inlined_probe_value returns a value it's always a
-                // `ty::Int(_)` or `ty::UInt(_)`, which nevers matches a
+                // `ty::Int(_)` or `ty::UInt(_)`, which never matches a
                 // `ty::Infer(_)`.
                 self.infcx.inner.borrow_mut().int_unification_table.inlined_probe_value(v).is_some()
             }
 
             ty::FloatVar(v) => {
                 // If inlined_probe_value returns a value it's always a
-                // `ty::Float(_)`, which nevers matches a `ty::Infer(_)`.
+                // `ty::Float(_)`, which never matches a `ty::Infer(_)`.
                 //
                 // Not `inlined_probe_value(v)` because this call site is colder.
                 self.infcx.inner.borrow_mut().float_unification_table.probe_value(v).is_some()
index e35b8f9c8ecd41d64d198fa1ef6c60b976ab206d..50bea300c50644ffe74ccba3c860c35f13ab561b 100644 (file)
@@ -340,7 +340,7 @@ fn relate_ty_var<PAIR: VidValuePair<'tcx>>(
             // In NLL, we don't have type inference variables
             // floating around, so we can do this rather imprecise
             // variant of the occurs-check.
-            assert!(!generalized_ty.has_infer_types());
+            assert!(!generalized_ty.has_infer_types_or_consts());
         }
 
         self.infcx.inner.borrow_mut().type_variables.instantiate(vid, generalized_ty);
diff --git a/src/librustc_infer/infer/opaque_types/mod.rs b/src/librustc_infer/infer/opaque_types/mod.rs
deleted file mode 100644 (file)
index 06d4569..0000000
+++ /dev/null
@@ -1,1328 +0,0 @@
-use crate::infer::error_reporting::{note_and_explain_free_region, note_and_explain_region};
-use crate::infer::{self, InferCtxt, InferOk, TypeVariableOrigin, TypeVariableOriginKind};
-use crate::traits::{self, PredicateObligation};
-use rustc::middle::region;
-use rustc::session::config::nightly_options;
-use rustc::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder, TypeVisitor};
-use rustc::ty::free_region_map::FreeRegionRelations;
-use rustc::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef};
-use rustc::ty::{self, GenericParamDefKind, Ty, TyCtxt};
-use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::sync::Lrc;
-use rustc_errors::{struct_span_err, DiagnosticBuilder};
-use rustc_hir as hir;
-use rustc_hir::def_id::{DefId, DefIdMap};
-use rustc_hir::Node;
-use rustc_span::Span;
-
-pub type OpaqueTypeMap<'tcx> = DefIdMap<OpaqueTypeDecl<'tcx>>;
-
-/// Information about the opaque types whose values we
-/// are inferring in this function (these are the `impl Trait` that
-/// appear in the return type).
-#[derive(Copy, Clone, Debug)]
-pub struct OpaqueTypeDecl<'tcx> {
-    /// The opaque type (`ty::Opaque`) for this declaration.
-    pub opaque_type: Ty<'tcx>,
-
-    /// The substitutions that we apply to the opaque type that this
-    /// `impl Trait` desugars to. e.g., if:
-    ///
-    ///     fn foo<'a, 'b, T>() -> impl Trait<'a>
-    ///
-    /// winds up desugared to:
-    ///
-    ///     type Foo<'x, X> = impl Trait<'x>
-    ///     fn foo<'a, 'b, T>() -> Foo<'a, T>
-    ///
-    /// then `substs` would be `['a, T]`.
-    pub substs: SubstsRef<'tcx>,
-
-    /// The span of this particular definition of the opaque type.  So
-    /// for example:
-    ///
-    /// ```
-    /// type Foo = impl Baz;
-    /// fn bar() -> Foo {
-    ///             ^^^ This is the span we are looking for!
-    /// ```
-    ///
-    /// In cases where the fn returns `(impl Trait, impl Trait)` or
-    /// other such combinations, the result is currently
-    /// over-approximated, but better than nothing.
-    pub definition_span: Span,
-
-    /// The type variable that represents the value of the opaque type
-    /// that we require. In other words, after we compile this function,
-    /// we will be created a constraint like:
-    ///
-    ///     Foo<'a, T> = ?C
-    ///
-    /// where `?C` is the value of this type variable. =) It may
-    /// naturally refer to the type and lifetime parameters in scope
-    /// in this function, though ultimately it should only reference
-    /// those that are arguments to `Foo` in the constraint above. (In
-    /// other words, `?C` should not include `'b`, even though it's a
-    /// lifetime parameter on `foo`.)
-    pub concrete_ty: Ty<'tcx>,
-
-    /// Returns `true` if the `impl Trait` bounds include region bounds.
-    /// For example, this would be true for:
-    ///
-    ///     fn foo<'a, 'b, 'c>() -> impl Trait<'c> + 'a + 'b
-    ///
-    /// but false for:
-    ///
-    ///     fn foo<'c>() -> impl Trait<'c>
-    ///
-    /// unless `Trait` was declared like:
-    ///
-    ///     trait Trait<'c>: 'c
-    ///
-    /// in which case it would be true.
-    ///
-    /// This is used during regionck to decide whether we need to
-    /// impose any additional constraints to ensure that region
-    /// variables in `concrete_ty` wind up being constrained to
-    /// something from `substs` (or, at minimum, things that outlive
-    /// the fn body). (Ultimately, writeback is responsible for this
-    /// check.)
-    pub has_required_region_bounds: bool,
-
-    /// The origin of the opaque type.
-    pub origin: hir::OpaqueTyOrigin,
-}
-
-/// Whether member constraints should be generated for all opaque types
-pub enum GenerateMemberConstraints {
-    /// The default, used by typeck
-    WhenRequired,
-    /// The borrow checker needs member constraints in any case where we don't
-    /// have a `'static` bound. This is because the borrow checker has more
-    /// flexibility in the values of regions. For example, given `f<'a, 'b>`
-    /// the borrow checker can have an inference variable outlive `'a` and `'b`,
-    /// but not be equal to `'static`.
-    IfNoStaticBound,
-}
-
-impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
-    /// Replaces all opaque types in `value` with fresh inference variables
-    /// and creates appropriate obligations. For example, given the input:
-    ///
-    ///     impl Iterator<Item = impl Debug>
-    ///
-    /// this method would create two type variables, `?0` and `?1`. It would
-    /// return the type `?0` but also the obligations:
-    ///
-    ///     ?0: Iterator<Item = ?1>
-    ///     ?1: Debug
-    ///
-    /// Moreover, it returns a `OpaqueTypeMap` that would map `?0` to
-    /// info about the `impl Iterator<..>` type and `?1` to info about
-    /// the `impl Debug` type.
-    ///
-    /// # Parameters
-    ///
-    /// - `parent_def_id` -- the `DefId` of the function in which the opaque type
-    ///   is defined
-    /// - `body_id` -- the body-id with which the resulting obligations should
-    ///   be associated
-    /// - `param_env` -- the in-scope parameter environment to be used for
-    ///   obligations
-    /// - `value` -- the value within which we are instantiating opaque types
-    /// - `value_span` -- the span where the value came from, used in error reporting
-    pub fn instantiate_opaque_types<T: TypeFoldable<'tcx>>(
-        &self,
-        parent_def_id: DefId,
-        body_id: hir::HirId,
-        param_env: ty::ParamEnv<'tcx>,
-        value: &T,
-        value_span: Span,
-    ) -> InferOk<'tcx, (T, OpaqueTypeMap<'tcx>)> {
-        debug!(
-            "instantiate_opaque_types(value={:?}, parent_def_id={:?}, body_id={:?}, \
-             param_env={:?}, value_span={:?})",
-            value, parent_def_id, body_id, param_env, value_span,
-        );
-        let mut instantiator = Instantiator {
-            infcx: self,
-            parent_def_id,
-            body_id,
-            param_env,
-            value_span,
-            opaque_types: Default::default(),
-            obligations: vec![],
-        };
-        let value = instantiator.instantiate_opaque_types_in_map(value);
-        InferOk { value: (value, instantiator.opaque_types), obligations: instantiator.obligations }
-    }
-
-    /// Given the map `opaque_types` containing the opaque
-    /// `impl Trait` types whose underlying, hidden types are being
-    /// inferred, this method adds constraints to the regions
-    /// appearing in those underlying hidden types to ensure that they
-    /// at least do not refer to random scopes within the current
-    /// function. These constraints are not (quite) sufficient to
-    /// guarantee that the regions are actually legal values; that
-    /// final condition is imposed after region inference is done.
-    ///
-    /// # The Problem
-    ///
-    /// Let's work through an example to explain how it works. Assume
-    /// the current function is as follows:
-    ///
-    /// ```text
-    /// fn foo<'a, 'b>(..) -> (impl Bar<'a>, impl Bar<'b>)
-    /// ```
-    ///
-    /// Here, we have two `impl Trait` types whose values are being
-    /// inferred (the `impl Bar<'a>` and the `impl
-    /// Bar<'b>`). Conceptually, this is sugar for a setup where we
-    /// define underlying opaque types (`Foo1`, `Foo2`) and then, in
-    /// the return type of `foo`, we *reference* those definitions:
-    ///
-    /// ```text
-    /// type Foo1<'x> = impl Bar<'x>;
-    /// type Foo2<'x> = impl Bar<'x>;
-    /// fn foo<'a, 'b>(..) -> (Foo1<'a>, Foo2<'b>) { .. }
-    ///                    //  ^^^^ ^^
-    ///                    //  |    |
-    ///                    //  |    substs
-    ///                    //  def_id
-    /// ```
-    ///
-    /// As indicating in the comments above, each of those references
-    /// is (in the compiler) basically a substitution (`substs`)
-    /// applied to the type of a suitable `def_id` (which identifies
-    /// `Foo1` or `Foo2`).
-    ///
-    /// Now, at this point in compilation, what we have done is to
-    /// replace each of the references (`Foo1<'a>`, `Foo2<'b>`) with
-    /// fresh inference variables C1 and C2. We wish to use the values
-    /// of these variables to infer the underlying types of `Foo1` and
-    /// `Foo2`. That is, this gives rise to higher-order (pattern) unification
-    /// constraints like:
-    ///
-    /// ```text
-    /// for<'a> (Foo1<'a> = C1)
-    /// for<'b> (Foo1<'b> = C2)
-    /// ```
-    ///
-    /// For these equation to be satisfiable, the types `C1` and `C2`
-    /// can only refer to a limited set of regions. For example, `C1`
-    /// can only refer to `'static` and `'a`, and `C2` can only refer
-    /// to `'static` and `'b`. The job of this function is to impose that
-    /// constraint.
-    ///
-    /// Up to this point, C1 and C2 are basically just random type
-    /// inference variables, and hence they may contain arbitrary
-    /// regions. In fact, it is fairly likely that they do! Consider
-    /// this possible definition of `foo`:
-    ///
-    /// ```text
-    /// fn foo<'a, 'b>(x: &'a i32, y: &'b i32) -> (impl Bar<'a>, impl Bar<'b>) {
-    ///         (&*x, &*y)
-    ///     }
-    /// ```
-    ///
-    /// Here, the values for the concrete types of the two impl
-    /// traits will include inference variables:
-    ///
-    /// ```text
-    /// &'0 i32
-    /// &'1 i32
-    /// ```
-    ///
-    /// Ordinarily, the subtyping rules would ensure that these are
-    /// sufficiently large. But since `impl Bar<'a>` isn't a specific
-    /// type per se, we don't get such constraints by default. This
-    /// is where this function comes into play. It adds extra
-    /// constraints to ensure that all the regions which appear in the
-    /// inferred type are regions that could validly appear.
-    ///
-    /// This is actually a bit of a tricky constraint in general. We
-    /// want to say that each variable (e.g., `'0`) can only take on
-    /// values that were supplied as arguments to the opaque type
-    /// (e.g., `'a` for `Foo1<'a>`) or `'static`, which is always in
-    /// scope. We don't have a constraint quite of this kind in the current
-    /// region checker.
-    ///
-    /// # The Solution
-    ///
-    /// We generally prefer to make `<=` constraints, since they
-    /// integrate best into the region solver. To do that, we find the
-    /// "minimum" of all the arguments that appear in the substs: that
-    /// is, some region which is less than all the others. In the case
-    /// of `Foo1<'a>`, that would be `'a` (it's the only choice, after
-    /// all). Then we apply that as a least bound to the variables
-    /// (e.g., `'a <= '0`).
-    ///
-    /// In some cases, there is no minimum. Consider this example:
-    ///
-    /// ```text
-    /// fn baz<'a, 'b>() -> impl Trait<'a, 'b> { ... }
-    /// ```
-    ///
-    /// Here we would report a more complex "in constraint", like `'r
-    /// in ['a, 'b, 'static]` (where `'r` is some regon appearing in
-    /// the hidden type).
-    ///
-    /// # Constrain regions, not the hidden concrete type
-    ///
-    /// Note that generating constraints on each region `Rc` is *not*
-    /// the same as generating an outlives constraint on `Tc` iself.
-    /// For example, if we had a function like this:
-    ///
-    /// ```rust
-    /// fn foo<'a, T>(x: &'a u32, y: T) -> impl Foo<'a> {
-    ///   (x, y)
-    /// }
-    ///
-    /// // Equivalent to:
-    /// type FooReturn<'a, T> = impl Foo<'a>;
-    /// fn foo<'a, T>(..) -> FooReturn<'a, T> { .. }
-    /// ```
-    ///
-    /// then the hidden type `Tc` would be `(&'0 u32, T)` (where `'0`
-    /// is an inference variable). If we generated a constraint that
-    /// `Tc: 'a`, then this would incorrectly require that `T: 'a` --
-    /// but this is not necessary, because the opaque type we
-    /// create will be allowed to reference `T`. So we only generate a
-    /// constraint that `'0: 'a`.
-    ///
-    /// # The `free_region_relations` parameter
-    ///
-    /// The `free_region_relations` argument is used to find the
-    /// "minimum" of the regions supplied to a given opaque type.
-    /// It must be a relation that can answer whether `'a <= 'b`,
-    /// where `'a` and `'b` are regions that appear in the "substs"
-    /// for the opaque type references (the `<'a>` in `Foo1<'a>`).
-    ///
-    /// Note that we do not impose the constraints based on the
-    /// generic regions from the `Foo1` definition (e.g., `'x`). This
-    /// is because the constraints we are imposing here is basically
-    /// the concern of the one generating the constraining type C1,
-    /// which is the current function. It also means that we can
-    /// take "implied bounds" into account in some cases:
-    ///
-    /// ```text
-    /// trait SomeTrait<'a, 'b> { }
-    /// fn foo<'a, 'b>(_: &'a &'b u32) -> impl SomeTrait<'a, 'b> { .. }
-    /// ```
-    ///
-    /// Here, the fact that `'b: 'a` is known only because of the
-    /// implied bounds from the `&'a &'b u32` parameter, and is not
-    /// "inherent" to the opaque type definition.
-    ///
-    /// # Parameters
-    ///
-    /// - `opaque_types` -- the map produced by `instantiate_opaque_types`
-    /// - `free_region_relations` -- something that can be used to relate
-    ///   the free regions (`'a`) that appear in the impl trait.
-    pub fn constrain_opaque_types<FRR: FreeRegionRelations<'tcx>>(
-        &self,
-        opaque_types: &OpaqueTypeMap<'tcx>,
-        free_region_relations: &FRR,
-    ) {
-        debug!("constrain_opaque_types()");
-
-        for (&def_id, opaque_defn) in opaque_types {
-            self.constrain_opaque_type(
-                def_id,
-                opaque_defn,
-                GenerateMemberConstraints::WhenRequired,
-                free_region_relations,
-            );
-        }
-    }
-
-    /// See `constrain_opaque_types` for documentation.
-    pub fn constrain_opaque_type<FRR: FreeRegionRelations<'tcx>>(
-        &self,
-        def_id: DefId,
-        opaque_defn: &OpaqueTypeDecl<'tcx>,
-        mode: GenerateMemberConstraints,
-        free_region_relations: &FRR,
-    ) {
-        debug!("constrain_opaque_type()");
-        debug!("constrain_opaque_type: def_id={:?}", def_id);
-        debug!("constrain_opaque_type: opaque_defn={:#?}", opaque_defn);
-
-        let tcx = self.tcx;
-
-        let concrete_ty = self.resolve_vars_if_possible(&opaque_defn.concrete_ty);
-
-        debug!("constrain_opaque_type: concrete_ty={:?}", concrete_ty);
-
-        let opaque_type_generics = tcx.generics_of(def_id);
-
-        let span = tcx.def_span(def_id);
-
-        // If there are required region bounds, we can use them.
-        if opaque_defn.has_required_region_bounds {
-            let predicates_of = tcx.predicates_of(def_id);
-            debug!("constrain_opaque_type: predicates: {:#?}", predicates_of,);
-            let bounds = predicates_of.instantiate(tcx, opaque_defn.substs);
-            debug!("constrain_opaque_type: bounds={:#?}", bounds);
-            let opaque_type = tcx.mk_opaque(def_id, opaque_defn.substs);
-
-            let required_region_bounds =
-                required_region_bounds(tcx, opaque_type, bounds.predicates);
-            debug_assert!(!required_region_bounds.is_empty());
-
-            for required_region in required_region_bounds {
-                concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor {
-                    tcx: self.tcx,
-                    op: |r| self.sub_regions(infer::CallReturn(span), required_region, r),
-                });
-            }
-            if let GenerateMemberConstraints::IfNoStaticBound = mode {
-                self.generate_member_constraint(
-                    concrete_ty,
-                    opaque_type_generics,
-                    opaque_defn,
-                    def_id,
-                );
-            }
-            return;
-        }
-
-        // There were no `required_region_bounds`,
-        // so we have to search for a `least_region`.
-        // Go through all the regions used as arguments to the
-        // opaque type. These are the parameters to the opaque
-        // type; so in our example above, `substs` would contain
-        // `['a]` for the first impl trait and `'b` for the
-        // second.
-        let mut least_region = None;
-        for param in &opaque_type_generics.params {
-            match param.kind {
-                GenericParamDefKind::Lifetime => {}
-                _ => continue,
-            }
-
-            // Get the value supplied for this region from the substs.
-            let subst_arg = opaque_defn.substs.region_at(param.index as usize);
-
-            // Compute the least upper bound of it with the other regions.
-            debug!("constrain_opaque_types: least_region={:?}", least_region);
-            debug!("constrain_opaque_types: subst_arg={:?}", subst_arg);
-            match least_region {
-                None => least_region = Some(subst_arg),
-                Some(lr) => {
-                    if free_region_relations.sub_free_regions(self.tcx, lr, subst_arg) {
-                        // keep the current least region
-                    } else if free_region_relations.sub_free_regions(self.tcx, subst_arg, lr) {
-                        // switch to `subst_arg`
-                        least_region = Some(subst_arg);
-                    } else {
-                        // There are two regions (`lr` and
-                        // `subst_arg`) which are not relatable. We
-                        // can't find a best choice. Therefore,
-                        // instead of creating a single bound like
-                        // `'r: 'a` (which is our preferred choice),
-                        // we will create a "in bound" like `'r in
-                        // ['a, 'b, 'c]`, where `'a..'c` are the
-                        // regions that appear in the impl trait.
-
-                        // For now, enforce a feature gate outside of async functions.
-                        self.member_constraint_feature_gate(opaque_defn, def_id, lr, subst_arg);
-
-                        return self.generate_member_constraint(
-                            concrete_ty,
-                            opaque_type_generics,
-                            opaque_defn,
-                            def_id,
-                        );
-                    }
-                }
-            }
-        }
-
-        let least_region = least_region.unwrap_or(tcx.lifetimes.re_static);
-        debug!("constrain_opaque_types: least_region={:?}", least_region);
-
-        if let GenerateMemberConstraints::IfNoStaticBound = mode {
-            if least_region != tcx.lifetimes.re_static {
-                self.generate_member_constraint(
-                    concrete_ty,
-                    opaque_type_generics,
-                    opaque_defn,
-                    def_id,
-                );
-            }
-        }
-        concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor {
-            tcx: self.tcx,
-            op: |r| self.sub_regions(infer::CallReturn(span), least_region, r),
-        });
-    }
-
-    /// As a fallback, we sometimes generate an "in constraint". For
-    /// a case like `impl Foo<'a, 'b>`, where `'a` and `'b` cannot be
-    /// related, we would generate a constraint `'r in ['a, 'b,
-    /// 'static]` for each region `'r` that appears in the hidden type
-    /// (i.e., it must be equal to `'a`, `'b`, or `'static`).
-    ///
-    /// `conflict1` and `conflict2` are the two region bounds that we
-    /// detected which were unrelated. They are used for diagnostics.
-    fn generate_member_constraint(
-        &self,
-        concrete_ty: Ty<'tcx>,
-        opaque_type_generics: &ty::Generics,
-        opaque_defn: &OpaqueTypeDecl<'tcx>,
-        opaque_type_def_id: DefId,
-    ) {
-        // Create the set of choice regions: each region in the hidden
-        // type can be equal to any of the region parameters of the
-        // opaque type definition.
-        let choice_regions: Lrc<Vec<ty::Region<'tcx>>> = Lrc::new(
-            opaque_type_generics
-                .params
-                .iter()
-                .filter(|param| match param.kind {
-                    GenericParamDefKind::Lifetime => true,
-                    GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => false,
-                })
-                .map(|param| opaque_defn.substs.region_at(param.index as usize))
-                .chain(std::iter::once(self.tcx.lifetimes.re_static))
-                .collect(),
-        );
-
-        concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor {
-            tcx: self.tcx,
-            op: |r| {
-                self.member_constraint(
-                    opaque_type_def_id,
-                    opaque_defn.definition_span,
-                    concrete_ty,
-                    r,
-                    &choice_regions,
-                )
-            },
-        });
-    }
-
-    /// Member constraints are presently feature-gated except for
-    /// async-await. We expect to lift this once we've had a bit more
-    /// time.
-    fn member_constraint_feature_gate(
-        &self,
-        opaque_defn: &OpaqueTypeDecl<'tcx>,
-        opaque_type_def_id: DefId,
-        conflict1: ty::Region<'tcx>,
-        conflict2: ty::Region<'tcx>,
-    ) -> bool {
-        // If we have `#![feature(member_constraints)]`, no problems.
-        if self.tcx.features().member_constraints {
-            return false;
-        }
-
-        let span = self.tcx.def_span(opaque_type_def_id);
-
-        // Without a feature-gate, we only generate member-constraints for async-await.
-        let context_name = match opaque_defn.origin {
-            // No feature-gate required for `async fn`.
-            hir::OpaqueTyOrigin::AsyncFn => return false,
-
-            // Otherwise, generate the label we'll use in the error message.
-            hir::OpaqueTyOrigin::TypeAlias
-            | hir::OpaqueTyOrigin::FnReturn
-            | hir::OpaqueTyOrigin::Misc => "impl Trait",
-        };
-        let msg = format!("ambiguous lifetime bound in `{}`", context_name);
-        let mut err = self.tcx.sess.struct_span_err(span, &msg);
-
-        let conflict1_name = conflict1.to_string();
-        let conflict2_name = conflict2.to_string();
-        let label_owned;
-        let label = match (&*conflict1_name, &*conflict2_name) {
-            ("'_", "'_") => "the elided lifetimes here do not outlive one another",
-            _ => {
-                label_owned = format!(
-                    "neither `{}` nor `{}` outlives the other",
-                    conflict1_name, conflict2_name,
-                );
-                &label_owned
-            }
-        };
-        err.span_label(span, label);
-
-        if nightly_options::is_nightly_build() {
-            err.help("add #![feature(member_constraints)] to the crate attributes to enable");
-        }
-
-        err.emit();
-        true
-    }
-
-    /// Given the fully resolved, instantiated type for an opaque
-    /// type, i.e., the value of an inference variable like C1 or C2
-    /// (*), computes the "definition type" for an opaque type
-    /// definition -- that is, the inferred value of `Foo1<'x>` or
-    /// `Foo2<'x>` that we would conceptually use in its definition:
-    ///
-    ///     type Foo1<'x> = impl Bar<'x> = AAA; <-- this type AAA
-    ///     type Foo2<'x> = impl Bar<'x> = BBB; <-- or this type BBB
-    ///     fn foo<'a, 'b>(..) -> (Foo1<'a>, Foo2<'b>) { .. }
-    ///
-    /// Note that these values are defined in terms of a distinct set of
-    /// generic parameters (`'x` instead of `'a`) from C1 or C2. The main
-    /// purpose of this function is to do that translation.
-    ///
-    /// (*) C1 and C2 were introduced in the comments on
-    /// `constrain_opaque_types`. Read that comment for more context.
-    ///
-    /// # Parameters
-    ///
-    /// - `def_id`, the `impl Trait` type
-    /// - `substs`, the substs  used to instantiate this opaque type
-    /// - `instantiated_ty`, the inferred type C1 -- fully resolved, lifted version of
-    ///   `opaque_defn.concrete_ty`
-    pub fn infer_opaque_definition_from_instantiation(
-        &self,
-        def_id: DefId,
-        substs: SubstsRef<'tcx>,
-        instantiated_ty: Ty<'tcx>,
-        span: Span,
-    ) -> Ty<'tcx> {
-        debug!(
-            "infer_opaque_definition_from_instantiation(def_id={:?}, instantiated_ty={:?})",
-            def_id, instantiated_ty
-        );
-
-        // Use substs to build up a reverse map from regions to their
-        // identity mappings. This is necessary because of `impl
-        // Trait` lifetimes are computed by replacing existing
-        // lifetimes with 'static and remapping only those used in the
-        // `impl Trait` return type, resulting in the parameters
-        // shifting.
-        let id_substs = InternalSubsts::identity_for_item(self.tcx, def_id);
-        let map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>> =
-            substs.iter().enumerate().map(|(index, subst)| (*subst, id_substs[index])).collect();
-
-        // Convert the type from the function into a type valid outside
-        // the function, by replacing invalid regions with 'static,
-        // after producing an error for each of them.
-        let definition_ty = instantiated_ty.fold_with(&mut ReverseMapper::new(
-            self.tcx,
-            self.is_tainted_by_errors(),
-            def_id,
-            map,
-            instantiated_ty,
-            span,
-        ));
-        debug!("infer_opaque_definition_from_instantiation: definition_ty={:?}", definition_ty);
-
-        definition_ty
-    }
-}
-
-pub fn unexpected_hidden_region_diagnostic(
-    tcx: TyCtxt<'tcx>,
-    region_scope_tree: Option<&region::ScopeTree>,
-    span: Span,
-    hidden_ty: Ty<'tcx>,
-    hidden_region: ty::Region<'tcx>,
-) -> DiagnosticBuilder<'tcx> {
-    let mut err = struct_span_err!(
-        tcx.sess,
-        span,
-        E0700,
-        "hidden type for `impl Trait` captures lifetime that does not appear in bounds",
-    );
-
-    // Explain the region we are capturing.
-    if let ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReStatic | ty::ReEmpty(_) = hidden_region {
-        // Assuming regionck succeeded (*), we ought to always be
-        // capturing *some* region from the fn header, and hence it
-        // ought to be free. So under normal circumstances, we will go
-        // down this path which gives a decent human readable
-        // explanation.
-        //
-        // (*) if not, the `tainted_by_errors` flag would be set to
-        // true in any case, so we wouldn't be here at all.
-        note_and_explain_free_region(
-            tcx,
-            &mut err,
-            &format!("hidden type `{}` captures ", hidden_ty),
-            hidden_region,
-            "",
-        );
-    } else {
-        // Ugh. This is a painful case: the hidden region is not one
-        // that we can easily summarize or explain. This can happen
-        // in a case like
-        // `src/test/ui/multiple-lifetimes/ordinary-bounds-unsuited.rs`:
-        //
-        // ```
-        // fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> {
-        //   if condition() { a } else { b }
-        // }
-        // ```
-        //
-        // Here the captured lifetime is the intersection of `'a` and
-        // `'b`, which we can't quite express.
-
-        if let Some(region_scope_tree) = region_scope_tree {
-            // If the `region_scope_tree` is available, this is being
-            // invoked from the "region inferencer error". We can at
-            // least report a really cryptic error for now.
-            note_and_explain_region(
-                tcx,
-                region_scope_tree,
-                &mut err,
-                &format!("hidden type `{}` captures ", hidden_ty),
-                hidden_region,
-                "",
-            );
-        } else {
-            // If the `region_scope_tree` is *unavailable*, this is
-            // being invoked by the code that comes *after* region
-            // inferencing. This is a bug, as the region inferencer
-            // ought to have noticed the failed constraint and invoked
-            // error reporting, which in turn should have prevented us
-            // from getting trying to infer the hidden type
-            // completely.
-            tcx.sess.delay_span_bug(
-                span,
-                &format!(
-                    "hidden type captures unexpected lifetime `{:?}` \
-                     but no region inference failure",
-                    hidden_region,
-                ),
-            );
-        }
-    }
-
-    err
-}
-
-// Visitor that requires that (almost) all regions in the type visited outlive
-// `least_region`. We cannot use `push_outlives_components` because regions in
-// closure signatures are not included in their outlives components. We need to
-// ensure all regions outlive the given bound so that we don't end up with,
-// say, `ReScope` appearing in a return type and causing ICEs when other
-// functions end up with region constraints involving regions from other
-// functions.
-//
-// We also cannot use `for_each_free_region` because for closures it includes
-// the regions parameters from the enclosing item.
-//
-// We ignore any type parameters because impl trait values are assumed to
-// capture all the in-scope type parameters.
-struct ConstrainOpaqueTypeRegionVisitor<'tcx, OP>
-where
-    OP: FnMut(ty::Region<'tcx>),
-{
-    tcx: TyCtxt<'tcx>,
-    op: OP,
-}
-
-impl<'tcx, OP> TypeVisitor<'tcx> for ConstrainOpaqueTypeRegionVisitor<'tcx, OP>
-where
-    OP: FnMut(ty::Region<'tcx>),
-{
-    fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &ty::Binder<T>) -> bool {
-        t.skip_binder().visit_with(self);
-        false // keep visiting
-    }
-
-    fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
-        match *r {
-            // ignore bound regions, keep visiting
-            ty::ReLateBound(_, _) => false,
-            _ => {
-                (self.op)(r);
-                false
-            }
-        }
-    }
-
-    fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
-        // We're only interested in types involving regions
-        if !ty.flags.intersects(ty::TypeFlags::HAS_FREE_REGIONS) {
-            return false; // keep visiting
-        }
-
-        match ty.kind {
-            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) {
-                    upvar_ty.visit_with(self);
-                }
-
-                substs.as_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) {
-                    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.as_generator().resume_ty(def_id, self.tcx).visit_with(self);
-            }
-            _ => {
-                ty.super_visit_with(self);
-            }
-        }
-
-        false
-    }
-}
-
-struct ReverseMapper<'tcx> {
-    tcx: TyCtxt<'tcx>,
-
-    /// If errors have already been reported in this fn, we suppress
-    /// our own errors because they are sometimes derivative.
-    tainted_by_errors: bool,
-
-    opaque_type_def_id: DefId,
-    map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>>,
-    map_missing_regions_to_empty: bool,
-
-    /// initially `Some`, set to `None` once error has been reported
-    hidden_ty: Option<Ty<'tcx>>,
-
-    /// Span of function being checked.
-    span: Span,
-}
-
-impl ReverseMapper<'tcx> {
-    fn new(
-        tcx: TyCtxt<'tcx>,
-        tainted_by_errors: bool,
-        opaque_type_def_id: DefId,
-        map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>>,
-        hidden_ty: Ty<'tcx>,
-        span: Span,
-    ) -> Self {
-        Self {
-            tcx,
-            tainted_by_errors,
-            opaque_type_def_id,
-            map,
-            map_missing_regions_to_empty: false,
-            hidden_ty: Some(hidden_ty),
-            span,
-        }
-    }
-
-    fn fold_kind_mapping_missing_regions_to_empty(
-        &mut self,
-        kind: GenericArg<'tcx>,
-    ) -> GenericArg<'tcx> {
-        assert!(!self.map_missing_regions_to_empty);
-        self.map_missing_regions_to_empty = true;
-        let kind = kind.fold_with(self);
-        self.map_missing_regions_to_empty = false;
-        kind
-    }
-
-    fn fold_kind_normally(&mut self, kind: GenericArg<'tcx>) -> GenericArg<'tcx> {
-        assert!(!self.map_missing_regions_to_empty);
-        kind.fold_with(self)
-    }
-}
-
-impl TypeFolder<'tcx> for ReverseMapper<'tcx> {
-    fn tcx(&self) -> TyCtxt<'tcx> {
-        self.tcx
-    }
-
-    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
-        match r {
-            // Ignore bound regions and `'static` regions that appear in the
-            // type, we only need to remap regions that reference lifetimes
-            // from the function declaraion.
-            // This would ignore `'r` in a type like `for<'r> fn(&'r u32)`.
-            ty::ReLateBound(..) | ty::ReStatic => return r,
-
-            // If regions have been erased (by writeback), don't try to unerase
-            // them.
-            ty::ReErased => return r,
-
-            // The regions that we expect from borrow checking.
-            ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReEmpty(ty::UniverseIndex::ROOT) => {}
-
-            ty::ReEmpty(_)
-            | ty::RePlaceholder(_)
-            | ty::ReVar(_)
-            | ty::ReScope(_)
-            | ty::ReClosureBound(_) => {
-                // All of the regions in the type should either have been
-                // erased by writeback, or mapped back to named regions by
-                // borrow checking.
-                bug!("unexpected region kind in opaque type: {:?}", r);
-            }
-        }
-
-        let generics = self.tcx().generics_of(self.opaque_type_def_id);
-        match self.map.get(&r.into()).map(|k| k.unpack()) {
-            Some(GenericArgKind::Lifetime(r1)) => r1,
-            Some(u) => panic!("region mapped to unexpected kind: {:?}", u),
-            None if self.map_missing_regions_to_empty || self.tainted_by_errors => {
-                self.tcx.lifetimes.re_root_empty
-            }
-            None if generics.parent.is_some() => {
-                if let Some(hidden_ty) = self.hidden_ty.take() {
-                    unexpected_hidden_region_diagnostic(
-                        self.tcx,
-                        None,
-                        self.tcx.def_span(self.opaque_type_def_id),
-                        hidden_ty,
-                        r,
-                    )
-                    .emit();
-                }
-                self.tcx.lifetimes.re_root_empty
-            }
-            None => {
-                self.tcx
-                    .sess
-                    .struct_span_err(self.span, "non-defining opaque type use in defining scope")
-                    .span_label(
-                        self.span,
-                        format!(
-                            "lifetime `{}` is part of concrete type but not used in \
-                                 parameter list of the `impl Trait` type alias",
-                            r
-                        ),
-                    )
-                    .emit();
-
-                self.tcx().lifetimes.re_static
-            }
-        }
-    }
-
-    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
-        match ty.kind {
-            ty::Closure(def_id, substs) => {
-                // I am a horrible monster and I pray for death. When
-                // we encounter a closure here, it is always a closure
-                // from within the function that we are currently
-                // type-checking -- one that is now being encapsulated
-                // in an opaque type. Ideally, we would
-                // go through the types/lifetimes that it references
-                // and treat them just like we would any other type,
-                // which means we would error out if we find any
-                // reference to a type/region that is not in the
-                // "reverse map".
-                //
-                // **However,** in the case of closures, there is a
-                // somewhat subtle (read: hacky) consideration. The
-                // problem is that our closure types currently include
-                // all the lifetime parameters declared on the
-                // enclosing function, even if they are unused by the
-                // closure itself. We can't readily filter them out,
-                // so here we replace those values with `'empty`. This
-                // can't really make a difference to the rest of the
-                // compiler; those regions are ignored for the
-                // outlives relation, and hence don't affect trait
-                // selection or auto traits, and they are erased
-                // during codegen.
-
-                let generics = self.tcx.generics_of(def_id);
-                let substs = self.tcx.mk_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)
-                    } else {
-                        // ...but not elsewhere.
-                        self.fold_kind_normally(kind)
-                    }
-                }));
-
-                self.tcx.mk_closure(def_id, 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)| {
-                    if index < generics.parent_count {
-                        // Accommodate missing regions in the parent kinds...
-                        self.fold_kind_mapping_missing_regions_to_empty(kind)
-                    } else {
-                        // ...but not elsewhere.
-                        self.fold_kind_normally(kind)
-                    }
-                }));
-
-                self.tcx.mk_generator(def_id, substs, movability)
-            }
-
-            ty::Param(..) => {
-                // Look it up in the substitution list.
-                match self.map.get(&ty.into()).map(|k| k.unpack()) {
-                    // Found it in the substitution list; replace with the parameter from the
-                    // opaque type.
-                    Some(GenericArgKind::Type(t1)) => t1,
-                    Some(u) => panic!("type mapped to unexpected kind: {:?}", u),
-                    None => {
-                        self.tcx
-                            .sess
-                            .struct_span_err(
-                                self.span,
-                                &format!(
-                                    "type parameter `{}` is part of concrete type but not \
-                                          used in parameter list for the `impl Trait` type alias",
-                                    ty
-                                ),
-                            )
-                            .emit();
-
-                        self.tcx().types.err
-                    }
-                }
-            }
-
-            _ => ty.super_fold_with(self),
-        }
-    }
-
-    fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
-        trace!("checking const {:?}", ct);
-        // Find a const parameter
-        match ct.val {
-            ty::ConstKind::Param(..) => {
-                // Look it up in the substitution list.
-                match self.map.get(&ct.into()).map(|k| k.unpack()) {
-                    // Found it in the substitution list, replace with the parameter from the
-                    // opaque type.
-                    Some(GenericArgKind::Const(c1)) => c1,
-                    Some(u) => panic!("const mapped to unexpected kind: {:?}", u),
-                    None => {
-                        self.tcx
-                            .sess
-                            .struct_span_err(
-                                self.span,
-                                &format!(
-                                    "const parameter `{}` is part of concrete type but not \
-                                          used in parameter list for the `impl Trait` type alias",
-                                    ct
-                                ),
-                            )
-                            .emit();
-
-                        self.tcx().consts.err
-                    }
-                }
-            }
-
-            _ => ct,
-        }
-    }
-}
-
-struct Instantiator<'a, 'tcx> {
-    infcx: &'a InferCtxt<'a, 'tcx>,
-    parent_def_id: DefId,
-    body_id: hir::HirId,
-    param_env: ty::ParamEnv<'tcx>,
-    value_span: Span,
-    opaque_types: OpaqueTypeMap<'tcx>,
-    obligations: Vec<PredicateObligation<'tcx>>,
-}
-
-impl<'a, 'tcx> Instantiator<'a, 'tcx> {
-    fn instantiate_opaque_types_in_map<T: TypeFoldable<'tcx>>(&mut self, value: &T) -> T {
-        debug!("instantiate_opaque_types_in_map(value={:?})", value);
-        let tcx = self.infcx.tcx;
-        value.fold_with(&mut BottomUpFolder {
-            tcx,
-            ty_op: |ty| {
-                if ty.references_error() {
-                    return tcx.types.err;
-                } else if let ty::Opaque(def_id, substs) = ty.kind {
-                    // Check that this is `impl Trait` type is
-                    // declared by `parent_def_id` -- i.e., one whose
-                    // value we are inferring.  At present, this is
-                    // always true during the first phase of
-                    // type-check, but not always true later on during
-                    // NLL. Once we support named opaque types more fully,
-                    // this same scenario will be able to arise during all phases.
-                    //
-                    // Here is an example using type alias `impl Trait`
-                    // that indicates the distinction we are checking for:
-                    //
-                    // ```rust
-                    // mod a {
-                    //   pub type Foo = impl Iterator;
-                    //   pub fn make_foo() -> Foo { .. }
-                    // }
-                    //
-                    // mod b {
-                    //   fn foo() -> a::Foo { a::make_foo() }
-                    // }
-                    // ```
-                    //
-                    // Here, the return type of `foo` references a
-                    // `Opaque` indeed, but not one whose value is
-                    // presently being inferred. You can get into a
-                    // similar situation with closure return types
-                    // today:
-                    //
-                    // ```rust
-                    // fn foo() -> impl Iterator { .. }
-                    // fn bar() {
-                    //     let x = || foo(); // returns the Opaque assoc with `foo`
-                    // }
-                    // ```
-                    if let Some(opaque_hir_id) = tcx.hir().as_local_hir_id(def_id) {
-                        let parent_def_id = self.parent_def_id;
-                        let def_scope_default = || {
-                            let opaque_parent_hir_id = tcx.hir().get_parent_item(opaque_hir_id);
-                            parent_def_id == tcx.hir().local_def_id(opaque_parent_hir_id)
-                        };
-                        let (in_definition_scope, origin) = match tcx.hir().find(opaque_hir_id) {
-                            Some(Node::Item(item)) => match item.kind {
-                                // Anonymous `impl Trait`
-                                hir::ItemKind::OpaqueTy(hir::OpaqueTy {
-                                    impl_trait_fn: Some(parent),
-                                    origin,
-                                    ..
-                                }) => (parent == self.parent_def_id, origin),
-                                // Named `type Foo = impl Bar;`
-                                hir::ItemKind::OpaqueTy(hir::OpaqueTy {
-                                    impl_trait_fn: None,
-                                    origin,
-                                    ..
-                                }) => (
-                                    may_define_opaque_type(tcx, self.parent_def_id, opaque_hir_id),
-                                    origin,
-                                ),
-                                _ => (def_scope_default(), hir::OpaqueTyOrigin::TypeAlias),
-                            },
-                            Some(Node::ImplItem(item)) => match item.kind {
-                                hir::ImplItemKind::OpaqueTy(_) => (
-                                    may_define_opaque_type(tcx, self.parent_def_id, opaque_hir_id),
-                                    hir::OpaqueTyOrigin::TypeAlias,
-                                ),
-                                _ => (def_scope_default(), hir::OpaqueTyOrigin::TypeAlias),
-                            },
-                            _ => bug!(
-                                "expected (impl) item, found {}",
-                                tcx.hir().node_to_string(opaque_hir_id),
-                            ),
-                        };
-                        if in_definition_scope {
-                            return self.fold_opaque_ty(ty, def_id, substs, origin);
-                        }
-
-                        debug!(
-                            "instantiate_opaque_types_in_map: \
-                             encountered opaque outside its definition scope \
-                             def_id={:?}",
-                            def_id,
-                        );
-                    }
-                }
-
-                ty
-            },
-            lt_op: |lt| lt,
-            ct_op: |ct| ct,
-        })
-    }
-
-    fn fold_opaque_ty(
-        &mut self,
-        ty: Ty<'tcx>,
-        def_id: DefId,
-        substs: SubstsRef<'tcx>,
-        origin: hir::OpaqueTyOrigin,
-    ) -> Ty<'tcx> {
-        let infcx = self.infcx;
-        let tcx = infcx.tcx;
-
-        debug!("instantiate_opaque_types: Opaque(def_id={:?}, substs={:?})", def_id, substs);
-
-        // Use the same type variable if the exact same opaque type appears more
-        // than once in the return type (e.g., if it's passed to a type alias).
-        if let Some(opaque_defn) = self.opaque_types.get(&def_id) {
-            debug!("instantiate_opaque_types: returning concrete ty {:?}", opaque_defn.concrete_ty);
-            return opaque_defn.concrete_ty;
-        }
-        let span = tcx.def_span(def_id);
-        debug!("fold_opaque_ty {:?} {:?}", self.value_span, span);
-        let ty_var = infcx
-            .next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span });
-
-        let predicates_of = tcx.predicates_of(def_id);
-        debug!("instantiate_opaque_types: predicates={:#?}", predicates_of,);
-        let bounds = predicates_of.instantiate(tcx, substs);
-
-        let param_env = tcx.param_env(def_id);
-        let InferOk { value: bounds, obligations } =
-            infcx.partially_normalize_associated_types_in(span, self.body_id, param_env, &bounds);
-        self.obligations.extend(obligations);
-
-        debug!("instantiate_opaque_types: bounds={:?}", bounds);
-
-        let required_region_bounds = required_region_bounds(tcx, ty, bounds.predicates.clone());
-        debug!("instantiate_opaque_types: required_region_bounds={:?}", required_region_bounds);
-
-        // Make sure that we are in fact defining the *entire* type
-        // (e.g., `type Foo<T: Bound> = impl Bar;` needs to be
-        // defined by a function like `fn foo<T: Bound>() -> Foo<T>`).
-        debug!("instantiate_opaque_types: param_env={:#?}", self.param_env,);
-        debug!("instantiate_opaque_types: generics={:#?}", tcx.generics_of(def_id),);
-
-        // Ideally, we'd get the span where *this specific `ty` came
-        // from*, but right now we just use the span from the overall
-        // value being folded. In simple cases like `-> impl Foo`,
-        // these are the same span, but not in cases like `-> (impl
-        // Foo, impl Bar)`.
-        let definition_span = self.value_span;
-
-        self.opaque_types.insert(
-            def_id,
-            OpaqueTypeDecl {
-                opaque_type: ty,
-                substs,
-                definition_span,
-                concrete_ty: ty_var,
-                has_required_region_bounds: !required_region_bounds.is_empty(),
-                origin,
-            },
-        );
-        debug!("instantiate_opaque_types: ty_var={:?}", ty_var);
-
-        for predicate in &bounds.predicates {
-            if let ty::Predicate::Projection(projection) = &predicate {
-                if projection.skip_binder().ty.references_error() {
-                    // No point on adding these obligations since there's a type error involved.
-                    return ty_var;
-                }
-            }
-        }
-
-        self.obligations.reserve(bounds.predicates.len());
-        for predicate in bounds.predicates {
-            // Change the predicate to refer to the type variable,
-            // which will be the concrete type instead of the opaque type.
-            // This also instantiates nested instances of `impl Trait`.
-            let predicate = self.instantiate_opaque_types_in_map(&predicate);
-
-            let cause = traits::ObligationCause::new(span, self.body_id, traits::SizedReturnType);
-
-            // Require that the predicate holds for the concrete type.
-            debug!("instantiate_opaque_types: predicate={:?}", predicate);
-            self.obligations.push(traits::Obligation::new(cause, self.param_env, predicate));
-        }
-
-        ty_var
-    }
-}
-
-/// Returns `true` if `opaque_hir_id` is a sibling or a child of a sibling of `def_id`.
-///
-/// Example:
-/// ```rust
-/// pub mod foo {
-///     pub mod bar {
-///         pub trait Bar { .. }
-///
-///         pub type Baz = impl Bar;
-///
-///         fn f1() -> Baz { .. }
-///     }
-///
-///     fn f2() -> bar::Baz { .. }
-/// }
-/// ```
-///
-/// Here, `def_id` is the `DefId` of the defining use of the opaque type (e.g., `f1` or `f2`),
-/// and `opaque_hir_id` is the `HirId` of the definition of the opaque type `Baz`.
-/// For the above example, this function returns `true` for `f1` and `false` for `f2`.
-pub fn may_define_opaque_type(tcx: TyCtxt<'_>, def_id: DefId, opaque_hir_id: hir::HirId) -> bool {
-    let mut hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
-
-    // Named opaque types can be defined by any siblings or children of siblings.
-    let scope = tcx.hir().get_defining_scope(opaque_hir_id);
-    // We walk up the node tree until we hit the root or the scope of the opaque type.
-    while hir_id != scope && hir_id != hir::CRATE_HIR_ID {
-        hir_id = tcx.hir().get_parent_item(hir_id);
-    }
-    // Syntactically, we are allowed to define the concrete type if:
-    let res = hir_id == scope;
-    trace!(
-        "may_define_opaque_type(def={:?}, opaque_node={:?}) = {}",
-        tcx.hir().find(hir_id),
-        tcx.hir().get(opaque_hir_id),
-        res
-    );
-    res
-}
-
-/// Given a set of predicates that apply to an object type, returns
-/// the region bounds that the (erased) `Self` type must
-/// outlive. Precisely *because* the `Self` type is erased, the
-/// parameter `erased_self_ty` must be supplied to indicate what type
-/// has been used to represent `Self` in the predicates
-/// themselves. This should really be a unique type; `FreshTy(0)` is a
-/// popular choice.
-///
-/// N.B., in some cases, particularly around higher-ranked bounds,
-/// this function returns a kind of conservative approximation.
-/// That is, all regions returned by this function are definitely
-/// required, but there may be other region bounds that are not
-/// returned, as well as requirements like `for<'a> T: 'a`.
-///
-/// Requires that trait definitions have been processed so that we can
-/// elaborate predicates and walk supertraits.
-//
-// FIXME: callers may only have a `&[Predicate]`, not a `Vec`, so that's
-// what this code should accept.
-crate fn required_region_bounds(
-    tcx: TyCtxt<'tcx>,
-    erased_self_ty: Ty<'tcx>,
-    predicates: Vec<ty::Predicate<'tcx>>,
-) -> Vec<ty::Region<'tcx>> {
-    debug!(
-        "required_region_bounds(erased_self_ty={:?}, predicates={:?})",
-        erased_self_ty, predicates
-    );
-
-    assert!(!erased_self_ty.has_escaping_bound_vars());
-
-    traits::elaborate_predicates(tcx, predicates)
-        .filter_map(|predicate| {
-            match predicate {
-                ty::Predicate::Projection(..)
-                | ty::Predicate::Trait(..)
-                | ty::Predicate::Subtype(..)
-                | ty::Predicate::WellFormed(..)
-                | ty::Predicate::ObjectSafe(..)
-                | ty::Predicate::ClosureKind(..)
-                | ty::Predicate::RegionOutlives(..)
-                | ty::Predicate::ConstEvaluatable(..) => None,
-                ty::Predicate::TypeOutlives(predicate) => {
-                    // Search for a bound of the form `erased_self_ty
-                    // : 'a`, but be wary of something like `for<'a>
-                    // erased_self_ty : 'a` (we interpret a
-                    // higher-ranked bound like that as 'static,
-                    // though at present the code in `fulfill.rs`
-                    // considers such bounds to be unsatisfiable, so
-                    // it's kind of a moot point since you could never
-                    // construct such an object, but this seems
-                    // correct even if that code changes).
-                    let ty::OutlivesPredicate(ref t, ref r) = predicate.skip_binder();
-                    if t == &erased_self_ty && !r.has_escaping_bound_vars() {
-                        Some(*r)
-                    } else {
-                        None
-                    }
-                }
-            }
-        })
-        .collect()
-}
index aac6c7640ca6b953cfb4152e7dc5d220b3543925..6c1e86bf408b0d97422e4f3512e4610c92466572 100644 (file)
@@ -1,10 +1,11 @@
 use crate::infer::{GenericKind, InferCtxt};
-use crate::traits::query::outlives_bounds::{self, OutlivesBound};
+use crate::traits::query::OutlivesBound;
+use rustc::ty;
 use rustc::ty::free_region_map::FreeRegionMap;
-use rustc::ty::{self, Ty};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir as hir;
-use rustc_span::Span;
+
+use super::explicit_outlives_bounds;
 
 /// The `OutlivesEnvironment` collects information about what outlives
 /// what in a given type-checking setting. For example, if we have a
@@ -76,7 +77,7 @@ pub fn new(param_env: ty::ParamEnv<'tcx>) -> Self {
             region_bound_pairs_accum: vec![],
         };
 
-        env.add_outlives_bounds(None, outlives_bounds::explicit_outlives_bounds(param_env));
+        env.add_outlives_bounds(None, explicit_outlives_bounds(param_env));
 
         env
     }
@@ -142,39 +143,6 @@ pub fn pop_snapshot_post_closure(&mut self, len: usize) {
         self.region_bound_pairs_accum.truncate(len);
     }
 
-    /// This method adds "implied bounds" into the outlives environment.
-    /// Implied bounds are outlives relationships that we can deduce
-    /// on the basis that certain types must be well-formed -- these are
-    /// either the types that appear in the function signature or else
-    /// the input types to an impl. For example, if you have a function
-    /// like
-    ///
-    /// ```
-    /// fn foo<'a, 'b, T>(x: &'a &'b [T]) { }
-    /// ```
-    ///
-    /// we can assume in the caller's body that `'b: 'a` and that `T:
-    /// 'b` (and hence, transitively, that `T: 'a`). This method would
-    /// add those assumptions into the outlives-environment.
-    ///
-    /// Tests: `src/test/compile-fail/regions-free-region-ordering-*.rs`
-    pub fn add_implied_bounds(
-        &mut self,
-        infcx: &InferCtxt<'a, 'tcx>,
-        fn_sig_tys: &[Ty<'tcx>],
-        body_id: hir::HirId,
-        span: Span,
-    ) {
-        debug!("add_implied_bounds()");
-
-        for &ty in fn_sig_tys {
-            let ty = infcx.resolve_vars_if_possible(&ty);
-            debug!("add_implied_bounds: ty = {}", ty);
-            let implied_bounds = infcx.implied_outlives_bounds(self.param_env, body_id, ty, span);
-            self.add_outlives_bounds(Some(infcx), implied_bounds)
-        }
-    }
-
     /// Save the current set of region-bound pairs under the given `body_id`.
     pub fn save_implied_bounds(&mut self, body_id: hir::HirId) {
         let old =
@@ -188,8 +156,11 @@ pub fn save_implied_bounds(&mut self, body_id: hir::HirId) {
     /// contain inference variables, it must be supplied, in which
     /// case we will register "givens" on the inference context. (See
     /// `RegionConstraintData`.)
-    fn add_outlives_bounds<I>(&mut self, infcx: Option<&InferCtxt<'a, 'tcx>>, outlives_bounds: I)
-    where
+    pub fn add_outlives_bounds<I>(
+        &mut self,
+        infcx: Option<&InferCtxt<'a, 'tcx>>,
+        outlives_bounds: I,
+    ) where
         I: IntoIterator<Item = OutlivesBound<'tcx>>,
     {
         // Record relationships such as `T:'x` that don't go into the
index 6fc72470c9fb7816a822e689ee5f57557fec7451..75cf742de31a7a5f01f6e186dd22aef176219724 100644 (file)
@@ -3,3 +3,25 @@
 pub mod env;
 pub mod obligations;
 pub mod verify;
+
+use rustc::traits::query::OutlivesBound;
+use rustc::ty;
+
+pub fn explicit_outlives_bounds<'tcx>(
+    param_env: ty::ParamEnv<'tcx>,
+) -> impl Iterator<Item = OutlivesBound<'tcx>> + 'tcx {
+    debug!("explicit_outlives_bounds()");
+    param_env.caller_bounds.into_iter().filter_map(move |predicate| match predicate {
+        ty::Predicate::Projection(..)
+        | ty::Predicate::Trait(..)
+        | ty::Predicate::Subtype(..)
+        | ty::Predicate::WellFormed(..)
+        | ty::Predicate::ObjectSafe(..)
+        | ty::Predicate::ClosureKind(..)
+        | ty::Predicate::TypeOutlives(..)
+        | ty::Predicate::ConstEvaluatable(..) => None,
+        ty::Predicate::RegionOutlives(ref data) => data
+            .no_bound_vars()
+            .map(|ty::OutlivesPredicate(r_a, r_b)| OutlivesBound::RegionSubRegion(r_b, r_a)),
+    })
+}
index d789fb0de109304748ef35e75039489fa54cdac1..0231dd066772570629a89cc37e79b23b0418dd4b 100644 (file)
@@ -1,3 +1,3 @@
-For info on how the current borrowck works, see the [rustc guide].
+For info on how the current borrowck works, see the [rustc dev guide].
 
-[rustc guide]: https://rust-lang.github.io/rustc-guide/borrow_check.html
+[rustc dev guide]: https://rustc-dev-guide.rust-lang.org/borrow_check.html
index 74ffdc7a4f0872c1091a37fe3a88e978615691cd..6ebe3f575976041781f949a37602b05c68ce6abd 100644 (file)
@@ -34,7 +34,7 @@ pub fn leak_check(
         assert!(self.in_snapshot());
 
         // Go through each placeholder that we created.
-        for (_, &placeholder_region) in placeholder_map {
+        for &placeholder_region in placeholder_map.values() {
             // Find the universe this placeholder inhabits.
             let placeholder = match placeholder_region {
                 ty::RePlaceholder(p) => p,
@@ -85,7 +85,7 @@ impl<'tcx> TaintSet<'tcx> {
     fn new(directions: TaintDirections, initial_region: ty::Region<'tcx>) -> Self {
         let mut regions = FxHashSet::default();
         regions.insert(initial_region);
-        TaintSet { directions: directions, regions: regions }
+        TaintSet { directions, regions }
     }
 
     fn fixed_point(
index 3f9fa6459b37f613bf0a7eee10d7594b97d32dd3..868b95043796b8b563e39727229ecb818e36bf03 100644 (file)
@@ -766,7 +766,7 @@ fn combine_vars(
         b: Region<'tcx>,
         origin: SubregionOrigin<'tcx>,
     ) -> Region<'tcx> {
-        let vars = TwoRegions { a: a, b: b };
+        let vars = TwoRegions { a, b };
         if let Some(&c) = self.combine_map(t).get(&vars) {
             return tcx.mk_region(ReVar(c));
         }
index 3510b927d960436d265c8235e6a7f530acc84307..ce0f2f40894f9091677775b2e0d3e98eaf6b16b5 100644 (file)
@@ -28,7 +28,7 @@ fn tcx<'b>(&'b self) -> TyCtxt<'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_or_consts() {
             t // micro-optimize -- if there is nothing in this type that this fold affects...
         } else {
             let t = self.infcx.shallow_resolve(t);
@@ -37,7 +37,7 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
     }
 
     fn fold_const(&mut self, ct: &'tcx Const<'tcx>) -> &'tcx Const<'tcx> {
-        if !ct.has_infer_consts() {
+        if !ct.has_infer_types_or_consts() {
             ct // micro-optimize -- if there is nothing in this const that this fold affects...
         } else {
             let ct = self.infcx.shallow_resolve(ct);
@@ -160,7 +160,7 @@ pub fn fully_resolve<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>, value: &T) -> Fix
 where
     T: TypeFoldable<'tcx>,
 {
-    let mut full_resolver = FullTypeResolver { infcx: infcx, err: None };
+    let mut full_resolver = FullTypeResolver { infcx, err: None };
     let result = value.fold_with(&mut full_resolver);
     match full_resolver.err {
         None => Ok(result),
@@ -169,7 +169,7 @@ pub fn fully_resolve<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>, value: &T) -> Fix
 }
 
 // N.B. This type is not public because the protocol around checking the
-// `err` field is not enforcable otherwise.
+// `err` field is not enforceable otherwise.
 struct FullTypeResolver<'a, 'tcx> {
     infcx: &'a InferCtxt<'a, 'tcx>,
     err: Option<FixupError<'tcx>>,
index 2b770ced42a55838f461543a4e82d0421abfa933..f6fc38b5358871d50a3c0e620e1c2daf683cc013 100644 (file)
@@ -19,7 +19,7 @@ pub fn new(
         f: &'combine mut CombineFields<'infcx, 'tcx>,
         a_is_expected: bool,
     ) -> Sub<'combine, 'infcx, 'tcx> {
-        Sub { fields: f, a_is_expected: a_is_expected }
+        Sub { fields: f, a_is_expected }
     }
 
     fn with_expected_switched<R, F: FnOnce(&mut Self) -> R>(&mut self, f: F) -> R {
index 6c66ef47f33f0478eeefb10f324908691188b50f..cb8ae8c592b228bdeef1f3b3255ed7bddc1c3b84 100644 (file)
@@ -1,13 +1,12 @@
-//! This crates defines the trait resolution method and the type inference engine.
+//! This crates defines the type inference engine.
 //!
-//! - **Traits.** Trait resolution is implemented in the `traits` module.
 //! - **Type inference.** The type inference code can be found in the `infer` module;
 //!   this code handles low-level equality and subtyping operations. The
 //!   type check pass in the compiler is found in the `librustc_typeck` crate.
 //!
-//! For more information about how rustc works, see the [rustc guide].
+//! For more information about how rustc works, see the [rustc dev guide].
 //!
-//! [rustc guide]: https://rust-lang.github.io/rustc-guide/
+//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/
 //!
 //! # Note
 //!
 #![feature(bool_to_option)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
-#![feature(drain_filter)]
 #![feature(never_type)]
 #![feature(range_is_empty)]
 #![feature(in_band_lifetimes)]
 #![feature(crate_visibility_modifier)]
-#![recursion_limit = "512"]
+#![recursion_limit = "512"] // For rustdoc
 
 #[macro_use]
 extern crate rustc_macros;
diff --git a/src/librustc_infer/traits/auto_trait.rs b/src/librustc_infer/traits/auto_trait.rs
deleted file mode 100644 (file)
index 1a4f899..0000000
+++ /dev/null
@@ -1,837 +0,0 @@
-//! Support code for rustdoc and external tools.
-//! You really don't want to be using this unless you need to.
-
-use super::*;
-
-use crate::infer::region_constraints::{Constraint, RegionConstraintData};
-use crate::infer::InferCtxt;
-use rustc::ty::fold::TypeFolder;
-use rustc::ty::{Region, RegionVid};
-
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-
-use std::collections::hash_map::Entry;
-use std::collections::VecDeque;
-
-// FIXME(twk): this is obviously not nice to duplicate like that
-#[derive(Eq, PartialEq, Hash, Copy, Clone, Debug)]
-pub enum RegionTarget<'tcx> {
-    Region(Region<'tcx>),
-    RegionVid(RegionVid),
-}
-
-#[derive(Default, Debug, Clone)]
-pub struct RegionDeps<'tcx> {
-    larger: FxHashSet<RegionTarget<'tcx>>,
-    smaller: FxHashSet<RegionTarget<'tcx>>,
-}
-
-pub enum AutoTraitResult<A> {
-    ExplicitImpl,
-    PositiveImpl(A),
-    NegativeImpl,
-}
-
-impl<A> AutoTraitResult<A> {
-    fn is_auto(&self) -> bool {
-        match *self {
-            AutoTraitResult::PositiveImpl(_) | AutoTraitResult::NegativeImpl => true,
-            _ => false,
-        }
-    }
-}
-
-pub struct AutoTraitInfo<'cx> {
-    pub full_user_env: ty::ParamEnv<'cx>,
-    pub region_data: RegionConstraintData<'cx>,
-    pub vid_to_region: FxHashMap<ty::RegionVid, ty::Region<'cx>>,
-}
-
-pub struct AutoTraitFinder<'tcx> {
-    tcx: TyCtxt<'tcx>,
-}
-
-impl<'tcx> AutoTraitFinder<'tcx> {
-    pub fn new(tcx: TyCtxt<'tcx>) -> Self {
-        AutoTraitFinder { tcx }
-    }
-
-    /// Makes a best effort to determine whether and under which conditions an auto trait is
-    /// implemented for a type. For example, if you have
-    ///
-    /// ```
-    /// struct Foo<T> { data: Box<T> }
-    /// ```
-    ///
-    /// then this might return that Foo<T>: Send if T: Send (encoded in the AutoTraitResult type).
-    /// The analysis attempts to account for custom impls as well as other complex cases. This
-    /// result is intended for use by rustdoc and other such consumers.
-    ///
-    /// (Note that due to the coinductive nature of Send, the full and correct result is actually
-    /// quite simple to generate. That is, when a type has no custom impl, it is Send iff its field
-    /// types are all Send. So, in our example, we might have that Foo<T>: Send if Box<T>: Send.
-    /// But this is often not the best way to present to the user.)
-    ///
-    /// Warning: The API should be considered highly unstable, and it may be refactored or removed
-    /// in the future.
-    pub fn find_auto_trait_generics<A>(
-        &self,
-        ty: Ty<'tcx>,
-        orig_env: ty::ParamEnv<'tcx>,
-        trait_did: DefId,
-        auto_trait_callback: impl Fn(&InferCtxt<'_, 'tcx>, AutoTraitInfo<'tcx>) -> A,
-    ) -> AutoTraitResult<A> {
-        let tcx = self.tcx;
-
-        let trait_ref = ty::TraitRef { def_id: trait_did, substs: tcx.mk_substs_trait(ty, &[]) };
-
-        let trait_pred = ty::Binder::bind(trait_ref);
-
-        let bail_out = tcx.infer_ctxt().enter(|infcx| {
-            let mut selcx = SelectionContext::with_negative(&infcx, true);
-            let result = selcx.select(&Obligation::new(
-                ObligationCause::dummy(),
-                orig_env,
-                trait_pred.to_poly_trait_predicate(),
-            ));
-
-            match result {
-                Ok(Some(Vtable::VtableImpl(_))) => {
-                    debug!(
-                        "find_auto_trait_generics({:?}): \
-                         manual impl found, bailing out",
-                        trait_ref
-                    );
-                    true
-                }
-                _ => false,
-            }
-        });
-
-        // If an explicit impl exists, it always takes priority over an auto impl
-        if bail_out {
-            return AutoTraitResult::ExplicitImpl;
-        }
-
-        return tcx.infer_ctxt().enter(|mut infcx| {
-            let mut fresh_preds = FxHashSet::default();
-
-            // Due to the way projections are handled by SelectionContext, we need to run
-            // evaluate_predicates twice: once on the original param env, and once on the result of
-            // the first evaluate_predicates call.
-            //
-            // The problem is this: most of rustc, including SelectionContext and traits::project,
-            // are designed to work with a concrete usage of a type (e.g., Vec<u8>
-            // fn<T>() { Vec<T> }. This information will generally never change - given
-            // the 'T' in fn<T>() { ... }, we'll never know anything else about 'T'.
-            // If we're unable to prove that 'T' implements a particular trait, we're done -
-            // there's nothing left to do but error out.
-            //
-            // However, synthesizing an auto trait impl works differently. Here, we start out with
-            // a set of initial conditions - the ParamEnv of the struct/enum/union we're dealing
-            // with - and progressively discover the conditions we need to fulfill for it to
-            // implement a certain auto trait. This ends up breaking two assumptions made by trait
-            // selection and projection:
-            //
-            // * We can always cache the result of a particular trait selection for the lifetime of
-            // an InfCtxt
-            // * Given a projection bound such as '<T as SomeTrait>::SomeItem = K', if 'T:
-            // SomeTrait' doesn't hold, then we don't need to care about the 'SomeItem = K'
-            //
-            // We fix the first assumption by manually clearing out all of the InferCtxt's caches
-            // in between calls to SelectionContext.select. This allows us to keep all of the
-            // intermediate types we create bound to the 'tcx lifetime, rather than needing to lift
-            // them between calls.
-            //
-            // We fix the second assumption by reprocessing the result of our first call to
-            // evaluate_predicates. Using the example of '<T as SomeTrait>::SomeItem = K', our first
-            // pass will pick up 'T: SomeTrait', but not 'SomeItem = K'. On our second pass,
-            // traits::project will see that 'T: SomeTrait' is in our ParamEnv, allowing
-            // SelectionContext to return it back to us.
-
-            let (new_env, user_env) = match self.evaluate_predicates(
-                &mut infcx,
-                trait_did,
-                ty,
-                orig_env,
-                orig_env,
-                &mut fresh_preds,
-                false,
-            ) {
-                Some(e) => e,
-                None => return AutoTraitResult::NegativeImpl,
-            };
-
-            let (full_env, full_user_env) = self
-                .evaluate_predicates(
-                    &mut infcx,
-                    trait_did,
-                    ty,
-                    new_env,
-                    user_env,
-                    &mut fresh_preds,
-                    true,
-                )
-                .unwrap_or_else(|| {
-                    panic!("Failed to fully process: {:?} {:?} {:?}", ty, trait_did, orig_env)
-                });
-
-            debug!(
-                "find_auto_trait_generics({:?}): fulfilling \
-                 with {:?}",
-                trait_ref, full_env
-            );
-            infcx.clear_caches();
-
-            // At this point, we already have all of the bounds we need. FulfillmentContext is used
-            // to store all of the necessary region/lifetime bounds in the InferContext, as well as
-            // an additional sanity check.
-            let mut fulfill = FulfillmentContext::new();
-            fulfill.register_bound(
-                &infcx,
-                full_env,
-                ty,
-                trait_did,
-                ObligationCause::misc(DUMMY_SP, hir::DUMMY_HIR_ID),
-            );
-            fulfill.select_all_or_error(&infcx).unwrap_or_else(|e| {
-                panic!("Unable to fulfill trait {:?} for '{:?}': {:?}", trait_did, ty, e)
-            });
-
-            let body_id_map: FxHashMap<_, _> = infcx
-                .inner
-                .borrow()
-                .region_obligations
-                .iter()
-                .map(|&(id, _)| (id, vec![]))
-                .collect();
-
-            infcx.process_registered_region_obligations(&body_id_map, None, full_env);
-
-            let region_data = infcx
-                .inner
-                .borrow_mut()
-                .unwrap_region_constraints()
-                .region_constraint_data()
-                .clone();
-
-            let vid_to_region = self.map_vid_to_region(&region_data);
-
-            let info = AutoTraitInfo { full_user_env, region_data, vid_to_region };
-
-            return AutoTraitResult::PositiveImpl(auto_trait_callback(&infcx, info));
-        });
-    }
-}
-
-impl AutoTraitFinder<'tcx> {
-    /// The core logic responsible for computing the bounds for our synthesized impl.
-    ///
-    /// To calculate the bounds, we call `SelectionContext.select` in a loop. Like
-    /// `FulfillmentContext`, we recursively select the nested obligations of predicates we
-    /// encounter. However, whenever we encounter an `UnimplementedError` involving a type
-    /// parameter, we add it to our `ParamEnv`. Since our goal is to determine when a particular
-    /// type implements an auto trait, Unimplemented errors tell us what conditions need to be met.
-    ///
-    /// This method ends up working somewhat similarly to `FulfillmentContext`, but with a few key
-    /// differences. `FulfillmentContext` works under the assumption that it's dealing with concrete
-    /// user code. According, it considers all possible ways that a `Predicate` could be met, which
-    /// isn't always what we want for a synthesized impl. For example, given the predicate `T:
-    /// Iterator`, `FulfillmentContext` can end up reporting an Unimplemented error for `T:
-    /// IntoIterator` -- since there's an implementation of `Iterator` where `T: IntoIterator`,
-    /// `FulfillmentContext` will drive `SelectionContext` to consider that impl before giving up.
-    /// If we were to rely on `FulfillmentContext`s decision, we might end up synthesizing an impl
-    /// like this:
-    ///
-    ///     impl<T> Send for Foo<T> where T: IntoIterator
-    ///
-    /// While it might be technically true that Foo implements Send where `T: IntoIterator`,
-    /// the bound is overly restrictive - it's really only necessary that `T: Iterator`.
-    ///
-    /// For this reason, `evaluate_predicates` handles predicates with type variables specially.
-    /// When we encounter an `Unimplemented` error for a bound such as `T: Iterator`, we immediately
-    /// add it to our `ParamEnv`, and add it to our stack for recursive evaluation. When we later
-    /// select it, we'll pick up any nested bounds, without ever inferring that `T: IntoIterator`
-    /// needs to hold.
-    ///
-    /// One additional consideration is supertrait bounds. Normally, a `ParamEnv` is only ever
-    /// constructed once for a given type. As part of the construction process, the `ParamEnv` will
-    /// have any supertrait bounds normalized -- e.g., if we have a type `struct Foo<T: Copy>`, the
-    /// `ParamEnv` will contain `T: Copy` and `T: Clone`, since `Copy: Clone`. When we construct our
-    /// own `ParamEnv`, we need to do this ourselves, through `traits::elaborate_predicates`, or
-    /// else `SelectionContext` will choke on the missing predicates. However, this should never
-    /// show up in the final synthesized generics: we don't want our generated docs page to contain
-    /// something like `T: Copy + Clone`, as that's redundant. Therefore, we keep track of a
-    /// separate `user_env`, which only holds the predicates that will actually be displayed to the
-    /// user.
-    fn evaluate_predicates(
-        &self,
-        infcx: &InferCtxt<'_, 'tcx>,
-        trait_did: DefId,
-        ty: Ty<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
-        user_env: ty::ParamEnv<'tcx>,
-        fresh_preds: &mut FxHashSet<ty::Predicate<'tcx>>,
-        only_projections: bool,
-    ) -> Option<(ty::ParamEnv<'tcx>, ty::ParamEnv<'tcx>)> {
-        let tcx = infcx.tcx;
-
-        let mut select = SelectionContext::with_negative(&infcx, true);
-
-        let mut already_visited = FxHashSet::default();
-        let mut predicates = VecDeque::new();
-        predicates.push_back(ty::Binder::bind(ty::TraitPredicate {
-            trait_ref: ty::TraitRef {
-                def_id: trait_did,
-                substs: infcx.tcx.mk_substs_trait(ty, &[]),
-            },
-        }));
-
-        let mut computed_preds: FxHashSet<_> = param_env.caller_bounds.iter().cloned().collect();
-        let mut user_computed_preds: FxHashSet<_> =
-            user_env.caller_bounds.iter().cloned().collect();
-
-        let mut new_env = param_env;
-        let dummy_cause = ObligationCause::misc(DUMMY_SP, hir::DUMMY_HIR_ID);
-
-        while let Some(pred) = predicates.pop_front() {
-            infcx.clear_caches();
-
-            if !already_visited.insert(pred) {
-                continue;
-            }
-
-            // Call `infcx.resolve_vars_if_possible` to see if we can
-            // get rid of any inference variables.
-            let obligation = infcx.resolve_vars_if_possible(&Obligation::new(
-                dummy_cause.clone(),
-                new_env,
-                pred,
-            ));
-            let result = select.select(&obligation);
-
-            match &result {
-                &Ok(Some(ref vtable)) => {
-                    // If we see an explicit negative impl (e.g., `impl !Send for MyStruct`),
-                    // we immediately bail out, since it's impossible for us to continue.
-                    match vtable {
-                        Vtable::VtableImpl(VtableImplData { impl_def_id, .. }) => {
-                            // Blame 'tidy' for the weird bracket placement.
-                            if infcx.tcx.impl_polarity(*impl_def_id) == ty::ImplPolarity::Negative {
-                                debug!(
-                                    "evaluate_nested_obligations: found explicit negative impl\
-                                        {:?}, bailing out",
-                                    impl_def_id
-                                );
-                                return None;
-                            }
-                        }
-                        _ => {}
-                    }
-
-                    let obligations = vtable.clone().nested_obligations().into_iter();
-
-                    if !self.evaluate_nested_obligations(
-                        ty,
-                        obligations,
-                        &mut user_computed_preds,
-                        fresh_preds,
-                        &mut predicates,
-                        &mut select,
-                        only_projections,
-                    ) {
-                        return None;
-                    }
-                }
-                &Ok(None) => {}
-                &Err(SelectionError::Unimplemented) => {
-                    if self.is_param_no_infer(pred.skip_binder().trait_ref.substs) {
-                        already_visited.remove(&pred);
-                        self.add_user_pred(
-                            &mut user_computed_preds,
-                            ty::Predicate::Trait(pred, hir::Constness::NotConst),
-                        );
-                        predicates.push_back(pred);
-                    } else {
-                        debug!(
-                            "evaluate_nested_obligations: `Unimplemented` found, bailing: \
-                             {:?} {:?} {:?}",
-                            ty,
-                            pred,
-                            pred.skip_binder().trait_ref.substs
-                        );
-                        return None;
-                    }
-                }
-                _ => panic!("Unexpected error for '{:?}': {:?}", ty, result),
-            };
-
-            computed_preds.extend(user_computed_preds.iter().cloned());
-            let normalized_preds =
-                elaborate_predicates(tcx, computed_preds.iter().cloned().collect());
-            new_env =
-                ty::ParamEnv::new(tcx.mk_predicates(normalized_preds), param_env.reveal, None);
-        }
-
-        let final_user_env = ty::ParamEnv::new(
-            tcx.mk_predicates(user_computed_preds.into_iter()),
-            user_env.reveal,
-            None,
-        );
-        debug!(
-            "evaluate_nested_obligations(ty={:?}, trait_did={:?}): succeeded with '{:?}' \
-             '{:?}'",
-            ty, trait_did, new_env, final_user_env
-        );
-
-        return Some((new_env, final_user_env));
-    }
-
-    /// This method is designed to work around the following issue:
-    /// When we compute auto trait bounds, we repeatedly call `SelectionContext.select`,
-    /// progressively building a `ParamEnv` based on the results we get.
-    /// However, our usage of `SelectionContext` differs from its normal use within the compiler,
-    /// in that we capture and re-reprocess predicates from `Unimplemented` errors.
-    ///
-    /// This can lead to a corner case when dealing with region parameters.
-    /// During our selection loop in `evaluate_predicates`, we might end up with
-    /// two trait predicates that differ only in their region parameters:
-    /// one containing a HRTB lifetime parameter, and one containing a 'normal'
-    /// lifetime parameter. For example:
-    ///
-    ///     T as MyTrait<'a>
-    ///     T as MyTrait<'static>
-    ///
-    /// If we put both of these predicates in our computed `ParamEnv`, we'll
-    /// confuse `SelectionContext`, since it will (correctly) view both as being applicable.
-    ///
-    /// To solve this, we pick the 'more strict' lifetime bound -- i.e., the HRTB
-    /// Our end goal is to generate a user-visible description of the conditions
-    /// under which a type implements an auto trait. A trait predicate involving
-    /// a HRTB means that the type needs to work with any choice of lifetime,
-    /// not just one specific lifetime (e.g., `'static`).
-    fn add_user_pred<'c>(
-        &self,
-        user_computed_preds: &mut FxHashSet<ty::Predicate<'c>>,
-        new_pred: ty::Predicate<'c>,
-    ) {
-        let mut should_add_new = true;
-        user_computed_preds.retain(|&old_pred| {
-            match (&new_pred, old_pred) {
-                (&ty::Predicate::Trait(new_trait, _), ty::Predicate::Trait(old_trait, _)) => {
-                    if new_trait.def_id() == old_trait.def_id() {
-                        let new_substs = new_trait.skip_binder().trait_ref.substs;
-                        let old_substs = old_trait.skip_binder().trait_ref.substs;
-
-                        if !new_substs.types().eq(old_substs.types()) {
-                            // We can't compare lifetimes if the types are different,
-                            // so skip checking `old_pred`.
-                            return true;
-                        }
-
-                        for (new_region, old_region) in
-                            new_substs.regions().zip(old_substs.regions())
-                        {
-                            match (new_region, old_region) {
-                                // If both predicates have an `ReLateBound` (a HRTB) in the
-                                // same spot, we do nothing.
-                                (
-                                    ty::RegionKind::ReLateBound(_, _),
-                                    ty::RegionKind::ReLateBound(_, _),
-                                ) => {}
-
-                                (ty::RegionKind::ReLateBound(_, _), _)
-                                | (_, ty::RegionKind::ReVar(_)) => {
-                                    // One of these is true:
-                                    // The new predicate has a HRTB in a spot where the old
-                                    // predicate does not (if they both had a HRTB, the previous
-                                    // match arm would have executed). A HRBT is a 'stricter'
-                                    // bound than anything else, so we want to keep the newer
-                                    // predicate (with the HRBT) in place of the old predicate.
-                                    //
-                                    // OR
-                                    //
-                                    // The old predicate has a region variable where the new
-                                    // predicate has some other kind of region. An region
-                                    // variable isn't something we can actually display to a user,
-                                    // so we choose their new predicate (which doesn't have a region
-                                    // varaible).
-                                    //
-                                    // In both cases, we want to remove the old predicate,
-                                    // from `user_computed_preds`, and replace it with the new
-                                    // one. Having both the old and the new
-                                    // predicate in a `ParamEnv` would confuse `SelectionContext`.
-                                    //
-                                    // We're currently in the predicate passed to 'retain',
-                                    // so we return `false` to remove the old predicate from
-                                    // `user_computed_preds`.
-                                    return false;
-                                }
-                                (_, ty::RegionKind::ReLateBound(_, _))
-                                | (ty::RegionKind::ReVar(_), _) => {
-                                    // This is the opposite situation as the previous arm.
-                                    // One of these is true:
-                                    //
-                                    // The old predicate has a HRTB lifetime in a place where the
-                                    // new predicate does not.
-                                    //
-                                    // OR
-                                    //
-                                    // The new predicate has a region variable where the old
-                                    // predicate has some other type of region.
-                                    //
-                                    // We want to leave the old
-                                    // predicate in `user_computed_preds`, and skip adding
-                                    // new_pred to `user_computed_params`.
-                                    should_add_new = false
-                                }
-                                _ => {}
-                            }
-                        }
-                    }
-                }
-                _ => {}
-            }
-            return true;
-        });
-
-        if should_add_new {
-            user_computed_preds.insert(new_pred);
-        }
-    }
-
-    /// This is very similar to `handle_lifetimes`. However, instead of matching `ty::Region`s
-    /// to each other, we match `ty::RegionVid`s to `ty::Region`s.
-    fn map_vid_to_region<'cx>(
-        &self,
-        regions: &RegionConstraintData<'cx>,
-    ) -> FxHashMap<ty::RegionVid, ty::Region<'cx>> {
-        let mut vid_map: FxHashMap<RegionTarget<'cx>, RegionDeps<'cx>> = FxHashMap::default();
-        let mut finished_map = FxHashMap::default();
-
-        for constraint in regions.constraints.keys() {
-            match constraint {
-                &Constraint::VarSubVar(r1, r2) => {
-                    {
-                        let deps1 = vid_map.entry(RegionTarget::RegionVid(r1)).or_default();
-                        deps1.larger.insert(RegionTarget::RegionVid(r2));
-                    }
-
-                    let deps2 = vid_map.entry(RegionTarget::RegionVid(r2)).or_default();
-                    deps2.smaller.insert(RegionTarget::RegionVid(r1));
-                }
-                &Constraint::RegSubVar(region, vid) => {
-                    {
-                        let deps1 = vid_map.entry(RegionTarget::Region(region)).or_default();
-                        deps1.larger.insert(RegionTarget::RegionVid(vid));
-                    }
-
-                    let deps2 = vid_map.entry(RegionTarget::RegionVid(vid)).or_default();
-                    deps2.smaller.insert(RegionTarget::Region(region));
-                }
-                &Constraint::VarSubReg(vid, region) => {
-                    finished_map.insert(vid, region);
-                }
-                &Constraint::RegSubReg(r1, r2) => {
-                    {
-                        let deps1 = vid_map.entry(RegionTarget::Region(r1)).or_default();
-                        deps1.larger.insert(RegionTarget::Region(r2));
-                    }
-
-                    let deps2 = vid_map.entry(RegionTarget::Region(r2)).or_default();
-                    deps2.smaller.insert(RegionTarget::Region(r1));
-                }
-            }
-        }
-
-        while !vid_map.is_empty() {
-            let target = *vid_map.keys().next().expect("Keys somehow empty");
-            let deps = vid_map.remove(&target).expect("Entry somehow missing");
-
-            for smaller in deps.smaller.iter() {
-                for larger in deps.larger.iter() {
-                    match (smaller, larger) {
-                        (&RegionTarget::Region(_), &RegionTarget::Region(_)) => {
-                            if let Entry::Occupied(v) = vid_map.entry(*smaller) {
-                                let smaller_deps = v.into_mut();
-                                smaller_deps.larger.insert(*larger);
-                                smaller_deps.larger.remove(&target);
-                            }
-
-                            if let Entry::Occupied(v) = vid_map.entry(*larger) {
-                                let larger_deps = v.into_mut();
-                                larger_deps.smaller.insert(*smaller);
-                                larger_deps.smaller.remove(&target);
-                            }
-                        }
-                        (&RegionTarget::RegionVid(v1), &RegionTarget::Region(r1)) => {
-                            finished_map.insert(v1, r1);
-                        }
-                        (&RegionTarget::Region(_), &RegionTarget::RegionVid(_)) => {
-                            // Do nothing; we don't care about regions that are smaller than vids.
-                        }
-                        (&RegionTarget::RegionVid(_), &RegionTarget::RegionVid(_)) => {
-                            if let Entry::Occupied(v) = vid_map.entry(*smaller) {
-                                let smaller_deps = v.into_mut();
-                                smaller_deps.larger.insert(*larger);
-                                smaller_deps.larger.remove(&target);
-                            }
-
-                            if let Entry::Occupied(v) = vid_map.entry(*larger) {
-                                let larger_deps = v.into_mut();
-                                larger_deps.smaller.insert(*smaller);
-                                larger_deps.smaller.remove(&target);
-                            }
-                        }
-                    }
-                }
-            }
-        }
-        finished_map
-    }
-
-    fn is_param_no_infer(&self, substs: SubstsRef<'_>) -> bool {
-        return self.is_of_param(substs.type_at(0)) && !substs.types().any(|t| t.has_infer_types());
-    }
-
-    pub fn is_of_param(&self, ty: Ty<'_>) -> bool {
-        return match ty.kind {
-            ty::Param(_) => true,
-            ty::Projection(p) => self.is_of_param(p.self_ty()),
-            _ => false,
-        };
-    }
-
-    fn is_self_referential_projection(&self, p: ty::PolyProjectionPredicate<'_>) -> bool {
-        match p.ty().skip_binder().kind {
-            ty::Projection(proj) if proj == p.skip_binder().projection_ty => true,
-            _ => false,
-        }
-    }
-
-    fn evaluate_nested_obligations(
-        &self,
-        ty: Ty<'_>,
-        nested: impl Iterator<Item = Obligation<'tcx, ty::Predicate<'tcx>>>,
-        computed_preds: &mut FxHashSet<ty::Predicate<'tcx>>,
-        fresh_preds: &mut FxHashSet<ty::Predicate<'tcx>>,
-        predicates: &mut VecDeque<ty::PolyTraitPredicate<'tcx>>,
-        select: &mut SelectionContext<'_, 'tcx>,
-        only_projections: bool,
-    ) -> bool {
-        let dummy_cause = ObligationCause::misc(DUMMY_SP, hir::DUMMY_HIR_ID);
-
-        for (obligation, mut predicate) in nested.map(|o| (o.clone(), o.predicate)) {
-            let is_new_pred = fresh_preds.insert(self.clean_pred(select.infcx(), predicate));
-
-            // Resolve any inference variables that we can, to help selection succeed
-            predicate = select.infcx().resolve_vars_if_possible(&predicate);
-
-            // We only add a predicate as a user-displayable bound if
-            // it involves a generic parameter, and doesn't contain
-            // any inference variables.
-            //
-            // Displaying a bound involving a concrete type (instead of a generic
-            // parameter) would be pointless, since it's always true
-            // (e.g. u8: Copy)
-            // Displaying an inference variable is impossible, since they're
-            // an internal compiler detail without a defined visual representation
-            //
-            // We check this by calling is_of_param on the relevant types
-            // from the various possible predicates
-            match &predicate {
-                &ty::Predicate::Trait(p, _) => {
-                    if self.is_param_no_infer(p.skip_binder().trait_ref.substs)
-                        && !only_projections
-                        && is_new_pred
-                    {
-                        self.add_user_pred(computed_preds, predicate);
-                    }
-                    predicates.push_back(p);
-                }
-                &ty::Predicate::Projection(p) => {
-                    debug!(
-                        "evaluate_nested_obligations: examining projection predicate {:?}",
-                        predicate
-                    );
-
-                    // As described above, we only want to display
-                    // bounds which include a generic parameter but don't include
-                    // an inference variable.
-                    // Additionally, we check if we've seen this predicate before,
-                    // to avoid rendering duplicate bounds to the user.
-                    if self.is_param_no_infer(p.skip_binder().projection_ty.substs)
-                        && !p.ty().skip_binder().has_infer_types()
-                        && is_new_pred
-                    {
-                        debug!(
-                            "evaluate_nested_obligations: adding projection predicate\
-                            to computed_preds: {:?}",
-                            predicate
-                        );
-
-                        // Under unusual circumstances, we can end up with a self-refeential
-                        // projection predicate. For example:
-                        // <T as MyType>::Value == <T as MyType>::Value
-                        // Not only is displaying this to the user pointless,
-                        // having it in the ParamEnv will cause an issue if we try to call
-                        // poly_project_and_unify_type on the predicate, since this kind of
-                        // predicate will normally never end up in a ParamEnv.
-                        //
-                        // For these reasons, we ignore these weird predicates,
-                        // ensuring that we're able to properly synthesize an auto trait impl
-                        if self.is_self_referential_projection(p) {
-                            debug!(
-                                "evaluate_nested_obligations: encountered a projection
-                                 predicate equating a type with itself! Skipping"
-                            );
-                        } else {
-                            self.add_user_pred(computed_preds, predicate);
-                        }
-                    }
-
-                    // There are three possible cases when we project a predicate:
-                    //
-                    // 1. We encounter an error. This means that it's impossible for
-                    // our current type to implement the auto trait - there's bound
-                    // that we could add to our ParamEnv that would 'fix' this kind
-                    // of error, as it's not caused by an unimplemented type.
-                    //
-                    // 2. We successfully project the predicate (Ok(Some(_))), generating
-                    //  some subobligations. We then process these subobligations
-                    //  like any other generated sub-obligations.
-                    //
-                    // 3. We receieve an 'ambiguous' result (Ok(None))
-                    // If we were actually trying to compile a crate,
-                    // we would need to re-process this obligation later.
-                    // However, all we care about is finding out what bounds
-                    // are needed for our type to implement a particular auto trait.
-                    // We've already added this obligation to our computed ParamEnv
-                    // above (if it was necessary). Therefore, we don't need
-                    // to do any further processing of the obligation.
-                    //
-                    // Note that we *must* try to project *all* projection predicates
-                    // we encounter, even ones without inference variable.
-                    // This ensures that we detect any projection errors,
-                    // which indicate that our type can *never* implement the given
-                    // auto trait. In that case, we will generate an explicit negative
-                    // impl (e.g. 'impl !Send for MyType'). However, we don't
-                    // try to process any of the generated subobligations -
-                    // they contain no new information, since we already know
-                    // that our type implements the projected-through trait,
-                    // and can lead to weird region issues.
-                    //
-                    // Normally, we'll generate a negative impl as a result of encountering
-                    // a type with an explicit negative impl of an auto trait
-                    // (for example, raw pointers have !Send and !Sync impls)
-                    // However, through some **interesting** manipulations of the type
-                    // system, it's actually possible to write a type that never
-                    // implements an auto trait due to a projection error, not a normal
-                    // negative impl error. To properly handle this case, we need
-                    // to ensure that we catch any potential projection errors,
-                    // and turn them into an explicit negative impl for our type.
-                    debug!("Projecting and unifying projection predicate {:?}", predicate);
-
-                    match poly_project_and_unify_type(select, &obligation.with(p)) {
-                        Err(e) => {
-                            debug!(
-                                "evaluate_nested_obligations: Unable to unify predicate \
-                                 '{:?}' '{:?}', bailing out",
-                                ty, e
-                            );
-                            return false;
-                        }
-                        Ok(Some(v)) => {
-                            // We only care about sub-obligations
-                            // when we started out trying to unify
-                            // some inference variables. See the comment above
-                            // for more infomration
-                            if p.ty().skip_binder().has_infer_types() {
-                                if !self.evaluate_nested_obligations(
-                                    ty,
-                                    v.clone().iter().cloned(),
-                                    computed_preds,
-                                    fresh_preds,
-                                    predicates,
-                                    select,
-                                    only_projections,
-                                ) {
-                                    return false;
-                                }
-                            }
-                        }
-                        Ok(None) => {
-                            // It's ok not to make progress when hvave no inference variables -
-                            // in that case, we were only performing unifcation to check if an
-                            // error occurred (which would indicate that it's impossible for our
-                            // type to implement the auto trait).
-                            // However, we should always make progress (either by generating
-                            // subobligations or getting an error) when we started off with
-                            // inference variables
-                            if p.ty().skip_binder().has_infer_types() {
-                                panic!("Unexpected result when selecting {:?} {:?}", ty, obligation)
-                            }
-                        }
-                    }
-                }
-                &ty::Predicate::RegionOutlives(ref binder) => {
-                    if select.infcx().region_outlives_predicate(&dummy_cause, binder).is_err() {
-                        return false;
-                    }
-                }
-                &ty::Predicate::TypeOutlives(ref binder) => {
-                    match (
-                        binder.no_bound_vars(),
-                        binder.map_bound_ref(|pred| pred.0).no_bound_vars(),
-                    ) {
-                        (None, Some(t_a)) => {
-                            select.infcx().register_region_obligation_with_cause(
-                                t_a,
-                                select.infcx().tcx.lifetimes.re_static,
-                                &dummy_cause,
-                            );
-                        }
-                        (Some(ty::OutlivesPredicate(t_a, r_b)), _) => {
-                            select.infcx().register_region_obligation_with_cause(
-                                t_a,
-                                r_b,
-                                &dummy_cause,
-                            );
-                        }
-                        _ => {}
-                    };
-                }
-                _ => panic!("Unexpected predicate {:?} {:?}", ty, predicate),
-            };
-        }
-        return true;
-    }
-
-    pub fn clean_pred(
-        &self,
-        infcx: &InferCtxt<'_, 'tcx>,
-        p: ty::Predicate<'tcx>,
-    ) -> ty::Predicate<'tcx> {
-        infcx.freshen(p)
-    }
-}
-
-// Replaces all ReVars in a type with ty::Region's, using the provided map
-pub struct RegionReplacer<'a, 'tcx> {
-    vid_to_region: &'a FxHashMap<ty::RegionVid, ty::Region<'tcx>>,
-    tcx: TyCtxt<'tcx>,
-}
-
-impl<'a, 'tcx> TypeFolder<'tcx> for RegionReplacer<'a, 'tcx> {
-    fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
-        self.tcx
-    }
-
-    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
-        (match r {
-            &ty::ReVar(vid) => self.vid_to_region.get(&vid).cloned(),
-            _ => None,
-        })
-        .unwrap_or_else(|| r.super_fold_with(self))
-    }
-}
diff --git a/src/librustc_infer/traits/chalk_fulfill.rs b/src/librustc_infer/traits/chalk_fulfill.rs
deleted file mode 100644 (file)
index 82fa683..0000000
+++ /dev/null
@@ -1,159 +0,0 @@
-use crate::infer::canonical::OriginalQueryValues;
-use crate::infer::InferCtxt;
-use crate::traits::query::NoSolution;
-use crate::traits::{
-    Environment, FulfillmentError, FulfillmentErrorCode, InEnvironment, ObligationCause,
-    PredicateObligation, SelectionError, TraitEngine,
-};
-use rustc::ty::{self, Ty};
-use rustc_data_structures::fx::FxHashSet;
-
-pub use rustc::traits::ChalkCanonicalGoal as CanonicalGoal;
-
-pub struct FulfillmentContext<'tcx> {
-    obligations: FxHashSet<InEnvironment<'tcx, PredicateObligation<'tcx>>>,
-}
-
-impl FulfillmentContext<'tcx> {
-    crate fn new() -> Self {
-        FulfillmentContext { obligations: FxHashSet::default() }
-    }
-}
-
-fn in_environment(
-    infcx: &InferCtxt<'_, 'tcx>,
-    obligation: PredicateObligation<'tcx>,
-) -> InEnvironment<'tcx, PredicateObligation<'tcx>> {
-    assert!(!infcx.is_in_snapshot());
-    let obligation = infcx.resolve_vars_if_possible(&obligation);
-
-    let environment = match obligation.param_env.def_id {
-        Some(def_id) => infcx.tcx.environment(def_id),
-        None if obligation.param_env.caller_bounds.is_empty() => {
-            Environment { clauses: ty::List::empty() }
-        }
-        _ => bug!("non-empty `ParamEnv` with no def-id"),
-    };
-
-    InEnvironment { environment, goal: obligation }
-}
-
-impl TraitEngine<'tcx> for FulfillmentContext<'tcx> {
-    fn normalize_projection_type(
-        &mut self,
-        infcx: &InferCtxt<'_, 'tcx>,
-        _param_env: ty::ParamEnv<'tcx>,
-        projection_ty: ty::ProjectionTy<'tcx>,
-        _cause: ObligationCause<'tcx>,
-    ) -> Ty<'tcx> {
-        infcx.tcx.mk_ty(ty::Projection(projection_ty))
-    }
-
-    fn register_predicate_obligation(
-        &mut self,
-        infcx: &InferCtxt<'_, 'tcx>,
-        obligation: PredicateObligation<'tcx>,
-    ) {
-        self.obligations.insert(in_environment(infcx, obligation));
-    }
-
-    fn select_all_or_error(
-        &mut self,
-        infcx: &InferCtxt<'_, 'tcx>,
-    ) -> Result<(), Vec<FulfillmentError<'tcx>>> {
-        self.select_where_possible(infcx)?;
-
-        if self.obligations.is_empty() {
-            Ok(())
-        } else {
-            let errors = self
-                .obligations
-                .iter()
-                .map(|obligation| FulfillmentError {
-                    obligation: obligation.goal.clone(),
-                    code: FulfillmentErrorCode::CodeAmbiguity,
-                    points_at_arg_span: false,
-                })
-                .collect();
-            Err(errors)
-        }
-    }
-
-    fn select_where_possible(
-        &mut self,
-        infcx: &InferCtxt<'_, 'tcx>,
-    ) -> Result<(), Vec<FulfillmentError<'tcx>>> {
-        let mut errors = Vec::new();
-        let mut next_round = FxHashSet::default();
-        let mut making_progress;
-
-        loop {
-            making_progress = false;
-
-            // We iterate over all obligations, and record if we are able
-            // to unambiguously prove at least one obligation.
-            for obligation in self.obligations.drain() {
-                let mut orig_values = OriginalQueryValues::default();
-                let canonical_goal = infcx.canonicalize_query(
-                    &InEnvironment {
-                        environment: obligation.environment,
-                        goal: obligation.goal.predicate,
-                    },
-                    &mut orig_values,
-                );
-
-                match infcx.tcx.evaluate_goal(canonical_goal) {
-                    Ok(response) => {
-                        if response.is_proven() {
-                            making_progress = true;
-
-                            match infcx.instantiate_query_response_and_region_obligations(
-                                &obligation.goal.cause,
-                                obligation.goal.param_env,
-                                &orig_values,
-                                &response,
-                            ) {
-                                Ok(infer_ok) => next_round.extend(
-                                    infer_ok
-                                        .obligations
-                                        .into_iter()
-                                        .map(|obligation| in_environment(infcx, obligation)),
-                                ),
-
-                                Err(_err) => errors.push(FulfillmentError {
-                                    obligation: obligation.goal,
-                                    code: FulfillmentErrorCode::CodeSelectionError(
-                                        SelectionError::Unimplemented,
-                                    ),
-                                    points_at_arg_span: false,
-                                }),
-                            }
-                        } else {
-                            // Ambiguous: retry at next round.
-                            next_round.insert(obligation);
-                        }
-                    }
-
-                    Err(NoSolution) => errors.push(FulfillmentError {
-                        obligation: obligation.goal,
-                        code: FulfillmentErrorCode::CodeSelectionError(
-                            SelectionError::Unimplemented,
-                        ),
-                        points_at_arg_span: false,
-                    }),
-                }
-            }
-            next_round = std::mem::replace(&mut self.obligations, next_round);
-
-            if !making_progress {
-                break;
-            }
-        }
-
-        if errors.is_empty() { Ok(()) } else { Err(errors) }
-    }
-
-    fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>> {
-        self.obligations.iter().map(|obligation| obligation.goal.clone()).collect()
-    }
-}
diff --git a/src/librustc_infer/traits/codegen/mod.rs b/src/librustc_infer/traits/codegen/mod.rs
deleted file mode 100644 (file)
index bd4129a..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-// This file contains various trait resolution methods used by codegen.
-// They all assume regions can be erased and monomorphic types.  It
-// seems likely that they should eventually be merged into more
-// general routines.
-
-use crate::infer::{InferCtxt, TyCtxtInferExt};
-use crate::traits::{
-    FulfillmentContext, Obligation, ObligationCause, SelectionContext, TraitEngine, Vtable,
-};
-use rustc::ty::fold::TypeFoldable;
-use rustc::ty::{self, TyCtxt};
-
-/// Attempts to resolve an obligation to a vtable. The result is
-/// a shallow vtable resolution, meaning that we do not
-/// (necessarily) resolve all nested obligations on the impl. Note
-/// that type check should guarantee to us that all nested
-/// obligations *could be* resolved if we wanted to.
-/// Assumes that this is run after the entire crate has been successfully type-checked.
-pub fn codegen_fulfill_obligation<'tcx>(
-    ty: TyCtxt<'tcx>,
-    (param_env, trait_ref): (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>),
-) -> Vtable<'tcx, ()> {
-    // Remove any references to regions; this helps improve caching.
-    let trait_ref = ty.erase_regions(&trait_ref);
-
-    debug!(
-        "codegen_fulfill_obligation(trait_ref={:?}, def_id={:?})",
-        (param_env, trait_ref),
-        trait_ref.def_id()
-    );
-
-    // Do the initial selection for the obligation. This yields the
-    // shallow result we are looking for -- that is, what specific impl.
-    ty.infer_ctxt().enter(|infcx| {
-        let mut selcx = SelectionContext::new(&infcx);
-
-        let obligation_cause = ObligationCause::dummy();
-        let obligation =
-            Obligation::new(obligation_cause, param_env, trait_ref.to_poly_trait_predicate());
-
-        let selection = match selcx.select(&obligation) {
-            Ok(Some(selection)) => selection,
-            Ok(None) => {
-                // Ambiguity can happen when monomorphizing during trans
-                // expands to some humongo type that never occurred
-                // statically -- this humongo type can then overflow,
-                // leading to an ambiguous result. So report this as an
-                // overflow bug, since I believe this is the only case
-                // where ambiguity can result.
-                bug!(
-                    "Encountered ambiguity selecting `{:?}` during codegen, \
-                      presuming due to overflow",
-                    trait_ref
-                )
-            }
-            Err(e) => {
-                bug!("Encountered error `{:?}` selecting `{:?}` during codegen", e, trait_ref)
-            }
-        };
-
-        debug!("fulfill_obligation: selection={:?}", selection);
-
-        // Currently, we use a fulfillment context to completely resolve
-        // all nested obligations. This is because they can inform the
-        // inference of the impl's type parameters.
-        let mut fulfill_cx = FulfillmentContext::new();
-        let vtable = selection.map(|predicate| {
-            debug!("fulfill_obligation: register_predicate_obligation {:?}", predicate);
-            fulfill_cx.register_predicate_obligation(&infcx, predicate);
-        });
-        let vtable = infcx.drain_fulfillment_cx_or_panic(&mut fulfill_cx, &vtable);
-
-        info!("Cache miss: {:?} => {:?}", trait_ref, vtable);
-        vtable
-    })
-}
-
-// # Global Cache
-
-impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
-    /// Finishes processes any obligations that remain in the
-    /// fulfillment context, and then returns the result with all type
-    /// variables removed and regions erased. Because this is intended
-    /// for use after type-check has completed, if any errors occur,
-    /// it will panic. It is used during normalization and other cases
-    /// where processing the obligations in `fulfill_cx` may cause
-    /// type inference variables that appear in `result` to be
-    /// unified, and hence we need to process those obligations to get
-    /// the complete picture of the type.
-    fn drain_fulfillment_cx_or_panic<T>(
-        &self,
-        fulfill_cx: &mut FulfillmentContext<'tcx>,
-        result: &T,
-    ) -> T
-    where
-        T: TypeFoldable<'tcx>,
-    {
-        debug!("drain_fulfillment_cx_or_panic()");
-
-        // In principle, we only need to do this so long as `result`
-        // contains unbound type parameters. It could be a slight
-        // optimization to stop iterating early.
-        if let Err(errors) = fulfill_cx.select_all_or_error(self) {
-            bug!("Encountered errors `{:?}` resolving bounds after type-checking", errors);
-        }
-
-        let result = self.resolve_vars_if_possible(result);
-        self.tcx.erase_regions(&result)
-    }
-}
diff --git a/src/librustc_infer/traits/coherence.rs b/src/librustc_infer/traits/coherence.rs
deleted file mode 100644 (file)
index 0dec5ae..0000000
+++ /dev/null
@@ -1,540 +0,0 @@
-//! See Rustc Guide chapters on [trait-resolution] and [trait-specialization] for more info on how
-//! this works.
-//!
-//! [trait-resolution]: https://rust-lang.github.io/rustc-guide/traits/resolution.html
-//! [trait-specialization]: https://rust-lang.github.io/rustc-guide/traits/specialization.html
-
-use crate::infer::{CombinedSnapshot, InferOk, TyCtxtInferExt};
-use crate::traits::select::IntercrateAmbiguityCause;
-use crate::traits::SkipLeakCheck;
-use crate::traits::{self, Normalized, Obligation, ObligationCause, SelectionContext};
-use rustc::ty::fold::TypeFoldable;
-use rustc::ty::subst::Subst;
-use rustc::ty::{self, Ty, TyCtxt};
-use rustc_hir::def_id::{DefId, LOCAL_CRATE};
-use rustc_span::symbol::sym;
-use rustc_span::DUMMY_SP;
-
-/// Whether we do the orphan check relative to this crate or
-/// to some remote crate.
-#[derive(Copy, Clone, Debug)]
-enum InCrate {
-    Local,
-    Remote,
-}
-
-#[derive(Debug, Copy, Clone)]
-pub enum Conflict {
-    Upstream,
-    Downstream,
-}
-
-pub struct OverlapResult<'tcx> {
-    pub impl_header: ty::ImplHeader<'tcx>,
-    pub intercrate_ambiguity_causes: Vec<IntercrateAmbiguityCause>,
-
-    /// `true` if the overlap might've been permitted before the shift
-    /// to universes.
-    pub involves_placeholder: bool,
-}
-
-pub fn add_placeholder_note(err: &mut rustc_errors::DiagnosticBuilder<'_>) {
-    err.note(
-        "this behavior recently changed as a result of a bug fix; \
-         see rust-lang/rust#56105 for details",
-    );
-}
-
-/// If there are types that satisfy both impls, invokes `on_overlap`
-/// with a suitably-freshened `ImplHeader` with those types
-/// substituted. Otherwise, invokes `no_overlap`.
-pub fn overlapping_impls<F1, F2, R>(
-    tcx: TyCtxt<'_>,
-    impl1_def_id: DefId,
-    impl2_def_id: DefId,
-    skip_leak_check: SkipLeakCheck,
-    on_overlap: F1,
-    no_overlap: F2,
-) -> R
-where
-    F1: FnOnce(OverlapResult<'_>) -> R,
-    F2: FnOnce() -> R,
-{
-    debug!(
-        "overlapping_impls(\
-           impl1_def_id={:?}, \
-           impl2_def_id={:?})",
-        impl1_def_id, impl2_def_id,
-    );
-
-    let overlaps = tcx.infer_ctxt().enter(|infcx| {
-        let selcx = &mut SelectionContext::intercrate(&infcx);
-        overlap(selcx, skip_leak_check, impl1_def_id, impl2_def_id).is_some()
-    });
-
-    if !overlaps {
-        return no_overlap();
-    }
-
-    // In the case where we detect an error, run the check again, but
-    // this time tracking intercrate ambuiguity causes for better
-    // diagnostics. (These take time and can lead to false errors.)
-    tcx.infer_ctxt().enter(|infcx| {
-        let selcx = &mut SelectionContext::intercrate(&infcx);
-        selcx.enable_tracking_intercrate_ambiguity_causes();
-        on_overlap(overlap(selcx, skip_leak_check, impl1_def_id, impl2_def_id).unwrap())
-    })
-}
-
-fn with_fresh_ty_vars<'cx, 'tcx>(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    impl_def_id: DefId,
-) -> ty::ImplHeader<'tcx> {
-    let tcx = selcx.tcx();
-    let impl_substs = selcx.infcx().fresh_substs_for_item(DUMMY_SP, impl_def_id);
-
-    let header = ty::ImplHeader {
-        impl_def_id,
-        self_ty: tcx.type_of(impl_def_id).subst(tcx, impl_substs),
-        trait_ref: tcx.impl_trait_ref(impl_def_id).subst(tcx, impl_substs),
-        predicates: tcx.predicates_of(impl_def_id).instantiate(tcx, impl_substs).predicates,
-    };
-
-    let Normalized { value: mut header, obligations } =
-        traits::normalize(selcx, param_env, ObligationCause::dummy(), &header);
-
-    header.predicates.extend(obligations.into_iter().map(|o| o.predicate));
-    header
-}
-
-/// Can both impl `a` and impl `b` be satisfied by a common type (including
-/// where-clauses)? If so, returns an `ImplHeader` that unifies the two impls.
-fn overlap<'cx, 'tcx>(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
-    skip_leak_check: SkipLeakCheck,
-    a_def_id: DefId,
-    b_def_id: DefId,
-) -> Option<OverlapResult<'tcx>> {
-    debug!("overlap(a_def_id={:?}, b_def_id={:?})", a_def_id, b_def_id);
-
-    selcx.infcx().probe_maybe_skip_leak_check(skip_leak_check.is_yes(), |snapshot| {
-        overlap_within_probe(selcx, a_def_id, b_def_id, snapshot)
-    })
-}
-
-fn overlap_within_probe(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
-    a_def_id: DefId,
-    b_def_id: DefId,
-    snapshot: &CombinedSnapshot<'_, 'tcx>,
-) -> Option<OverlapResult<'tcx>> {
-    // For the purposes of this check, we don't bring any placeholder
-    // types into scope; instead, we replace the generic types with
-    // fresh type variables, and hence we do our evaluations in an
-    // empty environment.
-    let param_env = ty::ParamEnv::empty();
-
-    let a_impl_header = with_fresh_ty_vars(selcx, param_env, a_def_id);
-    let b_impl_header = with_fresh_ty_vars(selcx, param_env, b_def_id);
-
-    debug!("overlap: a_impl_header={:?}", a_impl_header);
-    debug!("overlap: b_impl_header={:?}", b_impl_header);
-
-    // Do `a` and `b` unify? If not, no overlap.
-    let obligations = match selcx
-        .infcx()
-        .at(&ObligationCause::dummy(), param_env)
-        .eq_impl_headers(&a_impl_header, &b_impl_header)
-    {
-        Ok(InferOk { obligations, value: () }) => obligations,
-        Err(_) => {
-            return None;
-        }
-    };
-
-    debug!("overlap: unification check succeeded");
-
-    // Are any of the obligations unsatisfiable? If so, no overlap.
-    let infcx = selcx.infcx();
-    let opt_failing_obligation = a_impl_header
-        .predicates
-        .iter()
-        .chain(&b_impl_header.predicates)
-        .map(|p| infcx.resolve_vars_if_possible(p))
-        .map(|p| Obligation {
-            cause: ObligationCause::dummy(),
-            param_env,
-            recursion_depth: 0,
-            predicate: p,
-        })
-        .chain(obligations)
-        .find(|o| !selcx.predicate_may_hold_fatal(o));
-    // FIXME: the call to `selcx.predicate_may_hold_fatal` above should be ported
-    // to the canonical trait query form, `infcx.predicate_may_hold`, once
-    // the new system supports intercrate mode (which coherence needs).
-
-    if let Some(failing_obligation) = opt_failing_obligation {
-        debug!("overlap: obligation unsatisfiable {:?}", failing_obligation);
-        return None;
-    }
-
-    let impl_header = selcx.infcx().resolve_vars_if_possible(&a_impl_header);
-    let intercrate_ambiguity_causes = selcx.take_intercrate_ambiguity_causes();
-    debug!("overlap: intercrate_ambiguity_causes={:#?}", intercrate_ambiguity_causes);
-
-    let involves_placeholder = match selcx.infcx().region_constraints_added_in_snapshot(snapshot) {
-        Some(true) => true,
-        _ => false,
-    };
-
-    Some(OverlapResult { impl_header, intercrate_ambiguity_causes, involves_placeholder })
-}
-
-pub fn trait_ref_is_knowable<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    trait_ref: ty::TraitRef<'tcx>,
-) -> Option<Conflict> {
-    debug!("trait_ref_is_knowable(trait_ref={:?})", trait_ref);
-    if orphan_check_trait_ref(tcx, trait_ref, InCrate::Remote).is_ok() {
-        // A downstream or cousin crate is allowed to implement some
-        // substitution of this trait-ref.
-        return Some(Conflict::Downstream);
-    }
-
-    if trait_ref_is_local_or_fundamental(tcx, trait_ref) {
-        // This is a local or fundamental trait, so future-compatibility
-        // is no concern. We know that downstream/cousin crates are not
-        // allowed to implement a substitution of this trait ref, which
-        // means impls could only come from dependencies of this crate,
-        // which we already know about.
-        return None;
-    }
-
-    // This is a remote non-fundamental trait, so if another crate
-    // can be the "final owner" of a substitution of this trait-ref,
-    // they are allowed to implement it future-compatibly.
-    //
-    // However, if we are a final owner, then nobody else can be,
-    // and if we are an intermediate owner, then we don't care
-    // about future-compatibility, which means that we're OK if
-    // we are an owner.
-    if orphan_check_trait_ref(tcx, trait_ref, InCrate::Local).is_ok() {
-        debug!("trait_ref_is_knowable: orphan check passed");
-        return None;
-    } else {
-        debug!("trait_ref_is_knowable: nonlocal, nonfundamental, unowned");
-        return Some(Conflict::Upstream);
-    }
-}
-
-pub fn trait_ref_is_local_or_fundamental<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    trait_ref: ty::TraitRef<'tcx>,
-) -> bool {
-    trait_ref.def_id.krate == LOCAL_CRATE || tcx.has_attr(trait_ref.def_id, sym::fundamental)
-}
-
-pub enum OrphanCheckErr<'tcx> {
-    NonLocalInputType(Vec<(Ty<'tcx>, bool /* Is this the first input type? */)>),
-    UncoveredTy(Ty<'tcx>, Option<Ty<'tcx>>),
-}
-
-/// Checks the coherence orphan rules. `impl_def_id` should be the
-/// `DefId` of a trait impl. To pass, either the trait must be local, or else
-/// two conditions must be satisfied:
-///
-/// 1. All type parameters in `Self` must be "covered" by some local type constructor.
-/// 2. Some local type must appear in `Self`.
-pub fn orphan_check(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Result<(), OrphanCheckErr<'_>> {
-    debug!("orphan_check({:?})", impl_def_id);
-
-    // We only except this routine to be invoked on implementations
-    // of a trait, not inherent implementations.
-    let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
-    debug!("orphan_check: trait_ref={:?}", trait_ref);
-
-    // If the *trait* is local to the crate, ok.
-    if trait_ref.def_id.is_local() {
-        debug!("trait {:?} is local to current crate", trait_ref.def_id);
-        return Ok(());
-    }
-
-    orphan_check_trait_ref(tcx, trait_ref, InCrate::Local)
-}
-
-/// Checks whether a trait-ref is potentially implementable by a crate.
-///
-/// The current rule is that a trait-ref orphan checks in a crate C:
-///
-/// 1. Order the parameters in the trait-ref in subst order - Self first,
-///    others linearly (e.g., `<U as Foo<V, W>>` is U < V < W).
-/// 2. Of these type parameters, there is at least one type parameter
-///    in which, walking the type as a tree, you can reach a type local
-///    to C where all types in-between are fundamental types. Call the
-///    first such parameter the "local key parameter".
-///     - e.g., `Box<LocalType>` is OK, because you can visit LocalType
-///       going through `Box`, which is fundamental.
-///     - similarly, `FundamentalPair<Vec<()>, Box<LocalType>>` is OK for
-///       the same reason.
-///     - but (knowing that `Vec<T>` is non-fundamental, and assuming it's
-///       not local), `Vec<LocalType>` is bad, because `Vec<->` is between
-///       the local type and the type parameter.
-/// 3. Every type parameter before the local key parameter is fully known in C.
-///     - e.g., `impl<T> T: Trait<LocalType>` is bad, because `T` might be
-///       an unknown type.
-///     - but `impl<T> LocalType: Trait<T>` is OK, because `LocalType`
-///       occurs before `T`.
-/// 4. Every type in the local key parameter not known in C, going
-///    through the parameter's type tree, must appear only as a subtree of
-///    a type local to C, with only fundamental types between the type
-///    local to C and the local key parameter.
-///     - e.g., `Vec<LocalType<T>>>` (or equivalently `Box<Vec<LocalType<T>>>`)
-///     is bad, because the only local type with `T` as a subtree is
-///     `LocalType<T>`, and `Vec<->` is between it and the type parameter.
-///     - similarly, `FundamentalPair<LocalType<T>, T>` is bad, because
-///     the second occurrence of `T` is not a subtree of *any* local type.
-///     - however, `LocalType<Vec<T>>` is OK, because `T` is a subtree of
-///     `LocalType<Vec<T>>`, which is local and has no types between it and
-///     the type parameter.
-///
-/// The orphan rules actually serve several different purposes:
-///
-/// 1. They enable link-safety - i.e., 2 mutually-unknowing crates (where
-///    every type local to one crate is unknown in the other) can't implement
-///    the same trait-ref. This follows because it can be seen that no such
-///    type can orphan-check in 2 such crates.
-///
-///    To check that a local impl follows the orphan rules, we check it in
-///    InCrate::Local mode, using type parameters for the "generic" types.
-///
-/// 2. They ground negative reasoning for coherence. If a user wants to
-///    write both a conditional blanket impl and a specific impl, we need to
-///    make sure they do not overlap. For example, if we write
-///    ```
-///    impl<T> IntoIterator for Vec<T>
-///    impl<T: Iterator> IntoIterator for T
-///    ```
-///    We need to be able to prove that `Vec<$0>: !Iterator` for every type $0.
-///    We can observe that this holds in the current crate, but we need to make
-///    sure this will also hold in all unknown crates (both "independent" crates,
-///    which we need for link-safety, and also child crates, because we don't want
-///    child crates to get error for impl conflicts in a *dependency*).
-///
-///    For that, we only allow negative reasoning if, for every assignment to the
-///    inference variables, every unknown crate would get an orphan error if they
-///    try to implement this trait-ref. To check for this, we use InCrate::Remote
-///    mode. That is sound because we already know all the impls from known crates.
-///
-/// 3. For non-#[fundamental] traits, they guarantee that parent crates can
-///    add "non-blanket" impls without breaking negative reasoning in dependent
-///    crates. This is the "rebalancing coherence" (RFC 1023) restriction.
-///
-///    For that, we only a allow crate to perform negative reasoning on
-///    non-local-non-#[fundamental] only if there's a local key parameter as per (2).
-///
-///    Because we never perform negative reasoning generically (coherence does
-///    not involve type parameters), this can be interpreted as doing the full
-///    orphan check (using InCrate::Local mode), substituting non-local known
-///    types for all inference variables.
-///
-///    This allows for crates to future-compatibly add impls as long as they
-///    can't apply to types with a key parameter in a child crate - applying
-///    the rules, this basically means that every type parameter in the impl
-///    must appear behind a non-fundamental type (because this is not a
-///    type-system requirement, crate owners might also go for "semantic
-///    future-compatibility" involving things such as sealed traits, but
-///    the above requirement is sufficient, and is necessary in "open world"
-///    cases).
-///
-/// Note that this function is never called for types that have both type
-/// parameters and inference variables.
-fn orphan_check_trait_ref<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    trait_ref: ty::TraitRef<'tcx>,
-    in_crate: InCrate,
-) -> Result<(), OrphanCheckErr<'tcx>> {
-    debug!("orphan_check_trait_ref(trait_ref={:?}, in_crate={:?})", trait_ref, in_crate);
-
-    if trait_ref.needs_infer() && trait_ref.needs_subst() {
-        bug!(
-            "can't orphan check a trait ref with both params and inference variables {:?}",
-            trait_ref
-        );
-    }
-
-    // Given impl<P1..=Pn> Trait<T1..=Tn> for T0, an impl is valid only
-    // if at least one of the following is true:
-    //
-    // - Trait is a local trait
-    // (already checked in orphan_check prior to calling this function)
-    // - All of
-    //     - At least one of the types T0..=Tn must be a local type.
-    //      Let Ti be the first such type.
-    //     - No uncovered type parameters P1..=Pn may appear in T0..Ti (excluding Ti)
-    //
-    fn uncover_fundamental_ty<'tcx>(
-        tcx: TyCtxt<'tcx>,
-        ty: Ty<'tcx>,
-        in_crate: InCrate,
-    ) -> Vec<Ty<'tcx>> {
-        if fundamental_ty(ty) && ty_is_non_local(ty, in_crate).is_some() {
-            ty.walk_shallow().flat_map(|ty| uncover_fundamental_ty(tcx, ty, in_crate)).collect()
-        } else {
-            vec![ty]
-        }
-    }
-
-    let mut non_local_spans = vec![];
-    for (i, input_ty) in
-        trait_ref.input_types().flat_map(|ty| uncover_fundamental_ty(tcx, ty, in_crate)).enumerate()
-    {
-        debug!("orphan_check_trait_ref: check ty `{:?}`", input_ty);
-        let non_local_tys = ty_is_non_local(input_ty, in_crate);
-        if non_local_tys.is_none() {
-            debug!("orphan_check_trait_ref: ty_is_local `{:?}`", input_ty);
-            return Ok(());
-        } else if let ty::Param(_) = input_ty.kind {
-            debug!("orphan_check_trait_ref: uncovered ty: `{:?}`", input_ty);
-            let local_type = trait_ref
-                .input_types()
-                .flat_map(|ty| uncover_fundamental_ty(tcx, ty, in_crate))
-                .find(|ty| ty_is_non_local_constructor(ty, in_crate).is_none());
-
-            debug!("orphan_check_trait_ref: uncovered ty local_type: `{:?}`", local_type);
-
-            return Err(OrphanCheckErr::UncoveredTy(input_ty, local_type));
-        }
-        if let Some(non_local_tys) = non_local_tys {
-            for input_ty in non_local_tys {
-                non_local_spans.push((input_ty, i == 0));
-            }
-        }
-    }
-    // If we exit above loop, never found a local type.
-    debug!("orphan_check_trait_ref: no local type");
-    Err(OrphanCheckErr::NonLocalInputType(non_local_spans))
-}
-
-fn ty_is_non_local<'t>(ty: Ty<'t>, in_crate: InCrate) -> Option<Vec<Ty<'t>>> {
-    match ty_is_non_local_constructor(ty, in_crate) {
-        Some(ty) => {
-            if !fundamental_ty(ty) {
-                Some(vec![ty])
-            } else {
-                let tys: Vec<_> = ty
-                    .walk_shallow()
-                    .filter_map(|t| ty_is_non_local(t, in_crate))
-                    .flat_map(|i| i)
-                    .collect();
-                if tys.is_empty() { None } else { Some(tys) }
-            }
-        }
-        None => None,
-    }
-}
-
-fn fundamental_ty(ty: Ty<'_>) -> bool {
-    match ty.kind {
-        ty::Ref(..) => true,
-        ty::Adt(def, _) => def.is_fundamental(),
-        _ => false,
-    }
-}
-
-fn def_id_is_local(def_id: DefId, in_crate: InCrate) -> bool {
-    match in_crate {
-        // The type is local to *this* crate - it will not be
-        // local in any other crate.
-        InCrate::Remote => false,
-        InCrate::Local => def_id.is_local(),
-    }
-}
-
-fn ty_is_non_local_constructor<'tcx>(ty: Ty<'tcx>, in_crate: InCrate) -> Option<Ty<'tcx>> {
-    debug!("ty_is_non_local_constructor({:?})", ty);
-
-    match ty.kind {
-        ty::Bool
-        | ty::Char
-        | ty::Int(..)
-        | ty::Uint(..)
-        | ty::Float(..)
-        | ty::Str
-        | ty::FnDef(..)
-        | ty::FnPtr(_)
-        | ty::Array(..)
-        | ty::Slice(..)
-        | ty::RawPtr(..)
-        | ty::Ref(..)
-        | ty::Never
-        | ty::Tuple(..)
-        | ty::Param(..)
-        | ty::Projection(..) => Some(ty),
-
-        ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) => match in_crate {
-            InCrate::Local => Some(ty),
-            // The inference variable might be unified with a local
-            // type in that remote crate.
-            InCrate::Remote => None,
-        },
-
-        ty::Adt(def, _) => {
-            if def_id_is_local(def.did, in_crate) {
-                None
-            } else {
-                Some(ty)
-            }
-        }
-        ty::Foreign(did) => {
-            if def_id_is_local(did, in_crate) {
-                None
-            } else {
-                Some(ty)
-            }
-        }
-        ty::Opaque(..) => {
-            // This merits some explanation.
-            // Normally, opaque types are not involed when performing
-            // coherence checking, since it is illegal to directly
-            // implement a trait on an opaque type. However, we might
-            // end up looking at an opaque type during coherence checking
-            // if an opaque type gets used within another type (e.g. as
-            // a type parameter). This requires us to decide whether or
-            // not an opaque type should be considered 'local' or not.
-            //
-            // We choose to treat all opaque types as non-local, even
-            // those that appear within the same crate. This seems
-            // somewhat suprising at first, but makes sense when
-            // you consider that opaque types are supposed to hide
-            // the underlying type *within the same crate*. When an
-            // opaque type is used from outside the module
-            // where it is declared, it should be impossible to observe
-            // anyything about it other than the traits that it implements.
-            //
-            // The alternative would be to look at the underlying type
-            // to determine whether or not the opaque type itself should
-            // be considered local. However, this could make it a breaking change
-            // to switch the underlying ('defining') type from a local type
-            // to a remote type. This would violate the rule that opaque
-            // types should be completely opaque apart from the traits
-            // that they implement, so we don't use this behavior.
-            Some(ty)
-        }
-
-        ty::Dynamic(ref tt, ..) => {
-            if let Some(principal) = tt.principal() {
-                if def_id_is_local(principal.def_id(), in_crate) { None } else { Some(ty) }
-            } else {
-                Some(ty)
-            }
-        }
-
-        ty::Error => None,
-
-        ty::UnnormalizedProjection(..)
-        | ty::Closure(..)
-        | ty::Generator(..)
-        | ty::GeneratorWitness(..) => bug!("ty_is_local invoked on unexpected type: {:?}", ty),
-    }
-}
index ba1443796162fdfad330ea6ef413afc7633ad328..9ad722342a19ebad877383914d9fb97fdedbd8bb 100644 (file)
@@ -1,9 +1,9 @@
 use crate::infer::InferCtxt;
 use crate::traits::Obligation;
-use rustc::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness};
+use rustc::ty::{self, ToPredicate, Ty, WithConstness};
 use rustc_hir::def_id::DefId;
 
-use super::{ChalkFulfillmentContext, FulfillmentContext, FulfillmentError};
+use super::FulfillmentError;
 use super::{ObligationCause, PredicateObligation};
 
 pub trait TraitEngine<'tcx>: 'tcx {
@@ -76,13 +76,3 @@ fn register_predicate_obligations(
         }
     }
 }
-
-impl dyn TraitEngine<'tcx> {
-    pub fn new(tcx: TyCtxt<'tcx>) -> Box<Self> {
-        if tcx.sess.opts.debugging_opts.chalk {
-            Box::new(ChalkFulfillmentContext::new())
-        } else {
-            Box::new(FulfillmentContext::new())
-        }
-    }
-}
index 471f388f0bb18036ca54fa38780f439f25f1485e..8943ce4e6c505c5f9d0abcef7f4ea8c19638d583 100644 (file)
-pub mod on_unimplemented;
-pub mod suggestions;
+use super::ObjectSafetyViolation;
 
-use super::{
-    ConstEvalFailure, EvaluationResult, FulfillmentError, FulfillmentErrorCode,
-    MismatchedProjectionTypes, ObjectSafetyViolation, Obligation, ObligationCause,
-    ObligationCauseCode, OnUnimplementedDirective, OnUnimplementedNote,
-    OutputTypeParameterMismatch, Overflow, PredicateObligation, SelectionContext, SelectionError,
-    TraitNotObjectSafe,
-};
-
-use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode};
-use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
-use crate::infer::{self, InferCtxt, TyCtxtInferExt};
-use rustc::mir::interpret::ErrorHandled;
-use rustc::session::DiagnosticMessageId;
-use rustc::ty::error::ExpectedFound;
-use rustc::ty::fast_reject;
-use rustc::ty::fold::TypeFolder;
-use rustc::ty::SubtypePredicate;
-use rustc::ty::{
-    self, AdtKind, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness,
-};
+use crate::infer::InferCtxt;
+use rustc::ty::TyCtxt;
 use rustc_ast::ast;
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
-use rustc_hir::def_id::{DefId, LOCAL_CRATE};
-use rustc_hir::{QPath, TyKind, WhereBoundPredicate, WherePredicate};
-use rustc_span::source_map::SourceMap;
-use rustc_span::{ExpnKind, Span, DUMMY_SP};
+use rustc_hir::def_id::DefId;
+use rustc_span::Span;
 use std::fmt;
 
 impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
-    pub fn report_fulfillment_errors(
-        &self,
-        errors: &[FulfillmentError<'tcx>],
-        body_id: Option<hir::BodyId>,
-        fallback_has_occurred: bool,
-    ) {
-        #[derive(Debug)]
-        struct ErrorDescriptor<'tcx> {
-            predicate: ty::Predicate<'tcx>,
-            index: Option<usize>, // None if this is an old error
-        }
-
-        let mut error_map: FxHashMap<_, Vec<_>> = self
-            .reported_trait_errors
-            .borrow()
-            .iter()
-            .map(|(&span, predicates)| {
-                (
-                    span,
-                    predicates
-                        .iter()
-                        .map(|&predicate| ErrorDescriptor { predicate, index: None })
-                        .collect(),
-                )
-            })
-            .collect();
-
-        for (index, error) in errors.iter().enumerate() {
-            // We want to ignore desugarings here: spans are equivalent even
-            // if one is the result of a desugaring and the other is not.
-            let mut span = error.obligation.cause.span;
-            let expn_data = span.ctxt().outer_expn_data();
-            if let ExpnKind::Desugaring(_) = expn_data.kind {
-                span = expn_data.call_site;
-            }
-
-            error_map.entry(span).or_default().push(ErrorDescriptor {
-                predicate: error.obligation.predicate,
-                index: Some(index),
-            });
-
-            self.reported_trait_errors
-                .borrow_mut()
-                .entry(span)
-                .or_default()
-                .push(error.obligation.predicate.clone());
-        }
-
-        // We do this in 2 passes because we want to display errors in order, though
-        // maybe it *is* better to sort errors by span or something.
-        let mut is_suppressed = vec![false; errors.len()];
-        for (_, error_set) in error_map.iter() {
-            // We want to suppress "duplicate" errors with the same span.
-            for error in error_set {
-                if let Some(index) = error.index {
-                    // Suppress errors that are either:
-                    // 1) strictly implied by another error.
-                    // 2) implied by an error with a smaller index.
-                    for error2 in error_set {
-                        if error2.index.map_or(false, |index2| is_suppressed[index2]) {
-                            // Avoid errors being suppressed by already-suppressed
-                            // errors, to prevent all errors from being suppressed
-                            // at once.
-                            continue;
-                        }
-
-                        if self.error_implies(&error2.predicate, &error.predicate)
-                            && !(error2.index >= error.index
-                                && self.error_implies(&error.predicate, &error2.predicate))
-                        {
-                            info!("skipping {:?} (implied by {:?})", error, error2);
-                            is_suppressed[index] = true;
-                            break;
-                        }
-                    }
-                }
-            }
-        }
-
-        for (error, suppressed) in errors.iter().zip(is_suppressed) {
-            if !suppressed {
-                self.report_fulfillment_error(error, body_id, fallback_has_occurred);
-            }
-        }
-    }
-
-    // returns if `cond` not occurring implies that `error` does not occur - i.e., that
-    // `error` occurring implies that `cond` occurs.
-    fn error_implies(&self, cond: &ty::Predicate<'tcx>, error: &ty::Predicate<'tcx>) -> bool {
-        if cond == error {
-            return true;
-        }
-
-        let (cond, error) = match (cond, error) {
-            (&ty::Predicate::Trait(..), &ty::Predicate::Trait(ref error, _)) => (cond, error),
-            _ => {
-                // FIXME: make this work in other cases too.
-                return false;
-            }
-        };
-
-        for implication in super::elaborate_predicates(self.tcx, vec![*cond]) {
-            if let ty::Predicate::Trait(implication, _) = implication {
-                let error = error.to_poly_trait_ref();
-                let implication = implication.to_poly_trait_ref();
-                // FIXME: I'm just not taking associated types at all here.
-                // Eventually I'll need to implement param-env-aware
-                // `Γ₁ ⊦ φ₁ => Γ₂ ⊦ φ₂` logic.
-                let param_env = ty::ParamEnv::empty();
-                if self.can_sub(param_env, error, implication).is_ok() {
-                    debug!("error_implies: {:?} -> {:?} -> {:?}", cond, error, implication);
-                    return true;
-                }
-            }
-        }
-
-        false
-    }
-
-    fn report_fulfillment_error(
-        &self,
-        error: &FulfillmentError<'tcx>,
-        body_id: Option<hir::BodyId>,
-        fallback_has_occurred: bool,
-    ) {
-        debug!("report_fulfillment_error({:?})", error);
-        match error.code {
-            FulfillmentErrorCode::CodeSelectionError(ref selection_error) => {
-                self.report_selection_error(
-                    &error.obligation,
-                    selection_error,
-                    fallback_has_occurred,
-                    error.points_at_arg_span,
-                );
-            }
-            FulfillmentErrorCode::CodeProjectionError(ref e) => {
-                self.report_projection_error(&error.obligation, e);
-            }
-            FulfillmentErrorCode::CodeAmbiguity => {
-                self.maybe_report_ambiguity(&error.obligation, body_id);
-            }
-            FulfillmentErrorCode::CodeSubtypeError(ref expected_found, ref err) => {
-                self.report_mismatched_types(
-                    &error.obligation.cause,
-                    expected_found.expected,
-                    expected_found.found,
-                    err.clone(),
-                )
-                .emit();
-            }
-        }
-    }
-
-    fn report_projection_error(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        error: &MismatchedProjectionTypes<'tcx>,
-    ) {
-        let predicate = self.resolve_vars_if_possible(&obligation.predicate);
-
-        if predicate.references_error() {
-            return;
-        }
-
-        self.probe(|_| {
-            let err_buf;
-            let mut err = &error.err;
-            let mut values = None;
-
-            // try to find the mismatched types to report the error with.
-            //
-            // this can fail if the problem was higher-ranked, in which
-            // cause I have no idea for a good error message.
-            if let ty::Predicate::Projection(ref data) = predicate {
-                let mut selcx = SelectionContext::new(self);
-                let (data, _) = self.replace_bound_vars_with_fresh_vars(
-                    obligation.cause.span,
-                    infer::LateBoundRegionConversionTime::HigherRankedType,
-                    data,
-                );
-                let mut obligations = vec![];
-                let normalized_ty = super::normalize_projection_type(
-                    &mut selcx,
-                    obligation.param_env,
-                    data.projection_ty,
-                    obligation.cause.clone(),
-                    0,
-                    &mut obligations,
-                );
-
-                debug!(
-                    "report_projection_error obligation.cause={:?} obligation.param_env={:?}",
-                    obligation.cause, obligation.param_env
-                );
-
-                debug!(
-                    "report_projection_error normalized_ty={:?} data.ty={:?}",
-                    normalized_ty, data.ty
-                );
-
-                let is_normalized_ty_expected = match &obligation.cause.code {
-                    ObligationCauseCode::ItemObligation(_)
-                    | ObligationCauseCode::BindingObligation(_, _)
-                    | ObligationCauseCode::ObjectCastObligation(_) => false,
-                    _ => true,
-                };
-
-                if let Err(error) = self.at(&obligation.cause, obligation.param_env).eq_exp(
-                    is_normalized_ty_expected,
-                    normalized_ty,
-                    data.ty,
-                ) {
-                    values = Some(infer::ValuePairs::Types(ExpectedFound::new(
-                        is_normalized_ty_expected,
-                        normalized_ty,
-                        data.ty,
-                    )));
-
-                    err_buf = error;
-                    err = &err_buf;
-                }
-            }
-
-            let msg = format!("type mismatch resolving `{}`", predicate);
-            let error_id = (DiagnosticMessageId::ErrorId(271), Some(obligation.cause.span), msg);
-            let fresh = self.tcx.sess.one_time_diagnostics.borrow_mut().insert(error_id);
-            if fresh {
-                let mut diag = struct_span_err!(
-                    self.tcx.sess,
-                    obligation.cause.span,
-                    E0271,
-                    "type mismatch resolving `{}`",
-                    predicate
-                );
-                self.note_type_err(&mut diag, &obligation.cause, None, values, err);
-                self.note_obligation_cause(&mut diag, obligation);
-                diag.emit();
-            }
-        });
-    }
-
-    fn fuzzy_match_tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
-        /// returns the fuzzy category of a given type, or None
-        /// if the type can be equated to any type.
-        fn type_category(t: Ty<'_>) -> Option<u32> {
-            match t.kind {
-                ty::Bool => Some(0),
-                ty::Char => Some(1),
-                ty::Str => Some(2),
-                ty::Int(..) | ty::Uint(..) | ty::Infer(ty::IntVar(..)) => Some(3),
-                ty::Float(..) | ty::Infer(ty::FloatVar(..)) => Some(4),
-                ty::Ref(..) | ty::RawPtr(..) => Some(5),
-                ty::Array(..) | ty::Slice(..) => Some(6),
-                ty::FnDef(..) | ty::FnPtr(..) => Some(7),
-                ty::Dynamic(..) => Some(8),
-                ty::Closure(..) => Some(9),
-                ty::Tuple(..) => Some(10),
-                ty::Projection(..) => Some(11),
-                ty::Param(..) => Some(12),
-                ty::Opaque(..) => Some(13),
-                ty::Never => Some(14),
-                ty::Adt(adt, ..) => match adt.adt_kind() {
-                    AdtKind::Struct => Some(15),
-                    AdtKind::Union => Some(16),
-                    AdtKind::Enum => Some(17),
-                },
-                ty::Generator(..) => Some(18),
-                ty::Foreign(..) => Some(19),
-                ty::GeneratorWitness(..) => Some(20),
-                ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error => None,
-                ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
-            }
-        }
-
-        match (type_category(a), type_category(b)) {
-            (Some(cat_a), Some(cat_b)) => match (&a.kind, &b.kind) {
-                (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => def_a == def_b,
-                _ => cat_a == cat_b,
-            },
-            // infer and error can be equated to all types
-            _ => true,
-        }
-    }
-
-    fn describe_generator(&self, body_id: hir::BodyId) -> Option<&'static str> {
-        self.tcx.hir().body(body_id).generator_kind.map(|gen_kind| match gen_kind {
-            hir::GeneratorKind::Gen => "a generator",
-            hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block) => "an async block",
-            hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Fn) => "an async function",
-            hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Closure) => "an async closure",
-        })
-    }
-
-    fn find_similar_impl_candidates(
-        &self,
-        trait_ref: ty::PolyTraitRef<'tcx>,
-    ) -> Vec<ty::TraitRef<'tcx>> {
-        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);
-                    if let Some(imp_simp) = imp_simp {
-                        if simp != imp_simp {
-                            return None;
-                        }
-                    }
-
-                    Some(imp)
-                })
-                .collect(),
-            None => {
-                all_impls.iter().map(|&def_id| self.tcx.impl_trait_ref(def_id).unwrap()).collect()
-            }
-        }
-    }
-
-    fn report_similar_impl_candidates(
-        &self,
-        impl_candidates: Vec<ty::TraitRef<'tcx>>,
-        err: &mut DiagnosticBuilder<'_>,
-    ) {
-        if impl_candidates.is_empty() {
-            return;
-        }
-
-        let len = impl_candidates.len();
-        let end = if impl_candidates.len() <= 5 { impl_candidates.len() } else { 4 };
-
-        let normalize = |candidate| {
-            self.tcx.infer_ctxt().enter(|ref infcx| {
-                let normalized = infcx
-                    .at(&ObligationCause::dummy(), ty::ParamEnv::empty())
-                    .normalize(candidate)
-                    .ok();
-                match normalized {
-                    Some(normalized) => format!("\n  {:?}", normalized.value),
-                    None => format!("\n  {:?}", candidate),
-                }
-            })
-        };
-
-        // Sort impl candidates so that ordering is consistent for UI tests.
-        let mut normalized_impl_candidates =
-            impl_candidates.iter().map(normalize).collect::<Vec<String>>();
-
-        // Sort before taking the `..end` range,
-        // because the ordering of `impl_candidates` may not be deterministic:
-        // https://github.com/rust-lang/rust/pull/57475#issuecomment-455519507
-        normalized_impl_candidates.sort();
-
-        err.help(&format!(
-            "the following implementations were found:{}{}",
-            normalized_impl_candidates[..end].join(""),
-            if len > 5 { format!("\nand {} others", len - 4) } else { String::new() }
-        ));
-    }
-
-    /// Reports that an overflow has occurred and halts compilation. We
-    /// halt compilation unconditionally because it is important that
-    /// overflows never be masked -- they basically represent computations
-    /// whose result could not be truly determined and thus we can't say
-    /// if the program type checks or not -- and they are unusual
-    /// occurrences in any case.
-    pub fn report_overflow_error<T>(
-        &self,
-        obligation: &Obligation<'tcx, T>,
-        suggest_increasing_limit: bool,
-    ) -> !
-    where
-        T: fmt::Display + TypeFoldable<'tcx>,
-    {
-        let predicate = self.resolve_vars_if_possible(&obligation.predicate);
-        let mut err = struct_span_err!(
-            self.tcx.sess,
-            obligation.cause.span,
-            E0275,
-            "overflow evaluating the requirement `{}`",
-            predicate
-        );
-
-        if suggest_increasing_limit {
-            self.suggest_new_overflow_limit(&mut err);
-        }
-
-        self.note_obligation_cause_code(
-            &mut err,
-            &obligation.predicate,
-            &obligation.cause.code,
-            &mut vec![],
-        );
-
-        err.emit();
-        self.tcx.sess.abort_if_errors();
-        bug!();
-    }
-
-    /// Reports that a cycle was detected which led to overflow and halts
-    /// compilation. This is equivalent to `report_overflow_error` except
-    /// that we can give a more helpful error message (and, in particular,
-    /// we do not suggest increasing the overflow limit, which is not
-    /// going to help).
-    pub fn report_overflow_error_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> ! {
-        let cycle = self.resolve_vars_if_possible(&cycle.to_owned());
-        assert!(!cycle.is_empty());
-
-        debug!("report_overflow_error_cycle: cycle={:?}", cycle);
-
-        self.report_overflow_error(&cycle[0], false);
-    }
-
     pub fn report_extra_impl_obligation(
         &self,
         error_span: Span,
@@ -469,559 +33,6 @@ pub fn report_extra_impl_obligation(
 
         err
     }
-
-    /// Gets the parent trait chain start
-    fn get_parent_trait_ref(
-        &self,
-        code: &ObligationCauseCode<'tcx>,
-    ) -> Option<(String, Option<Span>)> {
-        match code {
-            &ObligationCauseCode::BuiltinDerivedObligation(ref data) => {
-                let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref);
-                match self.get_parent_trait_ref(&data.parent_code) {
-                    Some(t) => Some(t),
-                    None => {
-                        let ty = parent_trait_ref.skip_binder().self_ty();
-                        let span =
-                            TyCategory::from_ty(ty).map(|(_, def_id)| self.tcx.def_span(def_id));
-                        Some((ty.to_string(), span))
-                    }
-                }
-            }
-            _ => None,
-        }
-    }
-
-    pub fn report_selection_error(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        error: &SelectionError<'tcx>,
-        fallback_has_occurred: bool,
-        points_at_arg: bool,
-    ) {
-        let tcx = self.tcx;
-        let span = obligation.cause.span;
-
-        let mut err = match *error {
-            SelectionError::Unimplemented => {
-                if let ObligationCauseCode::CompareImplMethodObligation {
-                    item_name,
-                    impl_item_def_id,
-                    trait_item_def_id,
-                }
-                | ObligationCauseCode::CompareImplTypeObligation {
-                    item_name,
-                    impl_item_def_id,
-                    trait_item_def_id,
-                } = obligation.cause.code
-                {
-                    self.report_extra_impl_obligation(
-                        span,
-                        item_name,
-                        impl_item_def_id,
-                        trait_item_def_id,
-                        &format!("`{}`", obligation.predicate),
-                    )
-                    .emit();
-                    return;
-                }
-                match obligation.predicate {
-                    ty::Predicate::Trait(ref trait_predicate, _) => {
-                        let trait_predicate = self.resolve_vars_if_possible(trait_predicate);
-
-                        if self.tcx.sess.has_errors() && trait_predicate.references_error() {
-                            return;
-                        }
-                        let trait_ref = trait_predicate.to_poly_trait_ref();
-                        let (post_message, pre_message, type_def) = self
-                            .get_parent_trait_ref(&obligation.cause.code)
-                            .map(|(t, s)| {
-                                (
-                                    format!(" in `{}`", t),
-                                    format!("within `{}`, ", t),
-                                    s.map(|s| (format!("within this `{}`", t), s)),
-                                )
-                            })
-                            .unwrap_or_default();
-
-                        let OnUnimplementedNote { message, label, note, enclosing_scope } =
-                            self.on_unimplemented_note(trait_ref, obligation);
-                        let have_alt_message = message.is_some() || label.is_some();
-                        let is_try = self
-                            .tcx
-                            .sess
-                            .source_map()
-                            .span_to_snippet(span)
-                            .map(|s| &s == "?")
-                            .unwrap_or(false);
-                        let is_from = format!("{}", trait_ref.print_only_trait_path())
-                            .starts_with("std::convert::From<");
-                        let (message, note) = if is_try && is_from {
-                            (
-                                Some(format!(
-                                    "`?` couldn't convert the error to `{}`",
-                                    trait_ref.self_ty(),
-                                )),
-                                Some(
-                                    "the question mark operation (`?`) implicitly performs a \
-                                     conversion on the error value using the `From` trait"
-                                        .to_owned(),
-                                ),
-                            )
-                        } else {
-                            (message, note)
-                        };
-
-                        let mut err = struct_span_err!(
-                            self.tcx.sess,
-                            span,
-                            E0277,
-                            "{}",
-                            message.unwrap_or_else(|| format!(
-                                "the trait bound `{}` is not satisfied{}",
-                                trait_ref.without_const().to_predicate(),
-                                post_message,
-                            ))
-                        );
-
-                        let explanation =
-                            if obligation.cause.code == ObligationCauseCode::MainFunctionType {
-                                "consider using `()`, or a `Result`".to_owned()
-                            } else {
-                                format!(
-                                    "{}the trait `{}` is not implemented for `{}`",
-                                    pre_message,
-                                    trait_ref.print_only_trait_path(),
-                                    trait_ref.self_ty(),
-                                )
-                            };
-
-                        if self.suggest_add_reference_to_arg(
-                            &obligation,
-                            &mut err,
-                            &trait_ref,
-                            points_at_arg,
-                            have_alt_message,
-                        ) {
-                            self.note_obligation_cause(&mut err, obligation);
-                            err.emit();
-                            return;
-                        }
-                        if let Some(ref s) = label {
-                            // If it has a custom `#[rustc_on_unimplemented]`
-                            // error message, let's display it as the label!
-                            err.span_label(span, s.as_str());
-                            err.help(&explanation);
-                        } else {
-                            err.span_label(span, explanation);
-                        }
-                        if let Some((msg, span)) = type_def {
-                            err.span_label(span, &msg);
-                        }
-                        if let Some(ref s) = note {
-                            // If it has a custom `#[rustc_on_unimplemented]` note, let's display it
-                            err.note(s.as_str());
-                        }
-                        if let Some(ref s) = enclosing_scope {
-                            let enclosing_scope_span = tcx.def_span(
-                                tcx.hir()
-                                    .opt_local_def_id(obligation.cause.body_id)
-                                    .unwrap_or_else(|| {
-                                        tcx.hir().body_owner_def_id(hir::BodyId {
-                                            hir_id: obligation.cause.body_id,
-                                        })
-                                    }),
-                            );
-
-                            err.span_label(enclosing_scope_span, s.as_str());
-                        }
-
-                        self.suggest_borrow_on_unsized_slice(&obligation.cause.code, &mut err);
-                        self.suggest_fn_call(&obligation, &mut err, &trait_ref, points_at_arg);
-                        self.suggest_remove_reference(&obligation, &mut err, &trait_ref);
-                        self.suggest_semicolon_removal(&obligation, &mut err, span, &trait_ref);
-                        self.note_version_mismatch(&mut err, &trait_ref);
-                        if self.suggest_impl_trait(&mut err, span, &obligation, &trait_ref) {
-                            err.emit();
-                            return;
-                        }
-
-                        // Try to report a help message
-                        if !trait_ref.has_infer_types()
-                            && self.predicate_can_apply(obligation.param_env, trait_ref)
-                        {
-                            // If a where-clause may be useful, remind the
-                            // user that they can add it.
-                            //
-                            // don't display an on-unimplemented note, as
-                            // 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,
-                            );
-                        }
-
-                        // If this error is due to `!: Trait` not implemented but `(): Trait` is
-                        // implemented, and fallback has occurred, then it could be due to a
-                        // variable that used to fallback to `()` now falling back to `!`. Issue a
-                        // note informing about the change in behaviour.
-                        if trait_predicate.skip_binder().self_ty().is_never()
-                            && fallback_has_occurred
-                        {
-                            let predicate = trait_predicate.map_bound(|mut trait_pred| {
-                                trait_pred.trait_ref.substs = self.tcx.mk_substs_trait(
-                                    self.tcx.mk_unit(),
-                                    &trait_pred.trait_ref.substs[1..],
-                                );
-                                trait_pred
-                            });
-                            let unit_obligation = Obligation {
-                                predicate: ty::Predicate::Trait(
-                                    predicate,
-                                    hir::Constness::NotConst,
-                                ),
-                                ..obligation.clone()
-                            };
-                            if self.predicate_may_hold(&unit_obligation) {
-                                err.note(
-                                    "the trait is implemented for `()`. \
-                                     Possibly this error has been caused by changes to \
-                                     Rust's type-inference algorithm (see issue #48950 \
-                                     <https://github.com/rust-lang/rust/issues/48950> \
-                                     for more information). Consider whether you meant to use \
-                                     the type `()` here instead.",
-                                );
-                            }
-                        }
-
-                        err
-                    }
-
-                    ty::Predicate::Subtype(ref predicate) => {
-                        // Errors for Subtype predicates show up as
-                        // `FulfillmentErrorCode::CodeSubtypeError`,
-                        // not selection error.
-                        span_bug!(span, "subtype requirement gave wrong error: `{:?}`", predicate)
-                    }
-
-                    ty::Predicate::RegionOutlives(ref predicate) => {
-                        let predicate = self.resolve_vars_if_possible(predicate);
-                        let err = self
-                            .region_outlives_predicate(&obligation.cause, &predicate)
-                            .err()
-                            .unwrap();
-                        struct_span_err!(
-                            self.tcx.sess,
-                            span,
-                            E0279,
-                            "the requirement `{}` is not satisfied (`{}`)",
-                            predicate,
-                            err,
-                        )
-                    }
-
-                    ty::Predicate::Projection(..) | ty::Predicate::TypeOutlives(..) => {
-                        let predicate = self.resolve_vars_if_possible(&obligation.predicate);
-                        struct_span_err!(
-                            self.tcx.sess,
-                            span,
-                            E0280,
-                            "the requirement `{}` is not satisfied",
-                            predicate
-                        )
-                    }
-
-                    ty::Predicate::ObjectSafe(trait_def_id) => {
-                        let violations = self.tcx.object_safety_violations(trait_def_id);
-                        report_object_safety_error(self.tcx, span, trait_def_id, violations)
-                    }
-
-                    ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => {
-                        let found_kind = self.closure_kind(closure_def_id, closure_substs).unwrap();
-                        let closure_span = self
-                            .tcx
-                            .sess
-                            .source_map()
-                            .def_span(self.tcx.hir().span_if_local(closure_def_id).unwrap());
-                        let hir_id = self.tcx.hir().as_local_hir_id(closure_def_id).unwrap();
-                        let mut err = struct_span_err!(
-                            self.tcx.sess,
-                            closure_span,
-                            E0525,
-                            "expected a closure that implements the `{}` trait, \
-                             but this closure only implements `{}`",
-                            kind,
-                            found_kind
-                        );
-
-                        err.span_label(
-                            closure_span,
-                            format!("this closure implements `{}`, not `{}`", found_kind, kind),
-                        );
-                        err.span_label(
-                            obligation.cause.span,
-                            format!("the requirement to implement `{}` derives from here", kind),
-                        );
-
-                        // Additional context information explaining why the closure only implements
-                        // a particular trait.
-                        if let Some(tables) = self.in_progress_tables {
-                            let tables = tables.borrow();
-                            match (found_kind, tables.closure_kind_origins().get(hir_id)) {
-                                (ty::ClosureKind::FnOnce, Some((span, name))) => {
-                                    err.span_label(
-                                        *span,
-                                        format!(
-                                            "closure is `FnOnce` because it moves the \
-                                         variable `{}` out of its environment",
-                                            name
-                                        ),
-                                    );
-                                }
-                                (ty::ClosureKind::FnMut, Some((span, name))) => {
-                                    err.span_label(
-                                        *span,
-                                        format!(
-                                            "closure is `FnMut` because it mutates the \
-                                         variable `{}` here",
-                                            name
-                                        ),
-                                    );
-                                }
-                                _ => {}
-                            }
-                        }
-
-                        err.emit();
-                        return;
-                    }
-
-                    ty::Predicate::WellFormed(ty) => {
-                        if !self.tcx.sess.opts.debugging_opts.chalk {
-                            // WF predicates cannot themselves make
-                            // errors. They can only block due to
-                            // ambiguity; otherwise, they always
-                            // degenerate into other obligations
-                            // (which may fail).
-                            span_bug!(span, "WF predicate not satisfied for {:?}", ty);
-                        } else {
-                            // FIXME: we'll need a better message which takes into account
-                            // which bounds actually failed to hold.
-                            self.tcx.sess.struct_span_err(
-                                span,
-                                &format!("the type `{}` is not well-formed (chalk)", ty),
-                            )
-                        }
-                    }
-
-                    ty::Predicate::ConstEvaluatable(..) => {
-                        // Errors for `ConstEvaluatable` predicates show up as
-                        // `SelectionError::ConstEvalFailure`,
-                        // not `Unimplemented`.
-                        span_bug!(
-                            span,
-                            "const-evaluatable requirement gave wrong error: `{:?}`",
-                            obligation
-                        )
-                    }
-                }
-            }
-
-            OutputTypeParameterMismatch(ref found_trait_ref, ref expected_trait_ref, _) => {
-                let found_trait_ref = self.resolve_vars_if_possible(&*found_trait_ref);
-                let expected_trait_ref = self.resolve_vars_if_possible(&*expected_trait_ref);
-
-                if expected_trait_ref.self_ty().references_error() {
-                    return;
-                }
-
-                let found_trait_ty = found_trait_ref.self_ty();
-
-                let found_did = match found_trait_ty.kind {
-                    ty::Closure(did, _) | ty::Foreign(did) | ty::FnDef(did, _) => Some(did),
-                    ty::Adt(def, _) => Some(def.did),
-                    _ => None,
-                };
-
-                let found_span = found_did
-                    .and_then(|did| 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()],
-                };
-
-                let expected_ty = expected_trait_ref.skip_binder().substs.type_at(1);
-                let expected = match expected_ty.kind {
-                    ty::Tuple(ref tys) => tys
-                        .iter()
-                        .map(|t| ArgKind::from_expected_ty(t.expect_ty(), Some(span)))
-                        .collect(),
-                    _ => vec![ArgKind::Arg("_".to_owned(), expected_ty.to_string())],
-                };
-
-                if found.len() == expected.len() {
-                    self.report_closure_arg_mismatch(
-                        span,
-                        found_span,
-                        found_trait_ref,
-                        expected_trait_ref,
-                    )
-                } else {
-                    let (closure_span, found) = found_did
-                        .and_then(|did| self.tcx.hir().get_if_local(did))
-                        .map(|node| {
-                            let (found_span, found) = self.get_fn_like_arguments(node);
-                            (Some(found_span), found)
-                        })
-                        .unwrap_or((found_span, found));
-
-                    self.report_arg_count_mismatch(
-                        span,
-                        closure_span,
-                        expected,
-                        found,
-                        found_trait_ty.is_closure(),
-                    )
-                }
-            }
-
-            TraitNotObjectSafe(did) => {
-                let violations = self.tcx.object_safety_violations(did);
-                report_object_safety_error(self.tcx, span, did, violations)
-            }
-
-            ConstEvalFailure(ErrorHandled::TooGeneric) => {
-                // In this instance, we have a const expression containing an unevaluated
-                // generic parameter. We have no idea whether this expression is valid or
-                // not (e.g. it might result in an error), but we don't want to just assume
-                // that it's okay, because that might result in post-monomorphisation time
-                // errors. The onus is really on the caller to provide values that it can
-                // prove are well-formed.
-                let mut err = self
-                    .tcx
-                    .sess
-                    .struct_span_err(span, "constant expression depends on a generic parameter");
-                // FIXME(const_generics): we should suggest to the user how they can resolve this
-                // issue. However, this is currently not actually possible
-                // (see https://github.com/rust-lang/rust/issues/66962#issuecomment-575907083).
-                err.note("this may fail depending on what value the parameter takes");
-                err
-            }
-
-            // Already reported in the query.
-            ConstEvalFailure(ErrorHandled::Reported) => {
-                self.tcx.sess.delay_span_bug(span, "constant in type had an ignored error");
-                return;
-            }
-
-            Overflow => {
-                bug!("overflow should be handled before the `report_selection_error` path");
-            }
-        };
-
-        self.note_obligation_cause(&mut err, obligation);
-        self.point_at_returns_when_relevant(&mut err, &obligation);
-
-        err.emit();
-    }
-
-    /// If the `Self` type of the unsatisfied trait `trait_ref` implements a trait
-    /// with the same path as `trait_ref`, a help message about
-    /// a probable version mismatch is added to `err`
-    fn note_version_mismatch(
-        &self,
-        err: &mut DiagnosticBuilder<'_>,
-        trait_ref: &ty::PolyTraitRef<'tcx>,
-    ) {
-        let get_trait_impl = |trait_def_id| {
-            let mut trait_impl = None;
-            self.tcx.for_each_relevant_impl(trait_def_id, trait_ref.self_ty(), |impl_def_id| {
-                if trait_impl.is_none() {
-                    trait_impl = Some(impl_def_id);
-                }
-            });
-            trait_impl
-        };
-        let required_trait_path = self.tcx.def_path_str(trait_ref.def_id());
-        let all_traits = self.tcx.all_traits(LOCAL_CRATE);
-        let traits_with_same_path: std::collections::BTreeSet<_> = all_traits
-            .iter()
-            .filter(|trait_def_id| **trait_def_id != trait_ref.def_id())
-            .filter(|trait_def_id| self.tcx.def_path_str(**trait_def_id) == required_trait_path)
-            .collect();
-        for trait_with_same_path in traits_with_same_path {
-            if let Some(impl_def_id) = get_trait_impl(*trait_with_same_path) {
-                let impl_span = self.tcx.def_span(impl_def_id);
-                err.span_help(impl_span, "trait impl with same name found");
-                let trait_crate = self.tcx.crate_name(trait_with_same_path.krate);
-                let crate_msg = format!(
-                    "perhaps two different versions of crate `{}` are being used?",
-                    trait_crate
-                );
-                err.note(&crate_msg);
-            }
-        }
-    }
-
-    fn mk_obligation_for_def_id(
-        &self,
-        def_id: DefId,
-        output_ty: Ty<'tcx>,
-        cause: ObligationCause<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
-    ) -> PredicateObligation<'tcx> {
-        let new_trait_ref =
-            ty::TraitRef { def_id, substs: self.tcx.mk_substs_trait(output_ty, &[]) };
-        Obligation::new(cause, param_env, new_trait_ref.without_const().to_predicate())
-    }
-}
-
-pub fn recursive_type_with_infinite_size_error(
-    tcx: TyCtxt<'tcx>,
-    type_def_id: DefId,
-) -> DiagnosticBuilder<'tcx> {
-    assert!(type_def_id.is_local());
-    let span = tcx.hir().span_if_local(type_def_id).unwrap();
-    let span = tcx.sess.source_map().def_span(span);
-    let mut err = struct_span_err!(
-        tcx.sess,
-        span,
-        E0072,
-        "recursive type `{}` has infinite size",
-        tcx.def_path_str(type_def_id)
-    );
-    err.span_label(span, "recursive type has infinite size");
-    err.help(&format!(
-        "insert indirection (e.g., a `Box`, `Rc`, or `&`) \
-                           at some point to make `{}` representable",
-        tcx.def_path_str(type_def_id)
-    ));
-    err
 }
 
 pub fn report_object_safety_error(
@@ -1093,560 +104,3 @@ pub fn report_object_safety_error(
 
     err
 }
-
-impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
-    fn maybe_report_ambiguity(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        body_id: Option<hir::BodyId>,
-    ) {
-        // Unable to successfully determine, probably means
-        // insufficient type information, but could mean
-        // ambiguous impls. The latter *ought* to be a
-        // coherence violation, so we don't report it here.
-
-        let predicate = self.resolve_vars_if_possible(&obligation.predicate);
-        let span = obligation.cause.span;
-
-        debug!(
-            "maybe_report_ambiguity(predicate={:?}, obligation={:?} body_id={:?}, code={:?})",
-            predicate, obligation, body_id, obligation.cause.code,
-        );
-
-        // Ambiguity errors are often caused as fallout from earlier
-        // errors. So just ignore them if this infcx is tainted.
-        if self.is_tainted_by_errors() {
-            return;
-        }
-
-        let mut err = match predicate {
-            ty::Predicate::Trait(ref data, _) => {
-                let trait_ref = data.to_poly_trait_ref();
-                let self_ty = trait_ref.self_ty();
-                debug!("self_ty {:?} {:?} trait_ref {:?}", self_ty, self_ty.kind, trait_ref);
-
-                if predicate.references_error() {
-                    return;
-                }
-                // Typically, this ambiguity should only happen if
-                // there are unresolved type inference variables
-                // (otherwise it would suggest a coherence
-                // failure). But given #21974 that is not necessarily
-                // the case -- we can have multiple where clauses that
-                // are only distinguished by a region, which results
-                // in an ambiguity even when all types are fully
-                // known, since we don't dispatch based on region
-                // relationships.
-
-                // This is kind of a hack: it frequently happens that some earlier
-                // error prevents types from being fully inferred, and then we get
-                // a bunch of uninteresting errors saying something like "<generic
-                // #0> doesn't implement Sized".  It may even be true that we
-                // could just skip over all checks where the self-ty is an
-                // inference variable, but I was afraid that there might be an
-                // inference variable created, registered as an obligation, and
-                // then never forced by writeback, and hence by skipping here we'd
-                // be ignoring the fact that we don't KNOW the type works
-                // out. Though even that would probably be harmless, given that
-                // we're only talking about builtin traits, which are known to be
-                // inhabited. We used to check for `self.tcx.sess.has_errors()` to
-                // avoid inundating the user with unnecessary errors, but we now
-                // check upstream for type errors and dont add the obligations to
-                // begin with in those cases.
-                if self
-                    .tcx
-                    .lang_items()
-                    .sized_trait()
-                    .map_or(false, |sized_id| sized_id == trait_ref.def_id())
-                {
-                    self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0282).emit();
-                    return;
-                }
-                let mut err = self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0283);
-                err.note(&format!("cannot resolve `{}`", predicate));
-                if let ObligationCauseCode::ItemObligation(def_id) = obligation.cause.code {
-                    self.suggest_fully_qualified_path(&mut err, def_id, span, trait_ref.def_id());
-                } else if let (
-                    Ok(ref snippet),
-                    ObligationCauseCode::BindingObligation(ref def_id, _),
-                ) =
-                    (self.tcx.sess.source_map().span_to_snippet(span), &obligation.cause.code)
-                {
-                    let generics = self.tcx.generics_of(*def_id);
-                    if !generics.params.is_empty() && !snippet.ends_with('>') {
-                        // FIXME: To avoid spurious suggestions in functions where type arguments
-                        // where already supplied, we check the snippet to make sure it doesn't
-                        // end with a turbofish. Ideally we would have access to a `PathSegment`
-                        // instead. Otherwise we would produce the following output:
-                        //
-                        // error[E0283]: type annotations needed
-                        //   --> $DIR/issue-54954.rs:3:24
-                        //    |
-                        // LL | const ARR_LEN: usize = Tt::const_val::<[i8; 123]>();
-                        //    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^
-                        //    |                        |
-                        //    |                        cannot infer type
-                        //    |                        help: consider specifying the type argument
-                        //    |                        in the function call:
-                        //    |                        `Tt::const_val::<[i8; 123]>::<T>`
-                        // ...
-                        // LL |     const fn const_val<T: Sized>() -> usize {
-                        //    |              --------- - required by this bound in `Tt::const_val`
-                        //    |
-                        //    = note: cannot resolve `_: Tt`
-
-                        err.span_suggestion(
-                            span,
-                            &format!(
-                                "consider specifying the type argument{} in the function call",
-                                if generics.params.len() > 1 { "s" } else { "" },
-                            ),
-                            format!(
-                                "{}::<{}>",
-                                snippet,
-                                generics
-                                    .params
-                                    .iter()
-                                    .map(|p| p.name.to_string())
-                                    .collect::<Vec<String>>()
-                                    .join(", ")
-                            ),
-                            Applicability::HasPlaceholders,
-                        );
-                    }
-                }
-                err
-            }
-
-            ty::Predicate::WellFormed(ty) => {
-                // Same hacky approach as above to avoid deluging user
-                // with error messages.
-                if ty.references_error() || self.tcx.sess.has_errors() {
-                    return;
-                }
-                self.need_type_info_err(body_id, span, ty, ErrorCode::E0282)
-            }
-
-            ty::Predicate::Subtype(ref data) => {
-                if data.references_error() || self.tcx.sess.has_errors() {
-                    // no need to overload user in such cases
-                    return;
-                }
-                let &SubtypePredicate { a_is_expected: _, a, b } = data.skip_binder();
-                // both must be type variables, or the other would've been instantiated
-                assert!(a.is_ty_var() && b.is_ty_var());
-                self.need_type_info_err(body_id, span, a, ErrorCode::E0282)
-            }
-            ty::Predicate::Projection(ref data) => {
-                let trait_ref = data.to_poly_trait_ref(self.tcx);
-                let self_ty = trait_ref.self_ty();
-                if predicate.references_error() {
-                    return;
-                }
-                let mut err = self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0284);
-                err.note(&format!("cannot resolve `{}`", predicate));
-                err
-            }
-
-            _ => {
-                if self.tcx.sess.has_errors() {
-                    return;
-                }
-                let mut err = struct_span_err!(
-                    self.tcx.sess,
-                    span,
-                    E0284,
-                    "type annotations needed: cannot resolve `{}`",
-                    predicate,
-                );
-                err.span_label(span, &format!("cannot resolve `{}`", predicate));
-                err
-            }
-        };
-        self.note_obligation_cause(&mut err, obligation);
-        err.emit();
-    }
-
-    /// Returns `true` if the trait predicate may apply for *some* assignment
-    /// to the type parameters.
-    fn predicate_can_apply(
-        &self,
-        param_env: ty::ParamEnv<'tcx>,
-        pred: ty::PolyTraitRef<'tcx>,
-    ) -> bool {
-        struct ParamToVarFolder<'a, 'tcx> {
-            infcx: &'a InferCtxt<'a, 'tcx>,
-            var_map: FxHashMap<Ty<'tcx>, Ty<'tcx>>,
-        }
-
-        impl<'a, 'tcx> TypeFolder<'tcx> for ParamToVarFolder<'a, 'tcx> {
-            fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
-                self.infcx.tcx
-            }
-
-            fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
-                if let ty::Param(ty::ParamTy { name, .. }) = ty.kind {
-                    let infcx = self.infcx;
-                    self.var_map.entry(ty).or_insert_with(|| {
-                        infcx.next_ty_var(TypeVariableOrigin {
-                            kind: TypeVariableOriginKind::TypeParameterDefinition(name, None),
-                            span: DUMMY_SP,
-                        })
-                    })
-                } else {
-                    ty.super_fold_with(self)
-                }
-            }
-        }
-
-        self.probe(|_| {
-            let mut selcx = SelectionContext::new(self);
-
-            let cleaned_pred =
-                pred.fold_with(&mut ParamToVarFolder { infcx: self, var_map: Default::default() });
-
-            let cleaned_pred = super::project::normalize(
-                &mut selcx,
-                param_env,
-                ObligationCause::dummy(),
-                &cleaned_pred,
-            )
-            .value;
-
-            let obligation = Obligation::new(
-                ObligationCause::dummy(),
-                param_env,
-                cleaned_pred.without_const().to_predicate(),
-            );
-
-            self.predicate_may_hold(&obligation)
-        })
-    }
-
-    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.maybe_note_obligation_cause_for_async_await(err, obligation) {
-            self.note_obligation_cause_code(
-                err,
-                &obligation.predicate,
-                &obligation.cause.code,
-                &mut vec![],
-            );
-            self.suggest_unsized_bound_if_applicable(err, obligation);
-        }
-    }
-
-    fn suggest_unsized_bound_if_applicable(
-        &self,
-        err: &mut DiagnosticBuilder<'_>,
-        obligation: &PredicateObligation<'tcx>,
-    ) {
-        if let (
-            ty::Predicate::Trait(pred, _),
-            ObligationCauseCode::BindingObligation(item_def_id, span),
-        ) = (&obligation.predicate, &obligation.cause.code)
-        {
-            if let (Some(generics), true) = (
-                self.tcx.hir().get_if_local(*item_def_id).as_ref().and_then(|n| n.generics()),
-                Some(pred.def_id()) == self.tcx.lang_items().sized_trait(),
-            ) {
-                for param in generics.params {
-                    if param.span == *span
-                        && !param.bounds.iter().any(|bound| {
-                            bound.trait_def_id() == self.tcx.lang_items().sized_trait()
-                        })
-                    {
-                        let (span, separator) = match param.bounds {
-                            [] => (span.shrink_to_hi(), ":"),
-                            [.., bound] => (bound.span().shrink_to_hi(), " + "),
-                        };
-                        err.span_suggestion(
-                            span,
-                            "consider relaxing the implicit `Sized` restriction",
-                            format!("{} ?Sized", separator),
-                            Applicability::MachineApplicable,
-                        );
-                        return;
-                    }
-                }
-            }
-        }
-    }
-
-    fn is_recursive_obligation(
-        &self,
-        obligated_types: &mut Vec<&ty::TyS<'tcx>>,
-        cause_code: &ObligationCauseCode<'tcx>,
-    ) -> bool {
-        if let ObligationCauseCode::BuiltinDerivedObligation(ref data) = cause_code {
-            let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref);
-
-            if obligated_types.iter().any(|ot| ot == &parent_trait_ref.skip_binder().self_ty()) {
-                return true;
-            }
-        }
-        false
-    }
-}
-
-/// Summarizes information
-#[derive(Clone)]
-pub enum ArgKind {
-    /// An argument of non-tuple type. Parameters are (name, ty)
-    Arg(String, String),
-
-    /// An argument of tuple type. For a "found" argument, the span is
-    /// the locationo in the source of the pattern. For a "expected"
-    /// argument, it will be None. The vector is a list of (name, ty)
-    /// strings for the components of the tuple.
-    Tuple(Option<Span>, Vec<(String, String)>),
-}
-
-impl ArgKind {
-    fn empty() -> ArgKind {
-        ArgKind::Arg("_".to_owned(), "_".to_owned())
-    }
-
-    /// Creates an `ArgKind` from the expected type of an
-    /// argument. It has no name (`_`) and an optional source span.
-    pub fn from_expected_ty(t: Ty<'_>, span: Option<Span>) -> ArgKind {
-        match t.kind {
-            ty::Tuple(ref tys) => ArgKind::Tuple(
-                span,
-                tys.iter().map(|ty| ("_".to_owned(), ty.to_string())).collect::<Vec<_>>(),
-            ),
-            _ => ArgKind::Arg("_".to_owned(), t.to_string()),
-        }
-    }
-}
-
-/// Suggest restricting a type param with a new bound.
-pub fn suggest_constraining_type_param(
-    tcx: TyCtxt<'_>,
-    generics: &hir::Generics<'_>,
-    err: &mut DiagnosticBuilder<'_>,
-    param_name: &str,
-    constraint: &str,
-    source_map: &SourceMap,
-    span: Span,
-    def_id: Option<DefId>,
-) -> bool {
-    const MSG_RESTRICT_BOUND_FURTHER: &str = "consider further restricting this bound with";
-    const MSG_RESTRICT_TYPE: &str = "consider restricting this type parameter with";
-    const MSG_RESTRICT_TYPE_FURTHER: &str = "consider further restricting this type parameter with";
-
-    let param = generics.params.iter().find(|p| p.name.ident().as_str() == param_name);
-
-    let param = if let Some(param) = param {
-        param
-    } else {
-        return false;
-    };
-
-    if def_id == tcx.lang_items().sized_trait() {
-        // Type parameters are already `Sized` by default.
-        err.span_label(param.span, &format!("this type parameter needs to be `{}`", constraint));
-        return true;
-    }
-
-    if param_name.starts_with("impl ") {
-        // If there's an `impl Trait` used in argument position, suggest
-        // restricting it:
-        //
-        //   fn foo(t: impl Foo) { ... }
-        //             --------
-        //             |
-        //             help: consider further restricting this bound with `+ Bar`
-        //
-        // Suggestion for tools in this case is:
-        //
-        //   fn foo(t: impl Foo) { ... }
-        //             --------
-        //             |
-        //             replace with: `impl Foo + Bar`
-
-        err.span_help(param.span, &format!("{} `+ {}`", MSG_RESTRICT_BOUND_FURTHER, constraint));
-
-        err.tool_only_span_suggestion(
-            param.span,
-            MSG_RESTRICT_BOUND_FURTHER,
-            format!("{} + {}", param_name, constraint),
-            Applicability::MachineApplicable,
-        );
-
-        return true;
-    }
-
-    if generics.where_clause.predicates.is_empty() {
-        if let Some(bounds_span) = param.bounds_span() {
-            // If user has provided some bounds, suggest restricting them:
-            //
-            //   fn foo<T: Foo>(t: T) { ... }
-            //             ---
-            //             |
-            //             help: consider further restricting this bound with `+ Bar`
-            //
-            // Suggestion for tools in this case is:
-            //
-            //   fn foo<T: Foo>(t: T) { ... }
-            //          --
-            //          |
-            //          replace with: `T: Bar +`
-
-            err.span_help(
-                bounds_span,
-                &format!("{} `+ {}`", MSG_RESTRICT_BOUND_FURTHER, constraint),
-            );
-
-            let span_hi = param.span.with_hi(span.hi());
-            let span_with_colon = source_map.span_through_char(span_hi, ':');
-
-            if span_hi != param.span && span_with_colon != span_hi {
-                err.tool_only_span_suggestion(
-                    span_with_colon,
-                    MSG_RESTRICT_BOUND_FURTHER,
-                    format!("{}: {} + ", param_name, constraint),
-                    Applicability::MachineApplicable,
-                );
-            }
-        } else {
-            // If user hasn't provided any bounds, suggest adding a new one:
-            //
-            //   fn foo<T>(t: T) { ... }
-            //          - help: consider restricting this type parameter with `T: Foo`
-
-            err.span_help(
-                param.span,
-                &format!("{} `{}: {}`", MSG_RESTRICT_TYPE, param_name, constraint),
-            );
-
-            err.tool_only_span_suggestion(
-                param.span,
-                MSG_RESTRICT_TYPE,
-                format!("{}: {}", param_name, constraint),
-                Applicability::MachineApplicable,
-            );
-        }
-
-        true
-    } else {
-        // This part is a bit tricky, because using the `where` clause user can
-        // provide zero, one or many bounds for the same type parameter, so we
-        // have following cases to consider:
-        //
-        // 1) When the type parameter has been provided zero bounds
-        //
-        //    Message:
-        //      fn foo<X, Y>(x: X, y: Y) where Y: Foo { ... }
-        //             - help: consider restricting this type parameter with `where X: Bar`
-        //
-        //    Suggestion:
-        //      fn foo<X, Y>(x: X, y: Y) where Y: Foo { ... }
-        //                                           - insert: `, X: Bar`
-        //
-        //
-        // 2) When the type parameter has been provided one bound
-        //
-        //    Message:
-        //      fn foo<T>(t: T) where T: Foo { ... }
-        //                            ^^^^^^
-        //                            |
-        //                            help: consider further restricting this bound with `+ Bar`
-        //
-        //    Suggestion:
-        //      fn foo<T>(t: T) where T: Foo { ... }
-        //                            ^^
-        //                            |
-        //                            replace with: `T: Bar +`
-        //
-        //
-        // 3) When the type parameter has been provided many bounds
-        //
-        //    Message:
-        //      fn foo<T>(t: T) where T: Foo, T: Bar {... }
-        //             - help: consider further restricting this type parameter with `where T: Zar`
-        //
-        //    Suggestion:
-        //      fn foo<T>(t: T) where T: Foo, T: Bar {... }
-        //                                          - insert: `, T: Zar`
-
-        let mut param_spans = Vec::new();
-
-        for predicate in generics.where_clause.predicates {
-            if let WherePredicate::BoundPredicate(WhereBoundPredicate {
-                span, bounded_ty, ..
-            }) = predicate
-            {
-                if let TyKind::Path(QPath::Resolved(_, path)) = &bounded_ty.kind {
-                    if let Some(segment) = path.segments.first() {
-                        if segment.ident.to_string() == param_name {
-                            param_spans.push(span);
-                        }
-                    }
-                }
-            }
-        }
-
-        let where_clause_span =
-            generics.where_clause.span_for_predicates_or_empty_place().shrink_to_hi();
-
-        match &param_spans[..] {
-            &[] => {
-                err.span_help(
-                    param.span,
-                    &format!("{} `where {}: {}`", MSG_RESTRICT_TYPE, param_name, constraint),
-                );
-
-                err.tool_only_span_suggestion(
-                    where_clause_span,
-                    MSG_RESTRICT_TYPE,
-                    format!(", {}: {}", param_name, constraint),
-                    Applicability::MachineApplicable,
-                );
-            }
-
-            &[&param_span] => {
-                err.span_help(
-                    param_span,
-                    &format!("{} `+ {}`", MSG_RESTRICT_BOUND_FURTHER, constraint),
-                );
-
-                let span_hi = param_span.with_hi(span.hi());
-                let span_with_colon = source_map.span_through_char(span_hi, ':');
-
-                if span_hi != param_span && span_with_colon != span_hi {
-                    err.tool_only_span_suggestion(
-                        span_with_colon,
-                        MSG_RESTRICT_BOUND_FURTHER,
-                        format!("{}: {} +", param_name, constraint),
-                        Applicability::MachineApplicable,
-                    );
-                }
-            }
-
-            _ => {
-                err.span_help(
-                    param.span,
-                    &format!(
-                        "{} `where {}: {}`",
-                        MSG_RESTRICT_TYPE_FURTHER, param_name, constraint,
-                    ),
-                );
-
-                err.tool_only_span_suggestion(
-                    where_clause_span,
-                    MSG_RESTRICT_BOUND_FURTHER,
-                    format!(", {}: {}", param_name, constraint),
-                    Applicability::MachineApplicable,
-                );
-            }
-        }
-
-        true
-    }
-}
diff --git a/src/librustc_infer/traits/error_reporting/on_unimplemented.rs b/src/librustc_infer/traits/error_reporting/on_unimplemented.rs
deleted file mode 100644 (file)
index 87c1107..0000000
+++ /dev/null
@@ -1,223 +0,0 @@
-use super::{
-    ObligationCauseCode, OnUnimplementedDirective, OnUnimplementedNote, PredicateObligation,
-};
-use crate::infer::InferCtxt;
-use rustc::ty::subst::Subst;
-use rustc::ty::{self, GenericParamDefKind};
-use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
-use rustc_span::symbol::sym;
-
-impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
-    fn impl_similar_to(
-        &self,
-        trait_ref: ty::PolyTraitRef<'tcx>,
-        obligation: &PredicateObligation<'tcx>,
-    ) -> Option<DefId> {
-        let tcx = self.tcx;
-        let param_env = obligation.param_env;
-        let trait_ref = tcx.erase_late_bound_regions(&trait_ref);
-        let trait_self_ty = trait_ref.self_ty();
-
-        let mut self_match_impls = vec![];
-        let mut fuzzy_match_impls = vec![];
-
-        self.tcx.for_each_relevant_impl(trait_ref.def_id, trait_self_ty, |def_id| {
-            let impl_substs = self.fresh_substs_for_item(obligation.cause.span, def_id);
-            let impl_trait_ref = tcx.impl_trait_ref(def_id).unwrap().subst(tcx, impl_substs);
-
-            let impl_self_ty = impl_trait_ref.self_ty();
-
-            if let Ok(..) = self.can_eq(param_env, trait_self_ty, impl_self_ty) {
-                self_match_impls.push(def_id);
-
-                if trait_ref
-                    .substs
-                    .types()
-                    .skip(1)
-                    .zip(impl_trait_ref.substs.types().skip(1))
-                    .all(|(u, v)| self.fuzzy_match_tys(u, v))
-                {
-                    fuzzy_match_impls.push(def_id);
-                }
-            }
-        });
-
-        let impl_def_id = if self_match_impls.len() == 1 {
-            self_match_impls[0]
-        } else if fuzzy_match_impls.len() == 1 {
-            fuzzy_match_impls[0]
-        } else {
-            return None;
-        };
-
-        tcx.has_attr(impl_def_id, sym::rustc_on_unimplemented).then_some(impl_def_id)
-    }
-
-    /// Used to set on_unimplemented's `ItemContext`
-    /// to be the enclosing (async) block/function/closure
-    fn describe_enclosure(&self, hir_id: hir::HirId) -> Option<&'static str> {
-        let hir = &self.tcx.hir();
-        let node = hir.find(hir_id)?;
-        match &node {
-            hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, _, body_id), .. }) => {
-                self.describe_generator(*body_id).or_else(|| {
-                    Some(if let hir::FnHeader { asyncness: hir::IsAsync::Async, .. } = sig.header {
-                        "an async function"
-                    } else {
-                        "a function"
-                    })
-                })
-            }
-            hir::Node::TraitItem(hir::TraitItem {
-                kind: hir::TraitItemKind::Method(_, hir::TraitMethod::Provided(body_id)),
-                ..
-            }) => self.describe_generator(*body_id).or_else(|| Some("a trait method")),
-            hir::Node::ImplItem(hir::ImplItem {
-                kind: hir::ImplItemKind::Method(sig, body_id),
-                ..
-            }) => self.describe_generator(*body_id).or_else(|| {
-                Some(if let hir::FnHeader { asyncness: hir::IsAsync::Async, .. } = sig.header {
-                    "an async method"
-                } else {
-                    "a method"
-                })
-            }),
-            hir::Node::Expr(hir::Expr {
-                kind: hir::ExprKind::Closure(_is_move, _, body_id, _, gen_movability),
-                ..
-            }) => self.describe_generator(*body_id).or_else(|| {
-                Some(if gen_movability.is_some() { "an async closure" } else { "a closure" })
-            }),
-            hir::Node::Expr(hir::Expr { .. }) => {
-                let parent_hid = hir.get_parent_node(hir_id);
-                if parent_hid != hir_id {
-                    return self.describe_enclosure(parent_hid);
-                } else {
-                    None
-                }
-            }
-            _ => None,
-        }
-    }
-
-    crate fn on_unimplemented_note(
-        &self,
-        trait_ref: ty::PolyTraitRef<'tcx>,
-        obligation: &PredicateObligation<'tcx>,
-    ) -> OnUnimplementedNote {
-        let def_id =
-            self.impl_similar_to(trait_ref, obligation).unwrap_or_else(|| trait_ref.def_id());
-        let trait_ref = *trait_ref.skip_binder();
-
-        let mut flags = vec![];
-        flags.push((
-            sym::item_context,
-            self.describe_enclosure(obligation.cause.body_id).map(|s| s.to_owned()),
-        ));
-
-        match obligation.cause.code {
-            ObligationCauseCode::BuiltinDerivedObligation(..)
-            | ObligationCauseCode::ImplDerivedObligation(..) => {}
-            _ => {
-                // this is a "direct", user-specified, rather than derived,
-                // obligation.
-                flags.push((sym::direct, None));
-            }
-        }
-
-        if let ObligationCauseCode::ItemObligation(item) = obligation.cause.code {
-            // FIXME: maybe also have some way of handling methods
-            // from other traits? That would require name resolution,
-            // which we might want to be some sort of hygienic.
-            //
-            // Currently I'm leaving it for what I need for `try`.
-            if self.tcx.trait_of_item(item) == Some(trait_ref.def_id) {
-                let method = self.tcx.item_name(item);
-                flags.push((sym::from_method, None));
-                flags.push((sym::from_method, Some(method.to_string())));
-            }
-        }
-        if let Some((t, _)) = self.get_parent_trait_ref(&obligation.cause.code) {
-            flags.push((sym::parent_trait, Some(t)));
-        }
-
-        if let Some(k) = obligation.cause.span.desugaring_kind() {
-            flags.push((sym::from_desugaring, None));
-            flags.push((sym::from_desugaring, Some(format!("{:?}", k))));
-        }
-        let generics = self.tcx.generics_of(def_id);
-        let self_ty = trait_ref.self_ty();
-        // This is also included through the generics list as `Self`,
-        // but the parser won't allow you to use it
-        flags.push((sym::_Self, Some(self_ty.to_string())));
-        if let Some(def) = self_ty.ty_adt_def() {
-            // We also want to be able to select self's original
-            // signature with no type arguments resolved
-            flags.push((sym::_Self, Some(self.tcx.type_of(def.did).to_string())));
-        }
-
-        for param in generics.params.iter() {
-            let value = match param.kind {
-                GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => {
-                    trait_ref.substs[param.index as usize].to_string()
-                }
-                GenericParamDefKind::Lifetime => continue,
-            };
-            let name = param.name;
-            flags.push((name, Some(value)));
-        }
-
-        if let Some(true) = self_ty.ty_adt_def().map(|def| def.did.is_local()) {
-            flags.push((sym::crate_local, None));
-        }
-
-        // Allow targeting all integers using `{integral}`, even if the exact type was resolved
-        if self_ty.is_integral() {
-            flags.push((sym::_Self, Some("{integral}".to_owned())));
-        }
-
-        if let ty::Array(aty, len) = self_ty.kind {
-            flags.push((sym::_Self, Some("[]".to_owned())));
-            flags.push((sym::_Self, Some(format!("[{}]", aty))));
-            if let Some(def) = aty.ty_adt_def() {
-                // We also want to be able to select the array's type's original
-                // signature with no type arguments resolved
-                flags.push((
-                    sym::_Self,
-                    Some(format!("[{}]", self.tcx.type_of(def.did).to_string())),
-                ));
-                let tcx = self.tcx;
-                if let Some(len) = len.try_eval_usize(tcx, ty::ParamEnv::empty()) {
-                    flags.push((
-                        sym::_Self,
-                        Some(format!("[{}; {}]", self.tcx.type_of(def.did).to_string(), len)),
-                    ));
-                } else {
-                    flags.push((
-                        sym::_Self,
-                        Some(format!("[{}; _]", self.tcx.type_of(def.did).to_string())),
-                    ));
-                }
-            }
-        }
-        if let ty::Dynamic(traits, _) = self_ty.kind {
-            for t in *traits.skip_binder() {
-                match t {
-                    ty::ExistentialPredicate::Trait(trait_ref) => {
-                        flags.push((sym::_Self, Some(self.tcx.def_path_str(trait_ref.def_id))))
-                    }
-                    _ => {}
-                }
-            }
-        }
-
-        if let Ok(Some(command)) =
-            OnUnimplementedDirective::of_item(self.tcx, trait_ref.def_id, def_id)
-        {
-            command.evaluate(self.tcx, trait_ref, &flags[..])
-        } else {
-            OnUnimplementedNote::default()
-        }
-    }
-}
diff --git a/src/librustc_infer/traits/error_reporting/suggestions.rs b/src/librustc_infer/traits/error_reporting/suggestions.rs
deleted file mode 100644 (file)
index f1206dd..0000000
+++ /dev/null
@@ -1,1711 +0,0 @@
-use super::{
-    ArgKind, EvaluationResult, Obligation, ObligationCause, ObligationCauseCode,
-    PredicateObligation,
-};
-
-use crate::infer::InferCtxt;
-use crate::traits::error_reporting::suggest_constraining_type_param;
-
-use rustc::ty::TypeckTables;
-use rustc::ty::{self, AdtKind, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
-use rustc_errors::{
-    error_code, pluralize, struct_span_err, Applicability, DiagnosticBuilder, Style,
-};
-use rustc_hir as hir;
-use rustc_hir::def::DefKind;
-use rustc_hir::def_id::DefId;
-use rustc_hir::intravisit::Visitor;
-use rustc_hir::Node;
-use rustc_span::symbol::{kw, sym};
-use rustc_span::{MultiSpan, Span, DUMMY_SP};
-use std::fmt;
-
-impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
-    crate fn suggest_restricting_param_bound(
-        &self,
-        mut 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 suggest_restriction =
-            |generics: &hir::Generics<'_>, msg, err: &mut DiagnosticBuilder<'_>| {
-                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.without_const().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`", err);
-                    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", err);
-                    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 param_name = self_ty.to_string();
-                    let constraint = trait_ref.print_only_trait_path().to_string();
-                    if suggest_constraining_type_param(
-                        self.tcx,
-                        generics,
-                        &mut err,
-                        &param_name,
-                        &constraint,
-                        self.tcx.sess.source_map(),
-                        *span,
-                        Some(trait_ref.def_id()),
-                    ) {
-                        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.
-    crate fn suggest_borrow_on_unsized_slice(
-        &self,
-        code: &ObligationCauseCode<'tcx>,
-        err: &mut DiagnosticBuilder<'tcx>,
-    ) {
-        if let &ObligationCauseCode::VariableType(hir_id) = code {
-            let parent_node = self.tcx.hir().get_parent_node(hir_id);
-            if let Some(Node::Local(ref local)) = self.tcx.hir().find(parent_node) {
-                if let Some(ref expr) = local.init {
-                    if let hir::ExprKind::Index(_, _) = expr.kind {
-                        if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(expr.span) {
-                            err.span_suggestion(
-                                expr.span,
-                                "consider borrowing here",
-                                format!("&{}", snippet),
-                                Applicability::MachineApplicable,
-                            );
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    /// Given a closure's `DefId`, return the given name of the closure.
-    ///
-    /// This doesn't account for reassignments, but it's only used for suggestions.
-    crate fn get_closure_name(
-        &self,
-        def_id: DefId,
-        err: &mut DiagnosticBuilder<'_>,
-        msg: &str,
-    ) -> Option<String> {
-        let get_name =
-            |err: &mut DiagnosticBuilder<'_>, kind: &hir::PatKind<'_>| -> Option<String> {
-                // Get the local name of this closure. This can be inaccurate because
-                // of the possibility of reassignment, but this should be good enough.
-                match &kind {
-                    hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, _, name, None) => {
-                        Some(format!("{}", name))
-                    }
-                    _ => {
-                        err.note(&msg);
-                        None
-                    }
-                }
-            };
-
-        let hir = self.tcx.hir();
-        let hir_id = hir.as_local_hir_id(def_id)?;
-        let parent_node = hir.get_parent_node(hir_id);
-        match hir.find(parent_node) {
-            Some(hir::Node::Stmt(hir::Stmt { kind: hir::StmtKind::Local(local), .. })) => {
-                get_name(err, &local.pat.kind)
-            }
-            // Different to previous arm because one is `&hir::Local` and the other
-            // is `P<hir::Local>`.
-            Some(hir::Node::Local(local)) => get_name(err, &local.pat.kind),
-            _ => return None,
-        }
-    }
-
-    /// We tried to apply the bound to an `fn` or closure. Check whether calling it would
-    /// evaluate to a type that *would* satisfy the trait binding. If it would, suggest calling
-    /// it: `bar(foo)` → `bar(foo())`. This case is *very* likely to be hit if `foo` is `async`.
-    crate fn suggest_fn_call(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        err: &mut DiagnosticBuilder<'_>,
-        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
-        points_at_arg: bool,
-    ) {
-        let self_ty = trait_ref.self_ty();
-        let (def_id, output_ty, callable) = match self_ty.kind {
-            ty::Closure(def_id, substs) => {
-                (def_id, self.closure_sig(def_id, substs).output(), "closure")
-            }
-            ty::FnDef(def_id, _) => (def_id, self_ty.fn_sig(self.tcx).output(), "function"),
-            _ => return,
-        };
-        let msg = format!("use parentheses to call the {}", callable);
-
-        let obligation = self.mk_obligation_for_def_id(
-            trait_ref.def_id(),
-            output_ty.skip_binder(),
-            obligation.cause.clone(),
-            obligation.param_env,
-        );
-
-        match self.evaluate_obligation(&obligation) {
-            Ok(EvaluationResult::EvaluatedToOk)
-            | Ok(EvaluationResult::EvaluatedToOkModuloRegions)
-            | Ok(EvaluationResult::EvaluatedToAmbig) => {}
-            _ => return,
-        }
-        let hir = self.tcx.hir();
-        // Get the name of the callable and the arguments to be used in the suggestion.
-        let snippet = match hir.get_if_local(def_id) {
-            Some(hir::Node::Expr(hir::Expr {
-                kind: hir::ExprKind::Closure(_, decl, _, span, ..),
-                ..
-            })) => {
-                err.span_label(*span, "consider calling this closure");
-                let name = match self.get_closure_name(def_id, err, &msg) {
-                    Some(name) => name,
-                    None => return,
-                };
-                let args = decl.inputs.iter().map(|_| "_").collect::<Vec<_>>().join(", ");
-                format!("{}({})", name, args)
-            }
-            Some(hir::Node::Item(hir::Item {
-                ident,
-                kind: hir::ItemKind::Fn(.., body_id),
-                ..
-            })) => {
-                err.span_label(ident.span, "consider calling this function");
-                let body = hir.body(*body_id);
-                let args = body
-                    .params
-                    .iter()
-                    .map(|arg| match &arg.pat.kind {
-                        hir::PatKind::Binding(_, _, ident, None)
-                        // FIXME: provide a better suggestion when encountering `SelfLower`, it
-                        // should suggest a method call.
-                        if ident.name != kw::SelfLower => ident.to_string(),
-                        _ => "_".to_string(),
-                    })
-                    .collect::<Vec<_>>()
-                    .join(", ");
-                format!("{}({})", ident, args)
-            }
-            _ => return,
-        };
-        if points_at_arg {
-            // When the obligation error has been ensured to have been caused by
-            // an argument, the `obligation.cause.span` points at the expression
-            // of the argument, so we can provide a suggestion. This is signaled
-            // by `points_at_arg`. Otherwise, we give a more general note.
-            err.span_suggestion(
-                obligation.cause.span,
-                &msg,
-                snippet,
-                Applicability::HasPlaceholders,
-            );
-        } else {
-            err.help(&format!("{}: `{}`", msg, snippet));
-        }
-    }
-
-    crate fn suggest_add_reference_to_arg(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        err: &mut DiagnosticBuilder<'tcx>,
-        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
-        points_at_arg: bool,
-        has_custom_message: bool,
-    ) -> bool {
-        if !points_at_arg {
-            return false;
-        }
-
-        let span = obligation.cause.span;
-        let param_env = obligation.param_env;
-        let trait_ref = trait_ref.skip_binder();
-
-        if let ObligationCauseCode::ImplDerivedObligation(obligation) = &obligation.cause.code {
-            // Try to apply the original trait binding obligation by borrowing.
-            let self_ty = trait_ref.self_ty();
-            let found = self_ty.to_string();
-            let new_self_ty = self.tcx.mk_imm_ref(self.tcx.lifetimes.re_static, self_ty);
-            let substs = self.tcx.mk_substs_trait(new_self_ty, &[]);
-            let new_trait_ref = ty::TraitRef::new(obligation.parent_trait_ref.def_id(), substs);
-            let new_obligation = Obligation::new(
-                ObligationCause::dummy(),
-                param_env,
-                new_trait_ref.without_const().to_predicate(),
-            );
-            if self.predicate_must_hold_modulo_regions(&new_obligation) {
-                if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
-                    // We have a very specific type of error, where just borrowing this argument
-                    // might solve the problem. In cases like this, the important part is the
-                    // original type obligation, not the last one that failed, which is arbitrary.
-                    // Because of this, we modify the error to refer to the original obligation and
-                    // return early in the caller.
-                    let msg = format!(
-                        "the trait bound `{}: {}` is not satisfied",
-                        found,
-                        obligation.parent_trait_ref.skip_binder().print_only_trait_path(),
-                    );
-                    if has_custom_message {
-                        err.note(&msg);
-                    } else {
-                        err.message = vec![(msg, Style::NoStyle)];
-                    }
-                    if snippet.starts_with('&') {
-                        // This is already a literal borrow and the obligation is failing
-                        // somewhere else in the obligation chain. Do not suggest non-sense.
-                        return false;
-                    }
-                    err.span_label(
-                        span,
-                        &format!(
-                            "expected an implementor of trait `{}`",
-                            obligation.parent_trait_ref.skip_binder().print_only_trait_path(),
-                        ),
-                    );
-                    err.span_suggestion(
-                        span,
-                        "consider borrowing here",
-                        format!("&{}", snippet),
-                        Applicability::MaybeIncorrect,
-                    );
-                    return true;
-                }
-            }
-        }
-        false
-    }
-
-    /// Whenever references are used by mistake, like `for (i, e) in &vec.iter().enumerate()`,
-    /// suggest removing these references until we reach a type that implements the trait.
-    crate fn suggest_remove_reference(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        err: &mut DiagnosticBuilder<'tcx>,
-        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
-    ) {
-        let trait_ref = trait_ref.skip_binder();
-        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 mut trait_type = trait_ref.self_ty();
-
-            for refs_remaining in 0..refs_number {
-                if let ty::Ref(_, t_type, _) = trait_type.kind {
-                    trait_type = t_type;
-
-                    let new_obligation = self.mk_obligation_for_def_id(
-                        trait_ref.def_id,
-                        trait_type,
-                        ObligationCause::dummy(),
-                        obligation.param_env,
-                    );
-
-                    if self.predicate_may_hold(&new_obligation) {
-                        let sp = self
-                            .tcx
-                            .sess
-                            .source_map()
-                            .span_take_while(span, |c| c.is_whitespace() || *c == '&');
-
-                        let remove_refs = refs_remaining + 1;
-
-                        let msg = if remove_refs == 1 {
-                            "consider removing the leading `&`-reference".to_string()
-                        } else {
-                            format!("consider removing {} leading `&`-references", remove_refs)
-                        };
-
-                        err.span_suggestion_short(
-                            sp,
-                            &msg,
-                            String::new(),
-                            Applicability::MachineApplicable,
-                        );
-                        break;
-                    }
-                } else {
-                    break;
-                }
-            }
-        }
-    }
-
-    /// Check if the trait bound is implemented for a different mutability and note it in the
-    /// final error.
-    crate fn suggest_change_mut(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        err: &mut DiagnosticBuilder<'tcx>,
-        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
-        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::Mut => self.tcx.mk_imm_ref(region, t_type),
-                    hir::Mutability::Not => self.tcx.mk_mut_ref(region, t_type),
-                };
-
-                let new_obligation = self.mk_obligation_for_def_id(
-                    trait_ref.skip_binder().def_id,
-                    trait_type,
-                    ObligationCause::dummy(),
-                    obligation.param_env,
-                );
-
-                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::Not && 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.print_only_trait_path(),
-                            trait_type,
-                            trait_ref.skip_binder().self_ty(),
-                        ));
-                    }
-                }
-            }
-        }
-    }
-
-    crate fn suggest_semicolon_removal(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        err: &mut DiagnosticBuilder<'tcx>,
-        span: Span,
-        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
-    ) {
-        let hir = self.tcx.hir();
-        let parent_node = hir.get_parent_node(obligation.cause.body_id);
-        let node = hir.find(parent_node);
-        if let Some(hir::Node::Item(hir::Item {
-            kind: hir::ItemKind::Fn(sig, _, body_id), ..
-        })) = node
-        {
-            let body = hir.body(*body_id);
-            if let hir::ExprKind::Block(blk, _) = &body.value.kind {
-                if sig.decl.output.span().overlaps(span)
-                    && blk.expr.is_none()
-                    && "()" == &trait_ref.self_ty().to_string()
-                {
-                    // FIXME(estebank): When encountering a method with a trait
-                    // bound not satisfied in the return type with a body that has
-                    // no return, suggest removal of semicolon on last statement.
-                    // Once that is added, close #54771.
-                    if let Some(ref stmt) = blk.stmts.last() {
-                        let sp = self.tcx.sess.source_map().end_point(stmt.span);
-                        err.span_label(sp, "consider removing this semicolon");
-                    }
-                }
-            }
-        }
-    }
-
-    /// If all conditions are met to identify a returned `dyn Trait`, suggest using `impl Trait` if
-    /// applicable and signal that the error has been expanded appropriately and needs to be
-    /// emitted.
-    crate fn suggest_impl_trait(
-        &self,
-        err: &mut DiagnosticBuilder<'tcx>,
-        span: Span,
-        obligation: &PredicateObligation<'tcx>,
-        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
-    ) -> bool {
-        match obligation.cause.code.peel_derives() {
-            // Only suggest `impl Trait` if the return type is unsized because it is `dyn Trait`.
-            ObligationCauseCode::SizedReturnType => {}
-            _ => return false,
-        }
-
-        let hir = self.tcx.hir();
-        let parent_node = hir.get_parent_node(obligation.cause.body_id);
-        let node = hir.find(parent_node);
-        let (sig, body_id) = if let Some(hir::Node::Item(hir::Item {
-            kind: hir::ItemKind::Fn(sig, _, body_id),
-            ..
-        })) = node
-        {
-            (sig, body_id)
-        } else {
-            return false;
-        };
-        let body = hir.body(*body_id);
-        let trait_ref = self.resolve_vars_if_possible(trait_ref);
-        let ty = trait_ref.skip_binder().self_ty();
-        let is_object_safe = match ty.kind {
-            ty::Dynamic(predicates, _) => {
-                // If the `dyn Trait` is not object safe, do not suggest `Box<dyn Trait>`.
-                predicates
-                    .principal_def_id()
-                    .map_or(true, |def_id| self.tcx.object_safety_violations(def_id).is_empty())
-            }
-            // We only want to suggest `impl Trait` to `dyn Trait`s.
-            // For example, `fn foo() -> str` needs to be filtered out.
-            _ => return false,
-        };
-
-        let ret_ty = if let hir::FnRetTy::Return(ret_ty) = sig.decl.output {
-            ret_ty
-        } else {
-            return false;
-        };
-
-        // Use `TypeVisitor` instead of the output type directly to find the span of `ty` for
-        // cases like `fn foo() -> (dyn Trait, i32) {}`.
-        // Recursively look for `TraitObject` types and if there's only one, use that span to
-        // suggest `impl Trait`.
-
-        // Visit to make sure there's a single `return` type to suggest `impl Trait`,
-        // otherwise suggest using `Box<dyn Trait>` or an enum.
-        let mut visitor = ReturnsVisitor::default();
-        visitor.visit_body(&body);
-
-        let tables = self.in_progress_tables.map(|t| t.borrow()).unwrap();
-
-        let mut ret_types = visitor
-            .returns
-            .iter()
-            .filter_map(|expr| tables.node_type_opt(expr.hir_id))
-            .map(|ty| self.resolve_vars_if_possible(&ty));
-        let (last_ty, all_returns_have_same_type) = ret_types.clone().fold(
-            (None, true),
-            |(last_ty, mut same): (std::option::Option<Ty<'_>>, bool), ty| {
-                let ty = self.resolve_vars_if_possible(&ty);
-                same &= last_ty.map_or(true, |last_ty| last_ty == ty) && ty.kind != ty::Error;
-                (Some(ty), same)
-            },
-        );
-        let all_returns_conform_to_trait =
-            if let Some(ty_ret_ty) = tables.node_type_opt(ret_ty.hir_id) {
-                match ty_ret_ty.kind {
-                    ty::Dynamic(predicates, _) => {
-                        let cause = ObligationCause::misc(ret_ty.span, ret_ty.hir_id);
-                        let param_env = ty::ParamEnv::empty();
-                        ret_types.all(|returned_ty| {
-                            predicates.iter().all(|predicate| {
-                                let pred = predicate.with_self_ty(self.tcx, returned_ty);
-                                let obl = Obligation::new(cause.clone(), param_env, pred);
-                                self.predicate_may_hold(&obl)
-                            })
-                        })
-                    }
-                    _ => false,
-                }
-            } else {
-                true
-            };
-
-        let (snippet, last_ty) =
-            if let (true, hir::TyKind::TraitObject(..), Ok(snippet), true, Some(last_ty)) = (
-                // Verify that we're dealing with a return `dyn Trait`
-                ret_ty.span.overlaps(span),
-                &ret_ty.kind,
-                self.tcx.sess.source_map().span_to_snippet(ret_ty.span),
-                // If any of the return types does not conform to the trait, then we can't
-                // suggest `impl Trait` nor trait objects, it is a type mismatch error.
-                all_returns_conform_to_trait,
-                last_ty,
-            ) {
-                (snippet, last_ty)
-            } else {
-                return false;
-            };
-        err.code(error_code!(E0746));
-        err.set_primary_message("return type cannot have an unboxed trait object");
-        err.children.clear();
-        let impl_trait_msg = "for information on `impl Trait`, see \
-            <https://doc.rust-lang.org/book/ch10-02-traits.html\
-            #returning-types-that-implement-traits>";
-        let trait_obj_msg = "for information on trait objects, see \
-            <https://doc.rust-lang.org/book/ch17-02-trait-objects.html\
-            #using-trait-objects-that-allow-for-values-of-different-types>";
-        let has_dyn = snippet.split_whitespace().next().map_or(false, |s| s == "dyn");
-        let trait_obj = if has_dyn { &snippet[4..] } else { &snippet[..] };
-        if all_returns_have_same_type {
-            // Suggest `-> impl Trait`.
-            err.span_suggestion(
-                ret_ty.span,
-                &format!(
-                    "return `impl {1}` instead, as all return paths are of type `{}`, \
-                        which implements `{1}`",
-                    last_ty, trait_obj,
-                ),
-                format!("impl {}", trait_obj),
-                Applicability::MachineApplicable,
-            );
-            err.note(impl_trait_msg);
-        } else {
-            if is_object_safe {
-                // Suggest `-> Box<dyn Trait>` and `Box::new(returned_value)`.
-                // Get all the return values and collect their span and suggestion.
-                let mut suggestions = visitor
-                    .returns
-                    .iter()
-                    .map(|expr| {
-                        (
-                            expr.span,
-                            format!(
-                                "Box::new({})",
-                                self.tcx.sess.source_map().span_to_snippet(expr.span).unwrap()
-                            ),
-                        )
-                    })
-                    .collect::<Vec<_>>();
-                // Add the suggestion for the return type.
-                suggestions.push((ret_ty.span, format!("Box<dyn {}>", trait_obj)));
-                err.multipart_suggestion(
-                    "return a boxed trait object instead",
-                    suggestions,
-                    Applicability::MaybeIncorrect,
-                );
-            } else {
-                // This is currently not possible to trigger because E0038 takes precedence, but
-                // leave it in for completeness in case anything changes in an earlier stage.
-                err.note(&format!(
-                    "if trait `{}` was object safe, you could return a trait object",
-                    trait_obj,
-                ));
-            }
-            err.note(trait_obj_msg);
-            err.note(&format!(
-                "if all the returned values were of the same type you could use \
-                    `impl {}` as the return type",
-                trait_obj,
-            ));
-            err.note(impl_trait_msg);
-            err.note("you can create a new `enum` with a variant for each returned type");
-        }
-        true
-    }
-
-    crate fn point_at_returns_when_relevant(
-        &self,
-        err: &mut DiagnosticBuilder<'tcx>,
-        obligation: &PredicateObligation<'tcx>,
-    ) {
-        match obligation.cause.code.peel_derives() {
-            ObligationCauseCode::SizedReturnType => {}
-            _ => return,
-        }
-
-        let hir = self.tcx.hir();
-        let parent_node = hir.get_parent_node(obligation.cause.body_id);
-        let node = hir.find(parent_node);
-        if let Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. })) =
-            node
-        {
-            let body = hir.body(*body_id);
-            // Point at all the `return`s in the function as they have failed trait bounds.
-            let mut visitor = ReturnsVisitor::default();
-            visitor.visit_body(&body);
-            let tables = self.in_progress_tables.map(|t| t.borrow()).unwrap();
-            for expr in &visitor.returns {
-                if let Some(returned_ty) = tables.node_type_opt(expr.hir_id) {
-                    let ty = self.resolve_vars_if_possible(&returned_ty);
-                    err.span_label(expr.span, &format!("this returned value is of type `{}`", ty));
-                }
-            }
-        }
-    }
-
-    /// Given some node representing a fn-like thing in the HIR map,
-    /// returns a span and `ArgKind` information that describes the
-    /// arguments it expects. This can be supplied to
-    /// `report_arg_count_mismatch`.
-    pub fn get_fn_like_arguments(&self, node: Node<'_>) -> (Span, Vec<ArgKind>) {
-        match node {
-            Node::Expr(&hir::Expr {
-                kind: hir::ExprKind::Closure(_, ref _decl, id, span, _),
-                ..
-            }) => (
-                self.tcx.sess.source_map().def_span(span),
-                self.tcx
-                    .hir()
-                    .body(id)
-                    .params
-                    .iter()
-                    .map(|arg| {
-                        if let hir::Pat { kind: hir::PatKind::Tuple(ref args, _), span, .. } =
-                            *arg.pat
-                        {
-                            ArgKind::Tuple(
-                                Some(span),
-                                args.iter()
-                                    .map(|pat| {
-                                        let snippet = self
-                                            .tcx
-                                            .sess
-                                            .source_map()
-                                            .span_to_snippet(pat.span)
-                                            .unwrap();
-                                        (snippet, "_".to_owned())
-                                    })
-                                    .collect::<Vec<_>>(),
-                            )
-                        } else {
-                            let name =
-                                self.tcx.sess.source_map().span_to_snippet(arg.pat.span).unwrap();
-                            ArgKind::Arg(name, "_".to_owned())
-                        }
-                    })
-                    .collect::<Vec<ArgKind>>(),
-            ),
-            Node::Item(&hir::Item { span, kind: hir::ItemKind::Fn(ref sig, ..), .. })
-            | Node::ImplItem(&hir::ImplItem {
-                span,
-                kind: hir::ImplItemKind::Method(ref sig, _),
-                ..
-            })
-            | Node::TraitItem(&hir::TraitItem {
-                span,
-                kind: hir::TraitItemKind::Method(ref sig, _),
-                ..
-            }) => (
-                self.tcx.sess.source_map().def_span(span),
-                sig.decl
-                    .inputs
-                    .iter()
-                    .map(|arg| match arg.clone().kind {
-                        hir::TyKind::Tup(ref tys) => ArgKind::Tuple(
-                            Some(arg.span),
-                            vec![("_".to_owned(), "_".to_owned()); tys.len()],
-                        ),
-                        _ => ArgKind::empty(),
-                    })
-                    .collect::<Vec<ArgKind>>(),
-            ),
-            Node::Ctor(ref variant_data) => {
-                let span = variant_data
-                    .ctor_hir_id()
-                    .map(|hir_id| self.tcx.hir().span(hir_id))
-                    .unwrap_or(DUMMY_SP);
-                let span = self.tcx.sess.source_map().def_span(span);
-
-                (span, vec![ArgKind::empty(); variant_data.fields().len()])
-            }
-            _ => panic!("non-FnLike node found: {:?}", node),
-        }
-    }
-
-    /// Reports an error when the number of arguments needed by a
-    /// trait match doesn't match the number that the expression
-    /// provides.
-    pub fn report_arg_count_mismatch(
-        &self,
-        span: Span,
-        found_span: Option<Span>,
-        expected_args: Vec<ArgKind>,
-        found_args: Vec<ArgKind>,
-        is_closure: bool,
-    ) -> DiagnosticBuilder<'tcx> {
-        let kind = if is_closure { "closure" } else { "function" };
-
-        let args_str = |arguments: &[ArgKind], other: &[ArgKind]| {
-            let arg_length = arguments.len();
-            let distinct = match &other[..] {
-                &[ArgKind::Tuple(..)] => true,
-                _ => false,
-            };
-            match (arg_length, arguments.get(0)) {
-                (1, Some(&ArgKind::Tuple(_, ref fields))) => {
-                    format!("a single {}-tuple as argument", fields.len())
-                }
-                _ => format!(
-                    "{} {}argument{}",
-                    arg_length,
-                    if distinct && arg_length > 1 { "distinct " } else { "" },
-                    pluralize!(arg_length)
-                ),
-            }
-        };
-
-        let expected_str = args_str(&expected_args, &found_args);
-        let found_str = args_str(&found_args, &expected_args);
-
-        let mut err = struct_span_err!(
-            self.tcx.sess,
-            span,
-            E0593,
-            "{} is expected to take {}, but it takes {}",
-            kind,
-            expected_str,
-            found_str,
-        );
-
-        err.span_label(span, format!("expected {} that takes {}", kind, expected_str));
-
-        if let Some(found_span) = found_span {
-            err.span_label(found_span, format!("takes {}", found_str));
-
-            // move |_| { ... }
-            // ^^^^^^^^-- def_span
-            //
-            // move |_| { ... }
-            // ^^^^^-- prefix
-            let prefix_span = self.tcx.sess.source_map().span_until_non_whitespace(found_span);
-            // move |_| { ... }
-            //      ^^^-- pipe_span
-            let pipe_span =
-                if let Some(span) = found_span.trim_start(prefix_span) { span } else { found_span };
-
-            // Suggest to take and ignore the arguments with expected_args_length `_`s if
-            // found arguments is empty (assume the user just wants to ignore args in this case).
-            // For example, if `expected_args_length` is 2, suggest `|_, _|`.
-            if found_args.is_empty() && is_closure {
-                let underscores = vec!["_"; expected_args.len()].join(", ");
-                err.span_suggestion(
-                    pipe_span,
-                    &format!(
-                        "consider changing the closure to take and ignore the expected argument{}",
-                        if expected_args.len() < 2 { "" } else { "s" }
-                    ),
-                    format!("|{}|", underscores),
-                    Applicability::MachineApplicable,
-                );
-            }
-
-            if let &[ArgKind::Tuple(_, ref fields)] = &found_args[..] {
-                if fields.len() == expected_args.len() {
-                    let sugg = fields
-                        .iter()
-                        .map(|(name, _)| name.to_owned())
-                        .collect::<Vec<String>>()
-                        .join(", ");
-                    err.span_suggestion(
-                        found_span,
-                        "change the closure to take multiple arguments instead of a single tuple",
-                        format!("|{}|", sugg),
-                        Applicability::MachineApplicable,
-                    );
-                }
-            }
-            if let &[ArgKind::Tuple(_, ref fields)] = &expected_args[..] {
-                if fields.len() == found_args.len() && is_closure {
-                    let sugg = format!(
-                        "|({}){}|",
-                        found_args
-                            .iter()
-                            .map(|arg| match arg {
-                                ArgKind::Arg(name, _) => name.to_owned(),
-                                _ => "_".to_owned(),
-                            })
-                            .collect::<Vec<String>>()
-                            .join(", "),
-                        // add type annotations if available
-                        if found_args.iter().any(|arg| match arg {
-                            ArgKind::Arg(_, ty) => ty != "_",
-                            _ => false,
-                        }) {
-                            format!(
-                                ": ({})",
-                                fields
-                                    .iter()
-                                    .map(|(_, ty)| ty.to_owned())
-                                    .collect::<Vec<String>>()
-                                    .join(", ")
-                            )
-                        } else {
-                            String::new()
-                        },
-                    );
-                    err.span_suggestion(
-                        found_span,
-                        "change the closure to accept a tuple instead of individual arguments",
-                        sugg,
-                        Applicability::MachineApplicable,
-                    );
-                }
-            }
-        }
-
-        err
-    }
-
-    crate fn report_closure_arg_mismatch(
-        &self,
-        span: Span,
-        found_span: Option<Span>,
-        expected_ref: ty::PolyTraitRef<'tcx>,
-        found: ty::PolyTraitRef<'tcx>,
-    ) -> DiagnosticBuilder<'tcx> {
-        crate fn build_fn_sig_string<'tcx>(
-            tcx: TyCtxt<'tcx>,
-            trait_ref: &ty::TraitRef<'tcx>,
-        ) -> String {
-            let inputs = trait_ref.substs.type_at(1);
-            let sig = if let ty::Tuple(inputs) = inputs.kind {
-                tcx.mk_fn_sig(
-                    inputs.iter().map(|k| k.expect_ty()),
-                    tcx.mk_ty_infer(ty::TyVar(ty::TyVid { index: 0 })),
-                    false,
-                    hir::Unsafety::Normal,
-                    ::rustc_target::spec::abi::Abi::Rust,
-                )
-            } else {
-                tcx.mk_fn_sig(
-                    ::std::iter::once(inputs),
-                    tcx.mk_ty_infer(ty::TyVar(ty::TyVid { index: 0 })),
-                    false,
-                    hir::Unsafety::Normal,
-                    ::rustc_target::spec::abi::Abi::Rust,
-                )
-            };
-            ty::Binder::bind(sig).to_string()
-        }
-
-        let argument_is_closure = expected_ref.skip_binder().substs.type_at(0).is_closure();
-        let mut err = struct_span_err!(
-            self.tcx.sess,
-            span,
-            E0631,
-            "type mismatch in {} arguments",
-            if argument_is_closure { "closure" } else { "function" }
-        );
-
-        let found_str = format!(
-            "expected signature of `{}`",
-            build_fn_sig_string(self.tcx, found.skip_binder())
-        );
-        err.span_label(span, found_str);
-
-        let found_span = found_span.unwrap_or(span);
-        let expected_str = format!(
-            "found signature of `{}`",
-            build_fn_sig_string(self.tcx, expected_ref.skip_binder())
-        );
-        err.span_label(found_span, expected_str);
-
-        err
-    }
-}
-
-impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
-    crate fn suggest_fully_qualified_path(
-        &self,
-        err: &mut DiagnosticBuilder<'_>,
-        def_id: DefId,
-        span: Span,
-        trait_ref: DefId,
-    ) {
-        if let Some(assoc_item) = self.tcx.opt_associated_item(def_id) {
-            if let ty::AssocKind::Const | ty::AssocKind::Type = assoc_item.kind {
-                err.note(&format!(
-                    "{}s cannot be accessed directly on a `trait`, they can only be \
-                        accessed through a specific `impl`",
-                    assoc_item.kind.suggestion_descr(),
-                ));
-                err.span_suggestion(
-                    span,
-                    "use the fully qualified path to an implementation",
-                    format!("<Type as {}>::{}", self.tcx.def_path_str(trait_ref), assoc_item.ident),
-                    Applicability::HasPlaceholders,
-                );
-            }
-        }
-    }
-
-    /// Adds an async-await specific note to the diagnostic when the future does not implement
-    /// an auto trait because of a captured type.
-    ///
-    /// ```ignore (diagnostic)
-    /// note: future does not implement `Qux` as this value is used across an await
-    ///   --> $DIR/issue-64130-3-other.rs:17:5
-    ///    |
-    /// LL |     let x = Foo;
-    ///    |         - has type `Foo`
-    /// LL |     baz().await;
-    ///    |     ^^^^^^^^^^^ await occurs here, with `x` maybe used later
-    /// LL | }
-    ///    | - `x` is later dropped here
-    /// ```
-    ///
-    /// When the diagnostic does not implement `Send` or `Sync` specifically, then the diagnostic
-    /// is "replaced" with a different message and a more specific error.
-    ///
-    /// ```ignore (diagnostic)
-    /// error: future cannot be sent between threads safely
-    ///   --> $DIR/issue-64130-2-send.rs:21:5
-    ///    |
-    /// LL | fn is_send<T: Send>(t: T) { }
-    ///    |    -------    ---- required by this bound in `is_send`
-    /// ...
-    /// LL |     is_send(bar());
-    ///    |     ^^^^^^^ future returned by `bar` is not send
-    ///    |
-    ///    = help: within `impl std::future::Future`, the trait `std::marker::Send` is not
-    ///            implemented for `Foo`
-    /// note: future is not send as this value is used across an await
-    ///   --> $DIR/issue-64130-2-send.rs:15:5
-    ///    |
-    /// LL |     let x = Foo;
-    ///    |         - has type `Foo`
-    /// LL |     baz().await;
-    ///    |     ^^^^^^^^^^^ await occurs here, with `x` maybe used later
-    /// LL | }
-    ///    | - `x` is later dropped here
-    /// ```
-    ///
-    /// Returns `true` if an async-await specific note was added to the diagnostic.
-    crate fn maybe_note_obligation_cause_for_async_await(
-        &self,
-        err: &mut DiagnosticBuilder<'_>,
-        obligation: &PredicateObligation<'tcx>,
-    ) -> bool {
-        debug!(
-            "maybe_note_obligation_cause_for_async_await: obligation.predicate={:?} \
-                obligation.cause.span={:?}",
-            obligation.predicate, obligation.cause.span
-        );
-        let source_map = self.tcx.sess.source_map();
-
-        // Attempt to detect an async-await error by looking at the obligation causes, looking
-        // for a generator 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 obligation in the chain is the most useful and has the generator that captured
-        // the type. The last generator has information about where the bound was introduced. At
-        // least one generator should be present for this diagnostic to be modified.
-        let (mut trait_ref, mut target_ty) = match obligation.predicate {
-            ty::Predicate::Trait(p, _) => {
-                (Some(p.skip_binder().trait_ref), Some(p.skip_binder().self_ty()))
-            }
-            _ => (None, None),
-        };
-        let mut generator = None;
-        let mut last_generator = None;
-        let mut next_code = Some(&obligation.cause.code);
-        while let Some(code) = next_code {
-            debug!("maybe_note_obligation_cause_for_async_await: code={:?}", code);
-            match code {
-                ObligationCauseCode::BuiltinDerivedObligation(derived_obligation)
-                | ObligationCauseCode::ImplDerivedObligation(derived_obligation) => {
-                    let ty = derived_obligation.parent_trait_ref.self_ty();
-                    debug!(
-                        "maybe_note_obligation_cause_for_async_await: \
-                            parent_trait_ref={:?} self_ty.kind={:?}",
-                        derived_obligation.parent_trait_ref, ty.kind
-                    );
-
-                    match ty.kind {
-                        ty::Generator(did, ..) => {
-                            generator = generator.or(Some(did));
-                            last_generator = Some(did);
-                        }
-                        ty::GeneratorWitness(..) => {}
-                        _ if generator.is_none() => {
-                            trait_ref = Some(*derived_obligation.parent_trait_ref.skip_binder());
-                            target_ty = Some(ty);
-                        }
-                        _ => {}
-                    }
-
-                    next_code = Some(derived_obligation.parent_code.as_ref());
-                }
-                _ => break,
-            }
-        }
-
-        // Only continue if a generator was found.
-        debug!(
-            "maybe_note_obligation_cause_for_async_await: generator={:?} trait_ref={:?} \
-                target_ty={:?}",
-            generator, trait_ref, target_ty
-        );
-        let (generator_did, trait_ref, target_ty) = match (generator, trait_ref, target_ty) {
-            (Some(generator_did), Some(trait_ref), Some(target_ty)) => {
-                (generator_did, trait_ref, target_ty)
-            }
-            _ => return false,
-        };
-
-        let span = self.tcx.def_span(generator_did);
-
-        // Do not ICE on closure typeck (#66868).
-        if self.tcx.hir().as_local_hir_id(generator_did).is_none() {
-            return false;
-        }
-
-        // Get the tables from the infcx if the generator is the function we are
-        // currently type-checking; otherwise, get them by performing a query.
-        // This is needed to avoid cycles.
-        let in_progress_tables = self.in_progress_tables.map(|t| t.borrow());
-        let generator_did_root = self.tcx.closure_base_def_id(generator_did);
-        debug!(
-            "maybe_note_obligation_cause_for_async_await: generator_did={:?} \
-             generator_did_root={:?} in_progress_tables.local_id_root={:?} span={:?}",
-            generator_did,
-            generator_did_root,
-            in_progress_tables.as_ref().map(|t| t.local_id_root),
-            span
-        );
-        let query_tables;
-        let tables: &TypeckTables<'tcx> = match &in_progress_tables {
-            Some(t) if t.local_id_root == Some(generator_did_root) => t,
-            _ => {
-                query_tables = self.tcx.typeck_tables_of(generator_did);
-                &query_tables
-            }
-        };
-
-        // Look for a type inside the generator interior that matches the target type to get
-        // a span.
-        let target_ty_erased = self.tcx.erase_regions(&target_ty);
-        let target_span = tables
-            .generator_interior_types
-            .iter()
-            .find(|ty::GeneratorInteriorTypeCause { ty, .. }| {
-                // Careful: the regions for types that appear in the
-                // generator interior are not generally known, so we
-                // want to erase them when comparing (and anyway,
-                // `Send` and other bounds are generally unaffected by
-                // the choice of region).  When erasing regions, we
-                // also have to erase late-bound regions. This is
-                // because the types that appear in the generator
-                // interior generally contain "bound regions" to
-                // represent regions that are part of the suspended
-                // generator frame. Bound regions are preserved by
-                // `erase_regions` and so we must also call
-                // `erase_late_bound_regions`.
-                let ty_erased = self.tcx.erase_late_bound_regions(&ty::Binder::bind(*ty));
-                let ty_erased = self.tcx.erase_regions(&ty_erased);
-                let eq = ty::TyS::same_type(ty_erased, target_ty_erased);
-                debug!(
-                    "maybe_note_obligation_cause_for_async_await: ty_erased={:?} \
-                        target_ty_erased={:?} eq={:?}",
-                    ty_erased, target_ty_erased, eq
-                );
-                eq
-            })
-            .map(|ty::GeneratorInteriorTypeCause { span, scope_span, expr, .. }| {
-                (span, source_map.span_to_snippet(*span), scope_span, expr)
-            });
-
-        debug!(
-            "maybe_note_obligation_cause_for_async_await: target_ty={:?} \
-                generator_interior_types={:?} target_span={:?}",
-            target_ty, tables.generator_interior_types, target_span
-        );
-        if let Some((target_span, Ok(snippet), scope_span, expr)) = target_span {
-            self.note_obligation_cause_for_async_await(
-                err,
-                *target_span,
-                scope_span,
-                *expr,
-                snippet,
-                generator_did,
-                last_generator,
-                trait_ref,
-                target_ty,
-                tables,
-                obligation,
-                next_code,
-            );
-            true
-        } else {
-            false
-        }
-    }
-
-    /// Unconditionally adds the diagnostic note described in
-    /// `maybe_note_obligation_cause_for_async_await`'s documentation comment.
-    crate fn note_obligation_cause_for_async_await(
-        &self,
-        err: &mut DiagnosticBuilder<'_>,
-        target_span: Span,
-        scope_span: &Option<Span>,
-        expr: Option<hir::HirId>,
-        snippet: String,
-        first_generator: DefId,
-        last_generator: Option<DefId>,
-        trait_ref: ty::TraitRef<'_>,
-        target_ty: Ty<'tcx>,
-        tables: &ty::TypeckTables<'_>,
-        obligation: &PredicateObligation<'tcx>,
-        next_code: Option<&ObligationCauseCode<'tcx>>,
-    ) {
-        let source_map = self.tcx.sess.source_map();
-
-        let is_async_fn = self
-            .tcx
-            .parent(first_generator)
-            .map(|parent_did| self.tcx.asyncness(parent_did))
-            .map(|parent_asyncness| parent_asyncness == hir::IsAsync::Async)
-            .unwrap_or(false);
-        let is_async_move = self
-            .tcx
-            .hir()
-            .as_local_hir_id(first_generator)
-            .and_then(|hir_id| self.tcx.hir().maybe_body_owned_by(hir_id))
-            .map(|body_id| self.tcx.hir().body(body_id))
-            .and_then(|body| body.generator_kind())
-            .map(|generator_kind| match generator_kind {
-                hir::GeneratorKind::Async(..) => true,
-                _ => false,
-            })
-            .unwrap_or(false);
-        let await_or_yield = if is_async_fn || is_async_move { "await" } else { "yield" };
-
-        // Special case the primary error message when send or sync is the trait that was
-        // not implemented.
-        let is_send = self.tcx.is_diagnostic_item(sym::send_trait, trait_ref.def_id);
-        let is_sync = self.tcx.is_diagnostic_item(sym::sync_trait, trait_ref.def_id);
-        let hir = self.tcx.hir();
-        let trait_explanation = if is_send || is_sync {
-            let (trait_name, trait_verb) =
-                if is_send { ("`Send`", "sent") } else { ("`Sync`", "shared") };
-
-            err.clear_code();
-            err.set_primary_message(format!(
-                "future cannot be {} between threads safely",
-                trait_verb
-            ));
-
-            let original_span = err.span.primary_span().unwrap();
-            let mut span = MultiSpan::from_span(original_span);
-
-            let message = if let Some(name) = last_generator
-                .and_then(|generator_did| self.tcx.parent(generator_did))
-                .and_then(|parent_did| hir.as_local_hir_id(parent_did))
-                .and_then(|parent_hir_id| hir.opt_name(parent_hir_id))
-            {
-                format!("future returned by `{}` is not {}", name, trait_name)
-            } else {
-                format!("future is not {}", trait_name)
-            };
-
-            span.push_span_label(original_span, message);
-            err.set_span(span);
-
-            format!("is not {}", trait_name)
-        } else {
-            format!("does not implement `{}`", trait_ref.print_only_trait_path())
-        };
-
-        // Look at the last interior type to get a span for the `.await`.
-        let await_span = tables.generator_interior_types.iter().map(|t| t.span).last().unwrap();
-        let mut span = MultiSpan::from_span(await_span);
-        span.push_span_label(
-            await_span,
-            format!("{} occurs here, with `{}` maybe used later", await_or_yield, 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 {} as this value is used across an {}",
-                trait_explanation, await_or_yield,
-            ),
-        );
-
-        if let Some(expr_id) = expr {
-            let expr = hir.expect_expr(expr_id);
-            debug!("target_ty evaluated from {:?}", expr);
-
-            let parent = hir.get_parent_node(expr_id);
-            if let Some(hir::Node::Expr(e)) = hir.find(parent) {
-                let parent_span = hir.span(parent);
-                let parent_did = parent.owner_def_id();
-                // ```rust
-                // impl T {
-                //     fn foo(&self) -> i32 {}
-                // }
-                // T.foo();
-                // ^^^^^^^ a temporary `&T` created inside this method call due to `&self`
-                // ```
-                //
-                let is_region_borrow =
-                    tables.expr_adjustments(expr).iter().any(|adj| adj.is_region_borrow());
-
-                // ```rust
-                // struct Foo(*const u8);
-                // bar(Foo(std::ptr::null())).await;
-                //     ^^^^^^^^^^^^^^^^^^^^^ raw-ptr `*T` created inside this struct ctor.
-                // ```
-                debug!("parent_def_kind: {:?}", self.tcx.def_kind(parent_did));
-                let is_raw_borrow_inside_fn_like_call = match self.tcx.def_kind(parent_did) {
-                    Some(DefKind::Fn) | Some(DefKind::Ctor(..)) => target_ty.is_unsafe_ptr(),
-                    _ => false,
-                };
-
-                if (tables.is_method_call(e) && is_region_borrow)
-                    || is_raw_borrow_inside_fn_like_call
-                {
-                    err.span_help(
-                        parent_span,
-                        "consider moving this into a `let` \
-                        binding to create a shorter lived borrow",
-                    );
-                }
-            }
-        }
-
-        // 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(),
-        );
-    }
-
-    crate fn note_obligation_cause_code<T>(
-        &self,
-        err: &mut DiagnosticBuilder<'_>,
-        predicate: &T,
-        cause_code: &ObligationCauseCode<'tcx>,
-        obligated_types: &mut Vec<&ty::TyS<'tcx>>,
-    ) where
-        T: fmt::Display,
-    {
-        let tcx = self.tcx;
-        match *cause_code {
-            ObligationCauseCode::ExprAssignable
-            | ObligationCauseCode::MatchExpressionArm { .. }
-            | ObligationCauseCode::Pattern { .. }
-            | ObligationCauseCode::IfExpression { .. }
-            | ObligationCauseCode::IfExpressionWithNoElse
-            | ObligationCauseCode::MainFunctionType
-            | ObligationCauseCode::StartFunctionType
-            | ObligationCauseCode::IntrinsicType
-            | ObligationCauseCode::MethodReceiver
-            | ObligationCauseCode::ReturnNoExpression
-            | ObligationCauseCode::MiscObligation => {}
-            ObligationCauseCode::SliceOrArrayElem => {
-                err.note("slice and array elements must have `Sized` type");
-            }
-            ObligationCauseCode::TupleElem => {
-                err.note("only the last element of a tuple may have a dynamically sized type");
-            }
-            ObligationCauseCode::ProjectionWf(data) => {
-                err.note(&format!("required so that the projection `{}` is well-formed", data,));
-            }
-            ObligationCauseCode::ReferenceOutlivesReferent(ref_ty) => {
-                err.note(&format!(
-                    "required so that reference `{}` does not outlive its referent",
-                    ref_ty,
-                ));
-            }
-            ObligationCauseCode::ObjectTypeBound(object_ty, region) => {
-                err.note(&format!(
-                    "required so that the lifetime bound of `{}` for `{}` is satisfied",
-                    region, object_ty,
-                ));
-            }
-            ObligationCauseCode::ItemObligation(item_def_id) => {
-                let item_name = tcx.def_path_str(item_def_id);
-                let msg = format!("required by `{}`", item_name);
-
-                if let Some(sp) = tcx.hir().span_if_local(item_def_id) {
-                    let sp = tcx.sess.source_map().def_span(sp);
-                    err.span_label(sp, &msg);
-                } else {
-                    err.note(&msg);
-                }
-            }
-            ObligationCauseCode::BindingObligation(item_def_id, span) => {
-                let item_name = tcx.def_path_str(item_def_id);
-                let msg = format!("required by this bound in `{}`", item_name);
-                if let Some(ident) = tcx.opt_item_name(item_def_id) {
-                    err.span_label(ident.span, "");
-                }
-                if span != DUMMY_SP {
-                    err.span_label(span, &msg);
-                } else {
-                    err.note(&msg);
-                }
-            }
-            ObligationCauseCode::ObjectCastObligation(object_ty) => {
-                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(suggest_const_in_array_repeat_expressions) => {
-                err.note(
-                    "the `Copy` trait is required because the repeated element will be copied",
-                );
-                if suggest_const_in_array_repeat_expressions {
-                    err.note(
-                        "this array initializer can be evaluated at compile-time, see issue \
-                         #48147 <https://github.com/rust-lang/rust/issues/49147> \
-                         for more information",
-                    );
-                    if tcx.sess.opts.unstable_features.is_nightly_build() {
-                        err.help(
-                            "add `#![feature(const_in_array_repeat_expressions)]` to the \
-                             crate attributes to enable",
-                        );
-                    }
-                }
-            }
-            ObligationCauseCode::VariableType(_) => {
-                err.note("all local variables must have a statically known size");
-                if !self.tcx.features().unsized_locals {
-                    err.help("unsized locals are gated as an unstable feature");
-                }
-            }
-            ObligationCauseCode::SizedArgumentType => {
-                err.note("all function arguments must have a statically known size");
-                if !self.tcx.features().unsized_locals {
-                    err.help("unsized locals are gated as an unstable feature");
-                }
-            }
-            ObligationCauseCode::SizedReturnType => {
-                err.note("the return type of a function must have a statically known size");
-            }
-            ObligationCauseCode::SizedYieldType => {
-                err.note("the yield type of a generator must have a statically known size");
-            }
-            ObligationCauseCode::AssignmentLhsSized => {
-                err.note("the left-hand-side of an assignment must have a statically known size");
-            }
-            ObligationCauseCode::TupleInitializerSized => {
-                err.note("tuples must have a statically known size to be initialized");
-            }
-            ObligationCauseCode::StructInitializerSized => {
-                err.note("structs must have a statically known size to be initialized");
-            }
-            ObligationCauseCode::FieldSized { adt_kind: ref item, last } => match *item {
-                AdtKind::Struct => {
-                    if last {
-                        err.note(
-                            "the last field of a packed struct may only have a \
-                             dynamically sized type if it does not need drop to be run",
-                        );
-                    } else {
-                        err.note(
-                            "only the last field of a struct may have a dynamically sized type",
-                        );
-                    }
-                }
-                AdtKind::Union => {
-                    err.note("no field of a union may have a dynamically sized type");
-                }
-                AdtKind::Enum => {
-                    err.note("no field of an enum variant may have a dynamically sized type");
-                }
-            },
-            ObligationCauseCode::ConstSized => {
-                err.note("constant expressions must have a statically known size");
-            }
-            ObligationCauseCode::ConstPatternStructural => {
-                err.note("constants used for pattern-matching must derive `PartialEq` and `Eq`");
-            }
-            ObligationCauseCode::SharedStatic => {
-                err.note("shared static variables must have a type that implements `Sync`");
-            }
-            ObligationCauseCode::BuiltinDerivedObligation(ref data) => {
-                let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref);
-                let ty = parent_trait_ref.skip_binder().self_ty();
-                err.note(&format!("required because it appears within the type `{}`", ty));
-                obligated_types.push(ty);
-
-                let parent_predicate = parent_trait_ref.without_const().to_predicate();
-                if !self.is_recursive_obligation(obligated_types, &data.parent_code) {
-                    self.note_obligation_cause_code(
-                        err,
-                        &parent_predicate,
-                        &data.parent_code,
-                        obligated_types,
-                    );
-                }
-            }
-            ObligationCauseCode::ImplDerivedObligation(ref data) => {
-                let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref);
-                err.note(&format!(
-                    "required because of the requirements on the impl of `{}` for `{}`",
-                    parent_trait_ref.print_only_trait_path(),
-                    parent_trait_ref.skip_binder().self_ty()
-                ));
-                let parent_predicate = parent_trait_ref.without_const().to_predicate();
-                self.note_obligation_cause_code(
-                    err,
-                    &parent_predicate,
-                    &data.parent_code,
-                    obligated_types,
-                );
-            }
-            ObligationCauseCode::CompareImplMethodObligation { .. } => {
-                err.note(&format!(
-                    "the requirement `{}` appears on the impl method \
-                     but not on the corresponding trait method",
-                    predicate
-                ));
-            }
-            ObligationCauseCode::CompareImplTypeObligation { .. } => {
-                err.note(&format!(
-                    "the requirement `{}` appears on the associated impl type \
-                     but not on the corresponding associated trait type",
-                    predicate
-                ));
-            }
-            ObligationCauseCode::ReturnType
-            | ObligationCauseCode::ReturnValue(_)
-            | ObligationCauseCode::BlockTailExpression(_) => (),
-            ObligationCauseCode::TrivialBound => {
-                err.help("see issue #48214");
-                if tcx.sess.opts.unstable_features.is_nightly_build() {
-                    err.help("add `#![feature(trivial_bounds)]` to the crate attributes to enable");
-                }
-            }
-            ObligationCauseCode::AssocTypeBound(ref data) => {
-                err.span_label(data.original, "associated type defined here");
-                if let Some(sp) = data.impl_span {
-                    err.span_label(sp, "in this `impl` item");
-                }
-                for sp in &data.bounds {
-                    err.span_label(*sp, "restricted in this bound");
-                }
-            }
-        }
-    }
-
-    crate fn suggest_new_overflow_limit(&self, err: &mut DiagnosticBuilder<'_>) {
-        let current_limit = self.tcx.sess.recursion_limit.get();
-        let suggested_limit = current_limit * 2;
-        err.help(&format!(
-            "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate (`{}`)",
-            suggested_limit, self.tcx.crate_name,
-        ));
-    }
-}
-
-/// Collect all the returned expressions within the input expression.
-/// Used to point at the return spans when we want to suggest some change to them.
-#[derive(Default)]
-struct ReturnsVisitor<'v> {
-    returns: Vec<&'v hir::Expr<'v>>,
-    in_block_tail: bool,
-}
-
-impl<'v> Visitor<'v> for ReturnsVisitor<'v> {
-    type Map = rustc::hir::map::Map<'v>;
-
-    fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap<'_, Self::Map> {
-        hir::intravisit::NestedVisitorMap::None
-    }
-
-    fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
-        // Visit every expression to detect `return` paths, either through the function's tail
-        // expression or `return` statements. We walk all nodes to find `return` statements, but
-        // we only care about tail expressions when `in_block_tail` is `true`, which means that
-        // they're in the return path of the function body.
-        match ex.kind {
-            hir::ExprKind::Ret(Some(ex)) => {
-                self.returns.push(ex);
-            }
-            hir::ExprKind::Block(block, _) if self.in_block_tail => {
-                self.in_block_tail = false;
-                for stmt in block.stmts {
-                    hir::intravisit::walk_stmt(self, stmt);
-                }
-                self.in_block_tail = true;
-                if let Some(expr) = block.expr {
-                    self.visit_expr(expr);
-                }
-            }
-            hir::ExprKind::Match(_, arms, _) if self.in_block_tail => {
-                for arm in arms {
-                    self.visit_expr(arm.body);
-                }
-            }
-            // We need to walk to find `return`s in the entire body.
-            _ if !self.in_block_tail => hir::intravisit::walk_expr(self, ex),
-            _ => self.returns.push(ex),
-        }
-    }
-
-    fn visit_body(&mut self, body: &'v hir::Body<'v>) {
-        assert!(!self.in_block_tail);
-        if body.generator_kind().is_none() {
-            if let hir::ExprKind::Block(block, None) = body.value.kind {
-                if block.expr.is_some() {
-                    self.in_block_tail = true;
-                }
-            }
-        }
-        hir::intravisit::walk_body(self, body);
-    }
-}
diff --git a/src/librustc_infer/traits/fulfill.rs b/src/librustc_infer/traits/fulfill.rs
deleted file mode 100644 (file)
index 28d3f26..0000000
+++ /dev/null
@@ -1,565 +0,0 @@
-use crate::infer::{InferCtxt, ShallowResolver};
-use rustc::ty::error::ExpectedFound;
-use rustc::ty::{self, ToPolyTraitRef, Ty, TypeFoldable};
-use rustc_data_structures::obligation_forest::ProcessResult;
-use rustc_data_structures::obligation_forest::{DoCompleted, Error, ForestObligation};
-use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor};
-use std::marker::PhantomData;
-
-use super::engine::{TraitEngine, TraitEngineExt};
-use super::project;
-use super::select::SelectionContext;
-use super::wf;
-use super::CodeAmbiguity;
-use super::CodeProjectionError;
-use super::CodeSelectionError;
-use super::{ConstEvalFailure, Unimplemented};
-use super::{FulfillmentError, FulfillmentErrorCode};
-use super::{ObligationCause, PredicateObligation};
-
-impl<'tcx> ForestObligation for PendingPredicateObligation<'tcx> {
-    /// Note that we include both the `ParamEnv` and the `Predicate`,
-    /// as the `ParamEnv` can influence whether fulfillment succeeds
-    /// or fails.
-    type CacheKey = ty::ParamEnvAnd<'tcx, ty::Predicate<'tcx>>;
-
-    fn as_cache_key(&self) -> Self::CacheKey {
-        self.obligation.param_env.and(self.obligation.predicate)
-    }
-}
-
-/// The fulfillment context is used to drive trait resolution. It
-/// consists of a list of obligations that must be (eventually)
-/// satisfied. The job is to track which are satisfied, which yielded
-/// errors, and which are still pending. At any point, users can call
-/// `select_where_possible`, and the fulfillment context will try to do
-/// selection, retaining only those obligations that remain
-/// ambiguous. This may be helpful in pushing type inference
-/// along. Once all type inference constraints have been generated, the
-/// method `select_all_or_error` can be used to report any remaining
-/// ambiguous cases as errors.
-pub struct FulfillmentContext<'tcx> {
-    // A list of all obligations that have been registered with this
-    // fulfillment context.
-    predicates: ObligationForest<PendingPredicateObligation<'tcx>>,
-    // Should this fulfillment context register type-lives-for-region
-    // obligations on its parent infcx? In some cases, region
-    // obligations are either already known to hold (normalization) or
-    // hopefully verifed elsewhere (type-impls-bound), and therefore
-    // should not be checked.
-    //
-    // Note that if we are normalizing a type that we already
-    // know is well-formed, there should be no harm setting this
-    // to true - all the region variables should be determinable
-    // using the RFC 447 rules, which don't depend on
-    // type-lives-for-region constraints, and because the type
-    // is well-formed, the constraints should hold.
-    register_region_obligations: bool,
-    // Is it OK to register obligations into this infcx inside
-    // an infcx snapshot?
-    //
-    // The "primary fulfillment" in many cases in typeck lives
-    // outside of any snapshot, so any use of it inside a snapshot
-    // will lead to trouble and therefore is checked against, but
-    // other fulfillment contexts sometimes do live inside of
-    // a snapshot (they don't *straddle* a snapshot, so there
-    // is no trouble there).
-    usable_in_snapshot: bool,
-}
-
-#[derive(Clone, Debug)]
-pub struct PendingPredicateObligation<'tcx> {
-    pub obligation: PredicateObligation<'tcx>,
-    pub stalled_on: Vec<ty::InferTy>,
-}
-
-// `PendingPredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger.
-#[cfg(target_arch = "x86_64")]
-static_assert_size!(PendingPredicateObligation<'_>, 136);
-
-impl<'a, 'tcx> FulfillmentContext<'tcx> {
-    /// Creates a new fulfillment context.
-    pub fn new() -> FulfillmentContext<'tcx> {
-        FulfillmentContext {
-            predicates: ObligationForest::new(),
-            register_region_obligations: true,
-            usable_in_snapshot: false,
-        }
-    }
-
-    pub fn new_in_snapshot() -> FulfillmentContext<'tcx> {
-        FulfillmentContext {
-            predicates: ObligationForest::new(),
-            register_region_obligations: true,
-            usable_in_snapshot: true,
-        }
-    }
-
-    pub fn new_ignoring_regions() -> FulfillmentContext<'tcx> {
-        FulfillmentContext {
-            predicates: ObligationForest::new(),
-            register_region_obligations: false,
-            usable_in_snapshot: false,
-        }
-    }
-
-    /// Attempts to select obligations using `selcx`.
-    fn select(
-        &mut self,
-        selcx: &mut SelectionContext<'a, 'tcx>,
-    ) -> Result<(), Vec<FulfillmentError<'tcx>>> {
-        debug!("select(obligation-forest-size={})", self.predicates.len());
-
-        let mut errors = Vec::new();
-
-        loop {
-            debug!("select: starting another iteration");
-
-            // Process pending obligations.
-            let outcome = self.predicates.process_obligations(
-                &mut FulfillProcessor {
-                    selcx,
-                    register_region_obligations: self.register_region_obligations,
-                },
-                DoCompleted::No,
-            );
-            debug!("select: outcome={:#?}", outcome);
-
-            // FIXME: if we kept the original cache key, we could mark projection
-            // obligations as complete for the projection cache here.
-
-            errors.extend(outcome.errors.into_iter().map(|e| to_fulfillment_error(e)));
-
-            // If nothing new was added, no need to keep looping.
-            if outcome.stalled {
-                break;
-            }
-        }
-
-        debug!(
-            "select({} predicates remaining, {} errors) done",
-            self.predicates.len(),
-            errors.len()
-        );
-
-        if errors.is_empty() { Ok(()) } else { Err(errors) }
-    }
-}
-
-impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
-    /// "Normalize" a projection type `<SomeType as SomeTrait>::X` by
-    /// creating a fresh type variable `$0` as well as a projection
-    /// predicate `<SomeType as SomeTrait>::X == $0`. When the
-    /// inference engine runs, it will attempt to find an impl of
-    /// `SomeTrait` or a where-clause that lets us unify `$0` with
-    /// something concrete. If this fails, we'll unify `$0` with
-    /// `projection_ty` again.
-    fn normalize_projection_type(
-        &mut self,
-        infcx: &InferCtxt<'_, 'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
-        projection_ty: ty::ProjectionTy<'tcx>,
-        cause: ObligationCause<'tcx>,
-    ) -> Ty<'tcx> {
-        debug!("normalize_projection_type(projection_ty={:?})", projection_ty);
-
-        debug_assert!(!projection_ty.has_escaping_bound_vars());
-
-        // FIXME(#20304) -- cache
-
-        let mut selcx = SelectionContext::new(infcx);
-        let mut obligations = vec![];
-        let normalized_ty = project::normalize_projection_type(
-            &mut selcx,
-            param_env,
-            projection_ty,
-            cause,
-            0,
-            &mut obligations,
-        );
-        self.register_predicate_obligations(infcx, obligations);
-
-        debug!("normalize_projection_type: result={:?}", normalized_ty);
-
-        normalized_ty
-    }
-
-    fn register_predicate_obligation(
-        &mut self,
-        infcx: &InferCtxt<'_, 'tcx>,
-        obligation: PredicateObligation<'tcx>,
-    ) {
-        // this helps to reduce duplicate errors, as well as making
-        // debug output much nicer to read and so on.
-        let obligation = infcx.resolve_vars_if_possible(&obligation);
-
-        debug!("register_predicate_obligation(obligation={:?})", obligation);
-
-        assert!(!infcx.is_in_snapshot() || self.usable_in_snapshot);
-
-        self.predicates
-            .register_obligation(PendingPredicateObligation { obligation, stalled_on: vec![] });
-    }
-
-    fn select_all_or_error(
-        &mut self,
-        infcx: &InferCtxt<'_, 'tcx>,
-    ) -> Result<(), Vec<FulfillmentError<'tcx>>> {
-        self.select_where_possible(infcx)?;
-
-        let errors: Vec<_> = self
-            .predicates
-            .to_errors(CodeAmbiguity)
-            .into_iter()
-            .map(|e| to_fulfillment_error(e))
-            .collect();
-        if errors.is_empty() { Ok(()) } else { Err(errors) }
-    }
-
-    fn select_where_possible(
-        &mut self,
-        infcx: &InferCtxt<'_, 'tcx>,
-    ) -> Result<(), Vec<FulfillmentError<'tcx>>> {
-        let mut selcx = SelectionContext::new(infcx);
-        self.select(&mut selcx)
-    }
-
-    fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>> {
-        self.predicates.map_pending_obligations(|o| o.obligation.clone())
-    }
-}
-
-struct FulfillProcessor<'a, 'b, 'tcx> {
-    selcx: &'a mut SelectionContext<'b, 'tcx>,
-    register_region_obligations: bool,
-}
-
-fn mk_pending(os: Vec<PredicateObligation<'tcx>>) -> Vec<PendingPredicateObligation<'tcx>> {
-    os.into_iter()
-        .map(|o| PendingPredicateObligation { obligation: o, stalled_on: vec![] })
-        .collect()
-}
-
-impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
-    type Obligation = PendingPredicateObligation<'tcx>;
-    type Error = FulfillmentErrorCode<'tcx>;
-
-    /// Processes a predicate obligation and returns either:
-    /// - `Changed(v)` if the predicate is true, presuming that `v` are also true
-    /// - `Unchanged` if we don't have enough info to be sure
-    /// - `Error(e)` if the predicate does not hold
-    ///
-    /// This is always inlined, despite its size, because it has a single
-    /// callsite and it is called *very* frequently.
-    #[inline(always)]
-    fn process_obligation(
-        &mut self,
-        pending_obligation: &mut Self::Obligation,
-    ) -> ProcessResult<Self::Obligation, Self::Error> {
-        // If we were stalled on some unresolved variables, first check whether
-        // any of them have been resolved; if not, don't bother doing more work
-        // yet.
-        let change = match pending_obligation.stalled_on.len() {
-            // Match arms are in order of frequency, which matters because this
-            // code is so hot. 1 and 0 dominate; 2+ is fairly rare.
-            1 => {
-                let infer = pending_obligation.stalled_on[0];
-                ShallowResolver::new(self.selcx.infcx()).shallow_resolve_changed(infer)
-            }
-            0 => {
-                // In this case we haven't changed, but wish to make a change.
-                true
-            }
-            _ => {
-                // This `for` loop was once a call to `all()`, but this lower-level
-                // form was a perf win. See #64545 for details.
-                (|| {
-                    for &infer in &pending_obligation.stalled_on {
-                        if ShallowResolver::new(self.selcx.infcx()).shallow_resolve_changed(infer) {
-                            return true;
-                        }
-                    }
-                    false
-                })()
-            }
-        };
-
-        if !change {
-            debug!(
-                "process_predicate: pending obligation {:?} still stalled on {:?}",
-                self.selcx.infcx().resolve_vars_if_possible(&pending_obligation.obligation),
-                pending_obligation.stalled_on
-            );
-            return ProcessResult::Unchanged;
-        }
-
-        // This part of the code is much colder.
-
-        pending_obligation.stalled_on.truncate(0);
-
-        let obligation = &mut pending_obligation.obligation;
-
-        if obligation.predicate.has_infer_types() {
-            obligation.predicate =
-                self.selcx.infcx().resolve_vars_if_possible(&obligation.predicate);
-        }
-
-        debug!("process_obligation: obligation = {:?} cause = {:?}", obligation, obligation.cause);
-
-        fn infer_ty(ty: Ty<'tcx>) -> ty::InferTy {
-            match ty.kind {
-                ty::Infer(infer) => infer,
-                _ => panic!(),
-            }
-        }
-
-        match obligation.predicate {
-            ty::Predicate::Trait(ref data, _) => {
-                let trait_obligation = obligation.with(data.clone());
-
-                if data.is_global() {
-                    // no type variables present, can use evaluation for better caching.
-                    // FIXME: consider caching errors too.
-                    if self.selcx.infcx().predicate_must_hold_considering_regions(&obligation) {
-                        debug!(
-                            "selecting trait `{:?}` at depth {} evaluated to holds",
-                            data, obligation.recursion_depth
-                        );
-                        return ProcessResult::Changed(vec![]);
-                    }
-                }
-
-                match self.selcx.select(&trait_obligation) {
-                    Ok(Some(vtable)) => {
-                        debug!(
-                            "selecting trait `{:?}` at depth {} yielded Ok(Some)",
-                            data, obligation.recursion_depth
-                        );
-                        ProcessResult::Changed(mk_pending(vtable.nested_obligations()))
-                    }
-                    Ok(None) => {
-                        debug!(
-                            "selecting trait `{:?}` at depth {} yielded Ok(None)",
-                            data, obligation.recursion_depth
-                        );
-
-                        // This is a bit subtle: for the most part, the
-                        // only reason we can fail to make progress on
-                        // trait selection is because we don't have enough
-                        // information about the types in the trait. One
-                        // exception is that we sometimes haven't decided
-                        // what kind of closure a closure is. *But*, in
-                        // that case, it turns out, the type of the
-                        // closure will also change, because the closure
-                        // also includes references to its upvars as part
-                        // of its type, and those types are resolved at
-                        // the same time.
-                        //
-                        // FIXME(#32286) logic seems false if no upvars
-                        pending_obligation.stalled_on =
-                            trait_ref_type_vars(self.selcx, data.to_poly_trait_ref());
-
-                        debug!(
-                            "process_predicate: pending obligation {:?} now stalled on {:?}",
-                            self.selcx.infcx().resolve_vars_if_possible(obligation),
-                            pending_obligation.stalled_on
-                        );
-
-                        ProcessResult::Unchanged
-                    }
-                    Err(selection_err) => {
-                        info!(
-                            "selecting trait `{:?}` at depth {} yielded Err",
-                            data, obligation.recursion_depth
-                        );
-
-                        ProcessResult::Error(CodeSelectionError(selection_err))
-                    }
-                }
-            }
-
-            ty::Predicate::RegionOutlives(ref binder) => {
-                match self.selcx.infcx().region_outlives_predicate(&obligation.cause, binder) {
-                    Ok(()) => ProcessResult::Changed(vec![]),
-                    Err(_) => ProcessResult::Error(CodeSelectionError(Unimplemented)),
-                }
-            }
-
-            ty::Predicate::TypeOutlives(ref binder) => {
-                // Check if there are higher-ranked vars.
-                match binder.no_bound_vars() {
-                    // If there are, inspect the underlying type further.
-                    None => {
-                        // Convert from `Binder<OutlivesPredicate<Ty, Region>>` to `Binder<Ty>`.
-                        let binder = binder.map_bound_ref(|pred| pred.0);
-
-                        // Check if the type has any bound vars.
-                        match binder.no_bound_vars() {
-                            // If so, this obligation is an error (for now). Eventually we should be
-                            // able to support additional cases here, like `for<'a> &'a str: 'a`.
-                            // NOTE: this is duplicate-implemented between here and fulfillment.
-                            None => ProcessResult::Error(CodeSelectionError(Unimplemented)),
-                            // Otherwise, we have something of the form
-                            // `for<'a> T: 'a where 'a not in T`, which we can treat as
-                            // `T: 'static`.
-                            Some(t_a) => {
-                                let r_static = self.selcx.tcx().lifetimes.re_static;
-                                if self.register_region_obligations {
-                                    self.selcx.infcx().register_region_obligation_with_cause(
-                                        t_a,
-                                        r_static,
-                                        &obligation.cause,
-                                    );
-                                }
-                                ProcessResult::Changed(vec![])
-                            }
-                        }
-                    }
-                    // If there aren't, register the obligation.
-                    Some(ty::OutlivesPredicate(t_a, r_b)) => {
-                        if self.register_region_obligations {
-                            self.selcx.infcx().register_region_obligation_with_cause(
-                                t_a,
-                                r_b,
-                                &obligation.cause,
-                            );
-                        }
-                        ProcessResult::Changed(vec![])
-                    }
-                }
-            }
-
-            ty::Predicate::Projection(ref data) => {
-                let project_obligation = obligation.with(data.clone());
-                match project::poly_project_and_unify_type(self.selcx, &project_obligation) {
-                    Ok(None) => {
-                        let tcx = self.selcx.tcx();
-                        pending_obligation.stalled_on =
-                            trait_ref_type_vars(self.selcx, data.to_poly_trait_ref(tcx));
-                        ProcessResult::Unchanged
-                    }
-                    Ok(Some(os)) => ProcessResult::Changed(mk_pending(os)),
-                    Err(e) => ProcessResult::Error(CodeProjectionError(e)),
-                }
-            }
-
-            ty::Predicate::ObjectSafe(trait_def_id) => {
-                if !self.selcx.tcx().is_object_safe(trait_def_id) {
-                    ProcessResult::Error(CodeSelectionError(Unimplemented))
-                } else {
-                    ProcessResult::Changed(vec![])
-                }
-            }
-
-            ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => {
-                match self.selcx.infcx().closure_kind(closure_def_id, closure_substs) {
-                    Some(closure_kind) => {
-                        if closure_kind.extends(kind) {
-                            ProcessResult::Changed(vec![])
-                        } else {
-                            ProcessResult::Error(CodeSelectionError(Unimplemented))
-                        }
-                    }
-                    None => ProcessResult::Unchanged,
-                }
-            }
-
-            ty::Predicate::WellFormed(ty) => {
-                match wf::obligations(
-                    self.selcx.infcx(),
-                    obligation.param_env,
-                    obligation.cause.body_id,
-                    ty,
-                    obligation.cause.span,
-                ) {
-                    None => {
-                        pending_obligation.stalled_on = vec![infer_ty(ty)];
-                        ProcessResult::Unchanged
-                    }
-                    Some(os) => ProcessResult::Changed(mk_pending(os)),
-                }
-            }
-
-            ty::Predicate::Subtype(ref subtype) => {
-                match self.selcx.infcx().subtype_predicate(
-                    &obligation.cause,
-                    obligation.param_env,
-                    subtype,
-                ) {
-                    None => {
-                        // None means that both are unresolved.
-                        pending_obligation.stalled_on = vec![
-                            infer_ty(subtype.skip_binder().a),
-                            infer_ty(subtype.skip_binder().b),
-                        ];
-                        ProcessResult::Unchanged
-                    }
-                    Some(Ok(ok)) => ProcessResult::Changed(mk_pending(ok.obligations)),
-                    Some(Err(err)) => {
-                        let expected_found = ExpectedFound::new(
-                            subtype.skip_binder().a_is_expected,
-                            subtype.skip_binder().a,
-                            subtype.skip_binder().b,
-                        );
-                        ProcessResult::Error(FulfillmentErrorCode::CodeSubtypeError(
-                            expected_found,
-                            err,
-                        ))
-                    }
-                }
-            }
-
-            ty::Predicate::ConstEvaluatable(def_id, substs) => {
-                match self.selcx.infcx().const_eval_resolve(
-                    obligation.param_env,
-                    def_id,
-                    substs,
-                    None,
-                    Some(obligation.cause.span),
-                ) {
-                    Ok(_) => ProcessResult::Changed(vec![]),
-                    Err(err) => ProcessResult::Error(CodeSelectionError(ConstEvalFailure(err))),
-                }
-            }
-        }
-    }
-
-    fn process_backedge<'c, I>(
-        &mut self,
-        cycle: I,
-        _marker: PhantomData<&'c PendingPredicateObligation<'tcx>>,
-    ) where
-        I: Clone + Iterator<Item = &'c PendingPredicateObligation<'tcx>>,
-    {
-        if self.selcx.coinductive_match(cycle.clone().map(|s| s.obligation.predicate)) {
-            debug!("process_child_obligations: coinductive match");
-        } else {
-            let cycle: Vec<_> = cycle.map(|c| c.obligation.clone()).collect();
-            self.selcx.infcx().report_overflow_error_cycle(&cycle);
-        }
-    }
-}
-
-/// Returns the set of type variables contained in a trait ref
-fn trait_ref_type_vars<'a, 'tcx>(
-    selcx: &mut SelectionContext<'a, 'tcx>,
-    t: ty::PolyTraitRef<'tcx>,
-) -> Vec<ty::InferTy> {
-    t.skip_binder() // ok b/c this check doesn't care about regions
-        .input_types()
-        .map(|t| selcx.infcx().resolve_vars_if_possible(&t))
-        .filter(|t| t.has_infer_types())
-        .flat_map(|t| t.walk())
-        .filter_map(|t| match t.kind {
-            ty::Infer(infer) => Some(infer),
-            _ => None,
-        })
-        .collect()
-}
-
-fn to_fulfillment_error<'tcx>(
-    error: Error<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>>,
-) -> FulfillmentError<'tcx> {
-    let obligation = error.backtrace.into_iter().next().unwrap().obligation;
-    FulfillmentError::new(obligation, error.error)
-}
diff --git a/src/librustc_infer/traits/misc.rs b/src/librustc_infer/traits/misc.rs
deleted file mode 100644 (file)
index 7ab918c..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-//! Miscellaneous type-system utilities that are too small to deserve their own modules.
-
-use crate::infer::TyCtxtInferExt;
-use crate::traits::{self, ObligationCause};
-
-use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
-use rustc_hir as hir;
-
-#[derive(Clone)]
-pub enum CopyImplementationError<'tcx> {
-    InfrigingFields(Vec<&'tcx ty::FieldDef>),
-    NotAnAdt,
-    HasDestructor,
-}
-
-pub fn can_type_implement_copy(
-    tcx: TyCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    self_type: Ty<'tcx>,
-) -> Result<(), CopyImplementationError<'tcx>> {
-    // FIXME: (@jroesch) float this code up
-    tcx.infer_ctxt().enter(|infcx| {
-        let (adt, substs) = match self_type.kind {
-            // These types used to have a builtin impl.
-            // Now libcore provides that impl.
-            ty::Uint(_)
-            | ty::Int(_)
-            | ty::Bool
-            | ty::Float(_)
-            | ty::Char
-            | ty::RawPtr(..)
-            | ty::Never
-            | ty::Ref(_, _, hir::Mutability::Not) => return Ok(()),
-
-            ty::Adt(adt, substs) => (adt, substs),
-
-            _ => return Err(CopyImplementationError::NotAnAdt),
-        };
-
-        let mut infringing = Vec::new();
-        for variant in &adt.variants {
-            for field in &variant.fields {
-                let ty = field.ty(tcx, substs);
-                if ty.references_error() {
-                    continue;
-                }
-                let span = tcx.def_span(field.did);
-                let cause = ObligationCause { span, ..ObligationCause::dummy() };
-                let ctx = traits::FulfillmentContext::new();
-                match traits::fully_normalize(&infcx, ctx, cause, param_env, &ty) {
-                    Ok(ty) => {
-                        if !infcx.type_is_copy_modulo_regions(param_env, ty, span) {
-                            infringing.push(field);
-                        }
-                    }
-                    Err(errors) => {
-                        infcx.report_fulfillment_errors(&errors, None, false);
-                    }
-                };
-            }
-        }
-        if !infringing.is_empty() {
-            return Err(CopyImplementationError::InfrigingFields(infringing));
-        }
-        if adt.has_dtor(tcx) {
-            return Err(CopyImplementationError::HasDestructor);
-        }
-
-        Ok(())
-    })
-}
index fcaab093ee240036fe3dbba0669cf9b9fdcd0645..1c0785497be221501de17896961466a5558ffbb1 100644 (file)
 //!
 //! [rustc guide]: https://rust-lang.github.io/rustc-guide/traits/resolution.html
 
-#[allow(dead_code)]
-pub mod auto_trait;
-mod chalk_fulfill;
-pub mod codegen;
-mod coherence;
 mod engine;
 pub mod error_reporting;
-mod fulfill;
-pub mod misc;
-mod object_safety;
-mod on_unimplemented;
 mod project;
-pub mod query;
-mod select;
-mod specialize;
 mod structural_impls;
-mod structural_match;
 mod util;
-pub mod wf;
 
-use crate::infer::outlives::env::OutlivesEnvironment;
-use crate::infer::{InferCtxt, SuppressRegionErrors, TyCtxtInferExt};
-use rustc::middle::region;
 use rustc::ty::error::{ExpectedFound, TypeError};
-use rustc::ty::fold::TypeFoldable;
-use rustc::ty::subst::{InternalSubsts, SubstsRef};
-use rustc::ty::{self, GenericParamDefKind, ToPredicate, Ty, TyCtxt, WithConstness};
-use rustc::util::common::ErrorReported;
+use rustc::ty::{self, Ty};
 use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
-use rustc_span::{Span, DUMMY_SP};
-
-use std::fmt::Debug;
+use rustc_span::Span;
 
 pub use self::FulfillmentErrorCode::*;
 pub use self::ObligationCauseCode::*;
 pub use self::SelectionError::*;
 pub use self::Vtable::*;
 
-pub use self::coherence::{add_placeholder_note, orphan_check, overlapping_impls};
-pub use self::coherence::{OrphanCheckErr, OverlapResult};
 pub use self::engine::{TraitEngine, TraitEngineExt};
-pub use self::fulfill::{FulfillmentContext, PendingPredicateObligation};
-pub use self::object_safety::astconv_object_safety_violations;
-pub use self::object_safety::is_vtable_safe_method;
-pub use self::object_safety::MethodViolationCode;
-pub use self::object_safety::ObjectSafetyViolation;
-pub use self::on_unimplemented::{OnUnimplementedDirective, OnUnimplementedNote};
 pub use self::project::MismatchedProjectionTypes;
 pub use self::project::{
-    normalize, normalize_projection_type, normalize_to, poly_project_and_unify_type,
-};
-pub use self::project::{Normalized, ProjectionCache, ProjectionCacheSnapshot, Reveal};
-pub use self::select::{EvaluationCache, SelectionCache, SelectionContext};
-pub use self::select::{EvaluationResult, IntercrateAmbiguityCause, OverflowError};
-pub use self::specialize::find_associated_item;
-pub use self::specialize::specialization_graph::FutureCompatOverlapError;
-pub use self::specialize::specialization_graph::FutureCompatOverlapErrorKind;
-pub use self::specialize::{specialization_graph, translate_substs, OverlapError};
-pub use self::structural_match::search_for_structural_match_violation;
-pub use self::structural_match::type_marked_structural;
-pub use self::structural_match::NonStructuralMatchTy;
-pub use self::util::{elaborate_predicates, elaborate_trait_ref, elaborate_trait_refs};
-pub use self::util::{expand_trait_aliases, TraitAliasExpander};
-pub use self::util::{
-    get_vtable_index_of_object_method, impl_is_default, impl_item_is_final,
-    predicate_for_trait_def, upcast_choices,
-};
-pub use self::util::{
-    supertrait_def_ids, supertraits, transitive_bounds, SupertraitDefIds, Supertraits,
-};
-
-pub use self::chalk_fulfill::{
-    CanonicalGoal as ChalkCanonicalGoal, FulfillmentContext as ChalkFulfillmentContext,
+    Normalized, NormalizedTy, ProjectionCache, ProjectionCacheEntry, ProjectionCacheKey,
+    ProjectionCacheSnapshot, Reveal,
 };
+crate use self::util::elaborate_predicates;
 
 pub use rustc::traits::*;
 
-/// Whether to skip the leak check, as part of a future compatibility warning step.
-#[derive(Copy, Clone, PartialEq, Eq, Debug)]
-pub enum SkipLeakCheck {
-    Yes,
-    No,
-}
-
-impl SkipLeakCheck {
-    fn is_yes(self) -> bool {
-        self == SkipLeakCheck::Yes
-    }
-}
-
-/// The "default" for skip-leak-check corresponds to the current
-/// behavior (do not skip the leak check) -- not the behavior we are
-/// transitioning into.
-impl Default for SkipLeakCheck {
-    fn default() -> Self {
-        SkipLeakCheck::No
-    }
-}
-
-/// The mode that trait queries run in.
-#[derive(Copy, Clone, PartialEq, Eq, Debug)]
-pub enum TraitQueryMode {
-    // Standard/un-canonicalized queries get accurate
-    // spans etc. passed in and hence can do reasonable
-    // error reporting on their own.
-    Standard,
-    // Canonicalized queries get dummy spans and hence
-    // must generally propagate errors to
-    // pre-canonicalization callsites.
-    Canonical,
-}
-
 /// An `Obligation` represents some trait reference (e.g., `int: Eq`) for
 /// which the vtable must be found. The process of finding a vtable is
 /// called "resolving" the `Obligation`. This process consists of
@@ -170,418 +83,6 @@ pub enum FulfillmentErrorCode<'tcx> {
     CodeAmbiguity,
 }
 
-/// Creates predicate obligations from the generic bounds.
-pub fn predicates_for_generics<'tcx>(
-    cause: ObligationCause<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    generic_bounds: &ty::InstantiatedPredicates<'tcx>,
-) -> PredicateObligations<'tcx> {
-    util::predicates_for_generics(cause, 0, param_env, generic_bounds)
-}
-
-/// Determines whether the type `ty` is known to meet `bound` and
-/// returns true if so. Returns false if `ty` either does not meet
-/// `bound` or is not known to meet bound (note that this is
-/// conservative towards *no impl*, which is the opposite of the
-/// `evaluate` methods).
-pub fn type_known_to_meet_bound_modulo_regions<'a, 'tcx>(
-    infcx: &InferCtxt<'a, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    ty: Ty<'tcx>,
-    def_id: DefId,
-    span: Span,
-) -> bool {
-    debug!(
-        "type_known_to_meet_bound_modulo_regions(ty={:?}, bound={:?})",
-        ty,
-        infcx.tcx.def_path_str(def_id)
-    );
-
-    let trait_ref = ty::TraitRef { def_id, substs: infcx.tcx.mk_substs_trait(ty, &[]) };
-    let obligation = Obligation {
-        param_env,
-        cause: ObligationCause::misc(span, hir::DUMMY_HIR_ID),
-        recursion_depth: 0,
-        predicate: trait_ref.without_const().to_predicate(),
-    };
-
-    let result = infcx.predicate_must_hold_modulo_regions(&obligation);
-    debug!(
-        "type_known_to_meet_ty={:?} bound={} => {:?}",
-        ty,
-        infcx.tcx.def_path_str(def_id),
-        result
-    );
-
-    if result && (ty.has_infer_types() || ty.has_closure_types()) {
-        // Because of inference "guessing", selection can sometimes claim
-        // to succeed while the success requires a guess. To ensure
-        // this function's result remains infallible, we must confirm
-        // that guess. While imperfect, I believe this is sound.
-
-        // The handling of regions in this area of the code is terrible,
-        // see issue #29149. We should be able to improve on this with
-        // NLL.
-        let mut fulfill_cx = FulfillmentContext::new_ignoring_regions();
-
-        // We can use a dummy node-id here because we won't pay any mind
-        // to region obligations that arise (there shouldn't really be any
-        // anyhow).
-        let cause = ObligationCause::misc(span, hir::DUMMY_HIR_ID);
-
-        fulfill_cx.register_bound(infcx, param_env, ty, def_id, cause);
-
-        // Note: we only assume something is `Copy` if we can
-        // *definitively* show that it implements `Copy`. Otherwise,
-        // assume it is move; linear is always ok.
-        match fulfill_cx.select_all_or_error(infcx) {
-            Ok(()) => {
-                debug!(
-                    "type_known_to_meet_bound_modulo_regions: ty={:?} bound={} success",
-                    ty,
-                    infcx.tcx.def_path_str(def_id)
-                );
-                true
-            }
-            Err(e) => {
-                debug!(
-                    "type_known_to_meet_bound_modulo_regions: ty={:?} bound={} errors={:?}",
-                    ty,
-                    infcx.tcx.def_path_str(def_id),
-                    e
-                );
-                false
-            }
-        }
-    } else {
-        result
-    }
-}
-
-fn do_normalize_predicates<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    region_context: DefId,
-    cause: ObligationCause<'tcx>,
-    elaborated_env: ty::ParamEnv<'tcx>,
-    predicates: Vec<ty::Predicate<'tcx>>,
-) -> Result<Vec<ty::Predicate<'tcx>>, ErrorReported> {
-    debug!(
-        "do_normalize_predicates(predicates={:?}, region_context={:?}, cause={:?})",
-        predicates, region_context, cause,
-    );
-    let span = cause.span;
-    tcx.infer_ctxt().enter(|infcx| {
-        // FIXME. We should really... do something with these region
-        // obligations. But this call just continues the older
-        // behavior (i.e., doesn't cause any new bugs), and it would
-        // take some further refactoring to actually solve them. In
-        // particular, we would have to handle implied bounds
-        // properly, and that code is currently largely confined to
-        // regionck (though I made some efforts to extract it
-        // out). -nmatsakis
-        //
-        // @arielby: In any case, these obligations are checked
-        // by wfcheck anyway, so I'm not sure we have to check
-        // them here too, and we will remove this function when
-        // we move over to lazy normalization *anyway*.
-        let fulfill_cx = FulfillmentContext::new_ignoring_regions();
-        let predicates =
-            match fully_normalize(&infcx, fulfill_cx, cause, elaborated_env, &predicates) {
-                Ok(predicates) => predicates,
-                Err(errors) => {
-                    infcx.report_fulfillment_errors(&errors, None, false);
-                    return Err(ErrorReported);
-                }
-            };
-
-        debug!("do_normalize_predictes: normalized predicates = {:?}", predicates);
-
-        let region_scope_tree = region::ScopeTree::default();
-
-        // We can use the `elaborated_env` here; the region code only
-        // cares about declarations like `'a: 'b`.
-        let outlives_env = OutlivesEnvironment::new(elaborated_env);
-
-        infcx.resolve_regions_and_report_errors(
-            region_context,
-            &region_scope_tree,
-            &outlives_env,
-            SuppressRegionErrors::default(),
-        );
-
-        let predicates = match infcx.fully_resolve(&predicates) {
-            Ok(predicates) => predicates,
-            Err(fixup_err) => {
-                // If we encounter a fixup error, it means that some type
-                // variable wound up unconstrained. I actually don't know
-                // if this can happen, and I certainly don't expect it to
-                // happen often, but if it did happen it probably
-                // represents a legitimate failure due to some kind of
-                // unconstrained variable, and it seems better not to ICE,
-                // all things considered.
-                tcx.sess.span_err(span, &fixup_err.to_string());
-                return Err(ErrorReported);
-            }
-        };
-        if predicates.has_local_value() {
-            // FIXME: shouldn't we, you know, actually report an error here? or an ICE?
-            Err(ErrorReported)
-        } else {
-            Ok(predicates)
-        }
-    })
-}
-
-// FIXME: this is gonna need to be removed ...
-/// Normalizes the parameter environment, reporting errors if they occur.
-pub fn normalize_param_env_or_error<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    region_context: DefId,
-    unnormalized_env: ty::ParamEnv<'tcx>,
-    cause: ObligationCause<'tcx>,
-) -> ty::ParamEnv<'tcx> {
-    // I'm not wild about reporting errors here; I'd prefer to
-    // have the errors get reported at a defined place (e.g.,
-    // during typeck). Instead I have all parameter
-    // environments, in effect, going through this function
-    // and hence potentially reporting errors. This ensures of
-    // course that we never forget to normalize (the
-    // alternative seemed like it would involve a lot of
-    // manual invocations of this fn -- and then we'd have to
-    // deal with the errors at each of those sites).
-    //
-    // In any case, in practice, typeck constructs all the
-    // parameter environments once for every fn as it goes,
-    // and errors will get reported then; so after typeck we
-    // can be sure that no errors should occur.
-
-    debug!(
-        "normalize_param_env_or_error(region_context={:?}, unnormalized_env={:?}, cause={:?})",
-        region_context, unnormalized_env, cause
-    );
-
-    let mut predicates: Vec<_> =
-        util::elaborate_predicates(tcx, unnormalized_env.caller_bounds.to_vec()).collect();
-
-    debug!("normalize_param_env_or_error: elaborated-predicates={:?}", predicates);
-
-    let elaborated_env = ty::ParamEnv::new(
-        tcx.intern_predicates(&predicates),
-        unnormalized_env.reveal,
-        unnormalized_env.def_id,
-    );
-
-    // HACK: we are trying to normalize the param-env inside *itself*. The problem is that
-    // normalization expects its param-env to be already normalized, which means we have
-    // a circularity.
-    //
-    // The way we handle this is by normalizing the param-env inside an unnormalized version
-    // of the param-env, which means that if the param-env contains unnormalized projections,
-    // we'll have some normalization failures. This is unfortunate.
-    //
-    // Lazy normalization would basically handle this by treating just the
-    // normalizing-a-trait-ref-requires-itself cycles as evaluation failures.
-    //
-    // Inferred outlives bounds can create a lot of `TypeOutlives` predicates for associated
-    // types, so to make the situation less bad, we normalize all the predicates *but*
-    // the `TypeOutlives` predicates first inside the unnormalized parameter environment, and
-    // then we normalize the `TypeOutlives` bounds inside the normalized parameter environment.
-    //
-    // This works fairly well because trait matching  does not actually care about param-env
-    // TypeOutlives predicates - these are normally used by regionck.
-    let outlives_predicates: Vec<_> = predicates
-        .drain_filter(|predicate| match predicate {
-            ty::Predicate::TypeOutlives(..) => true,
-            _ => false,
-        })
-        .collect();
-
-    debug!(
-        "normalize_param_env_or_error: predicates=(non-outlives={:?}, outlives={:?})",
-        predicates, outlives_predicates
-    );
-    let non_outlives_predicates = match do_normalize_predicates(
-        tcx,
-        region_context,
-        cause.clone(),
-        elaborated_env,
-        predicates,
-    ) {
-        Ok(predicates) => predicates,
-        // An unnormalized env is better than nothing.
-        Err(ErrorReported) => {
-            debug!("normalize_param_env_or_error: errored resolving non-outlives predicates");
-            return elaborated_env;
-        }
-    };
-
-    debug!("normalize_param_env_or_error: non-outlives predicates={:?}", non_outlives_predicates);
-
-    // Not sure whether it is better to include the unnormalized TypeOutlives predicates
-    // here. I believe they should not matter, because we are ignoring TypeOutlives param-env
-    // predicates here anyway. Keeping them here anyway because it seems safer.
-    let outlives_env: Vec<_> =
-        non_outlives_predicates.iter().chain(&outlives_predicates).cloned().collect();
-    let outlives_env =
-        ty::ParamEnv::new(tcx.intern_predicates(&outlives_env), unnormalized_env.reveal, None);
-    let outlives_predicates = match do_normalize_predicates(
-        tcx,
-        region_context,
-        cause,
-        outlives_env,
-        outlives_predicates,
-    ) {
-        Ok(predicates) => predicates,
-        // An unnormalized env is better than nothing.
-        Err(ErrorReported) => {
-            debug!("normalize_param_env_or_error: errored resolving outlives predicates");
-            return elaborated_env;
-        }
-    };
-    debug!("normalize_param_env_or_error: outlives predicates={:?}", outlives_predicates);
-
-    let mut predicates = non_outlives_predicates;
-    predicates.extend(outlives_predicates);
-    debug!("normalize_param_env_or_error: final predicates={:?}", predicates);
-    ty::ParamEnv::new(
-        tcx.intern_predicates(&predicates),
-        unnormalized_env.reveal,
-        unnormalized_env.def_id,
-    )
-}
-
-pub fn fully_normalize<'a, 'tcx, T>(
-    infcx: &InferCtxt<'a, 'tcx>,
-    mut fulfill_cx: FulfillmentContext<'tcx>,
-    cause: ObligationCause<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    value: &T,
-) -> Result<T, Vec<FulfillmentError<'tcx>>>
-where
-    T: TypeFoldable<'tcx>,
-{
-    debug!("fully_normalize_with_fulfillcx(value={:?})", value);
-    let selcx = &mut SelectionContext::new(infcx);
-    let Normalized { value: normalized_value, obligations } =
-        project::normalize(selcx, param_env, cause, value);
-    debug!(
-        "fully_normalize: normalized_value={:?} obligations={:?}",
-        normalized_value, obligations
-    );
-    for obligation in obligations {
-        fulfill_cx.register_predicate_obligation(selcx.infcx(), obligation);
-    }
-
-    debug!("fully_normalize: select_all_or_error start");
-    fulfill_cx.select_all_or_error(infcx)?;
-    debug!("fully_normalize: select_all_or_error complete");
-    let resolved_value = infcx.resolve_vars_if_possible(&normalized_value);
-    debug!("fully_normalize: resolved_value={:?}", resolved_value);
-    Ok(resolved_value)
-}
-
-/// Normalizes the predicates and checks whether they hold in an empty
-/// environment. If this returns false, then either normalize
-/// encountered an error or one of the predicates did not hold. Used
-/// when creating vtables to check for unsatisfiable methods.
-pub fn normalize_and_test_predicates<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    predicates: Vec<ty::Predicate<'tcx>>,
-) -> bool {
-    debug!("normalize_and_test_predicates(predicates={:?})", predicates);
-
-    let result = tcx.infer_ctxt().enter(|infcx| {
-        let param_env = ty::ParamEnv::reveal_all();
-        let mut selcx = SelectionContext::new(&infcx);
-        let mut fulfill_cx = FulfillmentContext::new();
-        let cause = ObligationCause::dummy();
-        let Normalized { value: predicates, obligations } =
-            normalize(&mut selcx, param_env, cause.clone(), &predicates);
-        for obligation in obligations {
-            fulfill_cx.register_predicate_obligation(&infcx, obligation);
-        }
-        for predicate in predicates {
-            let obligation = Obligation::new(cause.clone(), param_env, predicate);
-            fulfill_cx.register_predicate_obligation(&infcx, obligation);
-        }
-
-        fulfill_cx.select_all_or_error(&infcx).is_ok()
-    });
-    debug!("normalize_and_test_predicates(predicates={:?}) = {:?}", predicates, result);
-    result
-}
-
-fn substitute_normalize_and_test_predicates<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    key: (DefId, SubstsRef<'tcx>),
-) -> bool {
-    debug!("substitute_normalize_and_test_predicates(key={:?})", key);
-
-    let predicates = tcx.predicates_of(key.0).instantiate(tcx, key.1).predicates;
-    let result = normalize_and_test_predicates(tcx, predicates);
-
-    debug!("substitute_normalize_and_test_predicates(key={:?}) = {:?}", key, result);
-    result
-}
-
-/// Given a trait `trait_ref`, iterates the vtable entries
-/// that come from `trait_ref`, including its supertraits.
-#[inline] // FIXME(#35870): avoid closures being unexported due to `impl Trait`.
-fn vtable_methods<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    trait_ref: ty::PolyTraitRef<'tcx>,
-) -> &'tcx [Option<(DefId, SubstsRef<'tcx>)>] {
-    debug!("vtable_methods({:?})", trait_ref);
-
-    tcx.arena.alloc_from_iter(supertraits(tcx, trait_ref).flat_map(move |trait_ref| {
-        let trait_methods = tcx
-            .associated_items(trait_ref.def_id())
-            .in_definition_order()
-            .filter(|item| item.kind == ty::AssocKind::Method);
-
-        // Now list each method's DefId and InternalSubsts (for within its trait).
-        // If the method can never be called from this object, produce None.
-        trait_methods.map(move |trait_method| {
-            debug!("vtable_methods: trait_method={:?}", trait_method);
-            let def_id = trait_method.def_id;
-
-            // Some methods cannot be called on an object; skip those.
-            if !is_vtable_safe_method(tcx, trait_ref.def_id(), &trait_method) {
-                debug!("vtable_methods: not vtable safe");
-                return None;
-            }
-
-            // The method may have some early-bound lifetimes; add regions for those.
-            let substs = trait_ref.map_bound(|trait_ref| {
-                InternalSubsts::for_item(tcx, def_id, |param, _| match param.kind {
-                    GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(),
-                    GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => {
-                        trait_ref.substs[param.index as usize]
-                    }
-                })
-            });
-
-            // The trait type may have higher-ranked lifetimes in it;
-            // erase them if they appear, so that we get the type
-            // at some particular call site.
-            let substs =
-                tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &substs);
-
-            // It's possible that the method relies on where-clauses that
-            // do not hold for this particular set of type parameters.
-            // Note that this method could then never be called, so we
-            // do not want to try and codegen it, in that case (see #23435).
-            let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, substs);
-            if !normalize_and_test_predicates(tcx, predicates.predicates) {
-                debug!("vtable_methods: predicates do not hold");
-                return None;
-            }
-
-            Some((def_id, substs))
-        })
-    }))
-}
-
 impl<'tcx, O> Obligation<'tcx, O> {
     pub fn new(
         cause: ObligationCause<'tcx>,
@@ -591,7 +92,7 @@ pub fn new(
         Obligation { cause, param_env, recursion_depth: 0, predicate }
     }
 
-    fn with_depth(
+    pub fn with_depth(
         cause: ObligationCause<'tcx>,
         recursion_depth: usize,
         param_env: ty::ParamEnv<'tcx>,
@@ -620,28 +121,16 @@ pub fn with<P>(&self, value: P) -> Obligation<'tcx, P> {
 }
 
 impl<'tcx> FulfillmentError<'tcx> {
-    fn new(
+    pub fn new(
         obligation: PredicateObligation<'tcx>,
         code: FulfillmentErrorCode<'tcx>,
     ) -> FulfillmentError<'tcx> {
-        FulfillmentError { obligation: obligation, code: code, points_at_arg_span: false }
+        FulfillmentError { obligation, code, points_at_arg_span: false }
     }
 }
 
 impl<'tcx> TraitObligation<'tcx> {
-    fn self_ty(&self) -> ty::Binder<Ty<'tcx>> {
+    pub fn self_ty(&self) -> ty::Binder<Ty<'tcx>> {
         self.predicate.map_bound(|p| p.self_ty())
     }
 }
-
-pub fn provide(providers: &mut ty::query::Providers<'_>) {
-    object_safety::provide(providers);
-    *providers = ty::query::Providers {
-        specialization_graph_of: specialize::specialization_graph_provider,
-        specializes: specialize::specializes,
-        codegen_fulfill_obligation: codegen::codegen_fulfill_obligation,
-        vtable_methods,
-        substitute_normalize_and_test_predicates,
-        ..*providers
-    };
-}
diff --git a/src/librustc_infer/traits/object_safety.rs b/src/librustc_infer/traits/object_safety.rs
deleted file mode 100644 (file)
index f5bab7c..0000000
+++ /dev/null
@@ -1,777 +0,0 @@
-//! "Object safety" refers to the ability for a trait to be converted
-//! to an object. In general, traits may only be converted to an
-//! object if all of their methods meet certain criteria. In particular,
-//! they must:
-//!
-//!   - have a suitable receiver from which we can extract a vtable and coerce to a "thin" version
-//!     that doesn't contain the vtable;
-//!   - not reference the erased type `Self` except for in this receiver;
-//!   - not have generic type parameters.
-
-use super::elaborate_predicates;
-
-use crate::infer::TyCtxtInferExt;
-use crate::traits::{self, Obligation, ObligationCause};
-use rustc::ty::subst::{InternalSubsts, Subst};
-use rustc::ty::{self, Predicate, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
-use rustc_errors::Applicability;
-use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
-use rustc_session::lint::builtin::WHERE_CLAUSES_OBJECT_SAFETY;
-use rustc_span::symbol::Symbol;
-use rustc_span::Span;
-use smallvec::SmallVec;
-
-use std::iter;
-
-pub use crate::traits::{MethodViolationCode, ObjectSafetyViolation};
-
-/// Returns the object safety violations that affect
-/// astconv -- currently, `Self` in supertraits. This is needed
-/// because `object_safety_violations` can't be used during
-/// type collection.
-pub fn astconv_object_safety_violations(
-    tcx: TyCtxt<'_>,
-    trait_def_id: DefId,
-) -> Vec<ObjectSafetyViolation> {
-    debug_assert!(tcx.generics_of(trait_def_id).has_self);
-    let violations = traits::supertrait_def_ids(tcx, trait_def_id)
-        .map(|def_id| predicates_reference_self(tcx, def_id, true))
-        .filter(|spans| !spans.is_empty())
-        .map(|spans| ObjectSafetyViolation::SupertraitSelf(spans))
-        .collect();
-
-    debug!("astconv_object_safety_violations(trait_def_id={:?}) = {:?}", trait_def_id, violations);
-
-    violations
-}
-
-fn object_safety_violations(tcx: TyCtxt<'_>, trait_def_id: DefId) -> Vec<ObjectSafetyViolation> {
-    debug_assert!(tcx.generics_of(trait_def_id).has_self);
-    debug!("object_safety_violations: {:?}", trait_def_id);
-
-    traits::supertrait_def_ids(tcx, trait_def_id)
-        .flat_map(|def_id| object_safety_violations_for_trait(tcx, def_id))
-        .collect()
-}
-
-/// We say a method is *vtable safe* if it can be invoked on a trait
-/// object. Note that object-safe traits can have some
-/// non-vtable-safe methods, so long as they require `Self: Sized` or
-/// otherwise ensure that they cannot be used when `Self = Trait`.
-pub fn is_vtable_safe_method(tcx: TyCtxt<'_>, trait_def_id: DefId, method: &ty::AssocItem) -> bool {
-    debug_assert!(tcx.generics_of(trait_def_id).has_self);
-    debug!("is_vtable_safe_method({:?}, {:?})", trait_def_id, method);
-    // Any method that has a `Self: Sized` bound cannot be called.
-    if generics_require_sized_self(tcx, method.def_id) {
-        return false;
-    }
-
-    match virtual_call_violation_for_method(tcx, trait_def_id, method) {
-        None | Some(MethodViolationCode::WhereClauseReferencesSelf) => true,
-        Some(_) => false,
-    }
-}
-
-fn object_safety_violations_for_trait(
-    tcx: TyCtxt<'_>,
-    trait_def_id: DefId,
-) -> Vec<ObjectSafetyViolation> {
-    // Check methods for violations.
-    let mut violations: Vec<_> = tcx
-        .associated_items(trait_def_id)
-        .in_definition_order()
-        .filter(|item| item.kind == ty::AssocKind::Method)
-        .filter_map(|item| {
-            object_safety_violation_for_method(tcx, trait_def_id, &item)
-                .map(|(code, span)| ObjectSafetyViolation::Method(item.ident.name, code, span))
-        })
-        .filter(|violation| {
-            if let ObjectSafetyViolation::Method(
-                _,
-                MethodViolationCode::WhereClauseReferencesSelf,
-                span,
-            ) = violation
-            {
-                // Using `CRATE_NODE_ID` is wrong, but it's hard to get a more precise id.
-                // It's also hard to get a use site span, so we use the method definition span.
-                tcx.struct_span_lint_hir(
-                    WHERE_CLAUSES_OBJECT_SAFETY,
-                    hir::CRATE_HIR_ID,
-                    *span,
-                    |lint| {
-                        let mut err = lint.build(&format!(
-                            "the trait `{}` cannot be made into an object",
-                            tcx.def_path_str(trait_def_id)
-                        ));
-                        let node = tcx.hir().get_if_local(trait_def_id);
-                        let msg = if let Some(hir::Node::Item(item)) = node {
-                            err.span_label(
-                                item.ident.span,
-                                "this trait cannot be made into an object...",
-                            );
-                            format!("...because {}", violation.error_msg())
-                        } else {
-                            format!(
-                                "the trait cannot be made into an object because {}",
-                                violation.error_msg()
-                            )
-                        };
-                        err.span_label(*span, &msg);
-                        match (node, violation.solution()) {
-                            (Some(_), Some((note, None))) => {
-                                err.help(&note);
-                            }
-                            (Some(_), Some((note, Some((sugg, span))))) => {
-                                err.span_suggestion(
-                                    span,
-                                    &note,
-                                    sugg,
-                                    Applicability::MachineApplicable,
-                                );
-                            }
-                            // Only provide the help if its a local trait, otherwise it's not actionable.
-                            _ => {}
-                        }
-                        err.emit();
-                    },
-                );
-                false
-            } else {
-                true
-            }
-        })
-        .collect();
-
-    // Check the trait itself.
-    if trait_has_sized_self(tcx, trait_def_id) {
-        // We don't want to include the requirement from `Sized` itself to be `Sized` in the list.
-        let spans = get_sized_bounds(tcx, trait_def_id);
-        violations.push(ObjectSafetyViolation::SizedSelf(spans));
-    }
-    let spans = predicates_reference_self(tcx, trait_def_id, false);
-    if !spans.is_empty() {
-        violations.push(ObjectSafetyViolation::SupertraitSelf(spans));
-    }
-
-    violations.extend(
-        tcx.associated_items(trait_def_id)
-            .in_definition_order()
-            .filter(|item| item.kind == ty::AssocKind::Const)
-            .map(|item| ObjectSafetyViolation::AssocConst(item.ident.name, item.ident.span)),
-    );
-
-    debug!(
-        "object_safety_violations_for_trait(trait_def_id={:?}) = {:?}",
-        trait_def_id, violations
-    );
-
-    violations
-}
-
-fn get_sized_bounds(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span; 1]> {
-    tcx.hir()
-        .get_if_local(trait_def_id)
-        .and_then(|node| match node {
-            hir::Node::Item(hir::Item {
-                kind: hir::ItemKind::Trait(.., generics, bounds, _),
-                ..
-            }) => Some(
-                generics
-                    .where_clause
-                    .predicates
-                    .iter()
-                    .filter_map(|pred| {
-                        match pred {
-                            hir::WherePredicate::BoundPredicate(pred)
-                                if pred.bounded_ty.hir_id.owner_def_id() == trait_def_id =>
-                            {
-                                // Fetch spans for trait bounds that are Sized:
-                                // `trait T where Self: Pred`
-                                Some(pred.bounds.iter().filter_map(|b| match b {
-                                    hir::GenericBound::Trait(
-                                        trait_ref,
-                                        hir::TraitBoundModifier::None,
-                                    ) if trait_has_sized_self(
-                                        tcx,
-                                        trait_ref.trait_ref.trait_def_id(),
-                                    ) =>
-                                    {
-                                        Some(trait_ref.span)
-                                    }
-                                    _ => None,
-                                }))
-                            }
-                            _ => None,
-                        }
-                    })
-                    .flatten()
-                    .chain(bounds.iter().filter_map(|b| match b {
-                        hir::GenericBound::Trait(trait_ref, hir::TraitBoundModifier::None)
-                            if trait_has_sized_self(tcx, trait_ref.trait_ref.trait_def_id()) =>
-                        {
-                            // Fetch spans for supertraits that are `Sized`: `trait T: Super`
-                            Some(trait_ref.span)
-                        }
-                        _ => None,
-                    }))
-                    .collect::<SmallVec<[Span; 1]>>(),
-            ),
-            _ => None,
-        })
-        .unwrap_or_else(SmallVec::new)
-}
-
-fn predicates_reference_self(
-    tcx: TyCtxt<'_>,
-    trait_def_id: DefId,
-    supertraits_only: bool,
-) -> SmallVec<[Span; 1]> {
-    let trait_ref = ty::Binder::dummy(ty::TraitRef::identity(tcx, trait_def_id));
-    let predicates = if supertraits_only {
-        tcx.super_predicates_of(trait_def_id)
-    } else {
-        tcx.predicates_of(trait_def_id)
-    };
-    let self_ty = tcx.types.self_param;
-    let has_self_ty = |t: Ty<'_>| t.walk().any(|t| t == self_ty);
-    predicates
-        .predicates
-        .iter()
-        .map(|(predicate, sp)| (predicate.subst_supertrait(tcx, &trait_ref), sp))
-        .filter_map(|(predicate, &sp)| {
-            match predicate {
-                ty::Predicate::Trait(ref data, _) => {
-                    // In the case of a trait predicate, we can skip the "self" type.
-                    if data.skip_binder().input_types().skip(1).any(has_self_ty) {
-                        Some(sp)
-                    } else {
-                        None
-                    }
-                }
-                ty::Predicate::Projection(ref data) => {
-                    // And similarly for projections. This should be redundant with
-                    // the previous check because any projection should have a
-                    // matching `Trait` predicate with the same inputs, but we do
-                    // the check to be safe.
-                    //
-                    // Note that we *do* allow projection *outputs* to contain
-                    // `self` (i.e., `trait Foo: Bar<Output=Self::Result> { type Result; }`),
-                    // we just require the user to specify *both* outputs
-                    // in the object type (i.e., `dyn Foo<Output=(), Result=()>`).
-                    //
-                    // This is ALT2 in issue #56288, see that for discussion of the
-                    // possible alternatives.
-                    if data
-                        .skip_binder()
-                        .projection_ty
-                        .trait_ref(tcx)
-                        .input_types()
-                        .skip(1)
-                        .any(has_self_ty)
-                    {
-                        Some(sp)
-                    } else {
-                        None
-                    }
-                }
-                ty::Predicate::WellFormed(..)
-                | ty::Predicate::ObjectSafe(..)
-                | ty::Predicate::TypeOutlives(..)
-                | ty::Predicate::RegionOutlives(..)
-                | ty::Predicate::ClosureKind(..)
-                | ty::Predicate::Subtype(..)
-                | ty::Predicate::ConstEvaluatable(..) => None,
-            }
-        })
-        .collect()
-}
-
-fn trait_has_sized_self(tcx: TyCtxt<'_>, trait_def_id: DefId) -> bool {
-    generics_require_sized_self(tcx, trait_def_id)
-}
-
-fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
-    let sized_def_id = match tcx.lang_items().sized_trait() {
-        Some(def_id) => def_id,
-        None => {
-            return false; /* No Sized trait, can't require it! */
-        }
-    };
-
-    // Search for a predicate like `Self : Sized` amongst the trait bounds.
-    let predicates = tcx.predicates_of(def_id);
-    let predicates = predicates.instantiate_identity(tcx).predicates;
-    elaborate_predicates(tcx, predicates).any(|predicate| match predicate {
-        ty::Predicate::Trait(ref trait_pred, _) => {
-            trait_pred.def_id() == sized_def_id && trait_pred.skip_binder().self_ty().is_param(0)
-        }
-        ty::Predicate::Projection(..)
-        | ty::Predicate::Subtype(..)
-        | ty::Predicate::RegionOutlives(..)
-        | ty::Predicate::WellFormed(..)
-        | ty::Predicate::ObjectSafe(..)
-        | ty::Predicate::ClosureKind(..)
-        | ty::Predicate::TypeOutlives(..)
-        | ty::Predicate::ConstEvaluatable(..) => false,
-    })
-}
-
-/// Returns `Some(_)` if this method makes the containing trait not object safe.
-fn object_safety_violation_for_method(
-    tcx: TyCtxt<'_>,
-    trait_def_id: DefId,
-    method: &ty::AssocItem,
-) -> Option<(MethodViolationCode, Span)> {
-    debug!("object_safety_violation_for_method({:?}, {:?})", trait_def_id, method);
-    // Any method that has a `Self : Sized` requisite is otherwise
-    // exempt from the regulations.
-    if generics_require_sized_self(tcx, method.def_id) {
-        return None;
-    }
-
-    let violation = virtual_call_violation_for_method(tcx, trait_def_id, method);
-    // Get an accurate span depending on the violation.
-    violation.map(|v| {
-        let node = tcx.hir().get_if_local(method.def_id);
-        let span = match (v, node) {
-            (MethodViolationCode::ReferencesSelfInput(arg), Some(node)) => node
-                .fn_decl()
-                .and_then(|decl| decl.inputs.get(arg + 1))
-                .map_or(method.ident.span, |arg| arg.span),
-            (MethodViolationCode::UndispatchableReceiver, Some(node)) => node
-                .fn_decl()
-                .and_then(|decl| decl.inputs.get(0))
-                .map_or(method.ident.span, |arg| arg.span),
-            (MethodViolationCode::ReferencesSelfOutput, Some(node)) => {
-                node.fn_decl().map_or(method.ident.span, |decl| decl.output.span())
-            }
-            _ => method.ident.span,
-        };
-        (v, span)
-    })
-}
-
-/// Returns `Some(_)` if this method cannot be called on a trait
-/// object; this does not necessarily imply that the enclosing trait
-/// is not object safe, because the method might have a where clause
-/// `Self:Sized`.
-fn virtual_call_violation_for_method<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    trait_def_id: DefId,
-    method: &ty::AssocItem,
-) -> Option<MethodViolationCode> {
-    // The method's first parameter must be named `self`
-    if !method.method_has_self_argument {
-        // We'll attempt to provide a structured suggestion for `Self: Sized`.
-        let sugg =
-            tcx.hir().get_if_local(method.def_id).as_ref().and_then(|node| node.generics()).map(
-                |generics| match generics.where_clause.predicates {
-                    [] => (" where Self: Sized", generics.where_clause.span),
-                    [.., pred] => (", Self: Sized", pred.span().shrink_to_hi()),
-                },
-            );
-        return Some(MethodViolationCode::StaticMethod(sugg));
-    }
-
-    let sig = tcx.fn_sig(method.def_id);
-
-    for (i, input_ty) in sig.skip_binder().inputs()[1..].iter().enumerate() {
-        if contains_illegal_self_type_reference(tcx, trait_def_id, input_ty) {
-            return Some(MethodViolationCode::ReferencesSelfInput(i));
-        }
-    }
-    if contains_illegal_self_type_reference(tcx, trait_def_id, sig.output().skip_binder()) {
-        return Some(MethodViolationCode::ReferencesSelfOutput);
-    }
-
-    // We can't monomorphize things like `fn foo<A>(...)`.
-    let own_counts = tcx.generics_of(method.def_id).own_counts();
-    if own_counts.types + own_counts.consts != 0 {
-        return Some(MethodViolationCode::Generic);
-    }
-
-    if tcx
-        .predicates_of(method.def_id)
-        .predicates
-        .iter()
-        // A trait object can't claim to live more than the concrete type,
-        // so outlives predicates will always hold.
-        .cloned()
-        .filter(|(p, _)| p.to_opt_type_outlives().is_none())
-        .collect::<Vec<_>>()
-        // Do a shallow visit so that `contains_illegal_self_type_reference`
-        // may apply it's custom visiting.
-        .visit_tys_shallow(|t| contains_illegal_self_type_reference(tcx, trait_def_id, t))
-    {
-        return Some(MethodViolationCode::WhereClauseReferencesSelf);
-    }
-
-    let receiver_ty =
-        tcx.liberate_late_bound_regions(method.def_id, &sig.map_bound(|sig| sig.inputs()[0]));
-
-    // Until `unsized_locals` is fully implemented, `self: Self` can't be dispatched on.
-    // However, this is already considered object-safe. We allow it as a special case here.
-    // FIXME(mikeyhew) get rid of this `if` statement once `receiver_is_dispatchable` allows
-    // `Receiver: Unsize<Receiver[Self => dyn Trait]>`.
-    if receiver_ty != tcx.types.self_param {
-        if !receiver_is_dispatchable(tcx, method, receiver_ty) {
-            return Some(MethodViolationCode::UndispatchableReceiver);
-        } else {
-            // Do sanity check to make sure the receiver actually has the layout of a pointer.
-
-            use rustc::ty::layout::Abi;
-
-            let param_env = tcx.param_env(method.def_id);
-
-            let abi_of_ty = |ty: Ty<'tcx>| -> &Abi {
-                match tcx.layout_of(param_env.and(ty)) {
-                    Ok(layout) => &layout.abi,
-                    Err(err) => bug!("error: {}\n while computing layout for type {:?}", err, ty),
-                }
-            };
-
-            // e.g., `Rc<()>`
-            let unit_receiver_ty =
-                receiver_for_self_ty(tcx, receiver_ty, tcx.mk_unit(), method.def_id);
-
-            match abi_of_ty(unit_receiver_ty) {
-                &Abi::Scalar(..) => (),
-                abi => {
-                    tcx.sess.delay_span_bug(
-                        tcx.def_span(method.def_id),
-                        &format!(
-                            "receiver when `Self = ()` should have a Scalar ABI; found {:?}",
-                            abi
-                        ),
-                    );
-                }
-            }
-
-            let trait_object_ty =
-                object_ty_for_trait(tcx, trait_def_id, tcx.mk_region(ty::ReStatic));
-
-            // e.g., `Rc<dyn Trait>`
-            let trait_object_receiver =
-                receiver_for_self_ty(tcx, receiver_ty, trait_object_ty, method.def_id);
-
-            match abi_of_ty(trait_object_receiver) {
-                &Abi::ScalarPair(..) => (),
-                abi => {
-                    tcx.sess.delay_span_bug(
-                        tcx.def_span(method.def_id),
-                        &format!(
-                            "receiver when `Self = {}` should have a ScalarPair ABI; \
-                                 found {:?}",
-                            trait_object_ty, abi
-                        ),
-                    );
-                }
-            }
-        }
-    }
-
-    None
-}
-
-/// Performs a type substitution to produce the version of `receiver_ty` when `Self = self_ty`.
-/// For example, for `receiver_ty = Rc<Self>` and `self_ty = Foo`, returns `Rc<Foo>`.
-fn receiver_for_self_ty<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    receiver_ty: Ty<'tcx>,
-    self_ty: Ty<'tcx>,
-    method_def_id: DefId,
-) -> Ty<'tcx> {
-    debug!("receiver_for_self_ty({:?}, {:?}, {:?})", receiver_ty, self_ty, method_def_id);
-    let substs = InternalSubsts::for_item(tcx, method_def_id, |param, _| {
-        if param.index == 0 { self_ty.into() } else { tcx.mk_param_from_def(param) }
-    });
-
-    let result = receiver_ty.subst(tcx, substs);
-    debug!(
-        "receiver_for_self_ty({:?}, {:?}, {:?}) = {:?}",
-        receiver_ty, self_ty, method_def_id, result
-    );
-    result
-}
-
-/// Creates the object type for the current trait. For example,
-/// if the current trait is `Deref`, then this will be
-/// `dyn Deref<Target = Self::Target> + 'static`.
-fn object_ty_for_trait<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    trait_def_id: DefId,
-    lifetime: ty::Region<'tcx>,
-) -> Ty<'tcx> {
-    debug!("object_ty_for_trait: trait_def_id={:?}", trait_def_id);
-
-    let trait_ref = ty::TraitRef::identity(tcx, trait_def_id);
-
-    let trait_predicate =
-        ty::ExistentialPredicate::Trait(ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref));
-
-    let mut associated_types = traits::supertraits(tcx, ty::Binder::dummy(trait_ref))
-        .flat_map(|super_trait_ref| {
-            tcx.associated_items(super_trait_ref.def_id())
-                .in_definition_order()
-                .map(move |item| (super_trait_ref, item))
-        })
-        .filter(|(_, item)| item.kind == ty::AssocKind::Type)
-        .collect::<Vec<_>>();
-
-    // existential predicates need to be in a specific order
-    associated_types.sort_by_cached_key(|(_, item)| tcx.def_path_hash(item.def_id));
-
-    let projection_predicates = associated_types.into_iter().map(|(super_trait_ref, item)| {
-        // We *can* get bound lifetimes here in cases like
-        // `trait MyTrait: for<'s> OtherTrait<&'s T, Output=bool>`.
-        //
-        // binder moved to (*)...
-        let super_trait_ref = super_trait_ref.skip_binder();
-        ty::ExistentialPredicate::Projection(ty::ExistentialProjection {
-            ty: tcx.mk_projection(item.def_id, super_trait_ref.substs),
-            item_def_id: item.def_id,
-            substs: super_trait_ref.substs,
-        })
-    });
-
-    let existential_predicates =
-        tcx.mk_existential_predicates(iter::once(trait_predicate).chain(projection_predicates));
-
-    let object_ty = tcx.mk_dynamic(
-        // (*) ... binder re-introduced here
-        ty::Binder::bind(existential_predicates),
-        lifetime,
-    );
-
-    debug!("object_ty_for_trait: object_ty=`{}`", object_ty);
-
-    object_ty
-}
-
-/// Checks the method's receiver (the `self` argument) can be dispatched on when `Self` is a
-/// trait object. We require that `DispatchableFromDyn` be implemented for the receiver type
-/// in the following way:
-/// - let `Receiver` be the type of the `self` argument, i.e `Self`, `&Self`, `Rc<Self>`,
-/// - require the following bound:
-///
-///   ```
-///   Receiver[Self => T]: DispatchFromDyn<Receiver[Self => dyn Trait]>
-///   ```
-///
-///   where `Foo[X => Y]` means "the same type as `Foo`, but with `X` replaced with `Y`"
-///   (substitution notation).
-///
-/// Some examples of receiver types and their required obligation:
-/// - `&'a mut self` requires `&'a mut Self: DispatchFromDyn<&'a mut dyn Trait>`,
-/// - `self: Rc<Self>` requires `Rc<Self>: DispatchFromDyn<Rc<dyn Trait>>`,
-/// - `self: Pin<Box<Self>>` requires `Pin<Box<Self>>: DispatchFromDyn<Pin<Box<dyn Trait>>>`.
-///
-/// The only case where the receiver is not dispatchable, but is still a valid receiver
-/// type (just not object-safe), is when there is more than one level of pointer indirection.
-/// E.g., `self: &&Self`, `self: &Rc<Self>`, `self: Box<Box<Self>>`. In these cases, there
-/// is no way, or at least no inexpensive way, to coerce the receiver from the version where
-/// `Self = dyn Trait` to the version where `Self = T`, where `T` is the unknown erased type
-/// contained by the trait object, because the object that needs to be coerced is behind
-/// a pointer.
-///
-/// In practice, we cannot use `dyn Trait` explicitly in the obligation because it would result
-/// in a new check that `Trait` is object safe, creating a cycle (until object_safe_for_dispatch
-/// is stabilized, see tracking issue https://github.com/rust-lang/rust/issues/43561).
-/// Instead, we fudge a little by introducing a new type parameter `U` such that
-/// `Self: Unsize<U>` and `U: Trait + ?Sized`, and use `U` in place of `dyn Trait`.
-/// Written as a chalk-style query:
-///
-///     forall (U: Trait + ?Sized) {
-///         if (Self: Unsize<U>) {
-///             Receiver: DispatchFromDyn<Receiver[Self => U]>
-///         }
-///     }
-///
-/// for `self: &'a mut Self`, this means `&'a mut Self: DispatchFromDyn<&'a mut U>`
-/// for `self: Rc<Self>`, this means `Rc<Self>: DispatchFromDyn<Rc<U>>`
-/// for `self: Pin<Box<Self>>`, this means `Pin<Box<Self>>: DispatchFromDyn<Pin<Box<U>>>`
-//
-// FIXME(mikeyhew) when unsized receivers are implemented as part of unsized rvalues, add this
-// fallback query: `Receiver: Unsize<Receiver[Self => U]>` to support receivers like
-// `self: Wrapper<Self>`.
-#[allow(dead_code)]
-fn receiver_is_dispatchable<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    method: &ty::AssocItem,
-    receiver_ty: Ty<'tcx>,
-) -> bool {
-    debug!("receiver_is_dispatchable: method = {:?}, receiver_ty = {:?}", method, receiver_ty);
-
-    let traits = (tcx.lang_items().unsize_trait(), tcx.lang_items().dispatch_from_dyn_trait());
-    let (unsize_did, dispatch_from_dyn_did) = if let (Some(u), Some(cu)) = traits {
-        (u, cu)
-    } else {
-        debug!("receiver_is_dispatchable: Missing Unsize or DispatchFromDyn traits");
-        return false;
-    };
-
-    // the type `U` in the query
-    // use a bogus type parameter to mimick a forall(U) query using u32::MAX for now.
-    // FIXME(mikeyhew) this is a total hack. Once object_safe_for_dispatch is stabilized, we can
-    // replace this with `dyn Trait`
-    let unsized_self_ty: Ty<'tcx> =
-        tcx.mk_ty_param(::std::u32::MAX, Symbol::intern("RustaceansAreAwesome"));
-
-    // `Receiver[Self => U]`
-    let unsized_receiver_ty =
-        receiver_for_self_ty(tcx, receiver_ty, unsized_self_ty, method.def_id);
-
-    // create a modified param env, with `Self: Unsize<U>` and `U: Trait` added to caller bounds
-    // `U: ?Sized` is already implied here
-    let param_env = {
-        let mut param_env = tcx.param_env(method.def_id);
-
-        // Self: Unsize<U>
-        let unsize_predicate = ty::TraitRef {
-            def_id: unsize_did,
-            substs: tcx.mk_substs_trait(tcx.types.self_param, &[unsized_self_ty.into()]),
-        }
-        .without_const()
-        .to_predicate();
-
-        // U: Trait<Arg1, ..., ArgN>
-        let trait_predicate = {
-            let substs =
-                InternalSubsts::for_item(tcx, method.container.assert_trait(), |param, _| {
-                    if param.index == 0 {
-                        unsized_self_ty.into()
-                    } else {
-                        tcx.mk_param_from_def(param)
-                    }
-                });
-
-            ty::TraitRef { def_id: unsize_did, substs }.without_const().to_predicate()
-        };
-
-        let caller_bounds: Vec<Predicate<'tcx>> = param_env
-            .caller_bounds
-            .iter()
-            .cloned()
-            .chain(iter::once(unsize_predicate))
-            .chain(iter::once(trait_predicate))
-            .collect();
-
-        param_env.caller_bounds = tcx.intern_predicates(&caller_bounds);
-
-        param_env
-    };
-
-    // Receiver: DispatchFromDyn<Receiver[Self => U]>
-    let obligation = {
-        let predicate = ty::TraitRef {
-            def_id: dispatch_from_dyn_did,
-            substs: tcx.mk_substs_trait(receiver_ty, &[unsized_receiver_ty.into()]),
-        }
-        .without_const()
-        .to_predicate();
-
-        Obligation::new(ObligationCause::dummy(), param_env, predicate)
-    };
-
-    tcx.infer_ctxt().enter(|ref infcx| {
-        // the receiver is dispatchable iff the obligation holds
-        infcx.predicate_must_hold_modulo_regions(&obligation)
-    })
-}
-
-fn contains_illegal_self_type_reference<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    trait_def_id: DefId,
-    ty: Ty<'tcx>,
-) -> bool {
-    // This is somewhat subtle. In general, we want to forbid
-    // references to `Self` in the argument and return types,
-    // since the value of `Self` is erased. However, there is one
-    // exception: it is ok to reference `Self` in order to access
-    // an associated type of the current trait, since we retain
-    // the value of those associated types in the object type
-    // itself.
-    //
-    // ```rust
-    // trait SuperTrait {
-    //     type X;
-    // }
-    //
-    // trait Trait : SuperTrait {
-    //     type Y;
-    //     fn foo(&self, x: Self) // bad
-    //     fn foo(&self) -> Self // bad
-    //     fn foo(&self) -> Option<Self> // bad
-    //     fn foo(&self) -> Self::Y // OK, desugars to next example
-    //     fn foo(&self) -> <Self as Trait>::Y // OK
-    //     fn foo(&self) -> Self::X // OK, desugars to next example
-    //     fn foo(&self) -> <Self as SuperTrait>::X // OK
-    // }
-    // ```
-    //
-    // However, it is not as simple as allowing `Self` in a projected
-    // type, because there are illegal ways to use `Self` as well:
-    //
-    // ```rust
-    // trait Trait : SuperTrait {
-    //     ...
-    //     fn foo(&self) -> <Self as SomeOtherTrait>::X;
-    // }
-    // ```
-    //
-    // Here we will not have the type of `X` recorded in the
-    // object type, and we cannot resolve `Self as SomeOtherTrait`
-    // without knowing what `Self` is.
-
-    let mut supertraits: Option<Vec<ty::PolyTraitRef<'tcx>>> = None;
-    let mut error = false;
-    let self_ty = tcx.types.self_param;
-    ty.maybe_walk(|ty| {
-        match ty.kind {
-            ty::Param(_) => {
-                if ty == self_ty {
-                    error = true;
-                }
-
-                false // no contained types to walk
-            }
-
-            ty::Projection(ref data) => {
-                // This is a projected type `<Foo as SomeTrait>::X`.
-
-                // Compute supertraits of current trait lazily.
-                if supertraits.is_none() {
-                    let trait_ref = ty::Binder::bind(ty::TraitRef::identity(tcx, trait_def_id));
-                    supertraits = Some(traits::supertraits(tcx, trait_ref).collect());
-                }
-
-                // Determine whether the trait reference `Foo as
-                // SomeTrait` is in fact a supertrait of the
-                // current trait. In that case, this type is
-                // legal, because the type `X` will be specified
-                // in the object type.  Note that we can just use
-                // direct equality here because all of these types
-                // are part of the formal parameter listing, and
-                // hence there should be no inference variables.
-                let projection_trait_ref = ty::Binder::bind(data.trait_ref(tcx));
-                let is_supertrait_of_current_trait =
-                    supertraits.as_ref().unwrap().contains(&projection_trait_ref);
-
-                if is_supertrait_of_current_trait {
-                    false // do not walk contained types, do not report error, do collect $200
-                } else {
-                    true // DO walk contained types, POSSIBLY reporting an error
-                }
-            }
-
-            _ => true, // walk contained types, if any
-        }
-    });
-
-    error
-}
-
-pub fn provide(providers: &mut ty::query::Providers<'_>) {
-    *providers = ty::query::Providers { object_safety_violations, ..*providers };
-}
diff --git a/src/librustc_infer/traits/on_unimplemented.rs b/src/librustc_infer/traits/on_unimplemented.rs
deleted file mode 100644 (file)
index 1926029..0000000
+++ /dev/null
@@ -1,383 +0,0 @@
-use fmt_macros::{Parser, Piece, Position};
-
-use rustc::ty::{self, GenericParamDefKind, TyCtxt};
-use rustc::util::common::ErrorReported;
-
-use rustc_ast::ast::{MetaItem, NestedMetaItem};
-use rustc_attr as attr;
-use rustc_data_structures::fx::FxHashMap;
-use rustc_errors::struct_span_err;
-use rustc_hir::def_id::DefId;
-use rustc_span::symbol::{kw, sym, Symbol};
-use rustc_span::Span;
-
-#[derive(Clone, Debug)]
-pub struct OnUnimplementedFormatString(Symbol);
-
-#[derive(Debug)]
-pub struct OnUnimplementedDirective {
-    pub condition: Option<MetaItem>,
-    pub subcommands: Vec<OnUnimplementedDirective>,
-    pub message: Option<OnUnimplementedFormatString>,
-    pub label: Option<OnUnimplementedFormatString>,
-    pub note: Option<OnUnimplementedFormatString>,
-    pub enclosing_scope: Option<OnUnimplementedFormatString>,
-}
-
-#[derive(Default)]
-pub struct OnUnimplementedNote {
-    pub message: Option<String>,
-    pub label: Option<String>,
-    pub note: Option<String>,
-    pub enclosing_scope: Option<String>,
-}
-
-fn parse_error(
-    tcx: TyCtxt<'_>,
-    span: Span,
-    message: &str,
-    label: &str,
-    note: Option<&str>,
-) -> ErrorReported {
-    let mut diag = struct_span_err!(tcx.sess, span, E0232, "{}", message);
-    diag.span_label(span, label);
-    if let Some(note) = note {
-        diag.note(note);
-    }
-    diag.emit();
-    ErrorReported
-}
-
-impl<'tcx> OnUnimplementedDirective {
-    fn parse(
-        tcx: TyCtxt<'tcx>,
-        trait_def_id: DefId,
-        items: &[NestedMetaItem],
-        span: Span,
-        is_root: bool,
-    ) -> Result<Self, ErrorReported> {
-        let mut errored = false;
-        let mut item_iter = items.iter();
-
-        let condition = if is_root {
-            None
-        } else {
-            let cond = item_iter
-                .next()
-                .ok_or_else(|| {
-                    parse_error(
-                        tcx,
-                        span,
-                        "empty `on`-clause in `#[rustc_on_unimplemented]`",
-                        "empty on-clause here",
-                        None,
-                    )
-                })?
-                .meta_item()
-                .ok_or_else(|| {
-                    parse_error(
-                        tcx,
-                        span,
-                        "invalid `on`-clause in `#[rustc_on_unimplemented]`",
-                        "invalid on-clause here",
-                        None,
-                    )
-                })?;
-            attr::eval_condition(cond, &tcx.sess.parse_sess, &mut |_| true);
-            Some(cond.clone())
-        };
-
-        let mut message = None;
-        let mut label = None;
-        let mut note = None;
-        let mut enclosing_scope = None;
-        let mut subcommands = vec![];
-
-        let parse_value = |value_str| {
-            OnUnimplementedFormatString::try_parse(tcx, trait_def_id, value_str, span).map(Some)
-        };
-
-        for item in item_iter {
-            if item.check_name(sym::message) && message.is_none() {
-                if let Some(message_) = item.value_str() {
-                    message = parse_value(message_)?;
-                    continue;
-                }
-            } else if item.check_name(sym::label) && label.is_none() {
-                if let Some(label_) = item.value_str() {
-                    label = parse_value(label_)?;
-                    continue;
-                }
-            } else if item.check_name(sym::note) && note.is_none() {
-                if let Some(note_) = item.value_str() {
-                    note = parse_value(note_)?;
-                    continue;
-                }
-            } else if item.check_name(sym::enclosing_scope) && enclosing_scope.is_none() {
-                if let Some(enclosing_scope_) = item.value_str() {
-                    enclosing_scope = parse_value(enclosing_scope_)?;
-                    continue;
-                }
-            } else if item.check_name(sym::on)
-                && is_root
-                && message.is_none()
-                && label.is_none()
-                && note.is_none()
-            {
-                if let Some(items) = item.meta_item_list() {
-                    if let Ok(subcommand) =
-                        Self::parse(tcx, trait_def_id, &items, item.span(), false)
-                    {
-                        subcommands.push(subcommand);
-                    } else {
-                        errored = true;
-                    }
-                    continue;
-                }
-            }
-
-            // nothing found
-            parse_error(
-                tcx,
-                item.span(),
-                "this attribute must have a valid value",
-                "expected value here",
-                Some(r#"eg `#[rustc_on_unimplemented(message="foo")]`"#),
-            );
-        }
-
-        if errored {
-            Err(ErrorReported)
-        } else {
-            Ok(OnUnimplementedDirective {
-                condition,
-                subcommands,
-                message,
-                label,
-                note,
-                enclosing_scope,
-            })
-        }
-    }
-
-    pub fn of_item(
-        tcx: TyCtxt<'tcx>,
-        trait_def_id: DefId,
-        impl_def_id: DefId,
-    ) -> Result<Option<Self>, ErrorReported> {
-        let attrs = tcx.get_attrs(impl_def_id);
-
-        let attr = if let Some(item) = attr::find_by_name(&attrs, sym::rustc_on_unimplemented) {
-            item
-        } else {
-            return Ok(None);
-        };
-
-        let result = if let Some(items) = attr.meta_item_list() {
-            Self::parse(tcx, trait_def_id, &items, attr.span, true).map(Some)
-        } else if let Some(value) = attr.value_str() {
-            Ok(Some(OnUnimplementedDirective {
-                condition: None,
-                message: None,
-                subcommands: vec![],
-                label: Some(OnUnimplementedFormatString::try_parse(
-                    tcx,
-                    trait_def_id,
-                    value,
-                    attr.span,
-                )?),
-                note: None,
-                enclosing_scope: None,
-            }))
-        } else {
-            return Err(ErrorReported);
-        };
-        debug!("of_item({:?}/{:?}) = {:?}", trait_def_id, impl_def_id, result);
-        result
-    }
-
-    pub fn evaluate(
-        &self,
-        tcx: TyCtxt<'tcx>,
-        trait_ref: ty::TraitRef<'tcx>,
-        options: &[(Symbol, Option<String>)],
-    ) -> OnUnimplementedNote {
-        let mut message = None;
-        let mut label = None;
-        let mut note = None;
-        let mut enclosing_scope = None;
-        info!("evaluate({:?}, trait_ref={:?}, options={:?})", self, trait_ref, options);
-
-        for command in self.subcommands.iter().chain(Some(self)).rev() {
-            if let Some(ref condition) = command.condition {
-                if !attr::eval_condition(condition, &tcx.sess.parse_sess, &mut |c| {
-                    c.ident().map_or(false, |ident| {
-                        options.contains(&(ident.name, c.value_str().map(|s| s.to_string())))
-                    })
-                }) {
-                    debug!("evaluate: skipping {:?} due to condition", command);
-                    continue;
-                }
-            }
-            debug!("evaluate: {:?} succeeded", command);
-            if let Some(ref message_) = command.message {
-                message = Some(message_.clone());
-            }
-
-            if let Some(ref label_) = command.label {
-                label = Some(label_.clone());
-            }
-
-            if let Some(ref note_) = command.note {
-                note = Some(note_.clone());
-            }
-
-            if let Some(ref enclosing_scope_) = command.enclosing_scope {
-                enclosing_scope = Some(enclosing_scope_.clone());
-            }
-        }
-
-        let options: FxHashMap<Symbol, String> =
-            options.iter().filter_map(|(k, v)| v.as_ref().map(|v| (*k, v.to_owned()))).collect();
-        OnUnimplementedNote {
-            label: label.map(|l| l.format(tcx, trait_ref, &options)),
-            message: message.map(|m| m.format(tcx, trait_ref, &options)),
-            note: note.map(|n| n.format(tcx, trait_ref, &options)),
-            enclosing_scope: enclosing_scope.map(|e_s| e_s.format(tcx, trait_ref, &options)),
-        }
-    }
-}
-
-impl<'tcx> OnUnimplementedFormatString {
-    fn try_parse(
-        tcx: TyCtxt<'tcx>,
-        trait_def_id: DefId,
-        from: Symbol,
-        err_sp: Span,
-    ) -> Result<Self, ErrorReported> {
-        let result = OnUnimplementedFormatString(from);
-        result.verify(tcx, trait_def_id, err_sp)?;
-        Ok(result)
-    }
-
-    fn verify(
-        &self,
-        tcx: TyCtxt<'tcx>,
-        trait_def_id: DefId,
-        span: Span,
-    ) -> Result<(), ErrorReported> {
-        let name = tcx.item_name(trait_def_id);
-        let generics = tcx.generics_of(trait_def_id);
-        let s = self.0.as_str();
-        let parser = Parser::new(&s, None, vec![], false);
-        let mut result = Ok(());
-        for token in parser {
-            match token {
-                Piece::String(_) => (), // Normal string, no need to check it
-                Piece::NextArgument(a) => match a.position {
-                    // `{Self}` is allowed
-                    Position::ArgumentNamed(s) if s == kw::SelfUpper => (),
-                    // `{ThisTraitsName}` is allowed
-                    Position::ArgumentNamed(s) if s == name => (),
-                    // `{from_method}` is allowed
-                    Position::ArgumentNamed(s) if s == sym::from_method => (),
-                    // `{from_desugaring}` is allowed
-                    Position::ArgumentNamed(s) if s == sym::from_desugaring => (),
-                    // `{ItemContext}` is allowed
-                    Position::ArgumentNamed(s) if s == sym::item_context => (),
-                    // So is `{A}` if A is a type parameter
-                    Position::ArgumentNamed(s) => {
-                        match generics.params.iter().find(|param| param.name == s) {
-                            Some(_) => (),
-                            None => {
-                                struct_span_err!(
-                                    tcx.sess,
-                                    span,
-                                    E0230,
-                                    "there is no parameter `{}` on trait `{}`",
-                                    s,
-                                    name
-                                )
-                                .emit();
-                                result = Err(ErrorReported);
-                            }
-                        }
-                    }
-                    // `{:1}` and `{}` are not to be used
-                    Position::ArgumentIs(_) | Position::ArgumentImplicitlyIs(_) => {
-                        struct_span_err!(
-                            tcx.sess,
-                            span,
-                            E0231,
-                            "only named substitution parameters are allowed"
-                        )
-                        .emit();
-                        result = Err(ErrorReported);
-                    }
-                },
-            }
-        }
-
-        result
-    }
-
-    pub fn format(
-        &self,
-        tcx: TyCtxt<'tcx>,
-        trait_ref: ty::TraitRef<'tcx>,
-        options: &FxHashMap<Symbol, String>,
-    ) -> String {
-        let name = tcx.item_name(trait_ref.def_id);
-        let trait_str = tcx.def_path_str(trait_ref.def_id);
-        let generics = tcx.generics_of(trait_ref.def_id);
-        let generic_map = generics
-            .params
-            .iter()
-            .filter_map(|param| {
-                let value = match param.kind {
-                    GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => {
-                        trait_ref.substs[param.index as usize].to_string()
-                    }
-                    GenericParamDefKind::Lifetime => return None,
-                };
-                let name = param.name;
-                Some((name, value))
-            })
-            .collect::<FxHashMap<Symbol, String>>();
-        let empty_string = String::new();
-
-        let s = self.0.as_str();
-        let parser = Parser::new(&s, None, vec![], false);
-        let item_context = (options.get(&sym::item_context)).unwrap_or(&empty_string);
-        parser
-            .map(|p| match p {
-                Piece::String(s) => s,
-                Piece::NextArgument(a) => match a.position {
-                    Position::ArgumentNamed(s) => match generic_map.get(&s) {
-                        Some(val) => val,
-                        None if s == name => &trait_str,
-                        None => {
-                            if let Some(val) = options.get(&s) {
-                                val
-                            } else if s == sym::from_desugaring || s == sym::from_method {
-                                // don't break messages using these two arguments incorrectly
-                                &empty_string
-                            } else if s == sym::item_context {
-                                &item_context
-                            } else {
-                                bug!(
-                                    "broken on_unimplemented {:?} for {:?}: \
-                                      no argument matching {:?}",
-                                    self.0,
-                                    trait_ref,
-                                    s
-                                )
-                            }
-                        }
-                    },
-                    _ => bug!("broken on_unimplemented {:?} - bad format arg", self.0),
-                },
-            })
-            .collect()
-    }
-}
index cbe24320502a203d4c7efecfb3934e267a4b6186..183e4be189022df4e6a6b7ab89b869e30bd50ca6 100644 (file)
 //! Code for projecting associated types out of trait references.
 
-use super::elaborate_predicates;
-use super::specialization_graph;
-use super::translate_substs;
-use super::util;
-use super::Obligation;
-use super::ObligationCause;
 use super::PredicateObligation;
-use super::Selection;
-use super::SelectionContext;
-use super::SelectionError;
-use super::{VtableClosureData, VtableFnPointerData, VtableGeneratorData, VtableImplData};
 
-use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
-use crate::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime};
-use rustc::ty::fold::{TypeFoldable, TypeFolder};
-use rustc::ty::subst::{InternalSubsts, Subst};
-use rustc::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, WithConstness};
-use rustc_ast::ast::Ident;
+use rustc::ty::fold::TypeFoldable;
+use rustc::ty::{self, Ty};
 use rustc_data_structures::snapshot_map::{Snapshot, SnapshotMap};
-use rustc_hir::def_id::DefId;
-use rustc_span::symbol::sym;
-use rustc_span::DUMMY_SP;
 
 pub use rustc::traits::Reveal;
 
-pub type PolyProjectionObligation<'tcx> = Obligation<'tcx, ty::PolyProjectionPredicate<'tcx>>;
-
-pub type ProjectionObligation<'tcx> = Obligation<'tcx, ty::ProjectionPredicate<'tcx>>;
-
-pub type ProjectionTyObligation<'tcx> = Obligation<'tcx, ty::ProjectionTy<'tcx>>;
-
-/// When attempting to resolve `<T as TraitRef>::Name` ...
-#[derive(Debug)]
-pub enum ProjectionTyError<'tcx> {
-    /// ...we found multiple sources of information and couldn't resolve the ambiguity.
-    TooManyCandidates,
-
-    /// ...an error occurred matching `T : TraitRef`
-    TraitSelectionError(SelectionError<'tcx>),
-}
-
 #[derive(Clone)]
 pub struct MismatchedProjectionTypes<'tcx> {
     pub err: ty::error::TypeError<'tcx>,
 }
 
-#[derive(PartialEq, Eq, Debug)]
-enum ProjectionTyCandidate<'tcx> {
-    // from a where-clause in the env or object type
-    ParamEnv(ty::PolyProjectionPredicate<'tcx>),
-
-    // from the definition of `Trait` when you have something like <<A as Trait>::B as Trait2>::C
-    TraitDef(ty::PolyProjectionPredicate<'tcx>),
-
-    // from a "impl" (or a "pseudo-impl" returned by select)
-    Select(Selection<'tcx>),
-}
-
-enum ProjectionTyCandidateSet<'tcx> {
-    None,
-    Single(ProjectionTyCandidate<'tcx>),
-    Ambiguous,
-    Error(SelectionError<'tcx>),
-}
-
-impl<'tcx> ProjectionTyCandidateSet<'tcx> {
-    fn mark_ambiguous(&mut self) {
-        *self = ProjectionTyCandidateSet::Ambiguous;
-    }
-
-    fn mark_error(&mut self, err: SelectionError<'tcx>) {
-        *self = ProjectionTyCandidateSet::Error(err);
-    }
-
-    // Returns true if the push was successful, or false if the candidate
-    // was discarded -- this could be because of ambiguity, or because
-    // a higher-priority candidate is already there.
-    fn push_candidate(&mut self, candidate: ProjectionTyCandidate<'tcx>) -> bool {
-        use self::ProjectionTyCandidate::*;
-        use self::ProjectionTyCandidateSet::*;
-
-        // This wacky variable is just used to try and
-        // make code readable and avoid confusing paths.
-        // It is assigned a "value" of `()` only on those
-        // paths in which we wish to convert `*self` to
-        // ambiguous (and return false, because the candidate
-        // was not used). On other paths, it is not assigned,
-        // and hence if those paths *could* reach the code that
-        // comes after the match, this fn would not compile.
-        let convert_to_ambiguous;
-
-        match self {
-            None => {
-                *self = Single(candidate);
-                return true;
-            }
-
-            Single(current) => {
-                // Duplicates can happen inside ParamEnv. In the case, we
-                // perform a lazy deduplication.
-                if current == &candidate {
-                    return false;
-                }
-
-                // Prefer where-clauses. As in select, if there are multiple
-                // candidates, we prefer where-clause candidates over impls.  This
-                // may seem a bit surprising, since impls are the source of
-                // "truth" in some sense, but in fact some of the impls that SEEM
-                // applicable are not, because of nested obligations. Where
-                // clauses are the safer choice. See the comment on
-                // `select::SelectionCandidate` and #21974 for more details.
-                match (current, candidate) {
-                    (ParamEnv(..), ParamEnv(..)) => convert_to_ambiguous = (),
-                    (ParamEnv(..), _) => return false,
-                    (_, ParamEnv(..)) => unreachable!(),
-                    (_, _) => convert_to_ambiguous = (),
-                }
-            }
-
-            Ambiguous | Error(..) => {
-                return false;
-            }
-        }
-
-        // We only ever get here when we moved from a single candidate
-        // to ambiguous.
-        let () = convert_to_ambiguous;
-        *self = Ambiguous;
-        false
-    }
-}
-
-/// Evaluates constraints of the form:
-///
-///     for<...> <T as Trait>::U == V
-///
-/// If successful, this may result in additional obligations. Also returns
-/// the projection cache key used to track these additional obligations.
-pub fn poly_project_and_unify_type<'cx, 'tcx>(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &PolyProjectionObligation<'tcx>,
-) -> Result<Option<Vec<PredicateObligation<'tcx>>>, MismatchedProjectionTypes<'tcx>> {
-    debug!("poly_project_and_unify_type(obligation={:?})", obligation);
-
-    let infcx = selcx.infcx();
-    infcx.commit_if_ok(|snapshot| {
-        let (placeholder_predicate, placeholder_map) =
-            infcx.replace_bound_vars_with_placeholders(&obligation.predicate);
-
-        let placeholder_obligation = obligation.with(placeholder_predicate);
-        let result = project_and_unify_type(selcx, &placeholder_obligation)?;
-        infcx
-            .leak_check(false, &placeholder_map, snapshot)
-            .map_err(|err| MismatchedProjectionTypes { err })?;
-        Ok(result)
-    })
-}
-
-/// Evaluates constraints of the form:
-///
-///     <T as Trait>::U == V
-///
-/// If successful, this may result in additional obligations.
-fn project_and_unify_type<'cx, 'tcx>(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionObligation<'tcx>,
-) -> Result<Option<Vec<PredicateObligation<'tcx>>>, MismatchedProjectionTypes<'tcx>> {
-    debug!("project_and_unify_type(obligation={:?})", obligation);
-
-    let mut obligations = vec![];
-    let normalized_ty = match opt_normalize_projection_type(
-        selcx,
-        obligation.param_env,
-        obligation.predicate.projection_ty,
-        obligation.cause.clone(),
-        obligation.recursion_depth,
-        &mut obligations,
-    ) {
-        Some(n) => n,
-        None => return Ok(None),
-    };
-
-    debug!(
-        "project_and_unify_type: normalized_ty={:?} obligations={:?}",
-        normalized_ty, obligations
-    );
-
-    let infcx = selcx.infcx();
-    match infcx
-        .at(&obligation.cause, obligation.param_env)
-        .eq(normalized_ty, obligation.predicate.ty)
-    {
-        Ok(InferOk { obligations: inferred_obligations, value: () }) => {
-            obligations.extend(inferred_obligations);
-            Ok(Some(obligations))
-        }
-        Err(err) => {
-            debug!("project_and_unify_type: equating types encountered error {:?}", err);
-            Err(MismatchedProjectionTypes { err })
-        }
-    }
-}
-
-/// Normalizes any associated type projections in `value`, replacing
-/// them with a fully resolved type where possible. The return value
-/// combines the normalized result and any additional obligations that
-/// were incurred as result.
-pub fn normalize<'a, 'b, 'tcx, T>(
-    selcx: &'a mut SelectionContext<'b, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    cause: ObligationCause<'tcx>,
-    value: &T,
-) -> Normalized<'tcx, T>
-where
-    T: TypeFoldable<'tcx>,
-{
-    let mut obligations = Vec::new();
-    let value = normalize_to(selcx, param_env, cause, value, &mut obligations);
-    Normalized { value, obligations }
-}
-
-pub fn normalize_to<'a, 'b, 'tcx, T>(
-    selcx: &'a mut SelectionContext<'b, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    cause: ObligationCause<'tcx>,
-    value: &T,
-    obligations: &mut Vec<PredicateObligation<'tcx>>,
-) -> T
-where
-    T: TypeFoldable<'tcx>,
-{
-    normalize_with_depth_to(selcx, param_env, cause, 0, value, obligations)
-}
-
-/// As `normalize`, but with a custom depth.
-pub fn normalize_with_depth<'a, 'b, 'tcx, T>(
-    selcx: &'a mut SelectionContext<'b, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    cause: ObligationCause<'tcx>,
-    depth: usize,
-    value: &T,
-) -> Normalized<'tcx, T>
-where
-    T: TypeFoldable<'tcx>,
-{
-    let mut obligations = Vec::new();
-    let value = normalize_with_depth_to(selcx, param_env, cause, depth, value, &mut obligations);
-    Normalized { value, obligations }
-}
-
-pub fn normalize_with_depth_to<'a, 'b, 'tcx, T>(
-    selcx: &'a mut SelectionContext<'b, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    cause: ObligationCause<'tcx>,
-    depth: usize,
-    value: &T,
-    obligations: &mut Vec<PredicateObligation<'tcx>>,
-) -> T
-where
-    T: TypeFoldable<'tcx>,
-{
-    debug!("normalize_with_depth(depth={}, value={:?})", depth, value);
-    let mut normalizer = AssocTypeNormalizer::new(selcx, param_env, cause, depth, obligations);
-    let result = normalizer.fold(value);
-    debug!(
-        "normalize_with_depth: depth={} result={:?} with {} obligations",
-        depth,
-        result,
-        normalizer.obligations.len()
-    );
-    debug!("normalize_with_depth: depth={} obligations={:?}", depth, normalizer.obligations);
-    result
-}
-
-struct AssocTypeNormalizer<'a, 'b, 'tcx> {
-    selcx: &'a mut SelectionContext<'b, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    cause: ObligationCause<'tcx>,
-    obligations: &'a mut Vec<PredicateObligation<'tcx>>,
-    depth: usize,
-}
-
-impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> {
-    fn new(
-        selcx: &'a mut SelectionContext<'b, 'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
-        cause: ObligationCause<'tcx>,
-        depth: usize,
-        obligations: &'a mut Vec<PredicateObligation<'tcx>>,
-    ) -> AssocTypeNormalizer<'a, 'b, 'tcx> {
-        AssocTypeNormalizer { selcx, param_env, cause, obligations, depth }
-    }
-
-    fn fold<T: TypeFoldable<'tcx>>(&mut self, value: &T) -> T {
-        let value = self.selcx.infcx().resolve_vars_if_possible(value);
-
-        if !value.has_projections() { value } else { value.fold_with(self) }
-    }
-}
-
-impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
-    fn tcx<'c>(&'c self) -> TyCtxt<'tcx> {
-        self.selcx.tcx()
-    }
-
-    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
-        if !ty.has_projections() {
-            return ty;
-        }
-        // We don't want to normalize associated types that occur inside of region
-        // binders, because they may contain bound regions, and we can't cope with that.
-        //
-        // Example:
-        //
-        //     for<'a> fn(<T as Foo<&'a>>::A)
-        //
-        // Instead of normalizing `<T as Foo<&'a>>::A` here, we'll
-        // normalize it when we instantiate those bound regions (which
-        // should occur eventually).
-
-        let ty = ty.super_fold_with(self);
-        match ty.kind {
-            ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => {
-                // (*)
-                // Only normalize `impl Trait` after type-checking, usually in codegen.
-                match self.param_env.reveal {
-                    Reveal::UserFacing => ty,
-
-                    Reveal::All => {
-                        let recursion_limit = *self.tcx().sess.recursion_limit.get();
-                        if self.depth >= recursion_limit {
-                            let obligation = Obligation::with_depth(
-                                self.cause.clone(),
-                                recursion_limit,
-                                self.param_env,
-                                ty,
-                            );
-                            self.selcx.infcx().report_overflow_error(&obligation, true);
-                        }
-
-                        let generic_ty = self.tcx().type_of(def_id);
-                        let concrete_ty = generic_ty.subst(self.tcx(), substs);
-                        self.depth += 1;
-                        let folded_ty = self.fold_ty(concrete_ty);
-                        self.depth -= 1;
-                        folded_ty
-                    }
-                }
-            }
-
-            ty::Projection(ref data) if !data.has_escaping_bound_vars() => {
-                // (*)
-
-                // (*) This is kind of hacky -- we need to be able to
-                // handle normalization within binders because
-                // otherwise we wind up a need to normalize when doing
-                // trait matching (since you can have a trait
-                // obligation like `for<'a> T::B : Fn(&'a int)`), but
-                // we can't normalize with bound regions in scope. So
-                // far now we just ignore binders but only normalize
-                // if all bound regions are gone (and then we still
-                // have to renormalize whenever we instantiate a
-                // binder). It would be better to normalize in a
-                // binding-aware fashion.
-
-                let normalized_ty = normalize_projection_type(
-                    self.selcx,
-                    self.param_env,
-                    *data,
-                    self.cause.clone(),
-                    self.depth,
-                    &mut self.obligations,
-                );
-                debug!(
-                    "AssocTypeNormalizer: depth={} normalized {:?} to {:?}, \
-                     now with {} obligations",
-                    self.depth,
-                    ty,
-                    normalized_ty,
-                    self.obligations.len()
-                );
-                normalized_ty
-            }
-
-            _ => ty,
-        }
-    }
-
-    fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
-        constant.eval(self.selcx.tcx(), self.param_env)
-    }
-}
-
 #[derive(Clone, TypeFoldable)]
 pub struct Normalized<'tcx, T> {
     pub value: T,
@@ -407,1107 +27,6 @@ pub fn with<U>(self, value: U) -> Normalized<'tcx, U> {
     }
 }
 
-/// The guts of `normalize`: normalize a specific projection like `<T
-/// as Trait>::Item`. The result is always a type (and possibly
-/// additional obligations). If ambiguity arises, which implies that
-/// there are unresolved type variables in the projection, we will
-/// substitute a fresh type variable `$X` and generate a new
-/// obligation `<T as Trait>::Item == $X` for later.
-pub fn normalize_projection_type<'a, 'b, 'tcx>(
-    selcx: &'a mut SelectionContext<'b, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    projection_ty: ty::ProjectionTy<'tcx>,
-    cause: ObligationCause<'tcx>,
-    depth: usize,
-    obligations: &mut Vec<PredicateObligation<'tcx>>,
-) -> Ty<'tcx> {
-    opt_normalize_projection_type(
-        selcx,
-        param_env,
-        projection_ty,
-        cause.clone(),
-        depth,
-        obligations,
-    )
-    .unwrap_or_else(move || {
-        // if we bottom out in ambiguity, create a type variable
-        // and a deferred predicate to resolve this when more type
-        // information is available.
-
-        let tcx = selcx.infcx().tcx;
-        let def_id = projection_ty.item_def_id;
-        let ty_var = selcx.infcx().next_ty_var(TypeVariableOrigin {
-            kind: TypeVariableOriginKind::NormalizeProjectionType,
-            span: tcx.def_span(def_id),
-        });
-        let projection = ty::Binder::dummy(ty::ProjectionPredicate { projection_ty, ty: ty_var });
-        let obligation =
-            Obligation::with_depth(cause, depth + 1, param_env, projection.to_predicate());
-        obligations.push(obligation);
-        ty_var
-    })
-}
-
-/// The guts of `normalize`: normalize a specific projection like `<T
-/// as Trait>::Item`. The result is always a type (and possibly
-/// additional obligations). Returns `None` in the case of ambiguity,
-/// which indicates that there are unbound type variables.
-///
-/// This function used to return `Option<NormalizedTy<'tcx>>`, which contains a
-/// `Ty<'tcx>` and an obligations vector. But that obligation vector was very
-/// often immediately appended to another obligations vector. So now this
-/// function takes an obligations vector and appends to it directly, which is
-/// slightly uglier but avoids the need for an extra short-lived allocation.
-fn opt_normalize_projection_type<'a, 'b, 'tcx>(
-    selcx: &'a mut SelectionContext<'b, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    projection_ty: ty::ProjectionTy<'tcx>,
-    cause: ObligationCause<'tcx>,
-    depth: usize,
-    obligations: &mut Vec<PredicateObligation<'tcx>>,
-) -> Option<Ty<'tcx>> {
-    let infcx = selcx.infcx();
-
-    let projection_ty = infcx.resolve_vars_if_possible(&projection_ty);
-    let cache_key = ProjectionCacheKey { ty: projection_ty };
-
-    debug!(
-        "opt_normalize_projection_type(\
-         projection_ty={:?}, \
-         depth={})",
-        projection_ty, depth
-    );
-
-    // FIXME(#20304) For now, I am caching here, which is good, but it
-    // means we don't capture the type variables that are created in
-    // the case of ambiguity. Which means we may create a large stream
-    // of such variables. OTOH, if we move the caching up a level, we
-    // would not benefit from caching when proving `T: Trait<U=Foo>`
-    // bounds. It might be the case that we want two distinct caches,
-    // or else another kind of cache entry.
-
-    let cache_result = infcx.inner.borrow_mut().projection_cache.try_start(cache_key);
-    match cache_result {
-        Ok(()) => {}
-        Err(ProjectionCacheEntry::Ambiguous) => {
-            // If we found ambiguity the last time, that generally
-            // means we will continue to do so until some type in the
-            // key changes (and we know it hasn't, because we just
-            // fully resolved it). One exception though is closure
-            // types, which can transition from having a fixed kind to
-            // no kind with no visible change in the key.
-            //
-            // FIXME(#32286) refactor this so that closure type
-            // changes
-            debug!(
-                "opt_normalize_projection_type: \
-                 found cache entry: ambiguous"
-            );
-            if !projection_ty.has_closure_types() {
-                return None;
-            }
-        }
-        Err(ProjectionCacheEntry::InProgress) => {
-            // If while normalized A::B, we are asked to normalize
-            // A::B, just return A::B itself. This is a conservative
-            // answer, in the sense that A::B *is* clearly equivalent
-            // to A::B, though there may be a better value we can
-            // find.
-
-            // Under lazy normalization, this can arise when
-            // bootstrapping.  That is, imagine an environment with a
-            // where-clause like `A::B == u32`. Now, if we are asked
-            // to normalize `A::B`, we will want to check the
-            // where-clauses in scope. So we will try to unify `A::B`
-            // with `A::B`, which can trigger a recursive
-            // normalization. In that case, I think we will want this code:
-            //
-            // ```
-            // let ty = selcx.tcx().mk_projection(projection_ty.item_def_id,
-            //                                    projection_ty.substs;
-            // return Some(NormalizedTy { value: v, obligations: vec![] });
-            // ```
-
-            debug!(
-                "opt_normalize_projection_type: \
-                 found cache entry: in-progress"
-            );
-
-            // But for now, let's classify this as an overflow:
-            let recursion_limit = *selcx.tcx().sess.recursion_limit.get();
-            let obligation =
-                Obligation::with_depth(cause, recursion_limit, param_env, projection_ty);
-            selcx.infcx().report_overflow_error(&obligation, false);
-        }
-        Err(ProjectionCacheEntry::NormalizedTy(ty)) => {
-            // This is the hottest path in this function.
-            //
-            // If we find the value in the cache, then return it along
-            // with the obligations that went along with it. Note
-            // that, when using a fulfillment context, these
-            // obligations could in principle be ignored: they have
-            // already been registered when the cache entry was
-            // created (and hence the new ones will quickly be
-            // discarded as duplicated). But when doing trait
-            // evaluation this is not the case, and dropping the trait
-            // evaluations can causes ICEs (e.g., #43132).
-            debug!(
-                "opt_normalize_projection_type: \
-                 found normalized ty `{:?}`",
-                ty
-            );
-
-            // Once we have inferred everything we need to know, we
-            // can ignore the `obligations` from that point on.
-            if infcx.unresolved_type_vars(&ty.value).is_none() {
-                infcx.inner.borrow_mut().projection_cache.complete_normalized(cache_key, &ty);
-            // No need to extend `obligations`.
-            } else {
-                obligations.extend(ty.obligations);
-            }
-
-            obligations.push(get_paranoid_cache_value_obligation(
-                infcx,
-                param_env,
-                projection_ty,
-                cause,
-                depth,
-            ));
-            return Some(ty.value);
-        }
-        Err(ProjectionCacheEntry::Error) => {
-            debug!(
-                "opt_normalize_projection_type: \
-                 found error"
-            );
-            let result = normalize_to_error(selcx, param_env, projection_ty, cause, depth);
-            obligations.extend(result.obligations);
-            return Some(result.value);
-        }
-    }
-
-    let obligation = Obligation::with_depth(cause.clone(), depth, param_env, projection_ty);
-    match project_type(selcx, &obligation) {
-        Ok(ProjectedTy::Progress(Progress {
-            ty: projected_ty,
-            obligations: mut projected_obligations,
-        })) => {
-            // if projection succeeded, then what we get out of this
-            // is also non-normalized (consider: it was derived from
-            // an impl, where-clause etc) and hence we must
-            // re-normalize it
-
-            debug!(
-                "opt_normalize_projection_type: \
-                 projected_ty={:?} \
-                 depth={} \
-                 projected_obligations={:?}",
-                projected_ty, depth, projected_obligations
-            );
-
-            let result = if projected_ty.has_projections() {
-                let mut normalizer = AssocTypeNormalizer::new(
-                    selcx,
-                    param_env,
-                    cause,
-                    depth + 1,
-                    &mut projected_obligations,
-                );
-                let normalized_ty = normalizer.fold(&projected_ty);
-
-                debug!(
-                    "opt_normalize_projection_type: \
-                     normalized_ty={:?} depth={}",
-                    normalized_ty, depth
-                );
-
-                Normalized { value: normalized_ty, obligations: projected_obligations }
-            } else {
-                Normalized { value: projected_ty, obligations: projected_obligations }
-            };
-
-            let cache_value = prune_cache_value_obligations(infcx, &result);
-            infcx.inner.borrow_mut().projection_cache.insert_ty(cache_key, cache_value);
-            obligations.extend(result.obligations);
-            Some(result.value)
-        }
-        Ok(ProjectedTy::NoProgress(projected_ty)) => {
-            debug!(
-                "opt_normalize_projection_type: \
-                 projected_ty={:?} no progress",
-                projected_ty
-            );
-            let result = Normalized { value: projected_ty, obligations: vec![] };
-            infcx.inner.borrow_mut().projection_cache.insert_ty(cache_key, result.clone());
-            // No need to extend `obligations`.
-            Some(result.value)
-        }
-        Err(ProjectionTyError::TooManyCandidates) => {
-            debug!(
-                "opt_normalize_projection_type: \
-                 too many candidates"
-            );
-            infcx.inner.borrow_mut().projection_cache.ambiguous(cache_key);
-            None
-        }
-        Err(ProjectionTyError::TraitSelectionError(_)) => {
-            debug!("opt_normalize_projection_type: ERROR");
-            // if we got an error processing the `T as Trait` part,
-            // just return `ty::err` but add the obligation `T :
-            // Trait`, which when processed will cause the error to be
-            // reported later
-
-            infcx.inner.borrow_mut().projection_cache.error(cache_key);
-            let result = normalize_to_error(selcx, param_env, projection_ty, cause, depth);
-            obligations.extend(result.obligations);
-            Some(result.value)
-        }
-    }
-}
-
-/// If there are unresolved type variables, then we need to include
-/// any subobligations that bind them, at least until those type
-/// variables are fully resolved.
-fn prune_cache_value_obligations<'a, 'tcx>(
-    infcx: &'a InferCtxt<'a, 'tcx>,
-    result: &NormalizedTy<'tcx>,
-) -> NormalizedTy<'tcx> {
-    if infcx.unresolved_type_vars(&result.value).is_none() {
-        return NormalizedTy { value: result.value, obligations: vec![] };
-    }
-
-    let mut obligations: Vec<_> = result
-        .obligations
-        .iter()
-        .filter(|obligation| match obligation.predicate {
-            // We found a `T: Foo<X = U>` predicate, let's check
-            // if `U` references any unresolved type
-            // variables. In principle, we only care if this
-            // projection can help resolve any of the type
-            // variables found in `result.value` -- but we just
-            // check for any type variables here, for fear of
-            // indirect obligations (e.g., we project to `?0`,
-            // but we have `T: Foo<X = ?1>` and `?1: Bar<X =
-            // ?0>`).
-            ty::Predicate::Projection(ref data) => infcx.unresolved_type_vars(&data.ty()).is_some(),
-
-            // We are only interested in `T: Foo<X = U>` predicates, whre
-            // `U` references one of `unresolved_type_vars`. =)
-            _ => false,
-        })
-        .cloned()
-        .collect();
-
-    obligations.shrink_to_fit();
-
-    NormalizedTy { value: result.value, obligations }
-}
-
-/// Whenever we give back a cache result for a projection like `<T as
-/// Trait>::Item ==> X`, we *always* include the obligation to prove
-/// that `T: Trait` (we may also include some other obligations). This
-/// may or may not be necessary -- in principle, all the obligations
-/// that must be proven to show that `T: Trait` were also returned
-/// when the cache was first populated. But there are some vague concerns,
-/// and so we take the precautionary measure of including `T: Trait` in
-/// the result:
-///
-/// Concern #1. The current setup is fragile. Perhaps someone could
-/// have failed to prove the concerns from when the cache was
-/// populated, but also not have used a snapshot, in which case the
-/// cache could remain populated even though `T: Trait` has not been
-/// shown. In this case, the "other code" is at fault -- when you
-/// project something, you are supposed to either have a snapshot or
-/// else prove all the resulting obligations -- but it's still easy to
-/// get wrong.
-///
-/// Concern #2. Even within the snapshot, if those original
-/// obligations are not yet proven, then we are able to do projections
-/// that may yet turn out to be wrong. This *may* lead to some sort
-/// of trouble, though we don't have a concrete example of how that
-/// can occur yet. But it seems risky at best.
-fn get_paranoid_cache_value_obligation<'a, 'tcx>(
-    infcx: &'a InferCtxt<'a, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    projection_ty: ty::ProjectionTy<'tcx>,
-    cause: ObligationCause<'tcx>,
-    depth: usize,
-) -> PredicateObligation<'tcx> {
-    let trait_ref = projection_ty.trait_ref(infcx.tcx).to_poly_trait_ref();
-    Obligation {
-        cause,
-        recursion_depth: depth,
-        param_env,
-        predicate: trait_ref.without_const().to_predicate(),
-    }
-}
-
-/// If we are projecting `<T as Trait>::Item`, but `T: Trait` does not
-/// hold. In various error cases, we cannot generate a valid
-/// normalized projection. Therefore, we create an inference variable
-/// return an associated obligation that, when fulfilled, will lead to
-/// an error.
-///
-/// Note that we used to return `Error` here, but that was quite
-/// dubious -- the premise was that an error would *eventually* be
-/// reported, when the obligation was processed. But in general once
-/// you see a `Error` you are supposed to be able to assume that an
-/// error *has been* reported, so that you can take whatever heuristic
-/// paths you want to take. To make things worse, it was possible for
-/// cycles to arise, where you basically had a setup like `<MyType<$0>
-/// as Trait>::Foo == $0`. Here, normalizing `<MyType<$0> as
-/// Trait>::Foo> to `[type error]` would lead to an obligation of
-/// `<MyType<[type error]> as Trait>::Foo`. We are supposed to report
-/// an error for this obligation, but we legitimately should not,
-/// because it contains `[type error]`. Yuck! (See issue #29857 for
-/// one case where this arose.)
-fn normalize_to_error<'a, 'tcx>(
-    selcx: &mut SelectionContext<'a, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    projection_ty: ty::ProjectionTy<'tcx>,
-    cause: ObligationCause<'tcx>,
-    depth: usize,
-) -> NormalizedTy<'tcx> {
-    let trait_ref = projection_ty.trait_ref(selcx.tcx()).to_poly_trait_ref();
-    let trait_obligation = Obligation {
-        cause,
-        recursion_depth: depth,
-        param_env,
-        predicate: trait_ref.without_const().to_predicate(),
-    };
-    let tcx = selcx.infcx().tcx;
-    let def_id = projection_ty.item_def_id;
-    let new_value = selcx.infcx().next_ty_var(TypeVariableOrigin {
-        kind: TypeVariableOriginKind::NormalizeProjectionType,
-        span: tcx.def_span(def_id),
-    });
-    Normalized { value: new_value, obligations: vec![trait_obligation] }
-}
-
-enum ProjectedTy<'tcx> {
-    Progress(Progress<'tcx>),
-    NoProgress(Ty<'tcx>),
-}
-
-struct Progress<'tcx> {
-    ty: Ty<'tcx>,
-    obligations: Vec<PredicateObligation<'tcx>>,
-}
-
-impl<'tcx> Progress<'tcx> {
-    fn error(tcx: TyCtxt<'tcx>) -> Self {
-        Progress { ty: tcx.types.err, obligations: vec![] }
-    }
-
-    fn with_addl_obligations(mut self, mut obligations: Vec<PredicateObligation<'tcx>>) -> Self {
-        debug!(
-            "with_addl_obligations: self.obligations.len={} obligations.len={}",
-            self.obligations.len(),
-            obligations.len()
-        );
-
-        debug!(
-            "with_addl_obligations: self.obligations={:?} obligations={:?}",
-            self.obligations, obligations
-        );
-
-        self.obligations.append(&mut obligations);
-        self
-    }
-}
-
-/// Computes the result of a projection type (if we can).
-///
-/// IMPORTANT:
-/// - `obligation` must be fully normalized
-fn project_type<'cx, 'tcx>(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
-) -> Result<ProjectedTy<'tcx>, ProjectionTyError<'tcx>> {
-    debug!("project(obligation={:?})", obligation);
-
-    let recursion_limit = *selcx.tcx().sess.recursion_limit.get();
-    if obligation.recursion_depth >= recursion_limit {
-        debug!("project: overflow!");
-        return Err(ProjectionTyError::TraitSelectionError(SelectionError::Overflow));
-    }
-
-    let obligation_trait_ref = &obligation.predicate.trait_ref(selcx.tcx());
-
-    debug!("project: obligation_trait_ref={:?}", obligation_trait_ref);
-
-    if obligation_trait_ref.references_error() {
-        return Ok(ProjectedTy::Progress(Progress::error(selcx.tcx())));
-    }
-
-    let mut candidates = ProjectionTyCandidateSet::None;
-
-    // Make sure that the following procedures are kept in order. ParamEnv
-    // needs to be first because it has highest priority, and Select checks
-    // the return value of push_candidate which assumes it's ran at last.
-    assemble_candidates_from_param_env(selcx, obligation, &obligation_trait_ref, &mut candidates);
-
-    assemble_candidates_from_trait_def(selcx, obligation, &obligation_trait_ref, &mut candidates);
-
-    assemble_candidates_from_impls(selcx, obligation, &obligation_trait_ref, &mut candidates);
-
-    match candidates {
-        ProjectionTyCandidateSet::Single(candidate) => Ok(ProjectedTy::Progress(
-            confirm_candidate(selcx, obligation, &obligation_trait_ref, candidate),
-        )),
-        ProjectionTyCandidateSet::None => Ok(ProjectedTy::NoProgress(
-            selcx
-                .tcx()
-                .mk_projection(obligation.predicate.item_def_id, obligation.predicate.substs),
-        )),
-        // Error occurred while trying to processing impls.
-        ProjectionTyCandidateSet::Error(e) => Err(ProjectionTyError::TraitSelectionError(e)),
-        // Inherent ambiguity that prevents us from even enumerating the
-        // candidates.
-        ProjectionTyCandidateSet::Ambiguous => Err(ProjectionTyError::TooManyCandidates),
-    }
-}
-
-/// The first thing we have to do is scan through the parameter
-/// environment to see whether there are any projection predicates
-/// there that can answer this question.
-fn assemble_candidates_from_param_env<'cx, 'tcx>(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
-    obligation_trait_ref: &ty::TraitRef<'tcx>,
-    candidate_set: &mut ProjectionTyCandidateSet<'tcx>,
-) {
-    debug!("assemble_candidates_from_param_env(..)");
-    assemble_candidates_from_predicates(
-        selcx,
-        obligation,
-        obligation_trait_ref,
-        candidate_set,
-        ProjectionTyCandidate::ParamEnv,
-        obligation.param_env.caller_bounds.iter().cloned(),
-    );
-}
-
-/// In the case of a nested projection like <<A as Foo>::FooT as Bar>::BarT, we may find
-/// that the definition of `Foo` has some clues:
-///
-/// ```
-/// trait Foo {
-///     type FooT : Bar<BarT=i32>
-/// }
-/// ```
-///
-/// Here, for example, we could conclude that the result is `i32`.
-fn assemble_candidates_from_trait_def<'cx, 'tcx>(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
-    obligation_trait_ref: &ty::TraitRef<'tcx>,
-    candidate_set: &mut ProjectionTyCandidateSet<'tcx>,
-) {
-    debug!("assemble_candidates_from_trait_def(..)");
-
-    let tcx = selcx.tcx();
-    // Check whether the self-type is itself a projection.
-    let (def_id, substs) = match obligation_trait_ref.self_ty().kind {
-        ty::Projection(ref data) => (data.trait_ref(tcx).def_id, data.substs),
-        ty::Opaque(def_id, substs) => (def_id, substs),
-        ty::Infer(ty::TyVar(_)) => {
-            // If the self-type is an inference variable, then it MAY wind up
-            // being a projected type, so induce an ambiguity.
-            candidate_set.mark_ambiguous();
-            return;
-        }
-        _ => return,
-    };
-
-    // If so, extract what we know from the trait and try to come up with a good answer.
-    let trait_predicates = tcx.predicates_of(def_id);
-    let bounds = trait_predicates.instantiate(tcx, substs);
-    let bounds = elaborate_predicates(tcx, bounds.predicates);
-    assemble_candidates_from_predicates(
-        selcx,
-        obligation,
-        obligation_trait_ref,
-        candidate_set,
-        ProjectionTyCandidate::TraitDef,
-        bounds,
-    )
-}
-
-fn assemble_candidates_from_predicates<'cx, 'tcx, I>(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
-    obligation_trait_ref: &ty::TraitRef<'tcx>,
-    candidate_set: &mut ProjectionTyCandidateSet<'tcx>,
-    ctor: fn(ty::PolyProjectionPredicate<'tcx>) -> ProjectionTyCandidate<'tcx>,
-    env_predicates: I,
-) where
-    I: IntoIterator<Item = ty::Predicate<'tcx>>,
-{
-    debug!("assemble_candidates_from_predicates(obligation={:?})", obligation);
-    let infcx = selcx.infcx();
-    for predicate in env_predicates {
-        debug!("assemble_candidates_from_predicates: predicate={:?}", predicate);
-        if let ty::Predicate::Projection(data) = predicate {
-            let same_def_id = data.projection_def_id() == obligation.predicate.item_def_id;
-
-            let is_match = same_def_id
-                && infcx.probe(|_| {
-                    let data_poly_trait_ref = data.to_poly_trait_ref(infcx.tcx);
-                    let obligation_poly_trait_ref = obligation_trait_ref.to_poly_trait_ref();
-                    infcx
-                        .at(&obligation.cause, obligation.param_env)
-                        .sup(obligation_poly_trait_ref, data_poly_trait_ref)
-                        .map(|InferOk { obligations: _, value: () }| {
-                            // FIXME(#32730) -- do we need to take obligations
-                            // into account in any way? At the moment, no.
-                        })
-                        .is_ok()
-                });
-
-            debug!(
-                "assemble_candidates_from_predicates: candidate={:?} \
-                 is_match={} same_def_id={}",
-                data, is_match, same_def_id
-            );
-
-            if is_match {
-                candidate_set.push_candidate(ctor(data));
-            }
-        }
-    }
-}
-
-fn assemble_candidates_from_impls<'cx, 'tcx>(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
-    obligation_trait_ref: &ty::TraitRef<'tcx>,
-    candidate_set: &mut ProjectionTyCandidateSet<'tcx>,
-) {
-    // If we are resolving `<T as TraitRef<...>>::Item == Type`,
-    // start out by selecting the predicate `T as TraitRef<...>`:
-    let poly_trait_ref = obligation_trait_ref.to_poly_trait_ref();
-    let trait_obligation = obligation.with(poly_trait_ref.to_poly_trait_predicate());
-    let _ = selcx.infcx().commit_if_ok(|_| {
-        let vtable = match selcx.select(&trait_obligation) {
-            Ok(Some(vtable)) => vtable,
-            Ok(None) => {
-                candidate_set.mark_ambiguous();
-                return Err(());
-            }
-            Err(e) => {
-                debug!("assemble_candidates_from_impls: selection error {:?}", e);
-                candidate_set.mark_error(e);
-                return Err(());
-            }
-        };
-
-        let eligible = match &vtable {
-            super::VtableClosure(_)
-            | super::VtableGenerator(_)
-            | super::VtableFnPointer(_)
-            | super::VtableObject(_)
-            | super::VtableTraitAlias(_) => {
-                debug!("assemble_candidates_from_impls: vtable={:?}", vtable);
-                true
-            }
-            super::VtableImpl(impl_data) => {
-                // We have to be careful when projecting out of an
-                // impl because of specialization. If we are not in
-                // codegen (i.e., projection mode is not "any"), and the
-                // impl's type is declared as default, then we disable
-                // projection (even if the trait ref is fully
-                // monomorphic). In the case where trait ref is not
-                // fully monomorphic (i.e., includes type parameters),
-                // this is because those type parameters may
-                // ultimately be bound to types from other crates that
-                // may have specialized impls we can't see. In the
-                // case where the trait ref IS fully monomorphic, this
-                // is a policy decision that we made in the RFC in
-                // order to preserve flexibility for the crate that
-                // defined the specializable impl to specialize later
-                // for existing types.
-                //
-                // In either case, we handle this by not adding a
-                // candidate for an impl if it contains a `default`
-                // type.
-                //
-                // NOTE: This should be kept in sync with the similar code in
-                // `rustc::ty::instance::resolve_associated_item()`.
-                let node_item =
-                    assoc_ty_def(selcx, impl_data.impl_def_id, obligation.predicate.item_def_id);
-
-                let is_default = if node_item.node.is_from_trait() {
-                    // If true, the impl inherited a `type Foo = Bar`
-                    // given in the trait, which is implicitly default.
-                    // Otherwise, the impl did not specify `type` and
-                    // neither did the trait:
-                    //
-                    // ```rust
-                    // trait Foo { type T; }
-                    // impl Foo for Bar { }
-                    // ```
-                    //
-                    // This is an error, but it will be
-                    // reported in `check_impl_items_against_trait`.
-                    // We accept it here but will flag it as
-                    // an error when we confirm the candidate
-                    // (which will ultimately lead to `normalize_to_error`
-                    // being invoked).
-                    false
-                } else {
-                    // If we're looking at a trait *impl*, the item is
-                    // specializable if the impl or the item are marked
-                    // `default`.
-                    node_item.item.defaultness.is_default()
-                        || super::util::impl_is_default(selcx.tcx(), node_item.node.def_id())
-                };
-
-                match is_default {
-                    // Non-specializable items are always projectable
-                    false => true,
-
-                    // Only reveal a specializable default if we're past type-checking
-                    // and the obligation is monomorphic, otherwise passes such as
-                    // transmute checking and polymorphic MIR optimizations could
-                    // get a result which isn't correct for all monomorphizations.
-                    true if obligation.param_env.reveal == Reveal::All => {
-                        // NOTE(eddyb) inference variables can resolve to parameters, so
-                        // assume `poly_trait_ref` isn't monomorphic, if it contains any.
-                        let poly_trait_ref =
-                            selcx.infcx().resolve_vars_if_possible(&poly_trait_ref);
-                        !poly_trait_ref.needs_infer() && !poly_trait_ref.needs_subst()
-                    }
-
-                    true => {
-                        debug!(
-                            "assemble_candidates_from_impls: not eligible due to default: \
-                             assoc_ty={} predicate={}",
-                            selcx.tcx().def_path_str(node_item.item.def_id),
-                            obligation.predicate,
-                        );
-                        false
-                    }
-                }
-            }
-            super::VtableParam(..) => {
-                // This case tell us nothing about the value of an
-                // associated type. Consider:
-                //
-                // ```
-                // trait SomeTrait { type Foo; }
-                // fn foo<T:SomeTrait>(...) { }
-                // ```
-                //
-                // If the user writes `<T as SomeTrait>::Foo`, then the `T
-                // : SomeTrait` binding does not help us decide what the
-                // type `Foo` is (at least, not more specifically than
-                // what we already knew).
-                //
-                // But wait, you say! What about an example like this:
-                //
-                // ```
-                // fn bar<T:SomeTrait<Foo=usize>>(...) { ... }
-                // ```
-                //
-                // Doesn't the `T : Sometrait<Foo=usize>` predicate help
-                // resolve `T::Foo`? And of course it does, but in fact
-                // that single predicate is desugared into two predicates
-                // in the compiler: a trait predicate (`T : SomeTrait`) and a
-                // projection. And the projection where clause is handled
-                // in `assemble_candidates_from_param_env`.
-                false
-            }
-            super::VtableAutoImpl(..) | super::VtableBuiltin(..) => {
-                // These traits have no associated types.
-                span_bug!(
-                    obligation.cause.span,
-                    "Cannot project an associated type from `{:?}`",
-                    vtable
-                );
-            }
-        };
-
-        if eligible {
-            if candidate_set.push_candidate(ProjectionTyCandidate::Select(vtable)) {
-                Ok(())
-            } else {
-                Err(())
-            }
-        } else {
-            Err(())
-        }
-    });
-}
-
-fn confirm_candidate<'cx, 'tcx>(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
-    obligation_trait_ref: &ty::TraitRef<'tcx>,
-    candidate: ProjectionTyCandidate<'tcx>,
-) -> Progress<'tcx> {
-    debug!("confirm_candidate(candidate={:?}, obligation={:?})", candidate, obligation);
-
-    match candidate {
-        ProjectionTyCandidate::ParamEnv(poly_projection)
-        | ProjectionTyCandidate::TraitDef(poly_projection) => {
-            confirm_param_env_candidate(selcx, obligation, poly_projection)
-        }
-
-        ProjectionTyCandidate::Select(vtable) => {
-            confirm_select_candidate(selcx, obligation, obligation_trait_ref, vtable)
-        }
-    }
-}
-
-fn confirm_select_candidate<'cx, 'tcx>(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
-    obligation_trait_ref: &ty::TraitRef<'tcx>,
-    vtable: Selection<'tcx>,
-) -> Progress<'tcx> {
-    match vtable {
-        super::VtableImpl(data) => confirm_impl_candidate(selcx, obligation, data),
-        super::VtableGenerator(data) => confirm_generator_candidate(selcx, obligation, data),
-        super::VtableClosure(data) => confirm_closure_candidate(selcx, obligation, data),
-        super::VtableFnPointer(data) => confirm_fn_pointer_candidate(selcx, obligation, data),
-        super::VtableObject(_) => confirm_object_candidate(selcx, obligation, obligation_trait_ref),
-        super::VtableAutoImpl(..)
-        | super::VtableParam(..)
-        | super::VtableBuiltin(..)
-        | super::VtableTraitAlias(..) =>
-        // we don't create Select candidates with this kind of resolution
-        {
-            span_bug!(
-                obligation.cause.span,
-                "Cannot project an associated type from `{:?}`",
-                vtable
-            )
-        }
-    }
-}
-
-fn confirm_object_candidate<'cx, 'tcx>(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
-    obligation_trait_ref: &ty::TraitRef<'tcx>,
-) -> Progress<'tcx> {
-    let self_ty = obligation_trait_ref.self_ty();
-    let object_ty = selcx.infcx().shallow_resolve(self_ty);
-    debug!("confirm_object_candidate(object_ty={:?})", object_ty);
-    let data = match object_ty.kind {
-        ty::Dynamic(ref data, ..) => data,
-        _ => span_bug!(
-            obligation.cause.span,
-            "confirm_object_candidate called with non-object: {:?}",
-            object_ty
-        ),
-    };
-    let env_predicates = data
-        .projection_bounds()
-        .map(|p| p.with_self_ty(selcx.tcx(), object_ty).to_predicate())
-        .collect();
-    let env_predicate = {
-        let env_predicates = elaborate_predicates(selcx.tcx(), env_predicates);
-
-        // select only those projections that are actually projecting an
-        // item with the correct name
-        let env_predicates = env_predicates.filter_map(|p| match p {
-            ty::Predicate::Projection(data) => {
-                if data.projection_def_id() == obligation.predicate.item_def_id {
-                    Some(data)
-                } else {
-                    None
-                }
-            }
-            _ => None,
-        });
-
-        // select those with a relevant trait-ref
-        let mut env_predicates = env_predicates.filter(|data| {
-            let data_poly_trait_ref = data.to_poly_trait_ref(selcx.tcx());
-            let obligation_poly_trait_ref = obligation_trait_ref.to_poly_trait_ref();
-            selcx.infcx().probe(|_| {
-                selcx
-                    .infcx()
-                    .at(&obligation.cause, obligation.param_env)
-                    .sup(obligation_poly_trait_ref, data_poly_trait_ref)
-                    .is_ok()
-            })
-        });
-
-        // select the first matching one; there really ought to be one or
-        // else the object type is not WF, since an object type should
-        // include all of its projections explicitly
-        match env_predicates.next() {
-            Some(env_predicate) => env_predicate,
-            None => {
-                debug!(
-                    "confirm_object_candidate: no env-predicate \
-                     found in object type `{:?}`; ill-formed",
-                    object_ty
-                );
-                return Progress::error(selcx.tcx());
-            }
-        }
-    };
-
-    confirm_param_env_candidate(selcx, obligation, env_predicate)
-}
-
-fn confirm_generator_candidate<'cx, 'tcx>(
-    selcx: &mut SelectionContext<'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 Normalized { value: gen_sig, obligations } = normalize_with_depth(
-        selcx,
-        obligation.param_env,
-        obligation.cause.clone(),
-        obligation.recursion_depth + 1,
-        &gen_sig,
-    );
-
-    debug!(
-        "confirm_generator_candidate: obligation={:?},gen_sig={:?},obligations={:?}",
-        obligation, gen_sig, obligations
-    );
-
-    let tcx = selcx.tcx();
-
-    let gen_def_id = tcx.lang_items().gen_trait().unwrap();
-
-    let predicate = super::util::generator_trait_ref_and_outputs(
-        tcx,
-        gen_def_id,
-        obligation.predicate.self_ty(),
-        gen_sig,
-    )
-    .map_bound(|(trait_ref, yield_ty, return_ty)| {
-        let name = tcx.associated_item(obligation.predicate.item_def_id).ident.name;
-        let ty = if name == sym::Return {
-            return_ty
-        } else if name == sym::Yield {
-            yield_ty
-        } else {
-            bug!()
-        };
-
-        ty::ProjectionPredicate {
-            projection_ty: ty::ProjectionTy {
-                substs: trait_ref.substs,
-                item_def_id: obligation.predicate.item_def_id,
-            },
-            ty: ty,
-        }
-    });
-
-    confirm_param_env_candidate(selcx, obligation, predicate)
-        .with_addl_obligations(vtable.nested)
-        .with_addl_obligations(obligations)
-}
-
-fn confirm_fn_pointer_candidate<'cx, 'tcx>(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
-    fn_pointer_vtable: VtableFnPointerData<'tcx, PredicateObligation<'tcx>>,
-) -> Progress<'tcx> {
-    let fn_type = selcx.infcx().shallow_resolve(fn_pointer_vtable.fn_ty);
-    let sig = fn_type.fn_sig(selcx.tcx());
-    let Normalized { value: sig, obligations } = normalize_with_depth(
-        selcx,
-        obligation.param_env,
-        obligation.cause.clone(),
-        obligation.recursion_depth + 1,
-        &sig,
-    );
-
-    confirm_callable_candidate(selcx, obligation, sig, util::TupleArgumentsFlag::Yes)
-        .with_addl_obligations(fn_pointer_vtable.nested)
-        .with_addl_obligations(obligations)
-}
-
-fn confirm_closure_candidate<'cx, 'tcx>(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
-    vtable: VtableClosureData<'tcx, PredicateObligation<'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 = infcx.shallow_resolve(closure_sig_ty).fn_sig(tcx);
-    let Normalized { value: closure_sig, obligations } = normalize_with_depth(
-        selcx,
-        obligation.param_env,
-        obligation.cause.clone(),
-        obligation.recursion_depth + 1,
-        &closure_sig,
-    );
-
-    debug!(
-        "confirm_closure_candidate: obligation={:?},closure_sig={:?},obligations={:?}",
-        obligation, closure_sig, obligations
-    );
-
-    confirm_callable_candidate(selcx, obligation, closure_sig, util::TupleArgumentsFlag::No)
-        .with_addl_obligations(vtable.nested)
-        .with_addl_obligations(obligations)
-}
-
-fn confirm_callable_candidate<'cx, 'tcx>(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
-    fn_sig: ty::PolyFnSig<'tcx>,
-    flag: util::TupleArgumentsFlag,
-) -> Progress<'tcx> {
-    let tcx = selcx.tcx();
-
-    debug!("confirm_callable_candidate({:?},{:?})", obligation, fn_sig);
-
-    // the `Output` associated type is declared on `FnOnce`
-    let fn_once_def_id = tcx.lang_items().fn_once_trait().unwrap();
-
-    let predicate = super::util::closure_trait_ref_and_return_type(
-        tcx,
-        fn_once_def_id,
-        obligation.predicate.self_ty(),
-        fn_sig,
-        flag,
-    )
-    .map_bound(|(trait_ref, ret_type)| ty::ProjectionPredicate {
-        projection_ty: ty::ProjectionTy::from_ref_and_name(
-            tcx,
-            trait_ref,
-            Ident::with_dummy_span(rustc_hir::FN_OUTPUT_NAME),
-        ),
-        ty: ret_type,
-    });
-
-    confirm_param_env_candidate(selcx, obligation, predicate)
-}
-
-fn confirm_param_env_candidate<'cx, 'tcx>(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
-    poly_cache_entry: ty::PolyProjectionPredicate<'tcx>,
-) -> Progress<'tcx> {
-    let infcx = selcx.infcx();
-    let cause = &obligation.cause;
-    let param_env = obligation.param_env;
-
-    let (cache_entry, _) = infcx.replace_bound_vars_with_fresh_vars(
-        cause.span,
-        LateBoundRegionConversionTime::HigherRankedType,
-        &poly_cache_entry,
-    );
-
-    let cache_trait_ref = cache_entry.projection_ty.trait_ref(infcx.tcx);
-    let obligation_trait_ref = obligation.predicate.trait_ref(infcx.tcx);
-    match infcx.at(cause, param_env).eq(cache_trait_ref, obligation_trait_ref) {
-        Ok(InferOk { value: _, obligations }) => Progress { ty: cache_entry.ty, obligations },
-        Err(e) => {
-            let msg = format!(
-                "Failed to unify obligation `{:?}` with poly_projection `{:?}`: {:?}",
-                obligation, poly_cache_entry, e,
-            );
-            debug!("confirm_param_env_candidate: {}", msg);
-            infcx.tcx.sess.delay_span_bug(obligation.cause.span, &msg);
-            Progress { ty: infcx.tcx.types.err, obligations: vec![] }
-        }
-    }
-}
-
-fn confirm_impl_candidate<'cx, 'tcx>(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
-    impl_vtable: VtableImplData<'tcx, PredicateObligation<'tcx>>,
-) -> Progress<'tcx> {
-    let tcx = selcx.tcx();
-
-    let VtableImplData { impl_def_id, substs, nested } = impl_vtable;
-    let assoc_item_id = obligation.predicate.item_def_id;
-    let trait_def_id = tcx.trait_id_of_impl(impl_def_id).unwrap();
-
-    let param_env = obligation.param_env;
-    let assoc_ty = assoc_ty_def(selcx, impl_def_id, assoc_item_id);
-
-    if !assoc_ty.item.defaultness.has_value() {
-        // This means that the impl is missing a definition for the
-        // associated type. This error will be reported by the type
-        // checker method `check_impl_items_against_trait`, so here we
-        // just return Error.
-        debug!(
-            "confirm_impl_candidate: no associated type {:?} for {:?}",
-            assoc_ty.item.ident, obligation.predicate
-        );
-        return Progress { ty: tcx.types.err, obligations: nested };
-    }
-    let substs = obligation.predicate.substs.rebase_onto(tcx, trait_def_id, substs);
-    let substs = translate_substs(selcx.infcx(), param_env, impl_def_id, substs, assoc_ty.node);
-    let ty = if let ty::AssocKind::OpaqueTy = assoc_ty.item.kind {
-        let item_substs = InternalSubsts::identity_for_item(tcx, assoc_ty.item.def_id);
-        tcx.mk_opaque(assoc_ty.item.def_id, item_substs)
-    } else {
-        tcx.type_of(assoc_ty.item.def_id)
-    };
-    if substs.len() != tcx.generics_of(assoc_ty.item.def_id).count() {
-        tcx.sess
-            .delay_span_bug(DUMMY_SP, "impl item and trait item have different parameter counts");
-        Progress { ty: tcx.types.err, obligations: nested }
-    } else {
-        Progress { ty: ty.subst(tcx, substs), obligations: nested }
-    }
-}
-
-/// Locate the definition of an associated type in the specialization hierarchy,
-/// starting from the given impl.
-///
-/// Based on the "projection mode", this lookup may in fact only examine the
-/// topmost impl. See the comments for `Reveal` for more details.
-fn assoc_ty_def(
-    selcx: &SelectionContext<'_, '_>,
-    impl_def_id: DefId,
-    assoc_ty_def_id: DefId,
-) -> specialization_graph::NodeItem<ty::AssocItem> {
-    let tcx = selcx.tcx();
-    let assoc_ty_name = tcx.associated_item(assoc_ty_def_id).ident;
-    let trait_def_id = tcx.impl_trait_ref(impl_def_id).unwrap().def_id;
-    let trait_def = tcx.trait_def(trait_def_id);
-
-    // This function may be called while we are still building the
-    // specialization graph that is queried below (via TraidDef::ancestors()),
-    // so, in order to avoid unnecessary infinite recursion, we manually look
-    // for the associated item at the given impl.
-    // If there is no such item in that impl, this function will fail with a
-    // cycle error if the specialization graph is currently being built.
-    let impl_node = specialization_graph::Node::Impl(impl_def_id);
-    for item in impl_node.items(tcx) {
-        if matches!(item.kind, ty::AssocKind::Type | ty::AssocKind::OpaqueTy)
-            && tcx.hygienic_eq(item.ident, assoc_ty_name, trait_def_id)
-        {
-            return specialization_graph::NodeItem {
-                node: specialization_graph::Node::Impl(impl_def_id),
-                item: *item,
-            };
-        }
-    }
-
-    if let Some(assoc_item) =
-        trait_def.ancestors(tcx, impl_def_id).leaf_def(tcx, assoc_ty_name, ty::AssocKind::Type)
-    {
-        assoc_item
-    } else {
-        // This is saying that neither the trait nor
-        // the impl contain a definition for this
-        // associated type.  Normally this situation
-        // could only arise through a compiler bug --
-        // if the user wrote a bad item name, it
-        // should have failed in astconv.
-        bug!("No associated type `{}` for {}", assoc_ty_name, tcx.def_path_str(impl_def_id))
-    }
-}
-
 // # Cache
 
 /// The projection cache. Unlike the standard caches, this can include
@@ -1549,26 +68,14 @@ pub struct ProjectionCacheKey<'tcx> {
     ty: ty::ProjectionTy<'tcx>,
 }
 
-impl<'cx, 'tcx> ProjectionCacheKey<'tcx> {
-    pub fn from_poly_projection_predicate(
-        selcx: &mut SelectionContext<'cx, 'tcx>,
-        predicate: &ty::PolyProjectionPredicate<'tcx>,
-    ) -> Option<Self> {
-        let infcx = selcx.infcx();
-        // We don't do cross-snapshot caching of obligations with escaping regions,
-        // so there's no cache key to use
-        predicate.no_bound_vars().map(|predicate| ProjectionCacheKey {
-            // We don't attempt to match up with a specific type-variable state
-            // from a specific call to `opt_normalize_projection_type` - if
-            // there's no precise match, the original cache entry is "stranded"
-            // anyway.
-            ty: infcx.resolve_vars_if_possible(&predicate.projection_ty),
-        })
+impl ProjectionCacheKey<'tcx> {
+    pub fn new(ty: ty::ProjectionTy<'tcx>) -> Self {
+        Self { ty }
     }
 }
 
 #[derive(Clone, Debug)]
-enum ProjectionCacheEntry<'tcx> {
+pub enum ProjectionCacheEntry<'tcx> {
     InProgress,
     Ambiguous,
     Error,
@@ -1604,7 +111,7 @@ pub fn commit(&mut self, snapshot: ProjectionCacheSnapshot) {
     /// Try to start normalize `key`; returns an error if
     /// normalization already occurred (this error corresponds to a
     /// cache hit, so it's actually a good thing).
-    fn try_start(
+    pub fn try_start(
         &mut self,
         key: ProjectionCacheKey<'tcx>,
     ) -> Result<(), ProjectionCacheEntry<'tcx>> {
@@ -1617,7 +124,7 @@ fn try_start(
     }
 
     /// Indicates that `key` was normalized to `value`.
-    fn insert_ty(&mut self, key: ProjectionCacheKey<'tcx>, value: NormalizedTy<'tcx>) {
+    pub fn insert_ty(&mut self, key: ProjectionCacheKey<'tcx>, value: NormalizedTy<'tcx>) {
         debug!(
             "ProjectionCacheEntry::insert_ty: adding cache entry: key={:?}, value={:?}",
             key, value
@@ -1670,14 +177,14 @@ pub fn complete_normalized(&mut self, key: ProjectionCacheKey<'tcx>, ty: &Normal
     /// ambiguity. No point in trying it again then until we gain more
     /// type information (in which case, the "fully resolved" key will
     /// be different).
-    fn ambiguous(&mut self, key: ProjectionCacheKey<'tcx>) {
+    pub fn ambiguous(&mut self, key: ProjectionCacheKey<'tcx>) {
         let fresh = self.map.insert(key, ProjectionCacheEntry::Ambiguous);
         assert!(!fresh, "never started projecting `{:?}`", key);
     }
 
     /// Indicates that trying to normalize `key` resulted in
     /// error.
-    fn error(&mut self, key: ProjectionCacheKey<'tcx>) {
+    pub fn error(&mut self, key: ProjectionCacheKey<'tcx>) {
         let fresh = self.map.insert(key, ProjectionCacheEntry::Error);
         assert!(!fresh, "never started projecting `{:?}`", key);
     }
diff --git a/src/librustc_infer/traits/query/dropck_outlives.rs b/src/librustc_infer/traits/query/dropck_outlives.rs
deleted file mode 100644 (file)
index a1d7a28..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-use crate::infer::at::At;
-use crate::infer::canonical::OriginalQueryValues;
-use crate::infer::InferOk;
-
-use rustc::ty::subst::GenericArg;
-use rustc::ty::{self, Ty, TyCtxt};
-
-pub use rustc::traits::query::{DropckOutlivesResult, DtorckConstraint};
-
-impl<'cx, 'tcx> At<'cx, 'tcx> {
-    /// Given a type `ty` of some value being dropped, computes a set
-    /// of "kinds" (types, regions) that must be outlive the execution
-    /// of the destructor. These basically correspond to data that the
-    /// destructor might access. This is used during regionck to
-    /// impose "outlives" constraints on any lifetimes referenced
-    /// within.
-    ///
-    /// The rules here are given by the "dropck" RFCs, notably [#1238]
-    /// and [#1327]. This is a fixed-point computation, where we
-    /// explore all the data that will be dropped (transitively) when
-    /// a value of type `ty` is dropped. For each type T that will be
-    /// dropped and which has a destructor, we must assume that all
-    /// the types/regions of T are live during the destructor, unless
-    /// they are marked with a special attribute (`#[may_dangle]`).
-    ///
-    /// [#1238]: https://github.com/rust-lang/rfcs/blob/master/text/1238-nonparametric-dropck.md
-    /// [#1327]: https://github.com/rust-lang/rfcs/blob/master/text/1327-dropck-param-eyepatch.md
-    pub fn dropck_outlives(&self, ty: Ty<'tcx>) -> InferOk<'tcx, Vec<GenericArg<'tcx>>> {
-        debug!("dropck_outlives(ty={:?}, param_env={:?})", ty, self.param_env,);
-
-        // Quick check: there are a number of cases that we know do not require
-        // any destructor.
-        let tcx = self.infcx.tcx;
-        if trivial_dropck_outlives(tcx, ty) {
-            return InferOk { value: vec![], obligations: vec![] };
-        }
-
-        let mut orig_values = OriginalQueryValues::default();
-        let c_ty = self.infcx.canonicalize_query(&self.param_env.and(ty), &mut orig_values);
-        let span = self.cause.span;
-        debug!("c_ty = {:?}", c_ty);
-        if let Ok(result) = &tcx.dropck_outlives(c_ty) {
-            if result.is_proven() {
-                if let Ok(InferOk { value, obligations }) =
-                    self.infcx.instantiate_query_response_and_region_obligations(
-                        self.cause,
-                        self.param_env,
-                        &orig_values,
-                        result,
-                    )
-                {
-                    let ty = self.infcx.resolve_vars_if_possible(&ty);
-                    let kinds = value.into_kinds_reporting_overflows(tcx, span, ty);
-                    return InferOk { value: kinds, obligations };
-                }
-            }
-        }
-
-        // Errors and ambiuity in dropck occur in two cases:
-        // - unresolved inference variables at the end of typeck
-        // - non well-formed types where projections cannot be resolved
-        // Either of these should have created an error before.
-        tcx.sess.delay_span_bug(span, "dtorck encountered internal error");
-
-        InferOk { value: vec![], obligations: vec![] }
-    }
-}
-
-/// This returns true if the type `ty` is "trivial" for
-/// dropck-outlives -- that is, if it doesn't require any types to
-/// outlive. This is similar but not *quite* the same as the
-/// `needs_drop` test in the compiler already -- that is, for every
-/// type T for which this function return true, needs-drop would
-/// return `false`. But the reverse does not hold: in particular,
-/// `needs_drop` returns false for `PhantomData`, but it is not
-/// trivial for dropck-outlives.
-///
-/// Note also that `needs_drop` requires a "global" type (i.e., one
-/// with erased regions), but this function does not.
-pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
-    match ty.kind {
-        // None of these types have a destructor and hence they do not
-        // require anything in particular to outlive the dtor's
-        // execution.
-        ty::Infer(ty::FreshIntTy(_))
-        | ty::Infer(ty::FreshFloatTy(_))
-        | ty::Bool
-        | ty::Int(_)
-        | ty::Uint(_)
-        | ty::Float(_)
-        | ty::Never
-        | ty::FnDef(..)
-        | ty::FnPtr(_)
-        | ty::Char
-        | ty::GeneratorWitness(..)
-        | ty::RawPtr(_)
-        | ty::Ref(..)
-        | ty::Str
-        | ty::Foreign(..)
-        | ty::Error => true,
-
-        // [T; N] and [T] have same properties as T.
-        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| trivial_dropck_outlives(tcx, t.expect_ty())),
-        ty::Closure(def_id, ref substs) => {
-            substs.as_closure().upvar_tys(def_id, tcx).all(|t| trivial_dropck_outlives(tcx, t))
-        }
-
-        ty::Adt(def, _) => {
-            if Some(def.did) == tcx.lang_items().manually_drop() {
-                // `ManuallyDrop` never has a dtor.
-                true
-            } else {
-                // Other types might. Moreover, PhantomData doesn't
-                // have a dtor, but it is considered to own its
-                // content, so it is non-trivial. Unions can have `impl Drop`,
-                // and hence are non-trivial as well.
-                false
-            }
-        }
-
-        // The following *might* require a destructor: needs deeper inspection.
-        ty::Dynamic(..)
-        | ty::Projection(..)
-        | ty::Param(_)
-        | ty::Opaque(..)
-        | ty::Placeholder(..)
-        | ty::Infer(_)
-        | ty::Bound(..)
-        | ty::Generator(..) => false,
-
-        ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
-    }
-}
diff --git a/src/librustc_infer/traits/query/evaluate_obligation.rs b/src/librustc_infer/traits/query/evaluate_obligation.rs
deleted file mode 100644 (file)
index b9ce3cc..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-use crate::infer::canonical::OriginalQueryValues;
-use crate::infer::InferCtxt;
-use crate::traits::{
-    EvaluationResult, OverflowError, PredicateObligation, SelectionContext, TraitQueryMode,
-};
-
-impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
-    /// Evaluates whether the predicate can be satisfied (by any means)
-    /// in the given `ParamEnv`.
-    pub fn predicate_may_hold(&self, obligation: &PredicateObligation<'tcx>) -> bool {
-        self.evaluate_obligation_no_overflow(obligation).may_apply()
-    }
-
-    /// Evaluates whether the predicate can be satisfied in the given
-    /// `ParamEnv`, and returns `false` if not certain. However, this is
-    /// not entirely accurate if inference variables are involved.
-    ///
-    /// This version may conservatively fail when outlives obligations
-    /// are required.
-    pub fn predicate_must_hold_considering_regions(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-    ) -> bool {
-        self.evaluate_obligation_no_overflow(obligation).must_apply_considering_regions()
-    }
-
-    /// Evaluates whether the predicate can be satisfied in the given
-    /// `ParamEnv`, and returns `false` if not certain. However, this is
-    /// not entirely accurate if inference variables are involved.
-    ///
-    /// This version ignores all outlives constraints.
-    pub fn predicate_must_hold_modulo_regions(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-    ) -> bool {
-        self.evaluate_obligation_no_overflow(obligation).must_apply_modulo_regions()
-    }
-
-    /// Evaluate a given predicate, capturing overflow and propagating it back.
-    pub fn evaluate_obligation(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-    ) -> Result<EvaluationResult, OverflowError> {
-        let mut _orig_values = OriginalQueryValues::default();
-        let c_pred = self
-            .canonicalize_query(&obligation.param_env.and(obligation.predicate), &mut _orig_values);
-        // Run canonical query. If overflow occurs, rerun from scratch but this time
-        // in standard trait query mode so that overflow is handled appropriately
-        // within `SelectionContext`.
-        self.tcx.evaluate_obligation(c_pred)
-    }
-
-    // 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(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-    ) -> EvaluationResult {
-        match self.evaluate_obligation(obligation) {
-            Ok(result) => result,
-            Err(OverflowError) => {
-                let mut selcx = SelectionContext::with_query_mode(&self, TraitQueryMode::Standard);
-                selcx.evaluate_root_obligation(obligation).unwrap_or_else(|r| {
-                    span_bug!(
-                        obligation.cause.span,
-                        "Overflow should be caught earlier in standard query mode: {:?}, {:?}",
-                        obligation,
-                        r,
-                    )
-                })
-            }
-        }
-    }
-}
diff --git a/src/librustc_infer/traits/query/method_autoderef.rs b/src/librustc_infer/traits/query/method_autoderef.rs
deleted file mode 100644 (file)
index 80748c5..0000000
+++ /dev/null
@@ -1 +0,0 @@
-pub use rustc::traits::query::{CandidateStep, MethodAutoderefBadTy, MethodAutoderefStepsResult};
diff --git a/src/librustc_infer/traits/query/mod.rs b/src/librustc_infer/traits/query/mod.rs
deleted file mode 100644 (file)
index 77b5ec6..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-//! Experimental types for the trait query interface. The methods
-//! defined in this module are all based on **canonicalization**,
-//! which makes a canonical query by replacing unbound inference
-//! variables and regions, so that results can be reused more broadly.
-//! The providers for the queries defined here can be found in
-//! `librustc_traits`.
-
-pub mod dropck_outlives;
-pub mod evaluate_obligation;
-pub mod method_autoderef;
-pub mod normalize;
-pub mod outlives_bounds;
-pub mod type_op;
-
-pub use rustc::traits::query::*;
diff --git a/src/librustc_infer/traits/query/normalize.rs b/src/librustc_infer/traits/query/normalize.rs
deleted file mode 100644 (file)
index 4577e3d..0000000
+++ /dev/null
@@ -1,189 +0,0 @@
-//! Code for the 'normalization' query. This consists of a wrapper
-//! which folds deeply, invoking the underlying
-//! `normalize_projection_ty` query when it encounters projections.
-
-use crate::infer::at::At;
-use crate::infer::canonical::OriginalQueryValues;
-use crate::infer::{InferCtxt, InferOk};
-use crate::traits::project::Normalized;
-use crate::traits::{Obligation, ObligationCause, PredicateObligation, Reveal};
-use rustc::ty::fold::{TypeFoldable, TypeFolder};
-use rustc::ty::subst::Subst;
-use rustc::ty::{self, Ty, TyCtxt};
-
-use super::NoSolution;
-
-pub use rustc::traits::query::NormalizationResult;
-
-impl<'cx, 'tcx> At<'cx, 'tcx> {
-    /// Normalize `value` in the context of the inference context,
-    /// yielding a resulting type, or an error if `value` cannot be
-    /// normalized. If you don't care about regions, you should prefer
-    /// `normalize_erasing_regions`, which is more efficient.
-    ///
-    /// If the normalization succeeds and is unambiguous, returns back
-    /// the normalized value along with various outlives relations (in
-    /// the form of obligations that must be discharged).
-    ///
-    /// N.B., this will *eventually* be the main means of
-    /// normalizing, but for now should be used only when we actually
-    /// know that normalization will succeed, since error reporting
-    /// and other details are still "under development".
-    pub fn normalize<T>(&self, value: &T) -> Result<Normalized<'tcx, T>, NoSolution>
-    where
-        T: TypeFoldable<'tcx>,
-    {
-        debug!(
-            "normalize::<{}>(value={:?}, param_env={:?})",
-            ::std::any::type_name::<T>(),
-            value,
-            self.param_env,
-        );
-        if !value.has_projections() {
-            return Ok(Normalized { value: value.clone(), obligations: vec![] });
-        }
-
-        let mut normalizer = QueryNormalizer {
-            infcx: self.infcx,
-            cause: self.cause,
-            param_env: self.param_env,
-            obligations: vec![],
-            error: false,
-            anon_depth: 0,
-        };
-
-        let value1 = value.fold_with(&mut normalizer);
-        if normalizer.error {
-            Err(NoSolution)
-        } else {
-            Ok(Normalized { value: value1, obligations: normalizer.obligations })
-        }
-    }
-}
-
-struct QueryNormalizer<'cx, 'tcx> {
-    infcx: &'cx InferCtxt<'cx, 'tcx>,
-    cause: &'cx ObligationCause<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    obligations: Vec<PredicateObligation<'tcx>>,
-    error: bool,
-    anon_depth: usize,
-}
-
-impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
-    fn tcx<'c>(&'c self) -> TyCtxt<'tcx> {
-        self.infcx.tcx
-    }
-
-    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
-        if !ty.has_projections() {
-            return ty;
-        }
-
-        let ty = ty.super_fold_with(self);
-        match ty.kind {
-            ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => {
-                // (*)
-                // Only normalize `impl Trait` after type-checking, usually in codegen.
-                match self.param_env.reveal {
-                    Reveal::UserFacing => ty,
-
-                    Reveal::All => {
-                        let recursion_limit = *self.tcx().sess.recursion_limit.get();
-                        if self.anon_depth >= recursion_limit {
-                            let obligation = Obligation::with_depth(
-                                self.cause.clone(),
-                                recursion_limit,
-                                self.param_env,
-                                ty,
-                            );
-                            self.infcx.report_overflow_error(&obligation, true);
-                        }
-
-                        let generic_ty = self.tcx().type_of(def_id);
-                        let concrete_ty = generic_ty.subst(self.tcx(), substs);
-                        self.anon_depth += 1;
-                        if concrete_ty == ty {
-                            bug!(
-                                "infinite recursion generic_ty: {:#?}, substs: {:#?}, \
-                                 concrete_ty: {:#?}, ty: {:#?}",
-                                generic_ty,
-                                substs,
-                                concrete_ty,
-                                ty
-                            );
-                        }
-                        let folded_ty = self.fold_ty(concrete_ty);
-                        self.anon_depth -= 1;
-                        folded_ty
-                    }
-                }
-            }
-
-            ty::Projection(ref data) if !data.has_escaping_bound_vars() => {
-                // (*)
-                // (*) This is kind of hacky -- we need to be able to
-                // handle normalization within binders because
-                // otherwise we wind up a need to normalize when doing
-                // trait matching (since you can have a trait
-                // obligation like `for<'a> T::B : Fn(&'a int)`), but
-                // we can't normalize with bound regions in scope. So
-                // far now we just ignore binders but only normalize
-                // if all bound regions are gone (and then we still
-                // have to renormalize whenever we instantiate a
-                // binder). It would be better to normalize in a
-                // binding-aware fashion.
-
-                let tcx = self.infcx.tcx;
-
-                let mut orig_values = OriginalQueryValues::default();
-                // HACK(matthewjasper) `'static` is special-cased in selection,
-                // so we cannot canonicalize it.
-                let c_data = self
-                    .infcx
-                    .canonicalize_hr_query_hack(&self.param_env.and(*data), &mut orig_values);
-                debug!("QueryNormalizer: c_data = {:#?}", c_data);
-                debug!("QueryNormalizer: orig_values = {:#?}", orig_values);
-                match tcx.normalize_projection_ty(c_data) {
-                    Ok(result) => {
-                        // We don't expect ambiguity.
-                        if result.is_ambiguous() {
-                            self.error = true;
-                            return ty;
-                        }
-
-                        match self.infcx.instantiate_query_response_and_region_obligations(
-                            self.cause,
-                            self.param_env,
-                            &orig_values,
-                            &result,
-                        ) {
-                            Ok(InferOk { value: result, obligations }) => {
-                                debug!("QueryNormalizer: result = {:#?}", result);
-                                debug!("QueryNormalizer: obligations = {:#?}", obligations);
-                                self.obligations.extend(obligations);
-                                return result.normalized_ty;
-                            }
-
-                            Err(_) => {
-                                self.error = true;
-                                return ty;
-                            }
-                        }
-                    }
-
-                    Err(NoSolution) => {
-                        self.error = true;
-                        ty
-                    }
-                }
-            }
-
-            _ => ty,
-        }
-    }
-
-    fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
-        constant.eval(self.infcx.tcx, self.param_env)
-    }
-}
diff --git a/src/librustc_infer/traits/query/outlives_bounds.rs b/src/librustc_infer/traits/query/outlives_bounds.rs
deleted file mode 100644 (file)
index eb32ebf..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-use crate::infer::canonical::OriginalQueryValues;
-use crate::infer::InferCtxt;
-use crate::traits::query::NoSolution;
-use crate::traits::{FulfillmentContext, ObligationCause, TraitEngine, TraitEngineExt};
-use rustc::ty::{self, Ty};
-use rustc_hir as hir;
-use rustc_span::source_map::Span;
-
-pub use rustc::traits::query::OutlivesBound;
-
-impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
-    /// Implied bounds are region relationships that we deduce
-    /// automatically. The idea is that (e.g.) a caller must check that a
-    /// function's argument types are well-formed immediately before
-    /// calling that fn, and hence the *callee* can assume that its
-    /// argument types are well-formed. This may imply certain relationships
-    /// between generic parameters. For example:
-    ///
-    ///     fn foo<'a,T>(x: &'a T)
-    ///
-    /// can only be called with a `'a` and `T` such that `&'a T` is WF.
-    /// For `&'a T` to be WF, `T: 'a` must hold. So we can assume `T: 'a`.
-    ///
-    /// # Parameters
-    ///
-    /// - `param_env`, the where-clauses in scope
-    /// - `body_id`, the body-id to use when normalizing assoc types.
-    ///   Note that this may cause outlives obligations to be injected
-    ///   into the inference context with this body-id.
-    /// - `ty`, the type that we are supposed to assume is WF.
-    /// - `span`, a span to use when normalizing, hopefully not important,
-    ///   might be useful if a `bug!` occurs.
-    pub fn implied_outlives_bounds(
-        &self,
-        param_env: ty::ParamEnv<'tcx>,
-        body_id: hir::HirId,
-        ty: Ty<'tcx>,
-        span: Span,
-    ) -> Vec<OutlivesBound<'tcx>> {
-        debug!("implied_outlives_bounds(ty = {:?})", ty);
-
-        let mut orig_values = OriginalQueryValues::default();
-        let key = self.canonicalize_query(&param_env.and(ty), &mut orig_values);
-        let result = match self.tcx.implied_outlives_bounds(key) {
-            Ok(r) => r,
-            Err(NoSolution) => {
-                self.tcx.sess.delay_span_bug(
-                    span,
-                    "implied_outlives_bounds failed to solve all obligations",
-                );
-                return vec![];
-            }
-        };
-        assert!(result.value.is_proven());
-
-        let result = self.instantiate_query_response_and_region_obligations(
-            &ObligationCause::misc(span, body_id),
-            param_env,
-            &orig_values,
-            &result,
-        );
-        debug!("implied_outlives_bounds for {:?}: {:#?}", ty, result);
-        let result = match result {
-            Ok(v) => v,
-            Err(_) => {
-                self.tcx.sess.delay_span_bug(span, "implied_outlives_bounds failed to instantiate");
-                return vec![];
-            }
-        };
-
-        // Instantiation may have produced new inference variables and constraints on those
-        // variables. Process these constraints.
-        let mut fulfill_cx = FulfillmentContext::new();
-        fulfill_cx.register_predicate_obligations(self, result.obligations);
-        if fulfill_cx.select_all_or_error(self).is_err() {
-            self.tcx.sess.delay_span_bug(
-                span,
-                "implied_outlives_bounds failed to solve obligations from instantiation",
-            );
-        }
-
-        result.value
-    }
-}
-
-pub fn explicit_outlives_bounds<'tcx>(
-    param_env: ty::ParamEnv<'tcx>,
-) -> impl Iterator<Item = OutlivesBound<'tcx>> + 'tcx {
-    debug!("explicit_outlives_bounds()");
-    param_env.caller_bounds.into_iter().filter_map(move |predicate| match predicate {
-        ty::Predicate::Projection(..)
-        | ty::Predicate::Trait(..)
-        | ty::Predicate::Subtype(..)
-        | ty::Predicate::WellFormed(..)
-        | ty::Predicate::ObjectSafe(..)
-        | ty::Predicate::ClosureKind(..)
-        | ty::Predicate::TypeOutlives(..)
-        | ty::Predicate::ConstEvaluatable(..) => None,
-        ty::Predicate::RegionOutlives(ref data) => data
-            .no_bound_vars()
-            .map(|ty::OutlivesPredicate(r_a, r_b)| OutlivesBound::RegionSubRegion(r_b, r_a)),
-    })
-}
diff --git a/src/librustc_infer/traits/query/type_op/ascribe_user_type.rs b/src/librustc_infer/traits/query/type_op/ascribe_user_type.rs
deleted file mode 100644 (file)
index b14b79f..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-use crate::infer::canonical::{Canonicalized, CanonicalizedQueryResponse};
-use crate::traits::query::Fallible;
-use rustc::ty::{ParamEnvAnd, TyCtxt};
-
-pub use rustc::traits::query::type_op::AscribeUserType;
-
-impl<'tcx> super::QueryTypeOp<'tcx> for AscribeUserType<'tcx> {
-    type QueryResponse = ();
-
-    fn try_fast_path(
-        _tcx: TyCtxt<'tcx>,
-        _key: &ParamEnvAnd<'tcx, Self>,
-    ) -> Option<Self::QueryResponse> {
-        None
-    }
-
-    fn perform_query(
-        tcx: TyCtxt<'tcx>,
-        canonicalized: Canonicalized<'tcx, ParamEnvAnd<'tcx, Self>>,
-    ) -> Fallible<CanonicalizedQueryResponse<'tcx, ()>> {
-        tcx.type_op_ascribe_user_type(canonicalized)
-    }
-}
diff --git a/src/librustc_infer/traits/query/type_op/custom.rs b/src/librustc_infer/traits/query/type_op/custom.rs
deleted file mode 100644 (file)
index c1c9030..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-use crate::infer::{InferCtxt, InferOk};
-use crate::traits::query::Fallible;
-use std::fmt;
-
-use crate::infer::canonical::query_response;
-use crate::infer::canonical::QueryRegionConstraints;
-use crate::traits::{ObligationCause, TraitEngine, TraitEngineExt};
-use rustc_span::source_map::DUMMY_SP;
-use std::rc::Rc;
-
-pub struct CustomTypeOp<F, G> {
-    closure: F,
-    description: G,
-}
-
-impl<F, G> CustomTypeOp<F, G> {
-    pub fn new<'tcx, R>(closure: F, description: G) -> Self
-    where
-        F: FnOnce(&InferCtxt<'_, 'tcx>) -> Fallible<InferOk<'tcx, R>>,
-        G: Fn() -> String,
-    {
-        CustomTypeOp { closure, description }
-    }
-}
-
-impl<'tcx, F, R, G> super::TypeOp<'tcx> for CustomTypeOp<F, G>
-where
-    F: for<'a, 'cx> FnOnce(&'a InferCtxt<'cx, 'tcx>) -> Fallible<InferOk<'tcx, R>>,
-    G: Fn() -> String,
-{
-    type Output = R;
-
-    /// Processes the operation and all resulting obligations,
-    /// returning the final result along with any region constraints
-    /// (they will be given over to the NLL region solver).
-    fn fully_perform(
-        self,
-        infcx: &InferCtxt<'_, 'tcx>,
-    ) -> Fallible<(Self::Output, Option<Rc<QueryRegionConstraints<'tcx>>>)> {
-        if cfg!(debug_assertions) {
-            info!("fully_perform({:?})", self);
-        }
-
-        scrape_region_constraints(infcx, || Ok((self.closure)(infcx)?))
-    }
-}
-
-impl<F, G> fmt::Debug for CustomTypeOp<F, G>
-where
-    G: Fn() -> String,
-{
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "{}", (self.description)())
-    }
-}
-
-/// Executes `op` and then scrapes out all the "old style" region
-/// constraints that result, creating query-region-constraints.
-fn scrape_region_constraints<'tcx, R>(
-    infcx: &InferCtxt<'_, 'tcx>,
-    op: impl FnOnce() -> Fallible<InferOk<'tcx, R>>,
-) -> Fallible<(R, Option<Rc<QueryRegionConstraints<'tcx>>>)> {
-    let mut fulfill_cx = TraitEngine::new(infcx.tcx);
-    let dummy_body_id = ObligationCause::dummy().body_id;
-
-    // During NLL, we expect that nobody will register region
-    // obligations **except** as part of a custom type op (and, at the
-    // end of each custom type op, we scrape out the region
-    // obligations that resulted). So this vector should be empty on
-    // entry.
-    let pre_obligations = infcx.take_registered_region_obligations();
-    assert!(
-        pre_obligations.is_empty(),
-        "scrape_region_constraints: incoming region obligations = {:#?}",
-        pre_obligations,
-    );
-
-    let InferOk { value, obligations } = infcx.commit_if_ok(|_| op())?;
-    debug_assert!(obligations.iter().all(|o| o.cause.body_id == dummy_body_id));
-    fulfill_cx.register_predicate_obligations(infcx, obligations);
-    if let Err(e) = fulfill_cx.select_all_or_error(infcx) {
-        infcx.tcx.sess.diagnostic().delay_span_bug(
-            DUMMY_SP,
-            &format!("errors selecting obligation during MIR typeck: {:?}", e),
-        );
-    }
-
-    let region_obligations = infcx.take_registered_region_obligations();
-
-    let region_constraint_data = infcx.take_and_reset_region_constraints();
-
-    let region_constraints = query_response::make_query_region_constraints(
-        infcx.tcx,
-        region_obligations
-            .iter()
-            .map(|(_, r_o)| (r_o.sup_type, r_o.sub_region))
-            .map(|(ty, r)| (infcx.resolve_vars_if_possible(&ty), r)),
-        &region_constraint_data,
-    );
-
-    if region_constraints.is_empty() {
-        Ok((value, None))
-    } else {
-        Ok((value, Some(Rc::new(region_constraints))))
-    }
-}
diff --git a/src/librustc_infer/traits/query/type_op/eq.rs b/src/librustc_infer/traits/query/type_op/eq.rs
deleted file mode 100644 (file)
index 3b6fbc7..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-use crate::infer::canonical::{Canonicalized, CanonicalizedQueryResponse};
-use crate::traits::query::Fallible;
-use rustc::ty::{ParamEnvAnd, TyCtxt};
-
-pub use rustc::traits::query::type_op::Eq;
-
-impl<'tcx> super::QueryTypeOp<'tcx> for Eq<'tcx> {
-    type QueryResponse = ();
-
-    fn try_fast_path(
-        _tcx: TyCtxt<'tcx>,
-        key: &ParamEnvAnd<'tcx, Eq<'tcx>>,
-    ) -> Option<Self::QueryResponse> {
-        if key.value.a == key.value.b { Some(()) } else { None }
-    }
-
-    fn perform_query(
-        tcx: TyCtxt<'tcx>,
-        canonicalized: Canonicalized<'tcx, ParamEnvAnd<'tcx, Self>>,
-    ) -> Fallible<CanonicalizedQueryResponse<'tcx, ()>> {
-        tcx.type_op_eq(canonicalized)
-    }
-}
diff --git a/src/librustc_infer/traits/query/type_op/implied_outlives_bounds.rs b/src/librustc_infer/traits/query/type_op/implied_outlives_bounds.rs
deleted file mode 100644 (file)
index 3dad546..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-use crate::infer::canonical::{Canonicalized, CanonicalizedQueryResponse};
-use crate::traits::query::outlives_bounds::OutlivesBound;
-use crate::traits::query::Fallible;
-use rustc::ty::{ParamEnvAnd, Ty, TyCtxt};
-
-#[derive(Clone, Debug, HashStable, TypeFoldable, Lift)]
-pub struct ImpliedOutlivesBounds<'tcx> {
-    pub ty: Ty<'tcx>,
-}
-
-impl<'tcx> ImpliedOutlivesBounds<'tcx> {
-    pub fn new(ty: Ty<'tcx>) -> Self {
-        ImpliedOutlivesBounds { ty }
-    }
-}
-
-impl<'tcx> super::QueryTypeOp<'tcx> for ImpliedOutlivesBounds<'tcx> {
-    type QueryResponse = Vec<OutlivesBound<'tcx>>;
-
-    fn try_fast_path(
-        _tcx: TyCtxt<'tcx>,
-        _key: &ParamEnvAnd<'tcx, Self>,
-    ) -> Option<Self::QueryResponse> {
-        None
-    }
-
-    fn perform_query(
-        tcx: TyCtxt<'tcx>,
-        canonicalized: Canonicalized<'tcx, ParamEnvAnd<'tcx, Self>>,
-    ) -> Fallible<CanonicalizedQueryResponse<'tcx, Self::QueryResponse>> {
-        // FIXME this `unchecked_map` is only necessary because the
-        // query is defined as taking a `ParamEnvAnd<Ty>`; it should
-        // take a `ImpliedOutlivesBounds` instead
-        let canonicalized = canonicalized.unchecked_map(|ParamEnvAnd { param_env, value }| {
-            let ImpliedOutlivesBounds { ty } = value;
-            param_env.and(ty)
-        });
-
-        tcx.implied_outlives_bounds(canonicalized)
-    }
-}
diff --git a/src/librustc_infer/traits/query/type_op/mod.rs b/src/librustc_infer/traits/query/type_op/mod.rs
deleted file mode 100644 (file)
index eb4c0a0..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-use crate::infer::canonical::{
-    Canonicalized, CanonicalizedQueryResponse, OriginalQueryValues, QueryRegionConstraints,
-};
-use crate::infer::{InferCtxt, InferOk};
-use crate::traits::query::Fallible;
-use crate::traits::ObligationCause;
-use rustc::ty::fold::TypeFoldable;
-use rustc::ty::{ParamEnvAnd, TyCtxt};
-use std::fmt;
-use std::rc::Rc;
-
-pub mod ascribe_user_type;
-pub mod custom;
-pub mod eq;
-pub mod implied_outlives_bounds;
-pub mod normalize;
-pub mod outlives;
-pub mod prove_predicate;
-use self::prove_predicate::ProvePredicate;
-pub mod subtype;
-
-pub use rustc::traits::query::type_op::*;
-
-/// "Type ops" are used in NLL to perform some particular action and
-/// extract out the resulting region constraints (or an error if it
-/// cannot be completed).
-pub trait TypeOp<'tcx>: Sized + fmt::Debug {
-    type Output;
-
-    /// Processes the operation and all resulting obligations,
-    /// returning the final result along with any region constraints
-    /// (they will be given over to the NLL region solver).
-    fn fully_perform(
-        self,
-        infcx: &InferCtxt<'_, 'tcx>,
-    ) -> Fallible<(Self::Output, Option<Rc<QueryRegionConstraints<'tcx>>>)>;
-}
-
-/// "Query type ops" are type ops that are implemented using a
-/// [canonical query][c]. The `Self` type here contains the kernel of
-/// information needed to do the operation -- `TypeOp` is actually
-/// implemented for `ParamEnvAnd<Self>`, since we always need to bring
-/// along a parameter environment as well. For query type-ops, we will
-/// first canonicalize the key and then invoke the query on the tcx,
-/// which produces the resulting query region constraints.
-///
-/// [c]: https://rust-lang.github.io/rustc-guide/traits/canonicalization.html
-pub trait QueryTypeOp<'tcx>: fmt::Debug + Sized + TypeFoldable<'tcx> + 'tcx {
-    type QueryResponse: TypeFoldable<'tcx>;
-
-    /// Give query the option for a simple fast path that never
-    /// actually hits the tcx cache lookup etc. Return `Some(r)` with
-    /// a final result or `None` to do the full path.
-    fn try_fast_path(
-        tcx: TyCtxt<'tcx>,
-        key: &ParamEnvAnd<'tcx, Self>,
-    ) -> Option<Self::QueryResponse>;
-
-    /// Performs the actual query with the canonicalized key -- the
-    /// real work happens here. This method is not given an `infcx`
-    /// because it shouldn't need one -- and if it had access to one,
-    /// it might do things like invoke `sub_regions`, which would be
-    /// bad, because it would create subregion relationships that are
-    /// not captured in the return value.
-    fn perform_query(
-        tcx: TyCtxt<'tcx>,
-        canonicalized: Canonicalized<'tcx, ParamEnvAnd<'tcx, Self>>,
-    ) -> Fallible<CanonicalizedQueryResponse<'tcx, Self::QueryResponse>>;
-
-    fn fully_perform_into(
-        query_key: ParamEnvAnd<'tcx, Self>,
-        infcx: &InferCtxt<'_, 'tcx>,
-        output_query_region_constraints: &mut QueryRegionConstraints<'tcx>,
-    ) -> Fallible<Self::QueryResponse> {
-        if let Some(result) = QueryTypeOp::try_fast_path(infcx.tcx, &query_key) {
-            return Ok(result);
-        }
-
-        // FIXME(#33684) -- We need to use
-        // `canonicalize_hr_query_hack` here because of things
-        // like the subtype query, which go awry around
-        // `'static` otherwise.
-        let mut canonical_var_values = OriginalQueryValues::default();
-        let canonical_self =
-            infcx.canonicalize_hr_query_hack(&query_key, &mut canonical_var_values);
-        let canonical_result = Self::perform_query(infcx.tcx, canonical_self)?;
-
-        let param_env = query_key.param_env;
-
-        let InferOk { value, obligations } = infcx
-            .instantiate_nll_query_response_and_region_obligations(
-                &ObligationCause::dummy(),
-                param_env,
-                &canonical_var_values,
-                canonical_result,
-                output_query_region_constraints,
-            )?;
-
-        // Typically, instantiating NLL query results does not
-        // create obligations. However, in some cases there
-        // are unresolved type variables, and unify them *can*
-        // create obligations. In that case, we have to go
-        // fulfill them. We do this via a (recursive) query.
-        for obligation in obligations {
-            let () = ProvePredicate::fully_perform_into(
-                obligation.param_env.and(ProvePredicate::new(obligation.predicate)),
-                infcx,
-                output_query_region_constraints,
-            )?;
-        }
-
-        Ok(value)
-    }
-}
-
-impl<'tcx, Q> TypeOp<'tcx> for ParamEnvAnd<'tcx, Q>
-where
-    Q: QueryTypeOp<'tcx>,
-{
-    type Output = Q::QueryResponse;
-
-    fn fully_perform(
-        self,
-        infcx: &InferCtxt<'_, 'tcx>,
-    ) -> Fallible<(Self::Output, Option<Rc<QueryRegionConstraints<'tcx>>>)> {
-        let mut region_constraints = QueryRegionConstraints::default();
-        let r = Q::fully_perform_into(self, infcx, &mut region_constraints)?;
-
-        // Promote the final query-region-constraints into a
-        // (optional) ref-counted vector:
-        let opt_qrc =
-            if region_constraints.is_empty() { None } else { Some(Rc::new(region_constraints)) };
-
-        Ok((r, opt_qrc))
-    }
-}
diff --git a/src/librustc_infer/traits/query/type_op/normalize.rs b/src/librustc_infer/traits/query/type_op/normalize.rs
deleted file mode 100644 (file)
index d2eec53..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-use crate::infer::canonical::{Canonicalized, CanonicalizedQueryResponse};
-use crate::traits::query::Fallible;
-use rustc::ty::fold::TypeFoldable;
-use rustc::ty::{self, Lift, ParamEnvAnd, Ty, TyCtxt};
-use std::fmt;
-
-pub use rustc::traits::query::type_op::Normalize;
-
-impl<'tcx, T> super::QueryTypeOp<'tcx> for Normalize<T>
-where
-    T: Normalizable<'tcx> + 'tcx,
-{
-    type QueryResponse = T;
-
-    fn try_fast_path(_tcx: TyCtxt<'tcx>, key: &ParamEnvAnd<'tcx, Self>) -> Option<T> {
-        if !key.value.value.has_projections() { Some(key.value.value) } else { None }
-    }
-
-    fn perform_query(
-        tcx: TyCtxt<'tcx>,
-        canonicalized: Canonicalized<'tcx, ParamEnvAnd<'tcx, Self>>,
-    ) -> Fallible<CanonicalizedQueryResponse<'tcx, Self::QueryResponse>> {
-        T::type_op_method(tcx, canonicalized)
-    }
-}
-
-pub trait Normalizable<'tcx>: fmt::Debug + TypeFoldable<'tcx> + Lift<'tcx> + Copy {
-    fn type_op_method(
-        tcx: TyCtxt<'tcx>,
-        canonicalized: Canonicalized<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
-    ) -> Fallible<CanonicalizedQueryResponse<'tcx, Self>>;
-}
-
-impl Normalizable<'tcx> for Ty<'tcx> {
-    fn type_op_method(
-        tcx: TyCtxt<'tcx>,
-        canonicalized: Canonicalized<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
-    ) -> Fallible<CanonicalizedQueryResponse<'tcx, Self>> {
-        tcx.type_op_normalize_ty(canonicalized)
-    }
-}
-
-impl Normalizable<'tcx> for ty::Predicate<'tcx> {
-    fn type_op_method(
-        tcx: TyCtxt<'tcx>,
-        canonicalized: Canonicalized<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
-    ) -> Fallible<CanonicalizedQueryResponse<'tcx, Self>> {
-        tcx.type_op_normalize_predicate(canonicalized)
-    }
-}
-
-impl Normalizable<'tcx> for ty::PolyFnSig<'tcx> {
-    fn type_op_method(
-        tcx: TyCtxt<'tcx>,
-        canonicalized: Canonicalized<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
-    ) -> Fallible<CanonicalizedQueryResponse<'tcx, Self>> {
-        tcx.type_op_normalize_poly_fn_sig(canonicalized)
-    }
-}
-
-impl Normalizable<'tcx> for ty::FnSig<'tcx> {
-    fn type_op_method(
-        tcx: TyCtxt<'tcx>,
-        canonicalized: Canonicalized<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
-    ) -> Fallible<CanonicalizedQueryResponse<'tcx, Self>> {
-        tcx.type_op_normalize_fn_sig(canonicalized)
-    }
-}
diff --git a/src/librustc_infer/traits/query/type_op/outlives.rs b/src/librustc_infer/traits/query/type_op/outlives.rs
deleted file mode 100644 (file)
index b94948c..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-use crate::infer::canonical::{Canonicalized, CanonicalizedQueryResponse};
-use crate::traits::query::dropck_outlives::{trivial_dropck_outlives, DropckOutlivesResult};
-use crate::traits::query::Fallible;
-use rustc::ty::{ParamEnvAnd, Ty, TyCtxt};
-
-#[derive(Copy, Clone, Debug, HashStable, TypeFoldable, Lift)]
-pub struct DropckOutlives<'tcx> {
-    dropped_ty: Ty<'tcx>,
-}
-
-impl<'tcx> DropckOutlives<'tcx> {
-    pub fn new(dropped_ty: Ty<'tcx>) -> Self {
-        DropckOutlives { dropped_ty }
-    }
-}
-
-impl super::QueryTypeOp<'tcx> for DropckOutlives<'tcx> {
-    type QueryResponse = DropckOutlivesResult<'tcx>;
-
-    fn try_fast_path(
-        tcx: TyCtxt<'tcx>,
-        key: &ParamEnvAnd<'tcx, Self>,
-    ) -> Option<Self::QueryResponse> {
-        if trivial_dropck_outlives(tcx, key.value.dropped_ty) {
-            Some(DropckOutlivesResult::default())
-        } else {
-            None
-        }
-    }
-
-    fn perform_query(
-        tcx: TyCtxt<'tcx>,
-        canonicalized: Canonicalized<'tcx, ParamEnvAnd<'tcx, Self>>,
-    ) -> Fallible<CanonicalizedQueryResponse<'tcx, Self::QueryResponse>> {
-        // Subtle: note that we are not invoking
-        // `infcx.at(...).dropck_outlives(...)` here, but rather the
-        // underlying `dropck_outlives` query. This same underlying
-        // query is also used by the
-        // `infcx.at(...).dropck_outlives(...)` fn. Avoiding the
-        // wrapper means we don't need an infcx in this code, which is
-        // good because the interface doesn't give us one (so that we
-        // know we are not registering any subregion relations or
-        // other things).
-
-        // FIXME convert to the type expected by the `dropck_outlives`
-        // query. This should eventually be fixed by changing the
-        // *underlying query*.
-        let canonicalized = canonicalized.unchecked_map(|ParamEnvAnd { param_env, value }| {
-            let DropckOutlives { dropped_ty } = value;
-            param_env.and(dropped_ty)
-        });
-
-        tcx.dropck_outlives(canonicalized)
-    }
-}
diff --git a/src/librustc_infer/traits/query/type_op/prove_predicate.rs b/src/librustc_infer/traits/query/type_op/prove_predicate.rs
deleted file mode 100644 (file)
index 8c68f7d..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-use crate::infer::canonical::{Canonicalized, CanonicalizedQueryResponse};
-use crate::traits::query::Fallible;
-use rustc::ty::{ParamEnvAnd, Predicate, TyCtxt};
-
-pub use rustc::traits::query::type_op::ProvePredicate;
-
-impl<'tcx> super::QueryTypeOp<'tcx> for ProvePredicate<'tcx> {
-    type QueryResponse = ();
-
-    fn try_fast_path(
-        tcx: TyCtxt<'tcx>,
-        key: &ParamEnvAnd<'tcx, Self>,
-    ) -> Option<Self::QueryResponse> {
-        // Proving Sized, very often on "obviously sized" types like
-        // `&T`, accounts for about 60% percentage of the predicates
-        // we have to prove. No need to canonicalize and all that for
-        // such cases.
-        if let Predicate::Trait(trait_ref, _) = key.value.predicate {
-            if let Some(sized_def_id) = tcx.lang_items().sized_trait() {
-                if trait_ref.def_id() == sized_def_id {
-                    if trait_ref.skip_binder().self_ty().is_trivially_sized(tcx) {
-                        return Some(());
-                    }
-                }
-            }
-        }
-
-        None
-    }
-
-    fn perform_query(
-        tcx: TyCtxt<'tcx>,
-        canonicalized: Canonicalized<'tcx, ParamEnvAnd<'tcx, Self>>,
-    ) -> Fallible<CanonicalizedQueryResponse<'tcx, ()>> {
-        tcx.type_op_prove_predicate(canonicalized)
-    }
-}
diff --git a/src/librustc_infer/traits/query/type_op/subtype.rs b/src/librustc_infer/traits/query/type_op/subtype.rs
deleted file mode 100644 (file)
index 053411b..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-use crate::infer::canonical::{Canonicalized, CanonicalizedQueryResponse};
-use crate::traits::query::Fallible;
-use rustc::ty::{ParamEnvAnd, TyCtxt};
-
-pub use rustc::traits::query::type_op::Subtype;
-
-impl<'tcx> super::QueryTypeOp<'tcx> for Subtype<'tcx> {
-    type QueryResponse = ();
-
-    fn try_fast_path(_tcx: TyCtxt<'tcx>, key: &ParamEnvAnd<'tcx, Self>) -> Option<()> {
-        if key.value.sub == key.value.sup { Some(()) } else { None }
-    }
-
-    fn perform_query(
-        tcx: TyCtxt<'tcx>,
-        canonicalized: Canonicalized<'tcx, ParamEnvAnd<'tcx, Self>>,
-    ) -> Fallible<CanonicalizedQueryResponse<'tcx, ()>> {
-        tcx.type_op_subtype(canonicalized)
-    }
-}
diff --git a/src/librustc_infer/traits/select.rs b/src/librustc_infer/traits/select.rs
deleted file mode 100644 (file)
index a79cbfd..0000000
+++ /dev/null
@@ -1,3827 +0,0 @@
-// ignore-tidy-filelength
-
-//! Candidate selection. See the [rustc guide] for more information on how this works.
-//!
-//! [rustc guide]: https://rust-lang.github.io/rustc-guide/traits/resolution.html#selection
-
-use self::EvaluationResult::*;
-use self::SelectionCandidate::*;
-
-use super::coherence::{self, Conflict};
-use super::project;
-use super::project::{
-    normalize_with_depth, normalize_with_depth_to, Normalized, ProjectionCacheKey,
-};
-use super::util;
-use super::util::{closure_trait_ref_and_return_type, predicate_for_trait_def};
-use super::wf;
-use super::DerivedObligationCause;
-use super::Selection;
-use super::SelectionResult;
-use super::TraitNotObjectSafe;
-use super::TraitQueryMode;
-use super::{BuiltinDerivedObligation, ImplDerivedObligation, ObligationCauseCode};
-use super::{ObjectCastObligation, Obligation};
-use super::{ObligationCause, PredicateObligation, TraitObligation};
-use super::{OutputTypeParameterMismatch, Overflow, SelectionError, Unimplemented};
-use super::{
-    VtableAutoImpl, VtableBuiltin, VtableClosure, VtableFnPointer, VtableGenerator, VtableImpl,
-    VtableObject, VtableParam, VtableTraitAlias,
-};
-use super::{
-    VtableAutoImplData, VtableBuiltinData, VtableClosureData, VtableFnPointerData,
-    VtableGeneratorData, VtableImplData, VtableObjectData, VtableTraitAliasData,
-};
-
-use crate::infer::{CombinedSnapshot, InferCtxt, InferOk, PlaceholderMap, TypeFreshener};
-use rustc::dep_graph::{DepKind, DepNodeIndex};
-use rustc::middle::lang_items;
-use rustc::ty::fast_reject;
-use rustc::ty::relate::TypeRelation;
-use rustc::ty::subst::{Subst, SubstsRef};
-use rustc::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
-use rustc_ast::attr;
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
-use rustc_index::bit_set::GrowableBitSet;
-use rustc_span::symbol::sym;
-use rustc_target::spec::abi::Abi;
-
-use std::cell::{Cell, RefCell};
-use std::cmp;
-use std::fmt::{self, Display};
-use std::iter;
-use std::rc::Rc;
-
-pub use rustc::traits::select::*;
-
-pub struct SelectionContext<'cx, 'tcx> {
-    infcx: &'cx InferCtxt<'cx, 'tcx>,
-
-    /// Freshener used specifically for entries on the obligation
-    /// stack. This ensures that all entries on the stack at one time
-    /// will have the same set of placeholder entries, which is
-    /// important for checking for trait bounds that recursively
-    /// require themselves.
-    freshener: TypeFreshener<'cx, 'tcx>,
-
-    /// If `true`, indicates that the evaluation should be conservative
-    /// and consider the possibility of types outside this crate.
-    /// This comes up primarily when resolving ambiguity. Imagine
-    /// there is some trait reference `$0: Bar` where `$0` is an
-    /// inference variable. If `intercrate` is true, then we can never
-    /// say for sure that this reference is not implemented, even if
-    /// there are *no impls at all for `Bar`*, because `$0` could be
-    /// bound to some type that in a downstream crate that implements
-    /// `Bar`. This is the suitable mode for coherence. Elsewhere,
-    /// though, we set this to false, because we are only interested
-    /// in types that the user could actually have written --- in
-    /// other words, we consider `$0: Bar` to be unimplemented if
-    /// there is no type that the user could *actually name* that
-    /// would satisfy it. This avoids crippling inference, basically.
-    intercrate: bool,
-
-    intercrate_ambiguity_causes: Option<Vec<IntercrateAmbiguityCause>>,
-
-    /// Controls whether or not to filter out negative impls when selecting.
-    /// This is used in librustdoc to distinguish between the lack of an impl
-    /// and a negative impl
-    allow_negative_impls: bool,
-
-    /// The mode that trait queries run in, which informs our error handling
-    /// policy. In essence, canonicalized queries need their errors propagated
-    /// rather than immediately reported because we do not have accurate spans.
-    query_mode: TraitQueryMode,
-}
-
-#[derive(Clone, Debug)]
-pub enum IntercrateAmbiguityCause {
-    DownstreamCrate { trait_desc: String, self_desc: Option<String> },
-    UpstreamCrateUpdate { trait_desc: String, self_desc: Option<String> },
-    ReservationImpl { message: String },
-}
-
-impl IntercrateAmbiguityCause {
-    /// Emits notes when the overlap is caused by complex intercrate ambiguities.
-    /// See #23980 for details.
-    pub fn add_intercrate_ambiguity_hint(&self, err: &mut rustc_errors::DiagnosticBuilder<'_>) {
-        err.note(&self.intercrate_ambiguity_hint());
-    }
-
-    pub fn intercrate_ambiguity_hint(&self) -> String {
-        match self {
-            &IntercrateAmbiguityCause::DownstreamCrate { ref trait_desc, ref self_desc } => {
-                let self_desc = if let &Some(ref ty) = self_desc {
-                    format!(" for type `{}`", ty)
-                } else {
-                    String::new()
-                };
-                format!("downstream crates may implement trait `{}`{}", trait_desc, self_desc)
-            }
-            &IntercrateAmbiguityCause::UpstreamCrateUpdate { ref trait_desc, ref self_desc } => {
-                let self_desc = if let &Some(ref ty) = self_desc {
-                    format!(" for type `{}`", ty)
-                } else {
-                    String::new()
-                };
-                format!(
-                    "upstream crates may add a new impl of trait `{}`{} \
-                     in future versions",
-                    trait_desc, self_desc
-                )
-            }
-            &IntercrateAmbiguityCause::ReservationImpl { ref message } => message.clone(),
-        }
-    }
-}
-
-// A stack that walks back up the stack frame.
-struct TraitObligationStack<'prev, 'tcx> {
-    obligation: &'prev TraitObligation<'tcx>,
-
-    /// The trait ref from `obligation` but "freshened" with the
-    /// selection-context's freshener. Used to check for recursion.
-    fresh_trait_ref: ty::PolyTraitRef<'tcx>,
-
-    /// Starts out equal to `depth` -- if, during evaluation, we
-    /// encounter a cycle, then we will set this flag to the minimum
-    /// depth of that cycle for all participants in the cycle. These
-    /// participants will then forego caching their results. This is
-    /// not the most efficient solution, but it addresses #60010. The
-    /// problem we are trying to prevent:
-    ///
-    /// - If you have `A: AutoTrait` requires `B: AutoTrait` and `C: NonAutoTrait`
-    /// - `B: AutoTrait` requires `A: AutoTrait` (coinductive cycle, ok)
-    /// - `C: NonAutoTrait` requires `A: AutoTrait` (non-coinductive cycle, not ok)
-    ///
-    /// you don't want to cache that `B: AutoTrait` or `A: AutoTrait`
-    /// is `EvaluatedToOk`; this is because they were only considered
-    /// ok on the premise that if `A: AutoTrait` held, but we indeed
-    /// encountered a problem (later on) with `A: AutoTrait. So we
-    /// currently set a flag on the stack node for `B: AutoTrait` (as
-    /// well as the second instance of `A: AutoTrait`) to suppress
-    /// caching.
-    ///
-    /// This is a simple, targeted fix. A more-performant fix requires
-    /// deeper changes, but would permit more caching: we could
-    /// basically defer caching until we have fully evaluated the
-    /// tree, and then cache the entire tree at once. In any case, the
-    /// performance impact here shouldn't be so horrible: every time
-    /// this is hit, we do cache at least one trait, so we only
-    /// evaluate each member of a cycle up to N times, where N is the
-    /// length of the cycle. This means the performance impact is
-    /// bounded and we shouldn't have any terrible worst-cases.
-    reached_depth: Cell<usize>,
-
-    previous: TraitObligationStackList<'prev, 'tcx>,
-
-    /// The number of parent frames plus one (thus, the topmost frame has depth 1).
-    depth: usize,
-
-    /// The depth-first number of this node in the search graph -- a
-    /// pre-order index. Basically, a freshly incremented counter.
-    dfn: usize,
-}
-
-struct SelectionCandidateSet<'tcx> {
-    // A list of candidates that definitely apply to the current
-    // obligation (meaning: types unify).
-    vec: Vec<SelectionCandidate<'tcx>>,
-
-    // If `true`, then there were candidates that might or might
-    // not have applied, but we couldn't tell. This occurs when some
-    // of the input types are type variables, in which case there are
-    // various "builtin" rules that might or might not trigger.
-    ambiguous: bool,
-}
-
-#[derive(PartialEq, Eq, Debug, Clone)]
-struct EvaluatedCandidate<'tcx> {
-    candidate: SelectionCandidate<'tcx>,
-    evaluation: EvaluationResult,
-}
-
-/// When does the builtin impl for `T: Trait` apply?
-enum BuiltinImplConditions<'tcx> {
-    /// The impl is conditional on `T1, T2, ...: Trait`.
-    Where(ty::Binder<Vec<Ty<'tcx>>>),
-    /// There is no built-in impl. There may be some other
-    /// candidate (a where-clause or user-defined impl).
-    None,
-    /// It is unknown whether there is an impl.
-    Ambiguous,
-}
-
-impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
-    pub fn new(infcx: &'cx InferCtxt<'cx, 'tcx>) -> SelectionContext<'cx, 'tcx> {
-        SelectionContext {
-            infcx,
-            freshener: infcx.freshener(),
-            intercrate: false,
-            intercrate_ambiguity_causes: None,
-            allow_negative_impls: false,
-            query_mode: TraitQueryMode::Standard,
-        }
-    }
-
-    pub fn intercrate(infcx: &'cx InferCtxt<'cx, 'tcx>) -> SelectionContext<'cx, 'tcx> {
-        SelectionContext {
-            infcx,
-            freshener: infcx.freshener(),
-            intercrate: true,
-            intercrate_ambiguity_causes: None,
-            allow_negative_impls: false,
-            query_mode: TraitQueryMode::Standard,
-        }
-    }
-
-    pub fn with_negative(
-        infcx: &'cx InferCtxt<'cx, 'tcx>,
-        allow_negative_impls: bool,
-    ) -> SelectionContext<'cx, 'tcx> {
-        debug!("with_negative({:?})", allow_negative_impls);
-        SelectionContext {
-            infcx,
-            freshener: infcx.freshener(),
-            intercrate: false,
-            intercrate_ambiguity_causes: None,
-            allow_negative_impls,
-            query_mode: TraitQueryMode::Standard,
-        }
-    }
-
-    pub fn with_query_mode(
-        infcx: &'cx InferCtxt<'cx, 'tcx>,
-        query_mode: TraitQueryMode,
-    ) -> SelectionContext<'cx, 'tcx> {
-        debug!("with_query_mode({:?})", query_mode);
-        SelectionContext {
-            infcx,
-            freshener: infcx.freshener(),
-            intercrate: false,
-            intercrate_ambiguity_causes: None,
-            allow_negative_impls: false,
-            query_mode,
-        }
-    }
-
-    /// Enables tracking of intercrate ambiguity causes. These are
-    /// used in coherence to give improved diagnostics. We don't do
-    /// this until we detect a coherence error because it can lead to
-    /// false overflow results (#47139) and because it costs
-    /// computation time.
-    pub fn enable_tracking_intercrate_ambiguity_causes(&mut self) {
-        assert!(self.intercrate);
-        assert!(self.intercrate_ambiguity_causes.is_none());
-        self.intercrate_ambiguity_causes = Some(vec![]);
-        debug!("selcx: enable_tracking_intercrate_ambiguity_causes");
-    }
-
-    /// Gets the intercrate ambiguity causes collected since tracking
-    /// was enabled and disables tracking at the same time. If
-    /// tracking is not enabled, just returns an empty vector.
-    pub fn take_intercrate_ambiguity_causes(&mut self) -> Vec<IntercrateAmbiguityCause> {
-        assert!(self.intercrate);
-        self.intercrate_ambiguity_causes.take().unwrap_or(vec![])
-    }
-
-    pub fn infcx(&self) -> &'cx InferCtxt<'cx, 'tcx> {
-        self.infcx
-    }
-
-    pub fn tcx(&self) -> TyCtxt<'tcx> {
-        self.infcx.tcx
-    }
-
-    pub fn closure_typer(&self) -> &'cx InferCtxt<'cx, 'tcx> {
-        self.infcx
-    }
-
-    ///////////////////////////////////////////////////////////////////////////
-    // Selection
-    //
-    // The selection phase tries to identify *how* an obligation will
-    // be resolved. For example, it will identify which impl or
-    // parameter bound is to be used. The process can be inconclusive
-    // if the self type in the obligation is not fully inferred. Selection
-    // can result in an error in one of two ways:
-    //
-    // 1. If no applicable impl or parameter bound can be found.
-    // 2. If the output type parameters in the obligation do not match
-    //    those specified by the impl/bound. For example, if the obligation
-    //    is `Vec<Foo>: Iterable<Bar>`, but the impl specifies
-    //    `impl<T> Iterable<T> for Vec<T>`, than an error would result.
-
-    /// Attempts to satisfy the obligation. If successful, this will affect the surrounding
-    /// type environment by performing unification.
-    pub fn select(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-    ) -> SelectionResult<'tcx, Selection<'tcx>> {
-        debug!("select({:?})", obligation);
-        debug_assert!(!obligation.predicate.has_escaping_bound_vars());
-
-        let pec = &ProvisionalEvaluationCache::default();
-        let stack = self.push_stack(TraitObligationStackList::empty(pec), obligation);
-
-        let candidate = match self.candidate_from_obligation(&stack) {
-            Err(SelectionError::Overflow) => {
-                // In standard mode, overflow must have been caught and reported
-                // earlier.
-                assert!(self.query_mode == TraitQueryMode::Canonical);
-                return Err(SelectionError::Overflow);
-            }
-            Err(e) => {
-                return Err(e);
-            }
-            Ok(None) => {
-                return Ok(None);
-            }
-            Ok(Some(candidate)) => candidate,
-        };
-
-        match self.confirm_candidate(obligation, candidate) {
-            Err(SelectionError::Overflow) => {
-                assert!(self.query_mode == TraitQueryMode::Canonical);
-                Err(SelectionError::Overflow)
-            }
-            Err(e) => Err(e),
-            Ok(candidate) => Ok(Some(candidate)),
-        }
-    }
-
-    ///////////////////////////////////////////////////////////////////////////
-    // EVALUATION
-    //
-    // Tests whether an obligation can be selected or whether an impl
-    // can be applied to particular types. It skips the "confirmation"
-    // step and hence completely ignores output type parameters.
-    //
-    // The result is "true" if the obligation *may* hold and "false" if
-    // we can be sure it does not.
-
-    /// Evaluates whether the obligation `obligation` can be satisfied (by any means).
-    pub fn predicate_may_hold_fatal(&mut self, obligation: &PredicateObligation<'tcx>) -> bool {
-        debug!("predicate_may_hold_fatal({:?})", obligation);
-
-        // This fatal query is a stopgap that should only be used in standard mode,
-        // where we do not expect overflow to be propagated.
-        assert!(self.query_mode == TraitQueryMode::Standard);
-
-        self.evaluate_root_obligation(obligation)
-            .expect("Overflow should be caught earlier in standard query mode")
-            .may_apply()
-    }
-
-    /// Evaluates whether the obligation `obligation` can be satisfied
-    /// and returns an `EvaluationResult`. This is meant for the
-    /// *initial* call.
-    pub fn evaluate_root_obligation(
-        &mut self,
-        obligation: &PredicateObligation<'tcx>,
-    ) -> Result<EvaluationResult, OverflowError> {
-        self.evaluation_probe(|this| {
-            this.evaluate_predicate_recursively(
-                TraitObligationStackList::empty(&ProvisionalEvaluationCache::default()),
-                obligation.clone(),
-            )
-        })
-    }
-
-    fn evaluation_probe(
-        &mut self,
-        op: impl FnOnce(&mut Self) -> Result<EvaluationResult, OverflowError>,
-    ) -> Result<EvaluationResult, OverflowError> {
-        self.infcx.probe(|snapshot| -> Result<EvaluationResult, OverflowError> {
-            let result = op(self)?;
-            match self.infcx.region_constraints_added_in_snapshot(snapshot) {
-                None => Ok(result),
-                Some(_) => Ok(result.max(EvaluatedToOkModuloRegions)),
-            }
-        })
-    }
-
-    /// Evaluates the predicates in `predicates` recursively. Note that
-    /// this applies projections in the predicates, and therefore
-    /// is run within an inference probe.
-    fn evaluate_predicates_recursively<'o, I>(
-        &mut self,
-        stack: TraitObligationStackList<'o, 'tcx>,
-        predicates: I,
-    ) -> Result<EvaluationResult, OverflowError>
-    where
-        I: IntoIterator<Item = PredicateObligation<'tcx>>,
-    {
-        let mut result = EvaluatedToOk;
-        for obligation in predicates {
-            let eval = self.evaluate_predicate_recursively(stack, obligation.clone())?;
-            debug!("evaluate_predicate_recursively({:?}) = {:?}", obligation, eval);
-            if let EvaluatedToErr = eval {
-                // fast-path - EvaluatedToErr is the top of the lattice,
-                // so we don't need to look on the other predicates.
-                return Ok(EvaluatedToErr);
-            } else {
-                result = cmp::max(result, eval);
-            }
-        }
-        Ok(result)
-    }
-
-    fn evaluate_predicate_recursively<'o>(
-        &mut self,
-        previous_stack: TraitObligationStackList<'o, 'tcx>,
-        obligation: PredicateObligation<'tcx>,
-    ) -> Result<EvaluationResult, OverflowError> {
-        debug!(
-            "evaluate_predicate_recursively(previous_stack={:?}, obligation={:?})",
-            previous_stack.head(),
-            obligation
-        );
-
-        // `previous_stack` stores a `TraitObligatiom`, while `obligation` is
-        // a `PredicateObligation`. These are distinct types, so we can't
-        // use any `Option` combinator method that would force them to be
-        // the same.
-        match previous_stack.head() {
-            Some(h) => self.check_recursion_limit(&obligation, h.obligation)?,
-            None => self.check_recursion_limit(&obligation, &obligation)?,
-        }
-
-        match obligation.predicate {
-            ty::Predicate::Trait(ref t, _) => {
-                debug_assert!(!t.has_escaping_bound_vars());
-                let obligation = obligation.with(t.clone());
-                self.evaluate_trait_predicate_recursively(previous_stack, obligation)
-            }
-
-            ty::Predicate::Subtype(ref p) => {
-                // Does this code ever run?
-                match self.infcx.subtype_predicate(&obligation.cause, obligation.param_env, p) {
-                    Some(Ok(InferOk { mut obligations, .. })) => {
-                        self.add_depth(obligations.iter_mut(), obligation.recursion_depth);
-                        self.evaluate_predicates_recursively(
-                            previous_stack,
-                            obligations.into_iter(),
-                        )
-                    }
-                    Some(Err(_)) => Ok(EvaluatedToErr),
-                    None => Ok(EvaluatedToAmbig),
-                }
-            }
-
-            ty::Predicate::WellFormed(ty) => match wf::obligations(
-                self.infcx,
-                obligation.param_env,
-                obligation.cause.body_id,
-                ty,
-                obligation.cause.span,
-            ) {
-                Some(mut obligations) => {
-                    self.add_depth(obligations.iter_mut(), obligation.recursion_depth);
-                    self.evaluate_predicates_recursively(previous_stack, obligations.into_iter())
-                }
-                None => Ok(EvaluatedToAmbig),
-            },
-
-            ty::Predicate::TypeOutlives(..) | ty::Predicate::RegionOutlives(..) => {
-                // We do not consider region relationships when evaluating trait matches.
-                Ok(EvaluatedToOkModuloRegions)
-            }
-
-            ty::Predicate::ObjectSafe(trait_def_id) => {
-                if self.tcx().is_object_safe(trait_def_id) {
-                    Ok(EvaluatedToOk)
-                } else {
-                    Ok(EvaluatedToErr)
-                }
-            }
-
-            ty::Predicate::Projection(ref data) => {
-                let project_obligation = obligation.with(data.clone());
-                match project::poly_project_and_unify_type(self, &project_obligation) {
-                    Ok(Some(mut subobligations)) => {
-                        self.add_depth(subobligations.iter_mut(), obligation.recursion_depth);
-                        let result = self.evaluate_predicates_recursively(
-                            previous_stack,
-                            subobligations.into_iter(),
-                        );
-                        if let Some(key) =
-                            ProjectionCacheKey::from_poly_projection_predicate(self, data)
-                        {
-                            self.infcx.inner.borrow_mut().projection_cache.complete(key);
-                        }
-                        result
-                    }
-                    Ok(None) => Ok(EvaluatedToAmbig),
-                    Err(_) => Ok(EvaluatedToErr),
-                }
-            }
-
-            ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => {
-                match self.infcx.closure_kind(closure_def_id, closure_substs) {
-                    Some(closure_kind) => {
-                        if closure_kind.extends(kind) {
-                            Ok(EvaluatedToOk)
-                        } else {
-                            Ok(EvaluatedToErr)
-                        }
-                    }
-                    None => Ok(EvaluatedToAmbig),
-                }
-            }
-
-            ty::Predicate::ConstEvaluatable(def_id, substs) => {
-                match self.tcx().const_eval_resolve(
-                    obligation.param_env,
-                    def_id,
-                    substs,
-                    None,
-                    None,
-                ) {
-                    Ok(_) => Ok(EvaluatedToOk),
-                    Err(_) => Ok(EvaluatedToErr),
-                }
-            }
-        }
-    }
-
-    fn evaluate_trait_predicate_recursively<'o>(
-        &mut self,
-        previous_stack: TraitObligationStackList<'o, 'tcx>,
-        mut obligation: TraitObligation<'tcx>,
-    ) -> Result<EvaluationResult, OverflowError> {
-        debug!("evaluate_trait_predicate_recursively({:?})", obligation);
-
-        if !self.intercrate
-            && obligation.is_global()
-            && obligation.param_env.caller_bounds.iter().all(|bound| bound.needs_subst())
-        {
-            // If a param env has no global bounds, global obligations do not
-            // depend on its particular value in order to work, so we can clear
-            // out the param env and get better caching.
-            debug!("evaluate_trait_predicate_recursively({:?}) - in global", obligation);
-            obligation.param_env = obligation.param_env.without_caller_bounds();
-        }
-
-        let stack = self.push_stack(previous_stack, &obligation);
-        let fresh_trait_ref = stack.fresh_trait_ref;
-        if let Some(result) = self.check_evaluation_cache(obligation.param_env, fresh_trait_ref) {
-            debug!("CACHE HIT: EVAL({:?})={:?}", fresh_trait_ref, result);
-            return Ok(result);
-        }
-
-        if let Some(result) = stack.cache().get_provisional(fresh_trait_ref) {
-            debug!("PROVISIONAL CACHE HIT: EVAL({:?})={:?}", fresh_trait_ref, result);
-            stack.update_reached_depth(stack.cache().current_reached_depth());
-            return Ok(result);
-        }
-
-        // Check if this is a match for something already on the
-        // stack. If so, we don't want to insert the result into the
-        // main cache (it is cycle dependent) nor the provisional
-        // cache (which is meant for things that have completed but
-        // for a "backedge" -- this result *is* the backedge).
-        if let Some(cycle_result) = self.check_evaluation_cycle(&stack) {
-            return Ok(cycle_result);
-        }
-
-        let (result, dep_node) = self.in_task(|this| this.evaluate_stack(&stack));
-        let result = result?;
-
-        if !result.must_apply_modulo_regions() {
-            stack.cache().on_failure(stack.dfn);
-        }
-
-        let reached_depth = stack.reached_depth.get();
-        if reached_depth >= stack.depth {
-            debug!("CACHE MISS: EVAL({:?})={:?}", fresh_trait_ref, result);
-            self.insert_evaluation_cache(obligation.param_env, fresh_trait_ref, dep_node, result);
-
-            stack.cache().on_completion(stack.depth, |fresh_trait_ref, provisional_result| {
-                self.insert_evaluation_cache(
-                    obligation.param_env,
-                    fresh_trait_ref,
-                    dep_node,
-                    provisional_result.max(result),
-                );
-            });
-        } else {
-            debug!("PROVISIONAL: {:?}={:?}", fresh_trait_ref, result);
-            debug!(
-                "evaluate_trait_predicate_recursively: caching provisionally because {:?} \
-                 is a cycle participant (at depth {}, reached depth {})",
-                fresh_trait_ref, stack.depth, reached_depth,
-            );
-
-            stack.cache().insert_provisional(stack.dfn, reached_depth, fresh_trait_ref, result);
-        }
-
-        Ok(result)
-    }
-
-    /// If there is any previous entry on the stack that precisely
-    /// matches this obligation, then we can assume that the
-    /// obligation is satisfied for now (still all other conditions
-    /// must be met of course). One obvious case this comes up is
-    /// marker traits like `Send`. Think of a linked list:
-    ///
-    ///    struct List<T> { data: T, next: Option<Box<List<T>>> }
-    ///
-    /// `Box<List<T>>` will be `Send` if `T` is `Send` and
-    /// `Option<Box<List<T>>>` is `Send`, and in turn
-    /// `Option<Box<List<T>>>` is `Send` if `Box<List<T>>` is
-    /// `Send`.
-    ///
-    /// Note that we do this comparison using the `fresh_trait_ref`
-    /// fields. Because these have all been freshened using
-    /// `self.freshener`, we can be sure that (a) this will not
-    /// affect the inferencer state and (b) that if we see two
-    /// fresh regions with the same index, they refer to the same
-    /// unbound type variable.
-    fn check_evaluation_cycle(
-        &mut self,
-        stack: &TraitObligationStack<'_, 'tcx>,
-    ) -> Option<EvaluationResult> {
-        if let Some(cycle_depth) = stack
-            .iter()
-            .skip(1) // Skip top-most frame.
-            .find(|prev| {
-                stack.obligation.param_env == prev.obligation.param_env
-                    && stack.fresh_trait_ref == prev.fresh_trait_ref
-            })
-            .map(|stack| stack.depth)
-        {
-            debug!(
-                "evaluate_stack({:?}) --> recursive at depth {}",
-                stack.fresh_trait_ref, cycle_depth,
-            );
-
-            // If we have a stack like `A B C D E A`, where the top of
-            // the stack is the final `A`, then this will iterate over
-            // `A, E, D, C, B` -- i.e., all the participants apart
-            // from the cycle head. We mark them as participating in a
-            // cycle. This suppresses caching for those nodes. See
-            // `in_cycle` field for more details.
-            stack.update_reached_depth(cycle_depth);
-
-            // Subtle: when checking for a coinductive cycle, we do
-            // not compare using the "freshened trait refs" (which
-            // have erased regions) but rather the fully explicit
-            // trait refs. This is important because it's only a cycle
-            // if the regions match exactly.
-            let cycle = stack.iter().skip(1).take_while(|s| s.depth >= cycle_depth);
-            let cycle = cycle.map(|stack| {
-                ty::Predicate::Trait(stack.obligation.predicate, hir::Constness::NotConst)
-            });
-            if self.coinductive_match(cycle) {
-                debug!("evaluate_stack({:?}) --> recursive, coinductive", stack.fresh_trait_ref);
-                Some(EvaluatedToOk)
-            } else {
-                debug!("evaluate_stack({:?}) --> recursive, inductive", stack.fresh_trait_ref);
-                Some(EvaluatedToRecur)
-            }
-        } else {
-            None
-        }
-    }
-
-    fn evaluate_stack<'o>(
-        &mut self,
-        stack: &TraitObligationStack<'o, 'tcx>,
-    ) -> Result<EvaluationResult, OverflowError> {
-        // In intercrate mode, whenever any of the types are unbound,
-        // there can always be an impl. Even if there are no impls in
-        // this crate, perhaps the type would be unified with
-        // something from another crate that does provide an impl.
-        //
-        // In intra mode, we must still be conservative. The reason is
-        // that we want to avoid cycles. Imagine an impl like:
-        //
-        //     impl<T:Eq> Eq for Vec<T>
-        //
-        // and a trait reference like `$0 : Eq` where `$0` is an
-        // unbound variable. When we evaluate this trait-reference, we
-        // will unify `$0` with `Vec<$1>` (for some fresh variable
-        // `$1`), on the condition that `$1 : Eq`. We will then wind
-        // up with many candidates (since that are other `Eq` impls
-        // that apply) and try to winnow things down. This results in
-        // a recursive evaluation that `$1 : Eq` -- as you can
-        // imagine, this is just where we started. To avoid that, we
-        // check for unbound variables and return an ambiguous (hence possible)
-        // match if we've seen this trait before.
-        //
-        // This suffices to allow chains like `FnMut` implemented in
-        // terms of `Fn` etc, but we could probably make this more
-        // precise still.
-        let unbound_input_types =
-            stack.fresh_trait_ref.skip_binder().input_types().any(|ty| ty.is_fresh());
-        // This check was an imperfect workaround for a bug in the old
-        // intercrate mode; it should be removed when that goes away.
-        if unbound_input_types && self.intercrate {
-            debug!(
-                "evaluate_stack({:?}) --> unbound argument, intercrate -->  ambiguous",
-                stack.fresh_trait_ref
-            );
-            // Heuristics: show the diagnostics when there are no candidates in crate.
-            if self.intercrate_ambiguity_causes.is_some() {
-                debug!("evaluate_stack: intercrate_ambiguity_causes is some");
-                if let Ok(candidate_set) = self.assemble_candidates(stack) {
-                    if !candidate_set.ambiguous && candidate_set.vec.is_empty() {
-                        let trait_ref = stack.obligation.predicate.skip_binder().trait_ref;
-                        let self_ty = trait_ref.self_ty();
-                        let cause = IntercrateAmbiguityCause::DownstreamCrate {
-                            trait_desc: trait_ref.print_only_trait_path().to_string(),
-                            self_desc: if self_ty.has_concrete_skeleton() {
-                                Some(self_ty.to_string())
-                            } else {
-                                None
-                            },
-                        };
-                        debug!("evaluate_stack: pushing cause = {:?}", cause);
-                        self.intercrate_ambiguity_causes.as_mut().unwrap().push(cause);
-                    }
-                }
-            }
-            return Ok(EvaluatedToAmbig);
-        }
-        if unbound_input_types
-            && stack.iter().skip(1).any(|prev| {
-                stack.obligation.param_env == prev.obligation.param_env
-                    && self.match_fresh_trait_refs(
-                        &stack.fresh_trait_ref,
-                        &prev.fresh_trait_ref,
-                        prev.obligation.param_env,
-                    )
-            })
-        {
-            debug!(
-                "evaluate_stack({:?}) --> unbound argument, recursive --> giving up",
-                stack.fresh_trait_ref
-            );
-            return Ok(EvaluatedToUnknown);
-        }
-
-        match self.candidate_from_obligation(stack) {
-            Ok(Some(c)) => self.evaluate_candidate(stack, &c),
-            Ok(None) => Ok(EvaluatedToAmbig),
-            Err(Overflow) => Err(OverflowError),
-            Err(..) => Ok(EvaluatedToErr),
-        }
-    }
-
-    /// For defaulted traits, we use a co-inductive strategy to solve, so
-    /// that recursion is ok. This routine returns `true` if the top of the
-    /// stack (`cycle[0]`):
-    ///
-    /// - is a defaulted trait,
-    /// - it also appears in the backtrace at some position `X`,
-    /// - all the predicates at positions `X..` between `X` and the top are
-    ///   also defaulted traits.
-    pub fn coinductive_match<I>(&mut self, cycle: I) -> bool
-    where
-        I: Iterator<Item = ty::Predicate<'tcx>>,
-    {
-        let mut cycle = cycle;
-        cycle.all(|predicate| self.coinductive_predicate(predicate))
-    }
-
-    fn coinductive_predicate(&self, predicate: ty::Predicate<'tcx>) -> bool {
-        let result = match predicate {
-            ty::Predicate::Trait(ref data, _) => self.tcx().trait_is_auto(data.def_id()),
-            _ => false,
-        };
-        debug!("coinductive_predicate({:?}) = {:?}", predicate, result);
-        result
-    }
-
-    /// Further evaluates `candidate` to decide whether all type parameters match and whether nested
-    /// obligations are met. Returns whether `candidate` remains viable after this further
-    /// scrutiny.
-    fn evaluate_candidate<'o>(
-        &mut self,
-        stack: &TraitObligationStack<'o, 'tcx>,
-        candidate: &SelectionCandidate<'tcx>,
-    ) -> Result<EvaluationResult, OverflowError> {
-        debug!(
-            "evaluate_candidate: depth={} candidate={:?}",
-            stack.obligation.recursion_depth, candidate
-        );
-        let result = self.evaluation_probe(|this| {
-            let candidate = (*candidate).clone();
-            match this.confirm_candidate(stack.obligation, candidate) {
-                Ok(selection) => this.evaluate_predicates_recursively(
-                    stack.list(),
-                    selection.nested_obligations().into_iter(),
-                ),
-                Err(..) => Ok(EvaluatedToErr),
-            }
-        })?;
-        debug!(
-            "evaluate_candidate: depth={} result={:?}",
-            stack.obligation.recursion_depth, result
-        );
-        Ok(result)
-    }
-
-    fn check_evaluation_cache(
-        &self,
-        param_env: ty::ParamEnv<'tcx>,
-        trait_ref: ty::PolyTraitRef<'tcx>,
-    ) -> Option<EvaluationResult> {
-        let tcx = self.tcx();
-        if self.can_use_global_caches(param_env) {
-            let cache = tcx.evaluation_cache.hashmap.borrow();
-            if let Some(cached) = cache.get(&param_env.and(trait_ref)) {
-                return Some(cached.get(tcx));
-            }
-        }
-        self.infcx
-            .evaluation_cache
-            .hashmap
-            .borrow()
-            .get(&param_env.and(trait_ref))
-            .map(|v| v.get(tcx))
-    }
-
-    fn insert_evaluation_cache(
-        &mut self,
-        param_env: ty::ParamEnv<'tcx>,
-        trait_ref: ty::PolyTraitRef<'tcx>,
-        dep_node: DepNodeIndex,
-        result: EvaluationResult,
-    ) {
-        // Avoid caching results that depend on more than just the trait-ref
-        // - the stack can create recursion.
-        if result.is_stack_dependent() {
-            return;
-        }
-
-        if self.can_use_global_caches(param_env) {
-            if !trait_ref.has_local_value() {
-                debug!(
-                    "insert_evaluation_cache(trait_ref={:?}, candidate={:?}) global",
-                    trait_ref, result,
-                );
-                // This may overwrite the cache with the same value
-                // FIXME: Due to #50507 this overwrites the different values
-                // This should be changed to use HashMapExt::insert_same
-                // when that is fixed
-                self.tcx()
-                    .evaluation_cache
-                    .hashmap
-                    .borrow_mut()
-                    .insert(param_env.and(trait_ref), WithDepNode::new(dep_node, result));
-                return;
-            }
-        }
-
-        debug!("insert_evaluation_cache(trait_ref={:?}, candidate={:?})", trait_ref, result,);
-        self.infcx
-            .evaluation_cache
-            .hashmap
-            .borrow_mut()
-            .insert(param_env.and(trait_ref), WithDepNode::new(dep_node, result));
-    }
-
-    /// For various reasons, it's possible for a subobligation
-    /// to have a *lower* recursion_depth than the obligation used to create it.
-    /// Projection sub-obligations may be returned from the projection cache,
-    /// which results in obligations with an 'old' `recursion_depth`.
-    /// Additionally, methods like `wf::obligations` and
-    /// `InferCtxt.subtype_predicate` produce subobligations without
-    /// taking in a 'parent' depth, causing the generated subobligations
-    /// to have a `recursion_depth` of `0`.
-    ///
-    /// To ensure that obligation_depth never decreasees, we force all subobligations
-    /// to have at least the depth of the original obligation.
-    fn add_depth<T: 'cx, I: Iterator<Item = &'cx mut Obligation<'tcx, T>>>(
-        &self,
-        it: I,
-        min_depth: usize,
-    ) {
-        it.for_each(|o| o.recursion_depth = cmp::max(min_depth, o.recursion_depth) + 1);
-    }
-
-    /// Checks that the recursion limit has not been exceeded.
-    ///
-    /// The weird return type of this function allows it to be used with the `try` (`?`)
-    /// operator within certain functions.
-    fn check_recursion_limit<T: Display + TypeFoldable<'tcx>, V: Display + TypeFoldable<'tcx>>(
-        &self,
-        obligation: &Obligation<'tcx, T>,
-        error_obligation: &Obligation<'tcx, V>,
-    ) -> Result<(), OverflowError> {
-        let recursion_limit = *self.infcx.tcx.sess.recursion_limit.get();
-        if obligation.recursion_depth >= recursion_limit {
-            match self.query_mode {
-                TraitQueryMode::Standard => {
-                    self.infcx().report_overflow_error(error_obligation, true);
-                }
-                TraitQueryMode::Canonical => {
-                    return Err(OverflowError);
-                }
-            }
-        }
-        Ok(())
-    }
-
-    ///////////////////////////////////////////////////////////////////////////
-    // CANDIDATE ASSEMBLY
-    //
-    // The selection process begins by examining all in-scope impls,
-    // caller obligations, and so forth and assembling a list of
-    // candidates. See the [rustc guide] for more details.
-    //
-    // [rustc guide]:
-    // https://rust-lang.github.io/rustc-guide/traits/resolution.html#candidate-assembly
-
-    fn candidate_from_obligation<'o>(
-        &mut self,
-        stack: &TraitObligationStack<'o, 'tcx>,
-    ) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
-        // Watch out for overflow. This intentionally bypasses (and does
-        // not update) the cache.
-        self.check_recursion_limit(&stack.obligation, &stack.obligation)?;
-
-        // Check the cache. Note that we freshen the trait-ref
-        // separately rather than using `stack.fresh_trait_ref` --
-        // this is because we want the unbound variables to be
-        // replaced with fresh types starting from index 0.
-        let cache_fresh_trait_pred = self.infcx.freshen(stack.obligation.predicate.clone());
-        debug!(
-            "candidate_from_obligation(cache_fresh_trait_pred={:?}, obligation={:?})",
-            cache_fresh_trait_pred, stack
-        );
-        debug_assert!(!stack.obligation.predicate.has_escaping_bound_vars());
-
-        if let Some(c) =
-            self.check_candidate_cache(stack.obligation.param_env, &cache_fresh_trait_pred)
-        {
-            debug!("CACHE HIT: SELECT({:?})={:?}", cache_fresh_trait_pred, c);
-            return c;
-        }
-
-        // If no match, compute result and insert into cache.
-        //
-        // FIXME(nikomatsakis) -- this cache is not taking into
-        // account cycles that may have occurred in forming the
-        // candidate. I don't know of any specific problems that
-        // result but it seems awfully suspicious.
-        let (candidate, dep_node) =
-            self.in_task(|this| this.candidate_from_obligation_no_cache(stack));
-
-        debug!("CACHE MISS: SELECT({:?})={:?}", cache_fresh_trait_pred, candidate);
-        self.insert_candidate_cache(
-            stack.obligation.param_env,
-            cache_fresh_trait_pred,
-            dep_node,
-            candidate.clone(),
-        );
-        candidate
-    }
-
-    fn in_task<OP, R>(&mut self, op: OP) -> (R, DepNodeIndex)
-    where
-        OP: FnOnce(&mut Self) -> R,
-    {
-        let (result, dep_node) =
-            self.tcx().dep_graph.with_anon_task(DepKind::TraitSelect, || op(self));
-        self.tcx().dep_graph.read_index(dep_node);
-        (result, dep_node)
-    }
-
-    // Treat negative impls as unimplemented, and reservation impls as ambiguity.
-    fn filter_negative_and_reservation_impls(
-        &mut self,
-        candidate: SelectionCandidate<'tcx>,
-    ) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
-        if let ImplCandidate(def_id) = candidate {
-            let tcx = self.tcx();
-            match tcx.impl_polarity(def_id) {
-                ty::ImplPolarity::Negative if !self.allow_negative_impls => {
-                    return Err(Unimplemented);
-                }
-                ty::ImplPolarity::Reservation => {
-                    if let Some(intercrate_ambiguity_clauses) =
-                        &mut self.intercrate_ambiguity_causes
-                    {
-                        let attrs = tcx.get_attrs(def_id);
-                        let attr = attr::find_by_name(&attrs, sym::rustc_reservation_impl);
-                        let value = attr.and_then(|a| a.value_str());
-                        if let Some(value) = value {
-                            debug!(
-                                "filter_negative_and_reservation_impls: \
-                                 reservation impl ambiguity on {:?}",
-                                def_id
-                            );
-                            intercrate_ambiguity_clauses.push(
-                                IntercrateAmbiguityCause::ReservationImpl {
-                                    message: value.to_string(),
-                                },
-                            );
-                        }
-                    }
-                    return Ok(None);
-                }
-                _ => {}
-            };
-        }
-        Ok(Some(candidate))
-    }
-
-    fn candidate_from_obligation_no_cache<'o>(
-        &mut self,
-        stack: &TraitObligationStack<'o, 'tcx>,
-    ) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
-        if stack.obligation.predicate.references_error() {
-            // If we encounter a `Error`, we generally prefer the
-            // most "optimistic" result in response -- that is, the
-            // one least likely to report downstream errors. But
-            // because this routine is shared by coherence and by
-            // trait selection, there isn't an obvious "right" choice
-            // here in that respect, so we opt to just return
-            // ambiguity and let the upstream clients sort it out.
-            return Ok(None);
-        }
-
-        if let Some(conflict) = self.is_knowable(stack) {
-            debug!("coherence stage: not knowable");
-            if self.intercrate_ambiguity_causes.is_some() {
-                debug!("evaluate_stack: intercrate_ambiguity_causes is some");
-                // Heuristics: show the diagnostics when there are no candidates in crate.
-                if let Ok(candidate_set) = self.assemble_candidates(stack) {
-                    let mut no_candidates_apply = true;
-                    {
-                        let evaluated_candidates =
-                            candidate_set.vec.iter().map(|c| self.evaluate_candidate(stack, &c));
-
-                        for ec in evaluated_candidates {
-                            match ec {
-                                Ok(c) => {
-                                    if c.may_apply() {
-                                        no_candidates_apply = false;
-                                        break;
-                                    }
-                                }
-                                Err(e) => return Err(e.into()),
-                            }
-                        }
-                    }
-
-                    if !candidate_set.ambiguous && no_candidates_apply {
-                        let trait_ref = stack.obligation.predicate.skip_binder().trait_ref;
-                        let self_ty = trait_ref.self_ty();
-                        let trait_desc = trait_ref.print_only_trait_path().to_string();
-                        let self_desc = if self_ty.has_concrete_skeleton() {
-                            Some(self_ty.to_string())
-                        } else {
-                            None
-                        };
-                        let cause = if let Conflict::Upstream = conflict {
-                            IntercrateAmbiguityCause::UpstreamCrateUpdate { trait_desc, self_desc }
-                        } else {
-                            IntercrateAmbiguityCause::DownstreamCrate { trait_desc, self_desc }
-                        };
-                        debug!("evaluate_stack: pushing cause = {:?}", cause);
-                        self.intercrate_ambiguity_causes.as_mut().unwrap().push(cause);
-                    }
-                }
-            }
-            return Ok(None);
-        }
-
-        let candidate_set = self.assemble_candidates(stack)?;
-
-        if candidate_set.ambiguous {
-            debug!("candidate set contains ambig");
-            return Ok(None);
-        }
-
-        let mut candidates = candidate_set.vec;
-
-        debug!("assembled {} candidates for {:?}: {:?}", candidates.len(), stack, candidates);
-
-        // At this point, we know that each of the entries in the
-        // candidate set is *individually* applicable. Now we have to
-        // figure out if they contain mutual incompatibilities. This
-        // frequently arises if we have an unconstrained input type --
-        // for example, we are looking for `$0: Eq` where `$0` is some
-        // unconstrained type variable. In that case, we'll get a
-        // candidate which assumes $0 == int, one that assumes `$0 ==
-        // usize`, etc. This spells an ambiguity.
-
-        // If there is more than one candidate, first winnow them down
-        // by considering extra conditions (nested obligations and so
-        // forth). We don't winnow if there is exactly one
-        // candidate. This is a relatively minor distinction but it
-        // can lead to better inference and error-reporting. An
-        // example would be if there was an impl:
-        //
-        //     impl<T:Clone> Vec<T> { fn push_clone(...) { ... } }
-        //
-        // and we were to see some code `foo.push_clone()` where `boo`
-        // is a `Vec<Bar>` and `Bar` does not implement `Clone`.  If
-        // we were to winnow, we'd wind up with zero candidates.
-        // Instead, we select the right impl now but report "`Bar` does
-        // not implement `Clone`".
-        if candidates.len() == 1 {
-            return self.filter_negative_and_reservation_impls(candidates.pop().unwrap());
-        }
-
-        // Winnow, but record the exact outcome of evaluation, which
-        // is needed for specialization. Propagate overflow if it occurs.
-        let mut candidates = candidates
-            .into_iter()
-            .map(|c| match self.evaluate_candidate(stack, &c) {
-                Ok(eval) if eval.may_apply() => {
-                    Ok(Some(EvaluatedCandidate { candidate: c, evaluation: eval }))
-                }
-                Ok(_) => Ok(None),
-                Err(OverflowError) => Err(Overflow),
-            })
-            .flat_map(Result::transpose)
-            .collect::<Result<Vec<_>, _>>()?;
-
-        debug!("winnowed to {} candidates for {:?}: {:?}", candidates.len(), stack, candidates);
-
-        let needs_infer = stack.obligation.predicate.needs_infer();
-
-        // If there are STILL multiple candidates, we can further
-        // reduce the list by dropping duplicates -- including
-        // resolving specializations.
-        if candidates.len() > 1 {
-            let mut i = 0;
-            while i < candidates.len() {
-                let is_dup = (0..candidates.len()).filter(|&j| i != j).any(|j| {
-                    self.candidate_should_be_dropped_in_favor_of(
-                        &candidates[i],
-                        &candidates[j],
-                        needs_infer,
-                    )
-                });
-                if is_dup {
-                    debug!("Dropping candidate #{}/{}: {:?}", i, candidates.len(), candidates[i]);
-                    candidates.swap_remove(i);
-                } else {
-                    debug!("Retaining candidate #{}/{}: {:?}", i, candidates.len(), candidates[i]);
-                    i += 1;
-
-                    // If there are *STILL* multiple candidates, give up
-                    // and report ambiguity.
-                    if i > 1 {
-                        debug!("multiple matches, ambig");
-                        return Ok(None);
-                    }
-                }
-            }
-        }
-
-        // If there are *NO* candidates, then there are no impls --
-        // that we know of, anyway. Note that in the case where there
-        // are unbound type variables within the obligation, it might
-        // be the case that you could still satisfy the obligation
-        // from another crate by instantiating the type variables with
-        // a type from another crate that does have an impl. This case
-        // is checked for in `evaluate_stack` (and hence users
-        // who might care about this case, like coherence, should use
-        // that function).
-        if candidates.is_empty() {
-            return Err(Unimplemented);
-        }
-
-        // Just one candidate left.
-        self.filter_negative_and_reservation_impls(candidates.pop().unwrap().candidate)
-    }
-
-    fn is_knowable<'o>(&mut self, stack: &TraitObligationStack<'o, 'tcx>) -> Option<Conflict> {
-        debug!("is_knowable(intercrate={:?})", self.intercrate);
-
-        if !self.intercrate {
-            return None;
-        }
-
-        let obligation = &stack.obligation;
-        let predicate = self.infcx().resolve_vars_if_possible(&obligation.predicate);
-
-        // Okay to skip binder because of the nature of the
-        // trait-ref-is-knowable check, which does not care about
-        // bound regions.
-        let trait_ref = predicate.skip_binder().trait_ref;
-
-        coherence::trait_ref_is_knowable(self.tcx(), trait_ref)
-    }
-
-    /// Returns `true` if the global caches can be used.
-    /// Do note that if the type itself is not in the
-    /// global tcx, the local caches will be used.
-    fn can_use_global_caches(&self, param_env: ty::ParamEnv<'tcx>) -> bool {
-        // If there are any e.g. inference variables in the `ParamEnv`, then we
-        // always use a cache local to this particular scope. Otherwise, we
-        // switch to a global cache.
-        if param_env.has_local_value() {
-            return false;
-        }
-
-        // Avoid using the master cache during coherence and just rely
-        // on the local cache. This effectively disables caching
-        // during coherence. It is really just a simplification to
-        // avoid us having to fear that coherence results "pollute"
-        // the master cache. Since coherence executes pretty quickly,
-        // it's not worth going to more trouble to increase the
-        // hit-rate, I don't think.
-        if self.intercrate {
-            return false;
-        }
-
-        // Otherwise, we can use the global cache.
-        true
-    }
-
-    fn check_candidate_cache(
-        &mut self,
-        param_env: ty::ParamEnv<'tcx>,
-        cache_fresh_trait_pred: &ty::PolyTraitPredicate<'tcx>,
-    ) -> Option<SelectionResult<'tcx, SelectionCandidate<'tcx>>> {
-        let tcx = self.tcx();
-        let trait_ref = &cache_fresh_trait_pred.skip_binder().trait_ref;
-        if self.can_use_global_caches(param_env) {
-            let cache = tcx.selection_cache.hashmap.borrow();
-            if let Some(cached) = cache.get(&param_env.and(*trait_ref)) {
-                return Some(cached.get(tcx));
-            }
-        }
-        self.infcx
-            .selection_cache
-            .hashmap
-            .borrow()
-            .get(&param_env.and(*trait_ref))
-            .map(|v| v.get(tcx))
-    }
-
-    /// Determines whether can we safely cache the result
-    /// of selecting an obligation. This is almost always `true`,
-    /// except when dealing with certain `ParamCandidate`s.
-    ///
-    /// Ordinarily, a `ParamCandidate` will contain no inference variables,
-    /// since it was usually produced directly from a `DefId`. However,
-    /// certain cases (currently only librustdoc's blanket impl finder),
-    /// a `ParamEnv` may be explicitly constructed with inference types.
-    /// When this is the case, we do *not* want to cache the resulting selection
-    /// candidate. This is due to the fact that it might not always be possible
-    /// to equate the obligation's trait ref and the candidate's trait ref,
-    /// if more constraints end up getting added to an inference variable.
-    ///
-    /// Because of this, we always want to re-run the full selection
-    /// process for our obligation the next time we see it, since
-    /// we might end up picking a different `SelectionCandidate` (or none at all).
-    fn can_cache_candidate(
-        &self,
-        result: &SelectionResult<'tcx, SelectionCandidate<'tcx>>,
-    ) -> bool {
-        match result {
-            Ok(Some(SelectionCandidate::ParamCandidate(trait_ref))) => {
-                !trait_ref.skip_binder().input_types().any(|t| t.walk().any(|t_| t_.is_ty_infer()))
-            }
-            _ => true,
-        }
-    }
-
-    fn insert_candidate_cache(
-        &mut self,
-        param_env: ty::ParamEnv<'tcx>,
-        cache_fresh_trait_pred: ty::PolyTraitPredicate<'tcx>,
-        dep_node: DepNodeIndex,
-        candidate: SelectionResult<'tcx, SelectionCandidate<'tcx>>,
-    ) {
-        let tcx = self.tcx();
-        let trait_ref = cache_fresh_trait_pred.skip_binder().trait_ref;
-
-        if !self.can_cache_candidate(&candidate) {
-            debug!(
-                "insert_candidate_cache(trait_ref={:?}, candidate={:?} -\
-                 candidate is not cacheable",
-                trait_ref, candidate
-            );
-            return;
-        }
-
-        if self.can_use_global_caches(param_env) {
-            if let Err(Overflow) = candidate {
-                // Don't cache overflow globally; we only produce this in certain modes.
-            } else if !trait_ref.has_local_value() {
-                if !candidate.has_local_value() {
-                    debug!(
-                        "insert_candidate_cache(trait_ref={:?}, candidate={:?}) global",
-                        trait_ref, candidate,
-                    );
-                    // This may overwrite the cache with the same value.
-                    tcx.selection_cache
-                        .hashmap
-                        .borrow_mut()
-                        .insert(param_env.and(trait_ref), WithDepNode::new(dep_node, candidate));
-                    return;
-                }
-            }
-        }
-
-        debug!(
-            "insert_candidate_cache(trait_ref={:?}, candidate={:?}) local",
-            trait_ref, candidate,
-        );
-        self.infcx
-            .selection_cache
-            .hashmap
-            .borrow_mut()
-            .insert(param_env.and(trait_ref), WithDepNode::new(dep_node, candidate));
-    }
-
-    fn assemble_candidates<'o>(
-        &mut self,
-        stack: &TraitObligationStack<'o, 'tcx>,
-    ) -> Result<SelectionCandidateSet<'tcx>, SelectionError<'tcx>> {
-        let TraitObligationStack { obligation, .. } = *stack;
-        let ref obligation = Obligation {
-            param_env: obligation.param_env,
-            cause: obligation.cause.clone(),
-            recursion_depth: obligation.recursion_depth,
-            predicate: self.infcx().resolve_vars_if_possible(&obligation.predicate),
-        };
-
-        if obligation.predicate.skip_binder().self_ty().is_ty_var() {
-            // Self is a type variable (e.g., `_: AsRef<str>`).
-            //
-            // This is somewhat problematic, as the current scheme can't really
-            // handle it turning to be a projection. This does end up as truly
-            // ambiguous in most cases anyway.
-            //
-            // Take the fast path out - this also improves
-            // performance by preventing assemble_candidates_from_impls from
-            // matching every impl for this trait.
-            return Ok(SelectionCandidateSet { vec: vec![], ambiguous: true });
-        }
-
-        let mut candidates = SelectionCandidateSet { vec: Vec::new(), ambiguous: false };
-
-        self.assemble_candidates_for_trait_alias(obligation, &mut candidates)?;
-
-        // Other bounds. Consider both in-scope bounds from fn decl
-        // and applicable impls. There is a certain set of precedence rules here.
-        let def_id = obligation.predicate.def_id();
-        let lang_items = self.tcx().lang_items();
-
-        if lang_items.copy_trait() == Some(def_id) {
-            debug!("obligation self ty is {:?}", obligation.predicate.skip_binder().self_ty());
-
-            // User-defined copy impls are permitted, but only for
-            // structs and enums.
-            self.assemble_candidates_from_impls(obligation, &mut candidates)?;
-
-            // For other types, we'll use the builtin rules.
-            let copy_conditions = self.copy_clone_conditions(obligation);
-            self.assemble_builtin_bound_candidates(copy_conditions, &mut candidates)?;
-        } else if lang_items.sized_trait() == Some(def_id) {
-            // Sized is never implementable by end-users, it is
-            // always automatically computed.
-            let sized_conditions = self.sized_conditions(obligation);
-            self.assemble_builtin_bound_candidates(sized_conditions, &mut candidates)?;
-        } else if lang_items.unsize_trait() == Some(def_id) {
-            self.assemble_candidates_for_unsizing(obligation, &mut candidates);
-        } else {
-            if lang_items.clone_trait() == Some(def_id) {
-                // Same builtin conditions as `Copy`, i.e., every type which has builtin support
-                // for `Copy` also has builtin support for `Clone`, and tuples/arrays of `Clone`
-                // types have builtin support for `Clone`.
-                let clone_conditions = self.copy_clone_conditions(obligation);
-                self.assemble_builtin_bound_candidates(clone_conditions, &mut candidates)?;
-            }
-
-            self.assemble_generator_candidates(obligation, &mut candidates)?;
-            self.assemble_closure_candidates(obligation, &mut candidates)?;
-            self.assemble_fn_pointer_candidates(obligation, &mut candidates)?;
-            self.assemble_candidates_from_impls(obligation, &mut candidates)?;
-            self.assemble_candidates_from_object_ty(obligation, &mut candidates);
-        }
-
-        self.assemble_candidates_from_projected_tys(obligation, &mut candidates);
-        self.assemble_candidates_from_caller_bounds(stack, &mut candidates)?;
-        // Auto implementations have lower priority, so we only
-        // consider triggering a default if there is no other impl that can apply.
-        if candidates.vec.is_empty() {
-            self.assemble_candidates_from_auto_impls(obligation, &mut candidates)?;
-        }
-        debug!("candidate list size: {}", candidates.vec.len());
-        Ok(candidates)
-    }
-
-    fn assemble_candidates_from_projected_tys(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-        candidates: &mut SelectionCandidateSet<'tcx>,
-    ) {
-        debug!("assemble_candidates_for_projected_tys({:?})", obligation);
-
-        // Before we go into the whole placeholder thing, just
-        // quickly check if the self-type is a projection at all.
-        match obligation.predicate.skip_binder().trait_ref.self_ty().kind {
-            ty::Projection(_) | ty::Opaque(..) => {}
-            ty::Infer(ty::TyVar(_)) => {
-                span_bug!(
-                    obligation.cause.span,
-                    "Self=_ should have been handled by assemble_candidates"
-                );
-            }
-            _ => return,
-        }
-
-        let result = self.infcx.probe(|snapshot| {
-            self.match_projection_obligation_against_definition_bounds(obligation, snapshot)
-        });
-
-        if result {
-            candidates.vec.push(ProjectionCandidate);
-        }
-    }
-
-    fn match_projection_obligation_against_definition_bounds(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-        snapshot: &CombinedSnapshot<'_, 'tcx>,
-    ) -> bool {
-        let poly_trait_predicate = self.infcx().resolve_vars_if_possible(&obligation.predicate);
-        let (placeholder_trait_predicate, placeholder_map) =
-            self.infcx().replace_bound_vars_with_placeholders(&poly_trait_predicate);
-        debug!(
-            "match_projection_obligation_against_definition_bounds: \
-             placeholder_trait_predicate={:?}",
-            placeholder_trait_predicate,
-        );
-
-        let (def_id, substs) = match placeholder_trait_predicate.trait_ref.self_ty().kind {
-            ty::Projection(ref data) => (data.trait_ref(self.tcx()).def_id, data.substs),
-            ty::Opaque(def_id, substs) => (def_id, substs),
-            _ => {
-                span_bug!(
-                    obligation.cause.span,
-                    "match_projection_obligation_against_definition_bounds() called \
-                     but self-ty is not a projection: {:?}",
-                    placeholder_trait_predicate.trait_ref.self_ty()
-                );
-            }
-        };
-        debug!(
-            "match_projection_obligation_against_definition_bounds: \
-             def_id={:?}, substs={:?}",
-            def_id, substs
-        );
-
-        let predicates_of = self.tcx().predicates_of(def_id);
-        let bounds = predicates_of.instantiate(self.tcx(), substs);
-        debug!(
-            "match_projection_obligation_against_definition_bounds: \
-             bounds={:?}",
-            bounds
-        );
-
-        let elaborated_predicates = util::elaborate_predicates(self.tcx(), bounds.predicates);
-        let matching_bound = elaborated_predicates.filter_to_traits().find(|bound| {
-            self.infcx.probe(|_| {
-                self.match_projection(
-                    obligation,
-                    bound.clone(),
-                    placeholder_trait_predicate.trait_ref.clone(),
-                    &placeholder_map,
-                    snapshot,
-                )
-            })
-        });
-
-        debug!(
-            "match_projection_obligation_against_definition_bounds: \
-             matching_bound={:?}",
-            matching_bound
-        );
-        match matching_bound {
-            None => false,
-            Some(bound) => {
-                // Repeat the successful match, if any, this time outside of a probe.
-                let result = self.match_projection(
-                    obligation,
-                    bound,
-                    placeholder_trait_predicate.trait_ref.clone(),
-                    &placeholder_map,
-                    snapshot,
-                );
-
-                assert!(result);
-                true
-            }
-        }
-    }
-
-    fn match_projection(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-        trait_bound: ty::PolyTraitRef<'tcx>,
-        placeholder_trait_ref: ty::TraitRef<'tcx>,
-        placeholder_map: &PlaceholderMap<'tcx>,
-        snapshot: &CombinedSnapshot<'_, 'tcx>,
-    ) -> bool {
-        debug_assert!(!placeholder_trait_ref.has_escaping_bound_vars());
-        self.infcx
-            .at(&obligation.cause, obligation.param_env)
-            .sup(ty::Binder::dummy(placeholder_trait_ref), trait_bound)
-            .is_ok()
-            && self.infcx.leak_check(false, placeholder_map, snapshot).is_ok()
-    }
-
-    /// Given an obligation like `<SomeTrait for T>`, searches the obligations that the caller
-    /// supplied to find out whether it is listed among them.
-    ///
-    /// Never affects the inference environment.
-    fn assemble_candidates_from_caller_bounds<'o>(
-        &mut self,
-        stack: &TraitObligationStack<'o, 'tcx>,
-        candidates: &mut SelectionCandidateSet<'tcx>,
-    ) -> Result<(), SelectionError<'tcx>> {
-        debug!("assemble_candidates_from_caller_bounds({:?})", stack.obligation);
-
-        let all_bounds = stack
-            .obligation
-            .param_env
-            .caller_bounds
-            .iter()
-            .filter_map(|o| o.to_opt_poly_trait_ref());
-
-        // Micro-optimization: filter out predicates relating to different traits.
-        let matching_bounds =
-            all_bounds.filter(|p| p.def_id() == stack.obligation.predicate.def_id());
-
-        // Keep only those bounds which may apply, and propagate overflow if it occurs.
-        let mut param_candidates = vec![];
-        for bound in matching_bounds {
-            let wc = self.evaluate_where_clause(stack, bound.clone())?;
-            if wc.may_apply() {
-                param_candidates.push(ParamCandidate(bound));
-            }
-        }
-
-        candidates.vec.extend(param_candidates);
-
-        Ok(())
-    }
-
-    fn evaluate_where_clause<'o>(
-        &mut self,
-        stack: &TraitObligationStack<'o, 'tcx>,
-        where_clause_trait_ref: ty::PolyTraitRef<'tcx>,
-    ) -> Result<EvaluationResult, OverflowError> {
-        self.evaluation_probe(|this| {
-            match this.match_where_clause_trait_ref(stack.obligation, where_clause_trait_ref) {
-                Ok(obligations) => {
-                    this.evaluate_predicates_recursively(stack.list(), obligations.into_iter())
-                }
-                Err(()) => Ok(EvaluatedToErr),
-            }
-        })
-    }
-
-    fn assemble_generator_candidates(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-        candidates: &mut SelectionCandidateSet<'tcx>,
-    ) -> Result<(), SelectionError<'tcx>> {
-        if self.tcx().lang_items().gen_trait() != Some(obligation.predicate.def_id()) {
-            return Ok(());
-        }
-
-        // Okay to skip binder because the substs on generator types never
-        // touch bound regions, they just capture the in-scope
-        // type/region parameters.
-        let self_ty = *obligation.self_ty().skip_binder();
-        match self_ty.kind {
-            ty::Generator(..) => {
-                debug!(
-                    "assemble_generator_candidates: self_ty={:?} obligation={:?}",
-                    self_ty, obligation
-                );
-
-                candidates.vec.push(GeneratorCandidate);
-            }
-            ty::Infer(ty::TyVar(_)) => {
-                debug!("assemble_generator_candidates: ambiguous self-type");
-                candidates.ambiguous = true;
-            }
-            _ => {}
-        }
-
-        Ok(())
-    }
-
-    /// Checks for the artificial impl that the compiler will create for an obligation like `X :
-    /// FnMut<..>` where `X` is a closure type.
-    ///
-    /// Note: the type parameters on a closure candidate are modeled as *output* type
-    /// parameters and hence do not affect whether this trait is a match or not. They will be
-    /// unified during the confirmation step.
-    fn assemble_closure_candidates(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-        candidates: &mut SelectionCandidateSet<'tcx>,
-    ) -> Result<(), SelectionError<'tcx>> {
-        let kind = match self.tcx().fn_trait_kind_from_lang_item(obligation.predicate.def_id()) {
-            Some(k) => k,
-            None => {
-                return Ok(());
-            }
-        };
-
-        // Okay to skip binder because the substs on closure types never
-        // touch bound regions, they just capture the in-scope
-        // type/region parameters
-        match obligation.self_ty().skip_binder().kind {
-            ty::Closure(closure_def_id, closure_substs) => {
-                debug!("assemble_unboxed_candidates: kind={:?} obligation={:?}", kind, obligation);
-                match self.infcx.closure_kind(closure_def_id, closure_substs) {
-                    Some(closure_kind) => {
-                        debug!("assemble_unboxed_candidates: closure_kind = {:?}", closure_kind);
-                        if closure_kind.extends(kind) {
-                            candidates.vec.push(ClosureCandidate);
-                        }
-                    }
-                    None => {
-                        debug!("assemble_unboxed_candidates: closure_kind not yet known");
-                        candidates.vec.push(ClosureCandidate);
-                    }
-                }
-            }
-            ty::Infer(ty::TyVar(_)) => {
-                debug!("assemble_unboxed_closure_candidates: ambiguous self-type");
-                candidates.ambiguous = true;
-            }
-            _ => {}
-        }
-
-        Ok(())
-    }
-
-    /// Implements one of the `Fn()` family for a fn pointer.
-    fn assemble_fn_pointer_candidates(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-        candidates: &mut SelectionCandidateSet<'tcx>,
-    ) -> Result<(), SelectionError<'tcx>> {
-        // We provide impl of all fn traits for fn pointers.
-        if self.tcx().fn_trait_kind_from_lang_item(obligation.predicate.def_id()).is_none() {
-            return Ok(());
-        }
-
-        // Okay to skip binder because what we are inspecting doesn't involve bound regions.
-        let self_ty = *obligation.self_ty().skip_binder();
-        match self_ty.kind {
-            ty::Infer(ty::TyVar(_)) => {
-                debug!("assemble_fn_pointer_candidates: ambiguous self-type");
-                candidates.ambiguous = true; // Could wind up being a fn() type.
-            }
-            // Provide an impl, but only for suitable `fn` pointers.
-            ty::FnDef(..) | ty::FnPtr(_) => {
-                if let ty::FnSig {
-                    unsafety: hir::Unsafety::Normal,
-                    abi: Abi::Rust,
-                    c_variadic: false,
-                    ..
-                } = self_ty.fn_sig(self.tcx()).skip_binder()
-                {
-                    candidates.vec.push(FnPointerCandidate);
-                }
-            }
-            _ => {}
-        }
-
-        Ok(())
-    }
-
-    /// Searches for impls that might apply to `obligation`.
-    fn assemble_candidates_from_impls(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-        candidates: &mut SelectionCandidateSet<'tcx>,
-    ) -> Result<(), SelectionError<'tcx>> {
-        debug!("assemble_candidates_from_impls(obligation={:?})", obligation);
-
-        self.tcx().for_each_relevant_impl(
-            obligation.predicate.def_id(),
-            obligation.predicate.skip_binder().trait_ref.self_ty(),
-            |impl_def_id| {
-                self.infcx.probe(|snapshot| {
-                    if let Ok(_substs) = self.match_impl(impl_def_id, obligation, snapshot) {
-                        candidates.vec.push(ImplCandidate(impl_def_id));
-                    }
-                });
-            },
-        );
-
-        Ok(())
-    }
-
-    fn assemble_candidates_from_auto_impls(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-        candidates: &mut SelectionCandidateSet<'tcx>,
-    ) -> Result<(), SelectionError<'tcx>> {
-        // Okay to skip binder here because the tests we do below do not involve bound regions.
-        let self_ty = *obligation.self_ty().skip_binder();
-        debug!("assemble_candidates_from_auto_impls(self_ty={:?})", self_ty);
-
-        let def_id = obligation.predicate.def_id();
-
-        if self.tcx().trait_is_auto(def_id) {
-            match self_ty.kind {
-                ty::Dynamic(..) => {
-                    // For object types, we don't know what the closed
-                    // over types are. This means we conservatively
-                    // say nothing; a candidate may be added by
-                    // `assemble_candidates_from_object_ty`.
-                }
-                ty::Foreign(..) => {
-                    // Since the contents of foreign types is unknown,
-                    // we don't add any `..` impl. Default traits could
-                    // still be provided by a manual implementation for
-                    // this trait and type.
-                }
-                ty::Param(..) | ty::Projection(..) => {
-                    // In these cases, we don't know what the actual
-                    // type is.  Therefore, we cannot break it down
-                    // into its constituent types. So we don't
-                    // consider the `..` impl but instead just add no
-                    // candidates: this means that typeck will only
-                    // succeed if there is another reason to believe
-                    // that this obligation holds. That could be a
-                    // where-clause or, in the case of an object type,
-                    // it could be that the object type lists the
-                    // trait (e.g., `Foo+Send : Send`). See
-                    // `compile-fail/typeck-default-trait-impl-send-param.rs`
-                    // for an example of a test case that exercises
-                    // this path.
-                }
-                ty::Infer(ty::TyVar(_)) => {
-                    // The auto impl might apply; we don't know.
-                    candidates.ambiguous = true;
-                }
-                ty::Generator(_, _, movability)
-                    if self.tcx().lang_items().unpin_trait() == Some(def_id) =>
-                {
-                    match movability {
-                        hir::Movability::Static => {
-                            // Immovable generators are never `Unpin`, so
-                            // suppress the normal auto-impl candidate for it.
-                        }
-                        hir::Movability::Movable => {
-                            // Movable generators are always `Unpin`, so add an
-                            // unconditional builtin candidate.
-                            candidates.vec.push(BuiltinCandidate { has_nested: false });
-                        }
-                    }
-                }
-
-                _ => candidates.vec.push(AutoImplCandidate(def_id)),
-            }
-        }
-
-        Ok(())
-    }
-
-    /// Searches for impls that might apply to `obligation`.
-    fn assemble_candidates_from_object_ty(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-        candidates: &mut SelectionCandidateSet<'tcx>,
-    ) {
-        debug!(
-            "assemble_candidates_from_object_ty(self_ty={:?})",
-            obligation.self_ty().skip_binder()
-        );
-
-        self.infcx.probe(|_snapshot| {
-            // The code below doesn't care about regions, and the
-            // self-ty here doesn't escape this probe, so just erase
-            // any LBR.
-            let self_ty = self.tcx().erase_late_bound_regions(&obligation.self_ty());
-            let poly_trait_ref = match self_ty.kind {
-                ty::Dynamic(ref data, ..) => {
-                    if data.auto_traits().any(|did| did == obligation.predicate.def_id()) {
-                        debug!(
-                            "assemble_candidates_from_object_ty: matched builtin bound, \
-                             pushing candidate"
-                        );
-                        candidates.vec.push(BuiltinObjectCandidate);
-                        return;
-                    }
-
-                    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;
-                        }
-                    } else {
-                        // Only auto trait bounds exist.
-                        return;
-                    }
-                }
-                ty::Infer(ty::TyVar(_)) => {
-                    debug!("assemble_candidates_from_object_ty: ambiguous");
-                    candidates.ambiguous = true; // could wind up being an object type
-                    return;
-                }
-                _ => return,
-            };
-
-            debug!("assemble_candidates_from_object_ty: poly_trait_ref={:?}", poly_trait_ref);
-
-            // Count only those upcast versions that match the trait-ref
-            // we are looking for. Specifically, do not only check for the
-            // correct trait, but also the correct type parameters.
-            // For example, we may be trying to upcast `Foo` to `Bar<i32>`,
-            // but `Foo` is declared as `trait Foo: Bar<u32>`.
-            let upcast_trait_refs = util::supertraits(self.tcx(), poly_trait_ref)
-                .filter(|upcast_trait_ref| {
-                    self.infcx
-                        .probe(|_| self.match_poly_trait_ref(obligation, *upcast_trait_ref).is_ok())
-                })
-                .count();
-
-            if upcast_trait_refs > 1 {
-                // Can be upcast in many ways; need more type information.
-                candidates.ambiguous = true;
-            } else if upcast_trait_refs == 1 {
-                candidates.vec.push(ObjectCandidate);
-            }
-        })
-    }
-
-    /// Searches for unsizing that might apply to `obligation`.
-    fn assemble_candidates_for_unsizing(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-        candidates: &mut SelectionCandidateSet<'tcx>,
-    ) {
-        // We currently never consider higher-ranked obligations e.g.
-        // `for<'a> &'a T: Unsize<Trait+'a>` to be implemented. This is not
-        // because they are a priori invalid, and we could potentially add support
-        // for them later, it's just that there isn't really a strong need for it.
-        // A `T: Unsize<U>` obligation is always used as part of a `T: CoerceUnsize<U>`
-        // impl, and those are generally applied to concrete types.
-        //
-        // That said, one might try to write a fn with a where clause like
-        //     for<'a> Foo<'a, T>: Unsize<Foo<'a, Trait>>
-        // where the `'a` is kind of orthogonal to the relevant part of the `Unsize`.
-        // Still, you'd be more likely to write that where clause as
-        //     T: Trait
-        // so it seems ok if we (conservatively) fail to accept that `Unsize`
-        // obligation above. Should be possible to extend this in the future.
-        let source = match obligation.self_ty().no_bound_vars() {
-            Some(t) => t,
-            None => {
-                // Don't add any candidates if there are bound regions.
-                return;
-            }
-        };
-        let target = obligation.predicate.skip_binder().trait_ref.substs.type_at(1);
-
-        debug!("assemble_candidates_for_unsizing(source={:?}, target={:?})", source, target);
-
-        let may_apply = match (&source.kind, &target.kind) {
-            // Trait+Kx+'a -> Trait+Ky+'b (upcasts).
-            (&ty::Dynamic(ref data_a, ..), &ty::Dynamic(ref data_b, ..)) => {
-                // Upcasts permit two things:
-                //
-                // 1. Dropping auto traits, e.g., `Foo + Send` to `Foo`
-                // 2. Tightening the region bound, e.g., `Foo + 'a` to `Foo + 'b` if `'a: 'b`
-                //
-                // Note that neither of these changes requires any
-                // change at runtime. Eventually this will be
-                // generalized.
-                //
-                // We always upcast when we can because of reason
-                // #2 (region bounds).
-                data_a.principal_def_id() == data_b.principal_def_id()
-                    && data_b
-                        .auto_traits()
-                        // All of a's auto traits need to be in b's auto traits.
-                        .all(|b| data_a.auto_traits().any(|a| a == b))
-            }
-
-            // `T` -> `Trait`
-            (_, &ty::Dynamic(..)) => true,
-
-            // Ambiguous handling is below `T` -> `Trait`, because inference
-            // variables can still implement `Unsize<Trait>` and nested
-            // obligations will have the final say (likely deferred).
-            (&ty::Infer(ty::TyVar(_)), _) | (_, &ty::Infer(ty::TyVar(_))) => {
-                debug!("assemble_candidates_for_unsizing: ambiguous");
-                candidates.ambiguous = true;
-                false
-            }
-
-            // `[T; n]` -> `[T]`
-            (&ty::Array(..), &ty::Slice(_)) => true,
-
-            // `Struct<T>` -> `Struct<U>`
-            (&ty::Adt(def_id_a, _), &ty::Adt(def_id_b, _)) if def_id_a.is_struct() => {
-                def_id_a == def_id_b
-            }
-
-            // `(.., T)` -> `(.., U)`
-            (&ty::Tuple(tys_a), &ty::Tuple(tys_b)) => tys_a.len() == tys_b.len(),
-
-            _ => false,
-        };
-
-        if may_apply {
-            candidates.vec.push(BuiltinUnsizeCandidate);
-        }
-    }
-
-    fn assemble_candidates_for_trait_alias(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-        candidates: &mut SelectionCandidateSet<'tcx>,
-    ) -> Result<(), SelectionError<'tcx>> {
-        // Okay to skip binder here because the tests we do below do not involve bound regions.
-        let self_ty = *obligation.self_ty().skip_binder();
-        debug!("assemble_candidates_for_trait_alias(self_ty={:?})", self_ty);
-
-        let def_id = obligation.predicate.def_id();
-
-        if self.tcx().is_trait_alias(def_id) {
-            candidates.vec.push(TraitAliasCandidate(def_id));
-        }
-
-        Ok(())
-    }
-
-    ///////////////////////////////////////////////////////////////////////////
-    // WINNOW
-    //
-    // Winnowing is the process of attempting to resolve ambiguity by
-    // probing further. During the winnowing process, we unify all
-    // type variables and then we also attempt to evaluate recursive
-    // bounds to see if they are satisfied.
-
-    /// Returns `true` if `victim` should be dropped in favor of
-    /// `other`. Generally speaking we will drop duplicate
-    /// candidates and prefer where-clause candidates.
-    ///
-    /// See the comment for "SelectionCandidate" for more details.
-    fn candidate_should_be_dropped_in_favor_of(
-        &mut self,
-        victim: &EvaluatedCandidate<'tcx>,
-        other: &EvaluatedCandidate<'tcx>,
-        needs_infer: bool,
-    ) -> bool {
-        if victim.candidate == other.candidate {
-            return true;
-        }
-
-        // Check if a bound would previously have been removed when normalizing
-        // the param_env so that it can be given the lowest priority. See
-        // #50825 for the motivation for this.
-        let is_global =
-            |cand: &ty::PolyTraitRef<'_>| cand.is_global() && !cand.has_late_bound_regions();
-
-        match other.candidate {
-            // Prefer `BuiltinCandidate { has_nested: false }` to anything else.
-            // This is a fix for #53123 and prevents winnowing from accidentally extending the
-            // lifetime of a variable.
-            BuiltinCandidate { has_nested: false } => true,
-            ParamCandidate(ref cand) => match victim.candidate {
-                AutoImplCandidate(..) => {
-                    bug!(
-                        "default implementations shouldn't be recorded \
-                         when there are other valid candidates"
-                    );
-                }
-                // Prefer `BuiltinCandidate { has_nested: false }` to anything else.
-                // This is a fix for #53123 and prevents winnowing from accidentally extending the
-                // lifetime of a variable.
-                BuiltinCandidate { has_nested: false } => false,
-                ImplCandidate(..)
-                | ClosureCandidate
-                | GeneratorCandidate
-                | FnPointerCandidate
-                | BuiltinObjectCandidate
-                | BuiltinUnsizeCandidate
-                | BuiltinCandidate { .. }
-                | TraitAliasCandidate(..) => {
-                    // Global bounds from the where clause should be ignored
-                    // here (see issue #50825). Otherwise, we have a where
-                    // clause so don't go around looking for impls.
-                    !is_global(cand)
-                }
-                ObjectCandidate | ProjectionCandidate => {
-                    // Arbitrarily give param candidates priority
-                    // over projection and object candidates.
-                    !is_global(cand)
-                }
-                ParamCandidate(..) => false,
-            },
-            ObjectCandidate | ProjectionCandidate => match victim.candidate {
-                AutoImplCandidate(..) => {
-                    bug!(
-                        "default implementations shouldn't be recorded \
-                         when there are other valid candidates"
-                    );
-                }
-                // Prefer `BuiltinCandidate { has_nested: false }` to anything else.
-                // This is a fix for #53123 and prevents winnowing from accidentally extending the
-                // lifetime of a variable.
-                BuiltinCandidate { has_nested: false } => false,
-                ImplCandidate(..)
-                | ClosureCandidate
-                | GeneratorCandidate
-                | FnPointerCandidate
-                | BuiltinObjectCandidate
-                | BuiltinUnsizeCandidate
-                | BuiltinCandidate { .. }
-                | TraitAliasCandidate(..) => true,
-                ObjectCandidate | ProjectionCandidate => {
-                    // Arbitrarily give param candidates priority
-                    // over projection and object candidates.
-                    true
-                }
-                ParamCandidate(ref cand) => is_global(cand),
-            },
-            ImplCandidate(other_def) => {
-                // See if we can toss out `victim` based on specialization.
-                // This requires us to know *for sure* that the `other` impl applies
-                // i.e., `EvaluatedToOk`.
-                if other.evaluation.must_apply_modulo_regions() {
-                    match victim.candidate {
-                        ImplCandidate(victim_def) => {
-                            let tcx = self.tcx();
-                            if tcx.specializes((other_def, victim_def)) {
-                                return true;
-                            }
-                            return match tcx.impls_are_allowed_to_overlap(other_def, victim_def) {
-                                Some(ty::ImplOverlapKind::Permitted { marker: true }) => {
-                                    // Subtle: If the predicate we are evaluating has inference
-                                    // variables, do *not* allow discarding candidates due to
-                                    // marker trait impls.
-                                    //
-                                    // Without this restriction, we could end up accidentally
-                                    // constrainting inference variables based on an arbitrarily
-                                    // chosen trait impl.
-                                    //
-                                    // Imagine we have the following code:
-                                    //
-                                    // ```rust
-                                    // #[marker] trait MyTrait {}
-                                    // impl MyTrait for u8 {}
-                                    // impl MyTrait for bool {}
-                                    // ```
-                                    //
-                                    // And we are evaluating the predicate `<_#0t as MyTrait>`.
-                                    //
-                                    // During selection, we will end up with one candidate for each
-                                    // impl of `MyTrait`. If we were to discard one impl in favor
-                                    // of the other, we would be left with one candidate, causing
-                                    // us to "successfully" select the predicate, unifying
-                                    // _#0t with (for example) `u8`.
-                                    //
-                                    // However, we have no reason to believe that this unification
-                                    // is correct - we've essentially just picked an arbitrary
-                                    // *possibility* for _#0t, and required that this be the *only*
-                                    // possibility.
-                                    //
-                                    // Eventually, we will either:
-                                    // 1) Unify all inference variables in the predicate through
-                                    // some other means (e.g. type-checking of a function). We will
-                                    // then be in a position to drop marker trait candidates
-                                    // without constraining inference variables (since there are
-                                    // none left to constrin)
-                                    // 2) Be left with some unconstrained inference variables. We
-                                    // will then correctly report an inference error, since the
-                                    // existence of multiple marker trait impls tells us nothing
-                                    // about which one should actually apply.
-                                    !needs_infer
-                                }
-                                Some(_) => true,
-                                None => false,
-                            };
-                        }
-                        ParamCandidate(ref cand) => {
-                            // Prefer the impl to a global where clause candidate.
-                            return is_global(cand);
-                        }
-                        _ => (),
-                    }
-                }
-
-                false
-            }
-            ClosureCandidate
-            | GeneratorCandidate
-            | FnPointerCandidate
-            | BuiltinObjectCandidate
-            | BuiltinUnsizeCandidate
-            | BuiltinCandidate { has_nested: true } => {
-                match victim.candidate {
-                    ParamCandidate(ref cand) => {
-                        // Prefer these to a global where-clause bound
-                        // (see issue #50825).
-                        is_global(cand) && other.evaluation.must_apply_modulo_regions()
-                    }
-                    _ => false,
-                }
-            }
-            _ => false,
-        }
-    }
-
-    ///////////////////////////////////////////////////////////////////////////
-    // BUILTIN BOUNDS
-    //
-    // These cover the traits that are built-in to the language
-    // itself: `Copy`, `Clone` and `Sized`.
-
-    fn assemble_builtin_bound_candidates(
-        &mut self,
-        conditions: BuiltinImplConditions<'tcx>,
-        candidates: &mut SelectionCandidateSet<'tcx>,
-    ) -> Result<(), SelectionError<'tcx>> {
-        match conditions {
-            BuiltinImplConditions::Where(nested) => {
-                debug!("builtin_bound: nested={:?}", nested);
-                candidates
-                    .vec
-                    .push(BuiltinCandidate { has_nested: !nested.skip_binder().is_empty() });
-            }
-            BuiltinImplConditions::None => {}
-            BuiltinImplConditions::Ambiguous => {
-                debug!("assemble_builtin_bound_candidates: ambiguous builtin");
-                candidates.ambiguous = true;
-            }
-        }
-
-        Ok(())
-    }
-
-    fn sized_conditions(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-    ) -> BuiltinImplConditions<'tcx> {
-        use self::BuiltinImplConditions::{Ambiguous, None, Where};
-
-        // NOTE: binder moved to (*)
-        let self_ty = self.infcx.shallow_resolve(obligation.predicate.skip_binder().self_ty());
-
-        match self_ty.kind {
-            ty::Infer(ty::IntVar(_))
-            | ty::Infer(ty::FloatVar(_))
-            | ty::Uint(_)
-            | ty::Int(_)
-            | ty::Bool
-            | ty::Float(_)
-            | ty::FnDef(..)
-            | ty::FnPtr(_)
-            | ty::RawPtr(..)
-            | ty::Char
-            | ty::Ref(..)
-            | ty::Generator(..)
-            | ty::GeneratorWitness(..)
-            | ty::Array(..)
-            | ty::Closure(..)
-            | ty::Never
-            | ty::Error => {
-                // safe for everything
-                Where(ty::Binder::dummy(Vec::new()))
-            }
-
-            ty::Str | ty::Slice(_) | ty::Dynamic(..) | ty::Foreign(..) => None,
-
-            ty::Tuple(tys) => {
-                Where(ty::Binder::bind(tys.last().into_iter().map(|k| k.expect_ty()).collect()))
-            }
-
-            ty::Adt(def, substs) => {
-                let sized_crit = def.sized_constraint(self.tcx());
-                // (*) binder moved here
-                Where(ty::Binder::bind(
-                    sized_crit.iter().map(|ty| ty.subst(self.tcx(), substs)).collect(),
-                ))
-            }
-
-            ty::Projection(_) | ty::Param(_) | ty::Opaque(..) => None,
-            ty::Infer(ty::TyVar(_)) => Ambiguous,
-
-            ty::UnnormalizedProjection(..)
-            | ty::Placeholder(..)
-            | ty::Bound(..)
-            | ty::Infer(ty::FreshTy(_))
-            | ty::Infer(ty::FreshIntTy(_))
-            | ty::Infer(ty::FreshFloatTy(_)) => {
-                bug!("asked to assemble builtin bounds of unexpected type: {:?}", self_ty);
-            }
-        }
-    }
-
-    fn copy_clone_conditions(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-    ) -> BuiltinImplConditions<'tcx> {
-        // NOTE: binder moved to (*)
-        let self_ty = self.infcx.shallow_resolve(obligation.predicate.skip_binder().self_ty());
-
-        use self::BuiltinImplConditions::{Ambiguous, None, Where};
-
-        match self_ty.kind {
-            ty::Infer(ty::IntVar(_))
-            | ty::Infer(ty::FloatVar(_))
-            | ty::FnDef(..)
-            | ty::FnPtr(_)
-            | ty::Error => Where(ty::Binder::dummy(Vec::new())),
-
-            ty::Uint(_)
-            | ty::Int(_)
-            | ty::Bool
-            | ty::Float(_)
-            | ty::Char
-            | ty::RawPtr(..)
-            | ty::Never
-            | ty::Ref(_, _, hir::Mutability::Not) => {
-                // Implementations provided in libcore
-                None
-            }
-
-            ty::Dynamic(..)
-            | ty::Str
-            | ty::Slice(..)
-            | ty::Generator(..)
-            | ty::GeneratorWitness(..)
-            | ty::Foreign(..)
-            | ty::Ref(_, _, hir::Mutability::Mut) => None,
-
-            ty::Array(element_ty, _) => {
-                // (*) binder moved here
-                Where(ty::Binder::bind(vec![element_ty]))
-            }
-
-            ty::Tuple(tys) => {
-                // (*) binder moved here
-                Where(ty::Binder::bind(tys.iter().map(|k| k.expect_ty()).collect()))
-            }
-
-            ty::Closure(def_id, substs) => {
-                // (*) binder moved here
-                Where(ty::Binder::bind(substs.as_closure().upvar_tys(def_id, self.tcx()).collect()))
-            }
-
-            ty::Adt(..) | ty::Projection(..) | ty::Param(..) | ty::Opaque(..) => {
-                // Fallback to whatever user-defined impls exist in this case.
-                None
-            }
-
-            ty::Infer(ty::TyVar(_)) => {
-                // Unbound type variable. Might or might not have
-                // applicable impls and so forth, depending on what
-                // those type variables wind up being bound to.
-                Ambiguous
-            }
-
-            ty::UnnormalizedProjection(..)
-            | ty::Placeholder(..)
-            | ty::Bound(..)
-            | ty::Infer(ty::FreshTy(_))
-            | ty::Infer(ty::FreshIntTy(_))
-            | ty::Infer(ty::FreshFloatTy(_)) => {
-                bug!("asked to assemble builtin bounds of unexpected type: {:?}", self_ty);
-            }
-        }
-    }
-
-    /// For default impls, we need to break apart a type into its
-    /// "constituent types" -- meaning, the types that it contains.
-    ///
-    /// Here are some (simple) examples:
-    ///
-    /// ```
-    /// (i32, u32) -> [i32, u32]
-    /// Foo where struct Foo { x: i32, y: u32 } -> [i32, u32]
-    /// Bar<i32> where struct Bar<T> { x: T, y: u32 } -> [i32, u32]
-    /// Zed<i32> where enum Zed { A(T), B(u32) } -> [i32, u32]
-    /// ```
-    fn constituent_types_for_ty(&self, t: Ty<'tcx>) -> Vec<Ty<'tcx>> {
-        match t.kind {
-            ty::Uint(_)
-            | ty::Int(_)
-            | ty::Bool
-            | ty::Float(_)
-            | ty::FnDef(..)
-            | ty::FnPtr(_)
-            | ty::Str
-            | ty::Error
-            | ty::Infer(ty::IntVar(_))
-            | ty::Infer(ty::FloatVar(_))
-            | ty::Never
-            | ty::Char => Vec::new(),
-
-            ty::UnnormalizedProjection(..)
-            | ty::Placeholder(..)
-            | ty::Dynamic(..)
-            | ty::Param(..)
-            | ty::Foreign(..)
-            | ty::Projection(..)
-            | ty::Bound(..)
-            | ty::Infer(ty::TyVar(_))
-            | ty::Infer(ty::FreshTy(_))
-            | ty::Infer(ty::FreshIntTy(_))
-            | ty::Infer(ty::FreshFloatTy(_)) => {
-                bug!("asked to assemble constituent types of unexpected type: {:?}", t);
-            }
-
-            ty::RawPtr(ty::TypeAndMut { ty: element_ty, .. }) | ty::Ref(_, element_ty, _) => {
-                vec![element_ty]
-            }
-
-            ty::Array(element_ty, _) | ty::Slice(element_ty) => vec![element_ty],
-
-            ty::Tuple(ref tys) => {
-                // (T1, ..., Tn) -- meets any bound that all of T1...Tn meet
-                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::Generator(def_id, ref substs, _) => {
-                let witness = substs.as_generator().witness(def_id, self.tcx());
-                substs
-                    .as_generator()
-                    .upvar_tys(def_id, self.tcx())
-                    .chain(iter::once(witness))
-                    .collect()
-            }
-
-            ty::GeneratorWitness(types) => {
-                // This is sound because no regions in the witness can refer to
-                // the binder outside the witness. So we'll effectivly reuse
-                // the implicit binder around the witness.
-                types.skip_binder().to_vec()
-            }
-
-            // For `PhantomData<T>`, we pass `T`.
-            ty::Adt(def, substs) if def.is_phantom_data() => substs.types().collect(),
-
-            ty::Adt(def, substs) => def.all_fields().map(|f| f.ty(self.tcx(), substs)).collect(),
-
-            ty::Opaque(def_id, substs) => {
-                // We can resolve the `impl Trait` to its concrete type,
-                // which enforces a DAG between the functions requiring
-                // the auto trait bounds in question.
-                vec![self.tcx().type_of(def_id).subst(self.tcx(), substs)]
-            }
-        }
-    }
-
-    fn collect_predicates_for_types(
-        &mut self,
-        param_env: ty::ParamEnv<'tcx>,
-        cause: ObligationCause<'tcx>,
-        recursion_depth: usize,
-        trait_def_id: DefId,
-        types: ty::Binder<Vec<Ty<'tcx>>>,
-    ) -> Vec<PredicateObligation<'tcx>> {
-        // Because the types were potentially derived from
-        // higher-ranked obligations they may reference late-bound
-        // regions. For example, `for<'a> Foo<&'a int> : Copy` would
-        // yield a type like `for<'a> &'a int`. In general, we
-        // maintain the invariant that we never manipulate bound
-        // regions, so we have to process these bound regions somehow.
-        //
-        // The strategy is to:
-        //
-        // 1. Instantiate those regions to placeholder regions (e.g.,
-        //    `for<'a> &'a int` becomes `&0 int`.
-        // 2. Produce something like `&'0 int : Copy`
-        // 3. Re-bind the regions back to `for<'a> &'a int : Copy`
-
-        types
-            .skip_binder()
-            .iter()
-            .flat_map(|ty| {
-                // binder moved -\
-                let ty: ty::Binder<Ty<'tcx>> = ty::Binder::bind(ty); // <----/
-
-                self.infcx.commit_unconditionally(|_| {
-                    let (skol_ty, _) = self.infcx.replace_bound_vars_with_placeholders(&ty);
-                    let Normalized { value: normalized_ty, mut obligations } =
-                        project::normalize_with_depth(
-                            self,
-                            param_env,
-                            cause.clone(),
-                            recursion_depth,
-                            &skol_ty,
-                        );
-                    let skol_obligation = predicate_for_trait_def(
-                        self.tcx(),
-                        param_env,
-                        cause.clone(),
-                        trait_def_id,
-                        recursion_depth,
-                        normalized_ty,
-                        &[],
-                    );
-                    obligations.push(skol_obligation);
-                    obligations
-                })
-            })
-            .collect()
-    }
-
-    ///////////////////////////////////////////////////////////////////////////
-    // CONFIRMATION
-    //
-    // Confirmation unifies the output type parameters of the trait
-    // with the values found in the obligation, possibly yielding a
-    // type error.  See the [rustc guide] for more details.
-    //
-    // [rustc guide]:
-    // https://rust-lang.github.io/rustc-guide/traits/resolution.html#confirmation
-
-    fn confirm_candidate(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-        candidate: SelectionCandidate<'tcx>,
-    ) -> Result<Selection<'tcx>, SelectionError<'tcx>> {
-        debug!("confirm_candidate({:?}, {:?})", obligation, candidate);
-
-        match candidate {
-            BuiltinCandidate { has_nested } => {
-                let data = self.confirm_builtin_candidate(obligation, has_nested);
-                Ok(VtableBuiltin(data))
-            }
-
-            ParamCandidate(param) => {
-                let obligations = self.confirm_param_candidate(obligation, param);
-                Ok(VtableParam(obligations))
-            }
-
-            ImplCandidate(impl_def_id) => {
-                Ok(VtableImpl(self.confirm_impl_candidate(obligation, impl_def_id)))
-            }
-
-            AutoImplCandidate(trait_def_id) => {
-                let data = self.confirm_auto_impl_candidate(obligation, trait_def_id);
-                Ok(VtableAutoImpl(data))
-            }
-
-            ProjectionCandidate => {
-                self.confirm_projection_candidate(obligation);
-                Ok(VtableParam(Vec::new()))
-            }
-
-            ClosureCandidate => {
-                let vtable_closure = self.confirm_closure_candidate(obligation)?;
-                Ok(VtableClosure(vtable_closure))
-            }
-
-            GeneratorCandidate => {
-                let vtable_generator = self.confirm_generator_candidate(obligation)?;
-                Ok(VtableGenerator(vtable_generator))
-            }
-
-            FnPointerCandidate => {
-                let data = self.confirm_fn_pointer_candidate(obligation)?;
-                Ok(VtableFnPointer(data))
-            }
-
-            TraitAliasCandidate(alias_def_id) => {
-                let data = self.confirm_trait_alias_candidate(obligation, alias_def_id);
-                Ok(VtableTraitAlias(data))
-            }
-
-            ObjectCandidate => {
-                let data = self.confirm_object_candidate(obligation);
-                Ok(VtableObject(data))
-            }
-
-            BuiltinObjectCandidate => {
-                // This indicates something like `Trait + Send: Send`. In this case, we know that
-                // this holds because that's what the object type is telling us, and there's really
-                // no additional obligations to prove and no types in particular to unify, etc.
-                Ok(VtableParam(Vec::new()))
-            }
-
-            BuiltinUnsizeCandidate => {
-                let data = self.confirm_builtin_unsize_candidate(obligation)?;
-                Ok(VtableBuiltin(data))
-            }
-        }
-    }
-
-    fn confirm_projection_candidate(&mut self, obligation: &TraitObligation<'tcx>) {
-        self.infcx.commit_unconditionally(|snapshot| {
-            let result =
-                self.match_projection_obligation_against_definition_bounds(obligation, snapshot);
-            assert!(result);
-        })
-    }
-
-    fn confirm_param_candidate(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-        param: ty::PolyTraitRef<'tcx>,
-    ) -> Vec<PredicateObligation<'tcx>> {
-        debug!("confirm_param_candidate({:?},{:?})", obligation, param);
-
-        // During evaluation, we already checked that this
-        // where-clause trait-ref could be unified with the obligation
-        // trait-ref. Repeat that unification now without any
-        // transactional boundary; it should not fail.
-        match self.match_where_clause_trait_ref(obligation, param.clone()) {
-            Ok(obligations) => obligations,
-            Err(()) => {
-                bug!(
-                    "Where clause `{:?}` was applicable to `{:?}` but now is not",
-                    param,
-                    obligation
-                );
-            }
-        }
-    }
-
-    fn confirm_builtin_candidate(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-        has_nested: bool,
-    ) -> VtableBuiltinData<PredicateObligation<'tcx>> {
-        debug!("confirm_builtin_candidate({:?}, {:?})", obligation, has_nested);
-
-        let lang_items = self.tcx().lang_items();
-        let obligations = if has_nested {
-            let trait_def = obligation.predicate.def_id();
-            let conditions = if Some(trait_def) == lang_items.sized_trait() {
-                self.sized_conditions(obligation)
-            } else if Some(trait_def) == lang_items.copy_trait() {
-                self.copy_clone_conditions(obligation)
-            } else if Some(trait_def) == lang_items.clone_trait() {
-                self.copy_clone_conditions(obligation)
-            } else {
-                bug!("unexpected builtin trait {:?}", trait_def)
-            };
-            let nested = match conditions {
-                BuiltinImplConditions::Where(nested) => nested,
-                _ => bug!("obligation {:?} had matched a builtin impl but now doesn't", obligation),
-            };
-
-            let cause = obligation.derived_cause(BuiltinDerivedObligation);
-            self.collect_predicates_for_types(
-                obligation.param_env,
-                cause,
-                obligation.recursion_depth + 1,
-                trait_def,
-                nested,
-            )
-        } else {
-            vec![]
-        };
-
-        debug!("confirm_builtin_candidate: obligations={:?}", obligations);
-
-        VtableBuiltinData { nested: obligations }
-    }
-
-    /// This handles the case where a `auto trait Foo` impl is being used.
-    /// The idea is that the impl applies to `X : Foo` if the following conditions are met:
-    ///
-    /// 1. For each constituent type `Y` in `X`, `Y : Foo` holds
-    /// 2. For each where-clause `C` declared on `Foo`, `[Self => X] C` holds.
-    fn confirm_auto_impl_candidate(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-        trait_def_id: DefId,
-    ) -> VtableAutoImplData<PredicateObligation<'tcx>> {
-        debug!("confirm_auto_impl_candidate({:?}, {:?})", obligation, trait_def_id);
-
-        let types = obligation.predicate.map_bound(|inner| {
-            let self_ty = self.infcx.shallow_resolve(inner.self_ty());
-            self.constituent_types_for_ty(self_ty)
-        });
-        self.vtable_auto_impl(obligation, trait_def_id, types)
-    }
-
-    /// See `confirm_auto_impl_candidate`.
-    fn vtable_auto_impl(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-        trait_def_id: DefId,
-        nested: ty::Binder<Vec<Ty<'tcx>>>,
-    ) -> VtableAutoImplData<PredicateObligation<'tcx>> {
-        debug!("vtable_auto_impl: nested={:?}", nested);
-
-        let cause = obligation.derived_cause(BuiltinDerivedObligation);
-        let mut obligations = self.collect_predicates_for_types(
-            obligation.param_env,
-            cause,
-            obligation.recursion_depth + 1,
-            trait_def_id,
-            nested,
-        );
-
-        let trait_obligations: Vec<PredicateObligation<'_>> =
-            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,
-                )
-            });
-
-        // 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.
-        obligations.extend(trait_obligations);
-
-        debug!("vtable_auto_impl: obligations={:?}", obligations);
-
-        VtableAutoImplData { trait_def_id, nested: obligations }
-    }
-
-    fn confirm_impl_candidate(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-        impl_def_id: DefId,
-    ) -> VtableImplData<'tcx, PredicateObligation<'tcx>> {
-        debug!("confirm_impl_candidate({:?},{:?})", obligation, impl_def_id);
-
-        // First, create the substitutions by matching the impl again,
-        // this time not in a probe.
-        self.infcx.commit_unconditionally(|snapshot| {
-            let substs = self.rematch_impl(impl_def_id, obligation, snapshot);
-            debug!("confirm_impl_candidate: substs={:?}", substs);
-            let cause = obligation.derived_cause(ImplDerivedObligation);
-            self.vtable_impl(
-                impl_def_id,
-                substs,
-                cause,
-                obligation.recursion_depth + 1,
-                obligation.param_env,
-            )
-        })
-    }
-
-    fn vtable_impl(
-        &mut self,
-        impl_def_id: DefId,
-        mut substs: Normalized<'tcx, SubstsRef<'tcx>>,
-        cause: ObligationCause<'tcx>,
-        recursion_depth: usize,
-        param_env: ty::ParamEnv<'tcx>,
-    ) -> VtableImplData<'tcx, PredicateObligation<'tcx>> {
-        debug!(
-            "vtable_impl(impl_def_id={:?}, substs={:?}, recursion_depth={})",
-            impl_def_id, substs, recursion_depth,
-        );
-
-        let mut impl_obligations = self.impl_or_trait_obligations(
-            cause,
-            recursion_depth,
-            param_env,
-            impl_def_id,
-            &substs.value,
-        );
-
-        debug!(
-            "vtable_impl: impl_def_id={:?} impl_obligations={:?}",
-            impl_def_id, impl_obligations
-        );
-
-        // Because of RFC447, the impl-trait-ref and obligations
-        // are sufficient to determine the impl substs, without
-        // relying on projections in the impl-trait-ref.
-        //
-        // e.g., `impl<U: Tr, V: Iterator<Item=U>> Foo<<U as Tr>::T> for V`
-        impl_obligations.append(&mut substs.obligations);
-
-        VtableImplData { impl_def_id, substs: substs.value, nested: impl_obligations }
-    }
-
-    fn confirm_object_candidate(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-    ) -> VtableObjectData<'tcx, PredicateObligation<'tcx>> {
-        debug!("confirm_object_candidate({:?})", obligation);
-
-        // FIXME(nmatsakis) skipping binder here seems wrong -- we should
-        // probably flatten the binder from the obligation and the binder
-        // from the object. Have to try to make a broken test case that
-        // results.
-        let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder());
-        let poly_trait_ref = match self_ty.kind {
-            ty::Dynamic(ref data, ..) => data
-                .principal()
-                .unwrap_or_else(|| {
-                    span_bug!(obligation.cause.span, "object candidate with no principal")
-                })
-                .with_self_ty(self.tcx(), self_ty),
-            _ => span_bug!(obligation.cause.span, "object candidate with non-object"),
-        };
-
-        let mut upcast_trait_ref = None;
-        let mut nested = vec![];
-        let vtable_base;
-
-        {
-            let tcx = self.tcx();
-
-            // We want to find the first supertrait in the list of
-            // supertraits that we can unify with, and do that
-            // unification. We know that there is exactly one in the list
-            // where we can unify, because otherwise select would have
-            // reported an ambiguity. (When we do find a match, also
-            // record it for later.)
-            let nonmatching = util::supertraits(tcx, poly_trait_ref).take_while(|&t| {
-                match self.infcx.commit_if_ok(|_| self.match_poly_trait_ref(obligation, t)) {
-                    Ok(obligations) => {
-                        upcast_trait_ref = Some(t);
-                        nested.extend(obligations);
-                        false
-                    }
-                    Err(_) => true,
-                }
-            });
-
-            // Additionally, for each of the non-matching predicates that
-            // we pass over, we sum up the set of number of vtable
-            // entries, so that we can compute the offset for the selected
-            // trait.
-            vtable_base = nonmatching.map(|t| super::util::count_own_vtable_entries(tcx, t)).sum();
-        }
-
-        VtableObjectData { upcast_trait_ref: upcast_trait_ref.unwrap(), vtable_base, nested }
-    }
-
-    fn confirm_fn_pointer_candidate(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-    ) -> Result<VtableFnPointerData<'tcx, PredicateObligation<'tcx>>, SelectionError<'tcx>> {
-        debug!("confirm_fn_pointer_candidate({:?})", obligation);
-
-        // Okay to skip binder; it is reintroduced below.
-        let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder());
-        let sig = self_ty.fn_sig(self.tcx());
-        let trait_ref = closure_trait_ref_and_return_type(
-            self.tcx(),
-            obligation.predicate.def_id(),
-            self_ty,
-            sig,
-            util::TupleArgumentsFlag::Yes,
-        )
-        .map_bound(|(trait_ref, _)| trait_ref);
-
-        let Normalized { value: trait_ref, obligations } = project::normalize_with_depth(
-            self,
-            obligation.param_env,
-            obligation.cause.clone(),
-            obligation.recursion_depth + 1,
-            &trait_ref,
-        );
-
-        self.confirm_poly_trait_refs(
-            obligation.cause.clone(),
-            obligation.param_env,
-            obligation.predicate.to_poly_trait_ref(),
-            trait_ref,
-        )?;
-        Ok(VtableFnPointerData { fn_ty: self_ty, nested: obligations })
-    }
-
-    fn confirm_trait_alias_candidate(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-        alias_def_id: DefId,
-    ) -> VtableTraitAliasData<'tcx, PredicateObligation<'tcx>> {
-        debug!("confirm_trait_alias_candidate({:?}, {:?})", obligation, alias_def_id);
-
-        self.infcx.commit_unconditionally(|_| {
-            let (predicate, _) =
-                self.infcx().replace_bound_vars_with_placeholders(&obligation.predicate);
-            let trait_ref = predicate.trait_ref;
-            let trait_def_id = trait_ref.def_id;
-            let substs = trait_ref.substs;
-
-            let trait_obligations = self.impl_or_trait_obligations(
-                obligation.cause.clone(),
-                obligation.recursion_depth,
-                obligation.param_env,
-                trait_def_id,
-                &substs,
-            );
-
-            debug!(
-                "confirm_trait_alias_candidate: trait_def_id={:?} trait_obligations={:?}",
-                trait_def_id, trait_obligations
-            );
-
-            VtableTraitAliasData { alias_def_id, substs: substs, nested: trait_obligations }
-        })
-    }
-
-    fn confirm_generator_candidate(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-    ) -> Result<VtableGeneratorData<'tcx, PredicateObligation<'tcx>>, SelectionError<'tcx>> {
-        // Okay to skip binder because the substs on generator types never
-        // touch bound regions, they just capture the in-scope
-        // type/region parameters.
-        let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder());
-        let (generator_def_id, substs) = match self_ty.kind {
-            ty::Generator(id, substs, _) => (id, substs),
-            _ => bug!("closure candidate for non-closure {:?}", obligation),
-        };
-
-        debug!("confirm_generator_candidate({:?},{:?},{:?})", obligation, generator_def_id, substs);
-
-        let trait_ref = self.generator_trait_ref_unnormalized(obligation, generator_def_id, substs);
-        let Normalized { value: trait_ref, mut obligations } = normalize_with_depth(
-            self,
-            obligation.param_env,
-            obligation.cause.clone(),
-            obligation.recursion_depth + 1,
-            &trait_ref,
-        );
-
-        debug!(
-            "confirm_generator_candidate(generator_def_id={:?}, \
-             trait_ref={:?}, obligations={:?})",
-            generator_def_id, trait_ref, obligations
-        );
-
-        obligations.extend(self.confirm_poly_trait_refs(
-            obligation.cause.clone(),
-            obligation.param_env,
-            obligation.predicate.to_poly_trait_ref(),
-            trait_ref,
-        )?);
-
-        Ok(VtableGeneratorData { generator_def_id, substs, nested: obligations })
-    }
-
-    fn confirm_closure_candidate(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-    ) -> Result<VtableClosureData<'tcx, PredicateObligation<'tcx>>, SelectionError<'tcx>> {
-        debug!("confirm_closure_candidate({:?})", obligation);
-
-        let kind = self
-            .tcx()
-            .fn_trait_kind_from_lang_item(obligation.predicate.def_id())
-            .unwrap_or_else(|| bug!("closure candidate for non-fn trait {:?}", obligation));
-
-        // Okay to skip binder because the substs on closure types never
-        // touch bound regions, they just capture the in-scope
-        // type/region parameters.
-        let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder());
-        let (closure_def_id, substs) = match self_ty.kind {
-            ty::Closure(id, substs) => (id, substs),
-            _ => bug!("closure candidate for non-closure {:?}", obligation),
-        };
-
-        let trait_ref = self.closure_trait_ref_unnormalized(obligation, closure_def_id, substs);
-        let Normalized { value: trait_ref, mut obligations } = normalize_with_depth(
-            self,
-            obligation.param_env,
-            obligation.cause.clone(),
-            obligation.recursion_depth + 1,
-            &trait_ref,
-        );
-
-        debug!(
-            "confirm_closure_candidate(closure_def_id={:?}, trait_ref={:?}, obligations={:?})",
-            closure_def_id, trait_ref, obligations
-        );
-
-        obligations.extend(self.confirm_poly_trait_refs(
-            obligation.cause.clone(),
-            obligation.param_env,
-            obligation.predicate.to_poly_trait_ref(),
-            trait_ref,
-        )?);
-
-        // 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),
-            ));
-        }
-
-        Ok(VtableClosureData { closure_def_id, substs: substs, nested: obligations })
-    }
-
-    /// In the case of closure types and fn pointers,
-    /// we currently treat the input type parameters on the trait as
-    /// outputs. This means that when we have a match we have only
-    /// considered the self type, so we have to go back and make sure
-    /// to relate the argument types too. This is kind of wrong, but
-    /// since we control the full set of impls, also not that wrong,
-    /// and it DOES yield better error messages (since we don't report
-    /// errors as if there is no applicable impl, but rather report
-    /// errors are about mismatched argument types.
-    ///
-    /// Here is an example. Imagine we have a closure expression
-    /// and we desugared it so that the type of the expression is
-    /// `Closure`, and `Closure` expects an int as argument. Then it
-    /// is "as if" the compiler generated this impl:
-    ///
-    ///     impl Fn(int) for Closure { ... }
-    ///
-    /// Now imagine our obligation is `Fn(usize) for Closure`. So far
-    /// we have matched the self type `Closure`. At this point we'll
-    /// compare the `int` to `usize` and generate an error.
-    ///
-    /// Note that this checking occurs *after* the impl has selected,
-    /// because these output type parameters should not affect the
-    /// selection of the impl. Therefore, if there is a mismatch, we
-    /// report an error to the user.
-    fn confirm_poly_trait_refs(
-        &mut self,
-        obligation_cause: ObligationCause<'tcx>,
-        obligation_param_env: ty::ParamEnv<'tcx>,
-        obligation_trait_ref: ty::PolyTraitRef<'tcx>,
-        expected_trait_ref: ty::PolyTraitRef<'tcx>,
-    ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
-        self.infcx
-            .at(&obligation_cause, obligation_param_env)
-            .sup(obligation_trait_ref, expected_trait_ref)
-            .map(|InferOk { obligations, .. }| obligations)
-            .map_err(|e| OutputTypeParameterMismatch(expected_trait_ref, obligation_trait_ref, e))
-    }
-
-    fn confirm_builtin_unsize_candidate(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-    ) -> Result<VtableBuiltinData<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
-        let tcx = self.tcx();
-
-        // `assemble_candidates_for_unsizing` should ensure there are no late-bound
-        // regions here. See the comment there for more details.
-        let source = self.infcx.shallow_resolve(obligation.self_ty().no_bound_vars().unwrap());
-        let target = obligation.predicate.skip_binder().trait_ref.substs.type_at(1);
-        let target = self.infcx.shallow_resolve(target);
-
-        debug!("confirm_builtin_unsize_candidate(source={:?}, target={:?})", source, target);
-
-        let mut nested = vec![];
-        match (&source.kind, &target.kind) {
-            // Trait+Kx+'a -> Trait+Ky+'b (upcasts).
-            (&ty::Dynamic(ref data_a, r_a), &ty::Dynamic(ref data_b, r_b)) => {
-                // See `assemble_candidates_for_unsizing` for more info.
-                let existential_predicates = data_a.map_bound(|data_a| {
-                    let iter = data_a
-                        .principal()
-                        .map(|x| ty::ExistentialPredicate::Trait(x))
-                        .into_iter()
-                        .chain(
-                            data_a
-                                .projection_bounds()
-                                .map(|x| ty::ExistentialPredicate::Projection(x)),
-                        )
-                        .chain(data_b.auto_traits().map(ty::ExistentialPredicate::AutoTrait));
-                    tcx.mk_existential_predicates(iter)
-                });
-                let source_trait = tcx.mk_dynamic(existential_predicates, r_b);
-
-                // Require that the traits involved in this upcast are **equal**;
-                // only the **lifetime bound** is changed.
-                //
-                // FIXME: This condition is arguably too strong -- it would
-                // suffice for the source trait to be a *subtype* of the target
-                // trait. In particular, changing from something like
-                // `for<'a, 'b> Foo<'a, 'b>` to `for<'a> Foo<'a, 'a>` should be
-                // permitted. And, indeed, in the in commit
-                // 904a0bde93f0348f69914ee90b1f8b6e4e0d7cbc, this
-                // condition was loosened. However, when the leak check was
-                // added back, using subtype here actually guides the coercion
-                // code in such a way that it accepts `old-lub-glb-object.rs`.
-                // This is probably a good thing, but I've modified this to `.eq`
-                // because I want to continue rejecting that test (as we have
-                // done for quite some time) before we are firmly comfortable
-                // with what our behavior should be there. -nikomatsakis
-                let InferOk { obligations, .. } = self
-                    .infcx
-                    .at(&obligation.cause, obligation.param_env)
-                    .eq(target, source_trait) // FIXME -- see below
-                    .map_err(|_| Unimplemented)?;
-                nested.extend(obligations);
-
-                // Register one obligation for 'a: 'b.
-                let cause = ObligationCause::new(
-                    obligation.cause.span,
-                    obligation.cause.body_id,
-                    ObjectCastObligation(target),
-                );
-                let outlives = ty::OutlivesPredicate(r_a, r_b);
-                nested.push(Obligation::with_depth(
-                    cause,
-                    obligation.recursion_depth + 1,
-                    obligation.param_env,
-                    ty::Binder::bind(outlives).to_predicate(),
-                ));
-            }
-
-            // `T` -> `Trait`
-            (_, &ty::Dynamic(ref data, r)) => {
-                let mut object_dids = data.auto_traits().chain(data.principal_def_id());
-                if let Some(did) = object_dids.find(|did| !tcx.is_object_safe(*did)) {
-                    return Err(TraitNotObjectSafe(did));
-                }
-
-                let cause = ObligationCause::new(
-                    obligation.cause.span,
-                    obligation.cause.body_id,
-                    ObjectCastObligation(target),
-                );
-
-                let predicate_to_obligation = |predicate| {
-                    Obligation::with_depth(
-                        cause.clone(),
-                        obligation.recursion_depth + 1,
-                        obligation.param_env,
-                        predicate,
-                    )
-                };
-
-                // Create obligations:
-                //  - Casting `T` to `Trait`
-                //  - For all the various builtin bounds attached to the object cast. (In other
-                //  words, if the object type is `Foo + Send`, this would create an obligation for
-                //  the `Send` check.)
-                //  - Projection predicates
-                nested.extend(
-                    data.iter().map(|predicate| {
-                        predicate_to_obligation(predicate.with_self_ty(tcx, source))
-                    }),
-                );
-
-                // We can only make objects from sized types.
-                let tr = ty::TraitRef::new(
-                    tcx.require_lang_item(lang_items::SizedTraitLangItem, None),
-                    tcx.mk_substs_trait(source, &[]),
-                );
-                nested.push(predicate_to_obligation(tr.without_const().to_predicate()));
-
-                // If the type is `Foo + 'a`, ensure that the type
-                // being cast to `Foo + 'a` outlives `'a`:
-                let outlives = ty::OutlivesPredicate(source, r);
-                nested.push(predicate_to_obligation(ty::Binder::dummy(outlives).to_predicate()));
-            }
-
-            // `[T; n]` -> `[T]`
-            (&ty::Array(a, _), &ty::Slice(b)) => {
-                let InferOk { obligations, .. } = self
-                    .infcx
-                    .at(&obligation.cause, obligation.param_env)
-                    .eq(b, a)
-                    .map_err(|_| Unimplemented)?;
-                nested.extend(obligations);
-            }
-
-            // `Struct<T>` -> `Struct<U>`
-            (&ty::Adt(def, substs_a), &ty::Adt(_, substs_b)) => {
-                let fields =
-                    def.all_fields().map(|field| tcx.type_of(field.did)).collect::<Vec<_>>();
-
-                // The last field of the structure has to exist and contain type parameters.
-                let field = if let Some(&field) = fields.last() {
-                    field
-                } else {
-                    return Err(Unimplemented);
-                };
-                let mut ty_params = GrowableBitSet::new_empty();
-                let mut found = false;
-                for ty in field.walk() {
-                    if let ty::Param(p) = ty.kind {
-                        ty_params.insert(p.index as usize);
-                        found = true;
-                    }
-                }
-                if !found {
-                    return Err(Unimplemented);
-                }
-
-                // Replace type parameters used in unsizing with
-                // Error and ensure they do not affect any other fields.
-                // This could be checked after type collection for any struct
-                // with a potentially unsized trailing field.
-                let params = substs_a
-                    .iter()
-                    .enumerate()
-                    .map(|(i, &k)| if ty_params.contains(i) { tcx.types.err.into() } else { k });
-                let substs = tcx.mk_substs(params);
-                for &ty in fields.split_last().unwrap().1 {
-                    if ty.subst(tcx, substs).references_error() {
-                        return Err(Unimplemented);
-                    }
-                }
-
-                // Extract `Field<T>` and `Field<U>` from `Struct<T>` and `Struct<U>`.
-                let inner_source = field.subst(tcx, substs_a);
-                let inner_target = field.subst(tcx, substs_b);
-
-                // Check that the source struct with the target's
-                // unsized parameters is equal to the target.
-                let params = substs_a.iter().enumerate().map(|(i, &k)| {
-                    if ty_params.contains(i) { substs_b.type_at(i).into() } else { k }
-                });
-                let new_struct = tcx.mk_adt(def, tcx.mk_substs(params));
-                let InferOk { obligations, .. } = self
-                    .infcx
-                    .at(&obligation.cause, obligation.param_env)
-                    .eq(target, new_struct)
-                    .map_err(|_| Unimplemented)?;
-                nested.extend(obligations);
-
-                // Construct the nested `Field<T>: Unsize<Field<U>>` predicate.
-                nested.push(predicate_for_trait_def(
-                    tcx,
-                    obligation.param_env,
-                    obligation.cause.clone(),
-                    obligation.predicate.def_id(),
-                    obligation.recursion_depth + 1,
-                    inner_source,
-                    &[inner_target.into()],
-                ));
-            }
-
-            // `(.., T)` -> `(.., U)`
-            (&ty::Tuple(tys_a), &ty::Tuple(tys_b)) => {
-                assert_eq!(tys_a.len(), tys_b.len());
-
-                // The last field of the tuple has to exist.
-                let (&a_last, a_mid) = if let Some(x) = tys_a.split_last() {
-                    x
-                } else {
-                    return Err(Unimplemented);
-                };
-                let &b_last = tys_b.last().unwrap();
-
-                // Check that the source tuple with the target's
-                // last element is equal to the target.
-                let new_tuple = tcx.mk_tup(
-                    a_mid.iter().map(|k| k.expect_ty()).chain(iter::once(b_last.expect_ty())),
-                );
-                let InferOk { obligations, .. } = self
-                    .infcx
-                    .at(&obligation.cause, obligation.param_env)
-                    .eq(target, new_tuple)
-                    .map_err(|_| Unimplemented)?;
-                nested.extend(obligations);
-
-                // Construct the nested `T: Unsize<U>` predicate.
-                nested.push(predicate_for_trait_def(
-                    tcx,
-                    obligation.param_env,
-                    obligation.cause.clone(),
-                    obligation.predicate.def_id(),
-                    obligation.recursion_depth + 1,
-                    a_last.expect_ty(),
-                    &[b_last],
-                ));
-            }
-
-            _ => bug!(),
-        };
-
-        Ok(VtableBuiltinData { nested })
-    }
-
-    ///////////////////////////////////////////////////////////////////////////
-    // Matching
-    //
-    // Matching is a common path used for both evaluation and
-    // confirmation.  It basically unifies types that appear in impls
-    // and traits. This does affect the surrounding environment;
-    // therefore, when used during evaluation, match routines must be
-    // run inside of a `probe()` so that their side-effects are
-    // contained.
-
-    fn rematch_impl(
-        &mut self,
-        impl_def_id: DefId,
-        obligation: &TraitObligation<'tcx>,
-        snapshot: &CombinedSnapshot<'_, 'tcx>,
-    ) -> Normalized<'tcx, SubstsRef<'tcx>> {
-        match self.match_impl(impl_def_id, obligation, snapshot) {
-            Ok(substs) => substs,
-            Err(()) => {
-                bug!(
-                    "Impl {:?} was matchable against {:?} but now is not",
-                    impl_def_id,
-                    obligation
-                );
-            }
-        }
-    }
-
-    fn match_impl(
-        &mut self,
-        impl_def_id: DefId,
-        obligation: &TraitObligation<'tcx>,
-        snapshot: &CombinedSnapshot<'_, 'tcx>,
-    ) -> Result<Normalized<'tcx, SubstsRef<'tcx>>, ()> {
-        let impl_trait_ref = self.tcx().impl_trait_ref(impl_def_id).unwrap();
-
-        // Before we create the substitutions and everything, first
-        // consider a "quick reject". This avoids creating more types
-        // and so forth that we need to.
-        if self.fast_reject_trait_refs(obligation, &impl_trait_ref) {
-            return Err(());
-        }
-
-        let (skol_obligation, placeholder_map) =
-            self.infcx().replace_bound_vars_with_placeholders(&obligation.predicate);
-        let skol_obligation_trait_ref = skol_obligation.trait_ref;
-
-        let impl_substs = self.infcx.fresh_substs_for_item(obligation.cause.span, impl_def_id);
-
-        let impl_trait_ref = impl_trait_ref.subst(self.tcx(), impl_substs);
-
-        let Normalized { value: impl_trait_ref, obligations: mut nested_obligations } =
-            project::normalize_with_depth(
-                self,
-                obligation.param_env,
-                obligation.cause.clone(),
-                obligation.recursion_depth + 1,
-                &impl_trait_ref,
-            );
-
-        debug!(
-            "match_impl(impl_def_id={:?}, obligation={:?}, \
-             impl_trait_ref={:?}, skol_obligation_trait_ref={:?})",
-            impl_def_id, obligation, impl_trait_ref, skol_obligation_trait_ref
-        );
-
-        let InferOk { obligations, .. } = self
-            .infcx
-            .at(&obligation.cause, obligation.param_env)
-            .eq(skol_obligation_trait_ref, impl_trait_ref)
-            .map_err(|e| debug!("match_impl: failed eq_trait_refs due to `{}`", e))?;
-        nested_obligations.extend(obligations);
-
-        if let Err(e) = self.infcx.leak_check(false, &placeholder_map, snapshot) {
-            debug!("match_impl: failed leak check due to `{}`", e);
-            return Err(());
-        }
-
-        if !self.intercrate
-            && self.tcx().impl_polarity(impl_def_id) == ty::ImplPolarity::Reservation
-        {
-            debug!("match_impl: reservation impls only apply in intercrate mode");
-            return Err(());
-        }
-
-        debug!("match_impl: success impl_substs={:?}", impl_substs);
-        Ok(Normalized { value: impl_substs, obligations: nested_obligations })
-    }
-
-    fn fast_reject_trait_refs(
-        &mut self,
-        obligation: &TraitObligation<'_>,
-        impl_trait_ref: &ty::TraitRef<'_>,
-    ) -> bool {
-        // We can avoid creating type variables and doing the full
-        // substitution if we find that any of the input types, when
-        // simplified, do not match.
-
-        obligation.predicate.skip_binder().input_types().zip(impl_trait_ref.input_types()).any(
-            |(obligation_ty, impl_ty)| {
-                let simplified_obligation_ty =
-                    fast_reject::simplify_type(self.tcx(), obligation_ty, true);
-                let simplified_impl_ty = fast_reject::simplify_type(self.tcx(), impl_ty, false);
-
-                simplified_obligation_ty.is_some()
-                    && simplified_impl_ty.is_some()
-                    && simplified_obligation_ty != simplified_impl_ty
-            },
-        )
-    }
-
-    /// Normalize `where_clause_trait_ref` and try to match it against
-    /// `obligation`. If successful, return any predicates that
-    /// result from the normalization. Normalization is necessary
-    /// because where-clauses are stored in the parameter environment
-    /// unnormalized.
-    fn match_where_clause_trait_ref(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-        where_clause_trait_ref: ty::PolyTraitRef<'tcx>,
-    ) -> Result<Vec<PredicateObligation<'tcx>>, ()> {
-        self.match_poly_trait_ref(obligation, where_clause_trait_ref)
-    }
-
-    /// Returns `Ok` if `poly_trait_ref` being true implies that the
-    /// obligation is satisfied.
-    fn match_poly_trait_ref(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-        poly_trait_ref: ty::PolyTraitRef<'tcx>,
-    ) -> Result<Vec<PredicateObligation<'tcx>>, ()> {
-        debug!(
-            "match_poly_trait_ref: obligation={:?} poly_trait_ref={:?}",
-            obligation, poly_trait_ref
-        );
-
-        self.infcx
-            .at(&obligation.cause, obligation.param_env)
-            .sup(obligation.predicate.to_poly_trait_ref(), poly_trait_ref)
-            .map(|InferOk { obligations, .. }| obligations)
-            .map_err(|_| ())
-    }
-
-    ///////////////////////////////////////////////////////////////////////////
-    // Miscellany
-
-    fn match_fresh_trait_refs(
-        &self,
-        previous: &ty::PolyTraitRef<'tcx>,
-        current: &ty::PolyTraitRef<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
-    ) -> bool {
-        let mut matcher = ty::_match::Match::new(self.tcx(), param_env);
-        matcher.relate(previous, current).is_ok()
-    }
-
-    fn push_stack<'o>(
-        &mut self,
-        previous_stack: TraitObligationStackList<'o, 'tcx>,
-        obligation: &'o TraitObligation<'tcx>,
-    ) -> TraitObligationStack<'o, 'tcx> {
-        let fresh_trait_ref =
-            obligation.predicate.to_poly_trait_ref().fold_with(&mut self.freshener);
-
-        let dfn = previous_stack.cache.next_dfn();
-        let depth = previous_stack.depth() + 1;
-        TraitObligationStack {
-            obligation,
-            fresh_trait_ref,
-            reached_depth: Cell::new(depth),
-            previous: previous_stack,
-            dfn,
-            depth,
-        }
-    }
-
-    fn closure_trait_ref_unnormalized(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-        closure_def_id: DefId,
-        substs: SubstsRef<'tcx>,
-    ) -> ty::PolyTraitRef<'tcx> {
-        debug!(
-            "closure_trait_ref_unnormalized(obligation={:?}, closure_def_id={:?}, substs={:?})",
-            obligation, closure_def_id, substs,
-        );
-        let closure_type = self.infcx.closure_sig(closure_def_id, substs);
-
-        debug!("closure_trait_ref_unnormalized: closure_type = {:?}", closure_type);
-
-        // (1) Feels icky to skip the binder here, but OTOH we know
-        // that the self-type is an unboxed closure type and hence is
-        // in fact unparameterized (or at least does not reference any
-        // regions bound in the obligation). Still probably some
-        // refactoring could make this nicer.
-        closure_trait_ref_and_return_type(
-            self.tcx(),
-            obligation.predicate.def_id(),
-            obligation.predicate.skip_binder().self_ty(), // (1)
-            closure_type,
-            util::TupleArgumentsFlag::No,
-        )
-        .map_bound(|(trait_ref, _)| trait_ref)
-    }
-
-    fn generator_trait_ref_unnormalized(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-        closure_def_id: DefId,
-        substs: SubstsRef<'tcx>,
-    ) -> ty::PolyTraitRef<'tcx> {
-        let gen_sig = substs.as_generator().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
-        // in fact unparameterized (or at least does not reference any
-        // regions bound in the obligation). Still probably some
-        // refactoring could make this nicer.
-
-        super::util::generator_trait_ref_and_outputs(
-            self.tcx(),
-            obligation.predicate.def_id(),
-            obligation.predicate.skip_binder().self_ty(), // (1)
-            gen_sig,
-        )
-        .map_bound(|(trait_ref, ..)| trait_ref)
-    }
-
-    /// Returns the obligations that are implied by instantiating an
-    /// impl or trait. The obligations are substituted and fully
-    /// normalized. This is used when confirming an impl or default
-    /// impl.
-    fn impl_or_trait_obligations(
-        &mut self,
-        cause: ObligationCause<'tcx>,
-        recursion_depth: usize,
-        param_env: ty::ParamEnv<'tcx>,
-        def_id: DefId,           // of impl or trait
-        substs: SubstsRef<'tcx>, // for impl or trait
-    ) -> Vec<PredicateObligation<'tcx>> {
-        debug!("impl_or_trait_obligations(def_id={:?})", def_id);
-        let tcx = self.tcx();
-
-        // To allow for one-pass evaluation of the nested obligation,
-        // each predicate must be preceded by the obligations required
-        // to normalize it.
-        // for example, if we have:
-        //    impl<U: Iterator<Item: Copy>, V: Iterator<Item = U>> Foo for V
-        // the impl will have the following predicates:
-        //    <V as Iterator>::Item = U,
-        //    U: Iterator, U: Sized,
-        //    V: Iterator, V: Sized,
-        //    <U as Iterator>::Item: Copy
-        // When we substitute, say, `V => IntoIter<u32>, U => $0`, the last
-        // obligation will normalize to `<$0 as Iterator>::Item = $1` and
-        // `$1: Copy`, so we must ensure the obligations are emitted in
-        // that order.
-        let predicates = tcx.predicates_of(def_id);
-        assert_eq!(predicates.parent, None);
-        let mut obligations = Vec::with_capacity(predicates.predicates.len());
-        for (predicate, _) in predicates.predicates {
-            let predicate = normalize_with_depth_to(
-                self,
-                param_env,
-                cause.clone(),
-                recursion_depth,
-                &predicate.subst(tcx, substs),
-                &mut obligations,
-            );
-            obligations.push(Obligation {
-                cause: cause.clone(),
-                recursion_depth,
-                param_env,
-                predicate,
-            });
-        }
-
-        // We are performing deduplication here to avoid exponential blowups
-        // (#38528) from happening, but the real cause of the duplication is
-        // unknown. What we know is that the deduplication avoids exponential
-        // amount of predicates being propagated when processing deeply nested
-        // types.
-        //
-        // This code is hot enough that it's worth avoiding the allocation
-        // required for the FxHashSet when possible. Special-casing lengths 0,
-        // 1 and 2 covers roughly 75-80% of the cases.
-        if obligations.len() <= 1 {
-            // No possibility of duplicates.
-        } else if obligations.len() == 2 {
-            // Only two elements. Drop the second if they are equal.
-            if obligations[0] == obligations[1] {
-                obligations.truncate(1);
-            }
-        } else {
-            // Three or more elements. Use a general deduplication process.
-            let mut seen = FxHashSet::default();
-            obligations.retain(|i| seen.insert(i.clone()));
-        }
-
-        obligations
-    }
-}
-
-impl<'tcx> TraitObligation<'tcx> {
-    #[allow(unused_comparisons)]
-    pub fn derived_cause(
-        &self,
-        variant: fn(DerivedObligationCause<'tcx>) -> ObligationCauseCode<'tcx>,
-    ) -> ObligationCause<'tcx> {
-        /*!
-         * Creates a cause for obligations that are derived from
-         * `obligation` by a recursive search (e.g., for a builtin
-         * bound, or eventually a `auto trait Foo`). If `obligation`
-         * is itself a derived obligation, this is just a clone, but
-         * otherwise we create a "derived obligation" cause so as to
-         * keep track of the original root obligation for error
-         * reporting.
-         */
-
-        let obligation = self;
-
-        // NOTE(flaper87): As of now, it keeps track of the whole error
-        // chain. Ideally, we should have a way to configure this either
-        // by using -Z verbose or just a CLI argument.
-        let derived_cause = DerivedObligationCause {
-            parent_trait_ref: obligation.predicate.to_poly_trait_ref(),
-            parent_code: Rc::new(obligation.cause.code.clone()),
-        };
-        let derived_code = variant(derived_cause);
-        ObligationCause::new(obligation.cause.span, obligation.cause.body_id, derived_code)
-    }
-}
-
-impl<'o, 'tcx> TraitObligationStack<'o, 'tcx> {
-    fn list(&'o self) -> TraitObligationStackList<'o, 'tcx> {
-        TraitObligationStackList::with(self)
-    }
-
-    fn cache(&self) -> &'o ProvisionalEvaluationCache<'tcx> {
-        self.previous.cache
-    }
-
-    fn iter(&'o self) -> TraitObligationStackList<'o, 'tcx> {
-        self.list()
-    }
-
-    /// Indicates that attempting to evaluate this stack entry
-    /// required accessing something from the stack at depth `reached_depth`.
-    fn update_reached_depth(&self, reached_depth: usize) {
-        assert!(
-            self.depth > reached_depth,
-            "invoked `update_reached_depth` with something under this stack: \
-             self.depth={} reached_depth={}",
-            self.depth,
-            reached_depth,
-        );
-        debug!("update_reached_depth(reached_depth={})", reached_depth);
-        let mut p = self;
-        while reached_depth < p.depth {
-            debug!("update_reached_depth: marking {:?} as cycle participant", p.fresh_trait_ref);
-            p.reached_depth.set(p.reached_depth.get().min(reached_depth));
-            p = p.previous.head.unwrap();
-        }
-    }
-}
-
-/// The "provisional evaluation cache" is used to store intermediate cache results
-/// when solving auto traits. Auto traits are unusual in that they can support
-/// cycles. So, for example, a "proof tree" like this would be ok:
-///
-/// - `Foo<T>: Send` :-
-///   - `Bar<T>: Send` :-
-///     - `Foo<T>: Send` -- cycle, but ok
-///   - `Baz<T>: Send`
-///
-/// Here, to prove `Foo<T>: Send`, we have to prove `Bar<T>: Send` and
-/// `Baz<T>: Send`. Proving `Bar<T>: Send` in turn required `Foo<T>: Send`.
-/// For non-auto traits, this cycle would be an error, but for auto traits (because
-/// they are coinductive) it is considered ok.
-///
-/// However, there is a complication: at the point where we have
-/// "proven" `Bar<T>: Send`, we have in fact only proven it
-/// *provisionally*. In particular, we proved that `Bar<T>: Send`
-/// *under the assumption* that `Foo<T>: Send`. But what if we later
-/// find out this assumption is wrong?  Specifically, we could
-/// encounter some kind of error proving `Baz<T>: Send`. In that case,
-/// `Bar<T>: Send` didn't turn out to be true.
-///
-/// In Issue #60010, we found a bug in rustc where it would cache
-/// these intermediate results. This was fixed in #60444 by disabling
-/// *all* caching for things involved in a cycle -- in our example,
-/// that would mean we don't cache that `Bar<T>: Send`.  But this led
-/// to large slowdowns.
-///
-/// Specifically, imagine this scenario, where proving `Baz<T>: Send`
-/// first requires proving `Bar<T>: Send` (which is true:
-///
-/// - `Foo<T>: Send` :-
-///   - `Bar<T>: Send` :-
-///     - `Foo<T>: Send` -- cycle, but ok
-///   - `Baz<T>: Send`
-///     - `Bar<T>: Send` -- would be nice for this to be a cache hit!
-///     - `*const T: Send` -- but what if we later encounter an error?
-///
-/// The *provisional evaluation cache* resolves this issue. It stores
-/// cache results that we've proven but which were involved in a cycle
-/// in some way. We track the minimal stack depth (i.e., the
-/// farthest from the top of the stack) that we are dependent on.
-/// The idea is that the cache results within are all valid -- so long as
-/// none of the nodes in between the current node and the node at that minimum
-/// depth result in an error (in which case the cached results are just thrown away).
-///
-/// During evaluation, we consult this provisional cache and rely on
-/// it. Accessing a cached value is considered equivalent to accessing
-/// a result at `reached_depth`, so it marks the *current* solution as
-/// provisional as well. If an error is encountered, we toss out any
-/// provisional results added from the subtree that encountered the
-/// error.  When we pop the node at `reached_depth` from the stack, we
-/// can commit all the things that remain in the provisional cache.
-struct ProvisionalEvaluationCache<'tcx> {
-    /// next "depth first number" to issue -- just a counter
-    dfn: Cell<usize>,
-
-    /// Stores the "coldest" depth (bottom of stack) reached by any of
-    /// the evaluation entries. The idea here is that all things in the provisional
-    /// cache are always dependent on *something* that is colder in the stack:
-    /// therefore, if we add a new entry that is dependent on something *colder still*,
-    /// we have to modify the depth for all entries at once.
-    ///
-    /// Example:
-    ///
-    /// Imagine we have a stack `A B C D E` (with `E` being the top of
-    /// the stack).  We cache something with depth 2, which means that
-    /// it was dependent on C.  Then we pop E but go on and process a
-    /// new node F: A B C D F.  Now F adds something to the cache with
-    /// depth 1, meaning it is dependent on B.  Our original cache
-    /// entry is also dependent on B, because there is a path from E
-    /// to C and then from C to F and from F to B.
-    reached_depth: Cell<usize>,
-
-    /// Map from cache key to the provisionally evaluated thing.
-    /// The cache entries contain the result but also the DFN in which they
-    /// were added. The DFN is used to clear out values on failure.
-    ///
-    /// Imagine we have a stack like:
-    ///
-    /// - `A B C` and we add a cache for the result of C (DFN 2)
-    /// - Then we have a stack `A B D` where `D` has DFN 3
-    /// - We try to solve D by evaluating E: `A B D E` (DFN 4)
-    /// - `E` generates various cache entries which have cyclic dependices on `B`
-    ///   - `A B D E F` and so forth
-    ///   - the DFN of `F` for example would be 5
-    /// - then we determine that `E` is in error -- we will then clear
-    ///   all cache values whose DFN is >= 4 -- in this case, that
-    ///   means the cached value for `F`.
-    map: RefCell<FxHashMap<ty::PolyTraitRef<'tcx>, ProvisionalEvaluation>>,
-}
-
-/// A cache value for the provisional cache: contains the depth-first
-/// number (DFN) and result.
-#[derive(Copy, Clone, Debug)]
-struct ProvisionalEvaluation {
-    from_dfn: usize,
-    result: EvaluationResult,
-}
-
-impl<'tcx> Default for ProvisionalEvaluationCache<'tcx> {
-    fn default() -> Self {
-        Self {
-            dfn: Cell::new(0),
-            reached_depth: Cell::new(std::usize::MAX),
-            map: Default::default(),
-        }
-    }
-}
-
-impl<'tcx> ProvisionalEvaluationCache<'tcx> {
-    /// Get the next DFN in sequence (basically a counter).
-    fn next_dfn(&self) -> usize {
-        let result = self.dfn.get();
-        self.dfn.set(result + 1);
-        result
-    }
-
-    /// Check the provisional cache for any result for
-    /// `fresh_trait_ref`. If there is a hit, then you must consider
-    /// it an access to the stack slots at depth
-    /// `self.current_reached_depth()` and above.
-    fn get_provisional(&self, fresh_trait_ref: ty::PolyTraitRef<'tcx>) -> Option<EvaluationResult> {
-        debug!(
-            "get_provisional(fresh_trait_ref={:?}) = {:#?} with reached-depth {}",
-            fresh_trait_ref,
-            self.map.borrow().get(&fresh_trait_ref),
-            self.reached_depth.get(),
-        );
-        Some(self.map.borrow().get(&fresh_trait_ref)?.result)
-    }
-
-    /// Current value of the `reached_depth` counter -- all the
-    /// provisional cache entries are dependent on the item at this
-    /// depth.
-    fn current_reached_depth(&self) -> usize {
-        self.reached_depth.get()
-    }
-
-    /// Insert a provisional result into the cache. The result came
-    /// from the node with the given DFN. It accessed a minimum depth
-    /// of `reached_depth` to compute. It evaluated `fresh_trait_ref`
-    /// and resulted in `result`.
-    fn insert_provisional(
-        &self,
-        from_dfn: usize,
-        reached_depth: usize,
-        fresh_trait_ref: ty::PolyTraitRef<'tcx>,
-        result: EvaluationResult,
-    ) {
-        debug!(
-            "insert_provisional(from_dfn={}, reached_depth={}, fresh_trait_ref={:?}, result={:?})",
-            from_dfn, reached_depth, fresh_trait_ref, result,
-        );
-        let r_d = self.reached_depth.get();
-        self.reached_depth.set(r_d.min(reached_depth));
-
-        debug!("insert_provisional: reached_depth={:?}", self.reached_depth.get());
-
-        self.map.borrow_mut().insert(fresh_trait_ref, ProvisionalEvaluation { from_dfn, result });
-    }
-
-    /// Invoked when the node with dfn `dfn` does not get a successful
-    /// result.  This will clear out any provisional cache entries
-    /// that were added since `dfn` was created. This is because the
-    /// provisional entries are things which must assume that the
-    /// things on the stack at the time of their creation succeeded --
-    /// since the failing node is presently at the top of the stack,
-    /// these provisional entries must either depend on it or some
-    /// ancestor of it.
-    fn on_failure(&self, dfn: usize) {
-        debug!("on_failure(dfn={:?})", dfn,);
-        self.map.borrow_mut().retain(|key, eval| {
-            if !eval.from_dfn >= dfn {
-                debug!("on_failure: removing {:?}", key);
-                false
-            } else {
-                true
-            }
-        });
-    }
-
-    /// Invoked when the node at depth `depth` completed without
-    /// depending on anything higher in the stack (if that completion
-    /// was a failure, then `on_failure` should have been invoked
-    /// already). The callback `op` will be invoked for each
-    /// provisional entry that we can now confirm.
-    fn on_completion(
-        &self,
-        depth: usize,
-        mut op: impl FnMut(ty::PolyTraitRef<'tcx>, EvaluationResult),
-    ) {
-        debug!("on_completion(depth={}, reached_depth={})", depth, self.reached_depth.get(),);
-
-        if self.reached_depth.get() < depth {
-            debug!("on_completion: did not yet reach depth to complete");
-            return;
-        }
-
-        for (fresh_trait_ref, eval) in self.map.borrow_mut().drain() {
-            debug!("on_completion: fresh_trait_ref={:?} eval={:?}", fresh_trait_ref, eval,);
-
-            op(fresh_trait_ref, eval.result);
-        }
-
-        self.reached_depth.set(std::usize::MAX);
-    }
-}
-
-#[derive(Copy, Clone)]
-struct TraitObligationStackList<'o, 'tcx> {
-    cache: &'o ProvisionalEvaluationCache<'tcx>,
-    head: Option<&'o TraitObligationStack<'o, 'tcx>>,
-}
-
-impl<'o, 'tcx> TraitObligationStackList<'o, 'tcx> {
-    fn empty(cache: &'o ProvisionalEvaluationCache<'tcx>) -> TraitObligationStackList<'o, 'tcx> {
-        TraitObligationStackList { cache, head: None }
-    }
-
-    fn with(r: &'o TraitObligationStack<'o, 'tcx>) -> TraitObligationStackList<'o, 'tcx> {
-        TraitObligationStackList { cache: r.cache(), head: Some(r) }
-    }
-
-    fn head(&self) -> Option<&'o TraitObligationStack<'o, 'tcx>> {
-        self.head
-    }
-
-    fn depth(&self) -> usize {
-        if let Some(head) = self.head { head.depth } else { 0 }
-    }
-}
-
-impl<'o, 'tcx> Iterator for TraitObligationStackList<'o, 'tcx> {
-    type Item = &'o TraitObligationStack<'o, 'tcx>;
-
-    fn next(&mut self) -> Option<&'o TraitObligationStack<'o, 'tcx>> {
-        match self.head {
-            Some(o) => {
-                *self = o.previous;
-                Some(o)
-            }
-            None => None,
-        }
-    }
-}
-
-impl<'o, 'tcx> fmt::Debug for TraitObligationStack<'o, 'tcx> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "TraitObligationStack({:?})", self.obligation)
-    }
-}
diff --git a/src/librustc_infer/traits/specialize/mod.rs b/src/librustc_infer/traits/specialize/mod.rs
deleted file mode 100644 (file)
index ee1c737..0000000
+++ /dev/null
@@ -1,472 +0,0 @@
-//! Logic and data structures related to impl specialization, explained in
-//! greater detail below.
-//!
-//! At the moment, this implementation support only the simple "chain" rule:
-//! If any two impls overlap, one must be a strict subset of the other.
-//!
-//! See the [rustc guide] for a bit more detail on how specialization
-//! fits together with the rest of the trait machinery.
-//!
-//! [rustc guide]: https://rust-lang.github.io/rustc-guide/traits/specialization.html
-
-pub mod specialization_graph;
-use specialization_graph::GraphExt;
-
-use crate::infer::{InferCtxt, InferOk, TyCtxtInferExt};
-use crate::traits::select::IntercrateAmbiguityCause;
-use crate::traits::{self, coherence, FutureCompatOverlapErrorKind, ObligationCause, TraitEngine};
-use rustc::lint::LintDiagnosticBuilder;
-use rustc::ty::subst::{InternalSubsts, Subst, SubstsRef};
-use rustc::ty::{self, TyCtxt, TypeFoldable};
-use rustc_data_structures::fx::FxHashSet;
-use rustc_errors::struct_span_err;
-use rustc_hir::def_id::DefId;
-use rustc_session::lint::builtin::COHERENCE_LEAK_CHECK;
-use rustc_session::lint::builtin::ORDER_DEPENDENT_TRAIT_OBJECTS;
-use rustc_span::DUMMY_SP;
-
-use super::util::impl_trait_ref_and_oblig;
-use super::{FulfillmentContext, SelectionContext};
-
-/// Information pertinent to an overlapping impl error.
-#[derive(Debug)]
-pub struct OverlapError {
-    pub with_impl: DefId,
-    pub trait_desc: String,
-    pub self_desc: Option<String>,
-    pub intercrate_ambiguity_causes: Vec<IntercrateAmbiguityCause>,
-    pub involves_placeholder: bool,
-}
-
-/// Given a subst for the requested impl, translate it to a subst
-/// appropriate for the actual item definition (whether it be in that impl,
-/// a parent impl, or the trait).
-///
-/// When we have selected one impl, but are actually using item definitions from
-/// a parent impl providing a default, we need a way to translate between the
-/// type parameters of the two impls. Here the `source_impl` is the one we've
-/// selected, and `source_substs` is a substitution of its generics.
-/// And `target_node` is the impl/trait we're actually going to get the
-/// definition from. The resulting substitution will map from `target_node`'s
-/// generics to `source_impl`'s generics as instantiated by `source_subst`.
-///
-/// For example, consider the following scenario:
-///
-/// ```rust
-/// trait Foo { ... }
-/// impl<T, U> Foo for (T, U) { ... }  // target impl
-/// impl<V> Foo for (V, V) { ... }     // source impl
-/// ```
-///
-/// Suppose we have selected "source impl" with `V` instantiated with `u32`.
-/// This function will produce a substitution with `T` and `U` both mapping to `u32`.
-///
-/// where-clauses add some trickiness here, because they can be used to "define"
-/// an argument indirectly:
-///
-/// ```rust
-/// impl<'a, I, T: 'a> Iterator for Cloned<I>
-///    where I: Iterator<Item = &'a T>, T: Clone
-/// ```
-///
-/// In a case like this, the substitution for `T` is determined indirectly,
-/// through associated type projection. We deal with such cases by using
-/// *fulfillment* to relate the two impls, requiring that all projections are
-/// resolved.
-pub fn translate_substs<'a, 'tcx>(
-    infcx: &InferCtxt<'a, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    source_impl: DefId,
-    source_substs: SubstsRef<'tcx>,
-    target_node: specialization_graph::Node,
-) -> SubstsRef<'tcx> {
-    debug!(
-        "translate_substs({:?}, {:?}, {:?}, {:?})",
-        param_env, source_impl, source_substs, target_node
-    );
-    let source_trait_ref =
-        infcx.tcx.impl_trait_ref(source_impl).unwrap().subst(infcx.tcx, &source_substs);
-
-    // translate the Self and Param parts of the substitution, since those
-    // vary across impls
-    let target_substs = match target_node {
-        specialization_graph::Node::Impl(target_impl) => {
-            // no need to translate if we're targeting the impl we started with
-            if source_impl == target_impl {
-                return source_substs;
-            }
-
-            fulfill_implication(infcx, param_env, source_trait_ref, target_impl).unwrap_or_else(
-                |_| {
-                    bug!(
-                        "When translating substitutions for specialization, the expected \
-                         specialization failed to hold"
-                    )
-                },
-            )
-        }
-        specialization_graph::Node::Trait(..) => source_trait_ref.substs,
-    };
-
-    // directly inherent the method generics, since those do not vary across impls
-    source_substs.rebase_onto(infcx.tcx, source_impl, target_substs)
-}
-
-/// Given a selected impl described by `impl_data`, returns the
-/// definition and substitutions for the method with the name `name`
-/// the kind `kind`, and trait method substitutions `substs`, in
-/// that impl, a less specialized impl, or the trait default,
-/// whichever applies.
-pub fn find_associated_item<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    item: &ty::AssocItem,
-    substs: SubstsRef<'tcx>,
-    impl_data: &super::VtableImplData<'tcx, ()>,
-) -> (DefId, SubstsRef<'tcx>) {
-    debug!("find_associated_item({:?}, {:?}, {:?}, {:?})", param_env, item, substs, impl_data);
-    assert!(!substs.needs_infer());
-
-    let trait_def_id = tcx.trait_id_of_impl(impl_data.impl_def_id).unwrap();
-    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) {
-        Some(node_item) => {
-            let substs = tcx.infer_ctxt().enter(|infcx| {
-                let param_env = param_env.with_reveal_all();
-                let substs = substs.rebase_onto(tcx, trait_def_id, impl_data.substs);
-                let substs = translate_substs(
-                    &infcx,
-                    param_env,
-                    impl_data.impl_def_id,
-                    substs,
-                    node_item.node,
-                );
-                infcx.tcx.erase_regions(&substs)
-            });
-            (node_item.item.def_id, substs)
-        }
-        None => bug!("{:?} not found in {:?}", item, impl_data.impl_def_id),
-    }
-}
-
-/// Is `impl1` a specialization of `impl2`?
-///
-/// Specialization is determined by the sets of types to which the impls apply;
-/// `impl1` specializes `impl2` if it applies to a subset of the types `impl2` applies
-/// to.
-pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId, DefId)) -> bool {
-    debug!("specializes({:?}, {:?})", impl1_def_id, impl2_def_id);
-
-    // The feature gate should prevent introducing new specializations, but not
-    // taking advantage of upstream ones.
-    if !tcx.features().specialization && (impl1_def_id.is_local() || impl2_def_id.is_local()) {
-        return false;
-    }
-
-    // We determine whether there's a subset relationship by:
-    //
-    // - skolemizing impl1,
-    // - assuming the where clauses for impl1,
-    // - instantiating impl2 with fresh inference variables,
-    // - unifying,
-    // - attempting to prove the where clauses for impl2
-    //
-    // The last three steps are encapsulated in `fulfill_implication`.
-    //
-    // See RFC 1210 for more details and justification.
-
-    // Currently we do not allow e.g., a negative impl to specialize a positive one
-    if tcx.impl_polarity(impl1_def_id) != tcx.impl_polarity(impl2_def_id) {
-        return false;
-    }
-
-    // create a parameter environment corresponding to a (placeholder) instantiation of impl1
-    let penv = tcx.param_env(impl1_def_id);
-    let impl1_trait_ref = tcx.impl_trait_ref(impl1_def_id).unwrap();
-
-    // Create a infcx, taking the predicates of impl1 as assumptions:
-    tcx.infer_ctxt().enter(|infcx| {
-        // Normalize the trait reference. The WF rules ought to ensure
-        // that this always succeeds.
-        let impl1_trait_ref = match traits::fully_normalize(
-            &infcx,
-            FulfillmentContext::new(),
-            ObligationCause::dummy(),
-            penv,
-            &impl1_trait_ref,
-        ) {
-            Ok(impl1_trait_ref) => impl1_trait_ref,
-            Err(err) => {
-                bug!("failed to fully normalize {:?}: {:?}", impl1_trait_ref, err);
-            }
-        };
-
-        // Attempt to prove that impl2 applies, given all of the above.
-        fulfill_implication(&infcx, penv, impl1_trait_ref, impl2_def_id).is_ok()
-    })
-}
-
-/// Attempt to fulfill all obligations of `target_impl` after unification with
-/// `source_trait_ref`. If successful, returns a substitution for *all* the
-/// generics of `target_impl`, including both those needed to unify with
-/// `source_trait_ref` and those whose identity is determined via a where
-/// clause in the impl.
-fn fulfill_implication<'a, 'tcx>(
-    infcx: &InferCtxt<'a, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    source_trait_ref: ty::TraitRef<'tcx>,
-    target_impl: DefId,
-) -> Result<SubstsRef<'tcx>, ()> {
-    debug!(
-        "fulfill_implication({:?}, trait_ref={:?} |- {:?} applies)",
-        param_env, source_trait_ref, target_impl
-    );
-
-    let selcx = &mut SelectionContext::new(&infcx);
-    let target_substs = infcx.fresh_substs_for_item(DUMMY_SP, target_impl);
-    let (target_trait_ref, mut obligations) =
-        impl_trait_ref_and_oblig(selcx, param_env, target_impl, target_substs);
-    debug!(
-        "fulfill_implication: target_trait_ref={:?}, obligations={:?}",
-        target_trait_ref, obligations
-    );
-
-    // do the impls unify? If not, no specialization.
-    match infcx.at(&ObligationCause::dummy(), param_env).eq(source_trait_ref, target_trait_ref) {
-        Ok(InferOk { obligations: o, .. }) => {
-            obligations.extend(o);
-        }
-        Err(_) => {
-            debug!(
-                "fulfill_implication: {:?} does not unify with {:?}",
-                source_trait_ref, target_trait_ref
-            );
-            return Err(());
-        }
-    }
-
-    // attempt to prove all of the predicates for impl2 given those for impl1
-    // (which are packed up in penv)
-
-    infcx.save_and_restore_in_snapshot_flag(|infcx| {
-        // If we came from `translate_substs`, we already know that the
-        // predicates for our impl hold (after all, we know that a more
-        // specialized impl holds, so our impl must hold too), and
-        // we only want to process the projections to determine the
-        // the types in our substs using RFC 447, so we can safely
-        // ignore region obligations, which allows us to avoid threading
-        // a node-id to assign them with.
-        //
-        // If we came from specialization graph construction, then
-        // we already make a mockery out of the region system, so
-        // why not ignore them a bit earlier?
-        let mut fulfill_cx = FulfillmentContext::new_ignoring_regions();
-        for oblig in obligations.into_iter() {
-            fulfill_cx.register_predicate_obligation(&infcx, oblig);
-        }
-        match fulfill_cx.select_all_or_error(infcx) {
-            Err(errors) => {
-                // no dice!
-                debug!(
-                    "fulfill_implication: for impls on {:?} and {:?}, \
-                     could not fulfill: {:?} given {:?}",
-                    source_trait_ref, target_trait_ref, errors, param_env.caller_bounds
-                );
-                Err(())
-            }
-
-            Ok(()) => {
-                debug!(
-                    "fulfill_implication: an impl for {:?} specializes {:?}",
-                    source_trait_ref, target_trait_ref
-                );
-
-                // Now resolve the *substitution* we built for the target earlier, replacing
-                // the inference variables inside with whatever we got from fulfillment.
-                Ok(infcx.resolve_vars_if_possible(&target_substs))
-            }
-        }
-    })
-}
-
-// Query provider for `specialization_graph_of`.
-pub(super) fn specialization_graph_provider(
-    tcx: TyCtxt<'_>,
-    trait_id: DefId,
-) -> &specialization_graph::Graph {
-    let mut sg = specialization_graph::Graph::new();
-
-    let mut trait_impls = tcx.all_impls(trait_id);
-
-    // The coherence checking implementation seems to rely on impls being
-    // iterated over (roughly) in definition order, so we are sorting by
-    // negated `CrateNum` (so remote definitions are visited first) and then
-    // by a flattened version of the `DefIndex`.
-    trait_impls
-        .sort_unstable_by_key(|def_id| (-(def_id.krate.as_u32() as i64), def_id.index.index()));
-
-    for impl_def_id in trait_impls {
-        if impl_def_id.is_local() {
-            // This is where impl overlap checking happens:
-            let insert_result = sg.insert(tcx, impl_def_id);
-            // Report error if there was one.
-            let (overlap, used_to_be_allowed) = match insert_result {
-                Err(overlap) => (Some(overlap), None),
-                Ok(Some(overlap)) => (Some(overlap.error), Some(overlap.kind)),
-                Ok(None) => (None, None),
-            };
-
-            if let Some(overlap) = overlap {
-                let impl_span =
-                    tcx.sess.source_map().def_span(tcx.span_of_impl(impl_def_id).unwrap());
-
-                // Work to be done after we've built the DiagnosticBuilder. We have to define it
-                // now because the struct_lint methods don't return back the DiagnosticBuilder
-                // that's passed in.
-                let decorate = |err: LintDiagnosticBuilder<'_>| {
-                    let msg = format!(
-                        "conflicting implementations of trait `{}`{}:{}",
-                        overlap.trait_desc,
-                        overlap
-                            .self_desc
-                            .clone()
-                            .map_or(String::new(), |ty| { format!(" for type `{}`", ty) }),
-                        match used_to_be_allowed {
-                            Some(FutureCompatOverlapErrorKind::Issue33140) => " (E0119)",
-                            _ => "",
-                        }
-                    );
-                    let mut err = err.build(&msg);
-                    match tcx.span_of_impl(overlap.with_impl) {
-                        Ok(span) => {
-                            err.span_label(
-                                tcx.sess.source_map().def_span(span),
-                                "first implementation here".to_string(),
-                            );
-
-                            err.span_label(
-                                impl_span,
-                                format!(
-                                    "conflicting implementation{}",
-                                    overlap
-                                        .self_desc
-                                        .map_or(String::new(), |ty| format!(" for `{}`", ty))
-                                ),
-                            );
-                        }
-                        Err(cname) => {
-                            let msg = match to_pretty_impl_header(tcx, overlap.with_impl) {
-                                Some(s) => format!(
-                                    "conflicting implementation in crate `{}`:\n- {}",
-                                    cname, s
-                                ),
-                                None => format!("conflicting implementation in crate `{}`", cname),
-                            };
-                            err.note(&msg);
-                        }
-                    }
-
-                    for cause in &overlap.intercrate_ambiguity_causes {
-                        cause.add_intercrate_ambiguity_hint(&mut err);
-                    }
-
-                    if overlap.involves_placeholder {
-                        coherence::add_placeholder_note(&mut err);
-                    }
-                    err.emit()
-                };
-
-                match used_to_be_allowed {
-                    None => {
-                        let err = struct_span_err!(tcx.sess, impl_span, E0119, "");
-                        decorate(LintDiagnosticBuilder::new(err));
-                    }
-                    Some(kind) => {
-                        let lint = match kind {
-                            FutureCompatOverlapErrorKind::Issue33140 => {
-                                ORDER_DEPENDENT_TRAIT_OBJECTS
-                            }
-                            FutureCompatOverlapErrorKind::LeakCheck => COHERENCE_LEAK_CHECK,
-                        };
-                        tcx.struct_span_lint_hir(
-                            lint,
-                            tcx.hir().as_local_hir_id(impl_def_id).unwrap(),
-                            impl_span,
-                            decorate,
-                        )
-                    }
-                };
-            }
-        } else {
-            let parent = tcx.impl_parent(impl_def_id).unwrap_or(trait_id);
-            sg.record_impl_from_cstore(tcx, parent, impl_def_id)
-        }
-    }
-
-    tcx.arena.alloc(sg)
-}
-
-/// Recovers the "impl X for Y" signature from `impl_def_id` and returns it as a
-/// string.
-fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Option<String> {
-    use std::fmt::Write;
-
-    let trait_ref = if let Some(tr) = tcx.impl_trait_ref(impl_def_id) {
-        tr
-    } else {
-        return None;
-    };
-
-    let mut w = "impl".to_owned();
-
-    let substs = InternalSubsts::identity_for_item(tcx, impl_def_id);
-
-    // FIXME: Currently only handles ?Sized.
-    //        Needs to support ?Move and ?DynSized when they are implemented.
-    let mut types_without_default_bounds = FxHashSet::default();
-    let sized_trait = tcx.lang_items().sized_trait();
-
-    if !substs.is_noop() {
-        types_without_default_bounds.extend(substs.types());
-        w.push('<');
-        w.push_str(
-            &substs
-                .iter()
-                .map(|k| k.to_string())
-                .filter(|k| k != "'_")
-                .collect::<Vec<_>>()
-                .join(", "),
-        );
-        w.push('>');
-    }
-
-    write!(w, " {} for {}", trait_ref.print_only_trait_path(), tcx.type_of(impl_def_id)).unwrap();
-
-    // 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 mut pretty_predicates =
-        Vec::with_capacity(predicates.len() + types_without_default_bounds.len());
-
-    for (p, _) in predicates {
-        if let Some(poly_trait_ref) = p.to_opt_poly_trait_ref() {
-            if Some(poly_trait_ref.def_id()) == sized_trait {
-                types_without_default_bounds.remove(poly_trait_ref.self_ty());
-                continue;
-            }
-        }
-        pretty_predicates.push(p.to_string());
-    }
-
-    pretty_predicates
-        .extend(types_without_default_bounds.iter().map(|ty| format!("{}: ?Sized", ty)));
-
-    if !pretty_predicates.is_empty() {
-        write!(w, "\n  where {}", pretty_predicates.join(", ")).unwrap();
-    }
-
-    w.push(';');
-    Some(w)
-}
diff --git a/src/librustc_infer/traits/specialize/specialization_graph.rs b/src/librustc_infer/traits/specialize/specialization_graph.rs
deleted file mode 100644 (file)
index 17d4a22..0000000
+++ /dev/null
@@ -1,379 +0,0 @@
-use super::OverlapError;
-
-use crate::traits;
-use rustc::ty::fast_reject::{self, SimplifiedType};
-use rustc::ty::{self, TyCtxt, TypeFoldable};
-use rustc_hir::def_id::DefId;
-
-pub use rustc::traits::specialization_graph::*;
-
-#[derive(Copy, Clone, Debug)]
-pub enum FutureCompatOverlapErrorKind {
-    Issue33140,
-    LeakCheck,
-}
-
-#[derive(Debug)]
-pub struct FutureCompatOverlapError {
-    pub error: OverlapError,
-    pub kind: FutureCompatOverlapErrorKind,
-}
-
-/// The result of attempting to insert an impl into a group of children.
-enum Inserted {
-    /// The impl was inserted as a new child in this group of children.
-    BecameNewSibling(Option<FutureCompatOverlapError>),
-
-    /// The impl should replace existing impls [X1, ..], because the impl specializes X1, X2, etc.
-    ReplaceChildren(Vec<DefId>),
-
-    /// The impl is a specialization of an existing child.
-    ShouldRecurseOn(DefId),
-}
-
-trait ChildrenExt {
-    fn insert_blindly(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId);
-    fn remove_existing(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId);
-
-    fn insert(
-        &mut self,
-        tcx: TyCtxt<'tcx>,
-        impl_def_id: DefId,
-        simplified_self: Option<SimplifiedType>,
-    ) -> Result<Inserted, OverlapError>;
-}
-
-impl ChildrenExt for Children {
-    /// Insert an impl into this set of children without comparing to any existing impls.
-    fn insert_blindly(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) {
-        let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
-        if let Some(st) = fast_reject::simplify_type(tcx, trait_ref.self_ty(), false) {
-            debug!("insert_blindly: impl_def_id={:?} st={:?}", impl_def_id, st);
-            self.nonblanket_impls.entry(st).or_default().push(impl_def_id)
-        } else {
-            debug!("insert_blindly: impl_def_id={:?} st=None", impl_def_id);
-            self.blanket_impls.push(impl_def_id)
-        }
-    }
-
-    /// Removes an impl from this set of children. Used when replacing
-    /// an impl with a parent. The impl must be present in the list of
-    /// children already.
-    fn remove_existing(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) {
-        let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
-        let vec: &mut Vec<DefId>;
-        if let Some(st) = fast_reject::simplify_type(tcx, trait_ref.self_ty(), false) {
-            debug!("remove_existing: impl_def_id={:?} st={:?}", impl_def_id, st);
-            vec = self.nonblanket_impls.get_mut(&st).unwrap();
-        } else {
-            debug!("remove_existing: impl_def_id={:?} st=None", impl_def_id);
-            vec = &mut self.blanket_impls;
-        }
-
-        let index = vec.iter().position(|d| *d == impl_def_id).unwrap();
-        vec.remove(index);
-    }
-
-    /// Attempt to insert an impl into this set of children, while comparing for
-    /// specialization relationships.
-    fn insert(
-        &mut self,
-        tcx: TyCtxt<'tcx>,
-        impl_def_id: DefId,
-        simplified_self: Option<SimplifiedType>,
-    ) -> Result<Inserted, OverlapError> {
-        let mut last_lint = None;
-        let mut replace_children = Vec::new();
-
-        debug!("insert(impl_def_id={:?}, simplified_self={:?})", impl_def_id, simplified_self,);
-
-        let possible_siblings = match simplified_self {
-            Some(st) => PotentialSiblings::Filtered(filtered_children(self, st)),
-            None => PotentialSiblings::Unfiltered(iter_children(self)),
-        };
-
-        for possible_sibling in possible_siblings {
-            debug!(
-                "insert: impl_def_id={:?}, simplified_self={:?}, possible_sibling={:?}",
-                impl_def_id, simplified_self, possible_sibling,
-            );
-
-            let create_overlap_error = |overlap: traits::coherence::OverlapResult<'_>| {
-                let trait_ref = overlap.impl_header.trait_ref.unwrap();
-                let self_ty = trait_ref.self_ty();
-
-                OverlapError {
-                    with_impl: possible_sibling,
-                    trait_desc: trait_ref.print_only_trait_path().to_string(),
-                    // Only report the `Self` type if it has at least
-                    // some outer concrete shell; otherwise, it's
-                    // not adding much information.
-                    self_desc: if self_ty.has_concrete_skeleton() {
-                        Some(self_ty.to_string())
-                    } else {
-                        None
-                    },
-                    intercrate_ambiguity_causes: overlap.intercrate_ambiguity_causes,
-                    involves_placeholder: overlap.involves_placeholder,
-                }
-            };
-
-            let report_overlap_error = |overlap: traits::coherence::OverlapResult<'_>,
-                                        last_lint: &mut _| {
-                // Found overlap, but no specialization; error out or report future-compat warning.
-
-                // Do we *still* get overlap if we disable the future-incompatible modes?
-                let should_err = traits::overlapping_impls(
-                    tcx,
-                    possible_sibling,
-                    impl_def_id,
-                    traits::SkipLeakCheck::default(),
-                    |_| true,
-                    || false,
-                );
-
-                let error = create_overlap_error(overlap);
-
-                if should_err {
-                    Err(error)
-                } else {
-                    *last_lint = Some(FutureCompatOverlapError {
-                        error,
-                        kind: FutureCompatOverlapErrorKind::LeakCheck,
-                    });
-
-                    Ok((false, false))
-                }
-            };
-
-            let last_lint_mut = &mut last_lint;
-            let (le, ge) = traits::overlapping_impls(
-                tcx,
-                possible_sibling,
-                impl_def_id,
-                traits::SkipLeakCheck::Yes,
-                |overlap| {
-                    if let Some(overlap_kind) =
-                        tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling)
-                    {
-                        match overlap_kind {
-                            ty::ImplOverlapKind::Permitted { marker: _ } => {}
-                            ty::ImplOverlapKind::Issue33140 => {
-                                *last_lint_mut = Some(FutureCompatOverlapError {
-                                    error: create_overlap_error(overlap),
-                                    kind: FutureCompatOverlapErrorKind::Issue33140,
-                                });
-                            }
-                        }
-
-                        return Ok((false, false));
-                    }
-
-                    let le = tcx.specializes((impl_def_id, possible_sibling));
-                    let ge = tcx.specializes((possible_sibling, impl_def_id));
-
-                    if le == ge {
-                        report_overlap_error(overlap, last_lint_mut)
-                    } else {
-                        Ok((le, ge))
-                    }
-                },
-                || Ok((false, false)),
-            )?;
-
-            if le && !ge {
-                debug!(
-                    "descending as child of TraitRef {:?}",
-                    tcx.impl_trait_ref(possible_sibling).unwrap()
-                );
-
-                // The impl specializes `possible_sibling`.
-                return Ok(Inserted::ShouldRecurseOn(possible_sibling));
-            } else if ge && !le {
-                debug!(
-                    "placing as parent of TraitRef {:?}",
-                    tcx.impl_trait_ref(possible_sibling).unwrap()
-                );
-
-                replace_children.push(possible_sibling);
-            } else {
-                // Either there's no overlap, or the overlap was already reported by
-                // `overlap_error`.
-            }
-        }
-
-        if !replace_children.is_empty() {
-            return Ok(Inserted::ReplaceChildren(replace_children));
-        }
-
-        // No overlap with any potential siblings, so add as a new sibling.
-        debug!("placing as new sibling");
-        self.insert_blindly(tcx, impl_def_id);
-        Ok(Inserted::BecameNewSibling(last_lint))
-    }
-}
-
-fn iter_children(children: &mut Children) -> impl Iterator<Item = DefId> + '_ {
-    let nonblanket = children.nonblanket_impls.iter_mut().flat_map(|(_, v)| v.iter());
-    children.blanket_impls.iter().chain(nonblanket).cloned()
-}
-
-fn filtered_children(
-    children: &mut Children,
-    st: SimplifiedType,
-) -> impl Iterator<Item = DefId> + '_ {
-    let nonblanket = children.nonblanket_impls.entry(st).or_default().iter();
-    children.blanket_impls.iter().chain(nonblanket).cloned()
-}
-
-// A custom iterator used by Children::insert
-enum PotentialSiblings<I, J>
-where
-    I: Iterator<Item = DefId>,
-    J: Iterator<Item = DefId>,
-{
-    Unfiltered(I),
-    Filtered(J),
-}
-
-impl<I, J> Iterator for PotentialSiblings<I, J>
-where
-    I: Iterator<Item = DefId>,
-    J: Iterator<Item = DefId>,
-{
-    type Item = DefId;
-
-    fn next(&mut self) -> Option<Self::Item> {
-        match *self {
-            PotentialSiblings::Unfiltered(ref mut iter) => iter.next(),
-            PotentialSiblings::Filtered(ref mut iter) => iter.next(),
-        }
-    }
-}
-
-pub trait GraphExt {
-    /// Insert a local impl into the specialization graph. If an existing impl
-    /// conflicts with it (has overlap, but neither specializes the other),
-    /// information about the area of overlap is returned in the `Err`.
-    fn insert(
-        &mut self,
-        tcx: TyCtxt<'tcx>,
-        impl_def_id: DefId,
-    ) -> Result<Option<FutureCompatOverlapError>, OverlapError>;
-
-    /// Insert cached metadata mapping from a child impl back to its parent.
-    fn record_impl_from_cstore(&mut self, tcx: TyCtxt<'tcx>, parent: DefId, child: DefId);
-}
-
-impl GraphExt for Graph {
-    /// Insert a local impl into the specialization graph. If an existing impl
-    /// conflicts with it (has overlap, but neither specializes the other),
-    /// information about the area of overlap is returned in the `Err`.
-    fn insert(
-        &mut self,
-        tcx: TyCtxt<'tcx>,
-        impl_def_id: DefId,
-    ) -> Result<Option<FutureCompatOverlapError>, OverlapError> {
-        assert!(impl_def_id.is_local());
-
-        let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
-        let trait_def_id = trait_ref.def_id;
-
-        debug!(
-            "insert({:?}): inserting TraitRef {:?} into specialization graph",
-            impl_def_id, trait_ref
-        );
-
-        // If the reference itself contains an earlier error (e.g., due to a
-        // resolution failure), then we just insert the impl at the top level of
-        // the graph and claim that there's no overlap (in order to suppress
-        // bogus errors).
-        if trait_ref.references_error() {
-            debug!(
-                "insert: inserting dummy node for erroneous TraitRef {:?}, \
-                 impl_def_id={:?}, trait_def_id={:?}",
-                trait_ref, impl_def_id, trait_def_id
-            );
-
-            self.parent.insert(impl_def_id, trait_def_id);
-            self.children.entry(trait_def_id).or_default().insert_blindly(tcx, impl_def_id);
-            return Ok(None);
-        }
-
-        let mut parent = trait_def_id;
-        let mut last_lint = None;
-        let simplified = fast_reject::simplify_type(tcx, trait_ref.self_ty(), false);
-
-        // Descend the specialization tree, where `parent` is the current parent node.
-        loop {
-            use self::Inserted::*;
-
-            let insert_result =
-                self.children.entry(parent).or_default().insert(tcx, impl_def_id, simplified)?;
-
-            match insert_result {
-                BecameNewSibling(opt_lint) => {
-                    last_lint = opt_lint;
-                    break;
-                }
-                ReplaceChildren(grand_children_to_be) => {
-                    // We currently have
-                    //
-                    //     P
-                    //     |
-                    //     G
-                    //
-                    // and we are inserting the impl N. We want to make it:
-                    //
-                    //     P
-                    //     |
-                    //     N
-                    //     |
-                    //     G
-
-                    // Adjust P's list of children: remove G and then add N.
-                    {
-                        let siblings = self.children.get_mut(&parent).unwrap();
-                        for &grand_child_to_be in &grand_children_to_be {
-                            siblings.remove_existing(tcx, grand_child_to_be);
-                        }
-                        siblings.insert_blindly(tcx, impl_def_id);
-                    }
-
-                    // Set G's parent to N and N's parent to P.
-                    for &grand_child_to_be in &grand_children_to_be {
-                        self.parent.insert(grand_child_to_be, impl_def_id);
-                    }
-                    self.parent.insert(impl_def_id, parent);
-
-                    // Add G as N's child.
-                    for &grand_child_to_be in &grand_children_to_be {
-                        self.children
-                            .entry(impl_def_id)
-                            .or_default()
-                            .insert_blindly(tcx, grand_child_to_be);
-                    }
-                    break;
-                }
-                ShouldRecurseOn(new_parent) => {
-                    parent = new_parent;
-                }
-            }
-        }
-
-        self.parent.insert(impl_def_id, parent);
-        Ok(last_lint)
-    }
-
-    /// Insert cached metadata mapping from a child impl back to its parent.
-    fn record_impl_from_cstore(&mut self, tcx: TyCtxt<'tcx>, parent: DefId, child: DefId) {
-        if self.parent.insert(child, parent).is_some() {
-            bug!(
-                "When recording an impl from the crate store, information about its parent \
-                 was already present."
-            );
-        }
-
-        self.children.entry(parent).or_default().insert_blindly(tcx, child);
-    }
-}
diff --git a/src/librustc_infer/traits/structural_match.rs b/src/librustc_infer/traits/structural_match.rs
deleted file mode 100644 (file)
index 60682f5..0000000
+++ /dev/null
@@ -1,216 +0,0 @@
-use crate::infer::{InferCtxt, TyCtxtInferExt};
-use crate::traits::ObligationCause;
-use crate::traits::{self, ConstPatternStructural, TraitEngine};
-
-use rustc::ty::{self, AdtDef, Ty, TyCtxt, TypeFoldable, TypeVisitor};
-use rustc_data_structures::fx::FxHashSet;
-use rustc_hir as hir;
-use rustc_span::Span;
-
-#[derive(Debug)]
-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<T>`.
-///
-/// 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>(
-    id: hir::HirId,
-    span: Span,
-    tcx: TyCtxt<'tcx>,
-    ty: Ty<'tcx>,
-) -> Option<NonStructuralMatchTy<'tcx>> {
-    // FIXME: we should instead pass in an `infcx` from the outside.
-    tcx.infer_ctxt().enter(|infcx| {
-        let mut search = Search { id, span, infcx, found: None, seen: FxHashSet::default() };
-        ty.visit_with(&mut search);
-        search.found
-    })
-}
-
-/// This method returns true if and only if `adt_ty` itself has been marked as
-/// eligible for structural-match: namely, if it implements both
-/// `StructuralPartialEq` and `StructuralEq` (which are respectively injected by
-/// `#[derive(PartialEq)]` and `#[derive(Eq)]`).
-///
-/// Note that this does *not* recursively check if the substructure of `adt_ty`
-/// implements the traits.
-pub fn type_marked_structural(
-    id: hir::HirId,
-    span: Span,
-    infcx: &InferCtxt<'_, 'tcx>,
-    adt_ty: Ty<'tcx>,
-) -> bool {
-    let mut fulfillment_cx = traits::FulfillmentContext::new();
-    let cause = ObligationCause::new(span, id, ConstPatternStructural);
-    // require `#[derive(PartialEq)]`
-    let structural_peq_def_id = infcx.tcx.lang_items().structural_peq_trait().unwrap();
-    fulfillment_cx.register_bound(
-        infcx,
-        ty::ParamEnv::empty(),
-        adt_ty,
-        structural_peq_def_id,
-        cause,
-    );
-    // for now, require `#[derive(Eq)]`. (Doing so is a hack to work around
-    // the type `for<'a> fn(&'a ())` failing to implement `Eq` itself.)
-    let cause = ObligationCause::new(span, id, ConstPatternStructural);
-    let structural_teq_def_id = infcx.tcx.lang_items().structural_teq_trait().unwrap();
-    fulfillment_cx.register_bound(
-        infcx,
-        ty::ParamEnv::empty(),
-        adt_ty,
-        structural_teq_def_id,
-        cause,
-    );
-
-    // We deliberately skip *reporting* fulfillment errors (via
-    // `report_fulfillment_errors`), for two reasons:
-    //
-    // 1. The error messages would mention `std::marker::StructuralPartialEq`
-    //    (a trait which is solely meant as an implementation detail
-    //    for now), and
-    //
-    // 2. We are sometimes doing future-incompatibility lints for
-    //    now, so we do not want unconditional errors here.
-    fulfillment_cx.select_all_or_error(infcx).is_ok()
-}
-
-/// This implements the traversal over the structure of a given type to try to
-/// find instances of ADTs (specifically structs or enums) that do not implement
-/// the structural-match traits (`StructuralPartialEq` and `StructuralEq`).
-struct Search<'a, 'tcx> {
-    id: hir::HirId,
-    span: Span,
-
-    infcx: InferCtxt<'a, 'tcx>,
-
-    /// Records first ADT that does not implement a structural-match trait.
-    found: Option<NonStructuralMatchTy<'tcx>>,
-
-    /// Tracks ADTs previously encountered during search, so that
-    /// we will not recur on them again.
-    seen: FxHashSet<hir::def_id::DefId>,
-}
-
-impl Search<'a, 'tcx> {
-    fn tcx(&self) -> TyCtxt<'tcx> {
-        self.infcx.tcx
-    }
-
-    fn type_marked_structural(&self, adt_ty: Ty<'tcx>) -> bool {
-        type_marked_structural(self.id, self.span, &self.infcx, adt_ty)
-    }
-}
-
-impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, '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`.
-                //
-                // For example, if you have:
-                // ```
-                // struct NonStructural;
-                // #[derive(PartialEq, Eq)]
-                // struct T(*const NonStructural);
-                // const C: T = T(std::ptr::null());
-                // ```
-                //
-                // Even though `NonStructural` does not implement `PartialEq`,
-                // structural equality on `T` does not recur into the raw
-                // pointer. Therefore, one can still use `C` in a pattern.
-
-                // (But still tell caller to continue search.)
-                return false;
-            }
-            ty::FnDef(..) | ty::FnPtr(..) => {
-                // types of formals and return in `fn(_) -> _` are also irrelevant;
-                // so we do not recur into them via `super_visit_with`
-                //
-                // (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.seen.insert(adt_def.did) {
-            debug!("Search already seen adt_def: {:?}", adt_def);
-            // let caller continue its search
-            return false;
-        }
-
-        if !self.type_marked_structural(ty) {
-            debug!("Search found ty: {:?}", ty);
-            self.found = Some(NonStructuralMatchTy::Adt(&adt_def));
-            return true; // Halt visiting!
-        }
-
-        // 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<T>` 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
-    }
-}
index 1dca01b3468ae2fc4028c598f81cbbd96f4db661..a7c0267111522eee1f7cee40e439c24cce5833c4 100644 (file)
@@ -1,16 +1,8 @@
-use rustc_errors::DiagnosticBuilder;
-use rustc_span::Span;
 use smallvec::smallvec;
-use smallvec::SmallVec;
 
 use rustc::ty::outlives::Component;
-use rustc::ty::subst::{GenericArg, Subst, SubstsRef};
-use rustc::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, WithConstness};
+use rustc::ty::{self, ToPolyTraitRef, TyCtxt};
 use rustc_data_structures::fx::FxHashSet;
-use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
-
-use super::{Normalized, Obligation, ObligationCause, PredicateObligation, SelectionContext};
 
 fn anonymize_predicate<'tcx>(tcx: TyCtxt<'tcx>, pred: &ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
     match *pred {
@@ -96,21 +88,6 @@ pub struct Elaborator<'tcx> {
     visited: PredicateSet<'tcx>,
 }
 
-pub fn elaborate_trait_ref<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    trait_ref: ty::PolyTraitRef<'tcx>,
-) -> Elaborator<'tcx> {
-    elaborate_predicates(tcx, vec![trait_ref.without_const().to_predicate()])
-}
-
-pub fn elaborate_trait_refs<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    trait_refs: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
-) -> Elaborator<'tcx> {
-    let predicates = trait_refs.map(|trait_ref| trait_ref.without_const().to_predicate()).collect();
-    elaborate_predicates(tcx, predicates)
-}
-
 pub fn elaborate_predicates<'tcx>(
     tcx: TyCtxt<'tcx>,
     mut predicates: Vec<ty::Predicate<'tcx>>,
@@ -121,10 +98,6 @@ pub fn elaborate_predicates<'tcx>(
 }
 
 impl Elaborator<'tcx> {
-    pub fn filter_to_traits(self) -> FilterToTraits<Self> {
-        FilterToTraits::new(self)
-    }
-
     fn elaborate(&mut self, predicate: &ty::Predicate<'tcx>) {
         let tcx = self.visited.tcx;
         match *predicate {
@@ -250,426 +223,3 @@ fn next(&mut self) -> Option<ty::Predicate<'tcx>> {
         }
     }
 }
-
-///////////////////////////////////////////////////////////////////////////
-// Supertrait iterator
-///////////////////////////////////////////////////////////////////////////
-
-pub type Supertraits<'tcx> = FilterToTraits<Elaborator<'tcx>>;
-
-pub fn supertraits<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    trait_ref: ty::PolyTraitRef<'tcx>,
-) -> Supertraits<'tcx> {
-    elaborate_trait_ref(tcx, trait_ref).filter_to_traits()
-}
-
-pub fn transitive_bounds<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    bounds: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
-) -> Supertraits<'tcx> {
-    elaborate_trait_refs(tcx, bounds).filter_to_traits()
-}
-
-///////////////////////////////////////////////////////////////////////////
-// `TraitAliasExpander` iterator
-///////////////////////////////////////////////////////////////////////////
-
-/// "Trait alias expansion" is the process of expanding a sequence of trait
-/// references into another sequence by transitively following all trait
-/// aliases. e.g. If you have bounds like `Foo + Send`, a trait alias
-/// `trait Foo = Bar + Sync;`, and another trait alias
-/// `trait Bar = Read + Write`, then the bounds would expand to
-/// `Read + Write + Sync + Send`.
-/// Expansion is done via a DFS (depth-first search), and the `visited` field
-/// is used to avoid cycles.
-pub struct TraitAliasExpander<'tcx> {
-    tcx: TyCtxt<'tcx>,
-    stack: Vec<TraitAliasExpansionInfo<'tcx>>,
-}
-
-/// Stores information about the expansion of a trait via a path of zero or more trait aliases.
-#[derive(Debug, Clone)]
-pub struct TraitAliasExpansionInfo<'tcx> {
-    pub path: SmallVec<[(ty::PolyTraitRef<'tcx>, Span); 4]>,
-}
-
-impl<'tcx> TraitAliasExpansionInfo<'tcx> {
-    fn new(trait_ref: ty::PolyTraitRef<'tcx>, span: Span) -> Self {
-        Self { path: smallvec![(trait_ref, span)] }
-    }
-
-    /// Adds diagnostic labels to `diag` for the expansion path of a trait through all intermediate
-    /// trait aliases.
-    pub fn label_with_exp_info(
-        &self,
-        diag: &mut DiagnosticBuilder<'_>,
-        top_label: &str,
-        use_desc: &str,
-    ) {
-        diag.span_label(self.top().1, top_label);
-        if self.path.len() > 1 {
-            for (_, sp) in self.path.iter().rev().skip(1).take(self.path.len() - 2) {
-                diag.span_label(*sp, format!("referenced here ({})", use_desc));
-            }
-        }
-        diag.span_label(
-            self.bottom().1,
-            format!("trait alias used in trait object type ({})", use_desc),
-        );
-    }
-
-    pub fn trait_ref(&self) -> &ty::PolyTraitRef<'tcx> {
-        &self.top().0
-    }
-
-    pub fn top(&self) -> &(ty::PolyTraitRef<'tcx>, Span) {
-        self.path.last().unwrap()
-    }
-
-    pub fn bottom(&self) -> &(ty::PolyTraitRef<'tcx>, Span) {
-        self.path.first().unwrap()
-    }
-
-    fn clone_and_push(&self, trait_ref: ty::PolyTraitRef<'tcx>, span: Span) -> Self {
-        let mut path = self.path.clone();
-        path.push((trait_ref, span));
-
-        Self { path }
-    }
-}
-
-pub fn expand_trait_aliases<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    trait_refs: impl IntoIterator<Item = (ty::PolyTraitRef<'tcx>, Span)>,
-) -> TraitAliasExpander<'tcx> {
-    let items: Vec<_> = trait_refs
-        .into_iter()
-        .map(|(trait_ref, span)| TraitAliasExpansionInfo::new(trait_ref, span))
-        .collect();
-    TraitAliasExpander { tcx, stack: items }
-}
-
-impl<'tcx> TraitAliasExpander<'tcx> {
-    /// If `item` is a trait alias and its predicate has not yet been visited, then expands `item`
-    /// to the definition, pushes the resulting expansion onto `self.stack`, and returns `false`.
-    /// Otherwise, immediately returns `true` if `item` is a regular trait, or `false` if it is a
-    /// trait alias.
-    /// The return value indicates whether `item` should be yielded to the user.
-    fn expand(&mut self, item: &TraitAliasExpansionInfo<'tcx>) -> bool {
-        let tcx = self.tcx;
-        let trait_ref = item.trait_ref();
-        let pred = trait_ref.without_const().to_predicate();
-
-        debug!("expand_trait_aliases: trait_ref={:?}", trait_ref);
-
-        // Don't recurse if this bound is not a trait alias.
-        let is_alias = tcx.is_trait_alias(trait_ref.def_id());
-        if !is_alias {
-            return true;
-        }
-
-        // Don't recurse if this trait alias is already on the stack for the DFS search.
-        let anon_pred = anonymize_predicate(tcx, &pred);
-        if item.path.iter().rev().skip(1).any(|(tr, _)| {
-            anonymize_predicate(tcx, &tr.without_const().to_predicate()) == anon_pred
-        }) {
-            return false;
-        }
-
-        // Get components of trait alias.
-        let predicates = tcx.super_predicates_of(trait_ref.def_id());
-
-        let items = predicates.predicates.iter().rev().filter_map(|(pred, span)| {
-            pred.subst_supertrait(tcx, &trait_ref)
-                .to_opt_poly_trait_ref()
-                .map(|trait_ref| item.clone_and_push(trait_ref, *span))
-        });
-        debug!("expand_trait_aliases: items={:?}", items.clone());
-
-        self.stack.extend(items);
-
-        false
-    }
-}
-
-impl<'tcx> Iterator for TraitAliasExpander<'tcx> {
-    type Item = TraitAliasExpansionInfo<'tcx>;
-
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        (self.stack.len(), None)
-    }
-
-    fn next(&mut self) -> Option<TraitAliasExpansionInfo<'tcx>> {
-        while let Some(item) = self.stack.pop() {
-            if self.expand(&item) {
-                return Some(item);
-            }
-        }
-        None
-    }
-}
-
-///////////////////////////////////////////////////////////////////////////
-// Iterator over def-IDs of supertraits
-///////////////////////////////////////////////////////////////////////////
-
-pub struct SupertraitDefIds<'tcx> {
-    tcx: TyCtxt<'tcx>,
-    stack: Vec<DefId>,
-    visited: FxHashSet<DefId>,
-}
-
-pub fn supertrait_def_ids(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SupertraitDefIds<'_> {
-    SupertraitDefIds {
-        tcx,
-        stack: vec![trait_def_id],
-        visited: Some(trait_def_id).into_iter().collect(),
-    }
-}
-
-impl Iterator for SupertraitDefIds<'tcx> {
-    type Item = DefId;
-
-    fn next(&mut self) -> Option<DefId> {
-        let def_id = self.stack.pop()?;
-        let predicates = self.tcx.super_predicates_of(def_id);
-        let visited = &mut self.visited;
-        self.stack.extend(
-            predicates
-                .predicates
-                .iter()
-                .filter_map(|(pred, _)| pred.to_opt_poly_trait_ref())
-                .map(|trait_ref| trait_ref.def_id())
-                .filter(|&super_def_id| visited.insert(super_def_id)),
-        );
-        Some(def_id)
-    }
-}
-
-///////////////////////////////////////////////////////////////////////////
-// Other
-///////////////////////////////////////////////////////////////////////////
-
-/// A filter around an iterator of predicates that makes it yield up
-/// just trait references.
-pub struct FilterToTraits<I> {
-    base_iterator: I,
-}
-
-impl<I> FilterToTraits<I> {
-    fn new(base: I) -> FilterToTraits<I> {
-        FilterToTraits { base_iterator: base }
-    }
-}
-
-impl<'tcx, I: Iterator<Item = ty::Predicate<'tcx>>> Iterator for FilterToTraits<I> {
-    type Item = ty::PolyTraitRef<'tcx>;
-
-    fn next(&mut self) -> Option<ty::PolyTraitRef<'tcx>> {
-        while let Some(pred) = self.base_iterator.next() {
-            if let ty::Predicate::Trait(data, _) = pred {
-                return Some(data.to_poly_trait_ref());
-            }
-        }
-        None
-    }
-
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        let (_, upper) = self.base_iterator.size_hint();
-        (0, upper)
-    }
-}
-
-///////////////////////////////////////////////////////////////////////////
-// Other
-///////////////////////////////////////////////////////////////////////////
-
-/// Instantiate all bound parameters of the impl with the given substs,
-/// returning the resulting trait ref and all obligations that arise.
-/// The obligations are closed under normalization.
-pub fn impl_trait_ref_and_oblig<'a, 'tcx>(
-    selcx: &mut SelectionContext<'a, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    impl_def_id: DefId,
-    impl_substs: SubstsRef<'tcx>,
-) -> (ty::TraitRef<'tcx>, Vec<PredicateObligation<'tcx>>) {
-    let impl_trait_ref = selcx.tcx().impl_trait_ref(impl_def_id).unwrap();
-    let impl_trait_ref = impl_trait_ref.subst(selcx.tcx(), impl_substs);
-    let Normalized { value: impl_trait_ref, obligations: normalization_obligations1 } =
-        super::normalize(selcx, param_env, ObligationCause::dummy(), &impl_trait_ref);
-
-    let predicates = selcx.tcx().predicates_of(impl_def_id);
-    let predicates = predicates.instantiate(selcx.tcx(), impl_substs);
-    let Normalized { value: predicates, obligations: normalization_obligations2 } =
-        super::normalize(selcx, param_env, ObligationCause::dummy(), &predicates);
-    let impl_obligations =
-        predicates_for_generics(ObligationCause::dummy(), 0, param_env, &predicates);
-
-    let impl_obligations: Vec<_> = impl_obligations
-        .into_iter()
-        .chain(normalization_obligations1)
-        .chain(normalization_obligations2)
-        .collect();
-
-    (impl_trait_ref, impl_obligations)
-}
-
-/// See [`super::obligations_for_generics`].
-pub fn predicates_for_generics<'tcx>(
-    cause: ObligationCause<'tcx>,
-    recursion_depth: usize,
-    param_env: ty::ParamEnv<'tcx>,
-    generic_bounds: &ty::InstantiatedPredicates<'tcx>,
-) -> Vec<PredicateObligation<'tcx>> {
-    debug!("predicates_for_generics(generic_bounds={:?})", generic_bounds);
-
-    generic_bounds
-        .predicates
-        .iter()
-        .map(|&predicate| Obligation {
-            cause: cause.clone(),
-            recursion_depth,
-            param_env,
-            predicate,
-        })
-        .collect()
-}
-
-pub fn predicate_for_trait_ref<'tcx>(
-    cause: ObligationCause<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    trait_ref: ty::TraitRef<'tcx>,
-    recursion_depth: usize,
-) -> PredicateObligation<'tcx> {
-    Obligation {
-        cause,
-        param_env,
-        recursion_depth,
-        predicate: trait_ref.without_const().to_predicate(),
-    }
-}
-
-pub fn predicate_for_trait_def(
-    tcx: TyCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    cause: ObligationCause<'tcx>,
-    trait_def_id: DefId,
-    recursion_depth: usize,
-    self_ty: Ty<'tcx>,
-    params: &[GenericArg<'tcx>],
-) -> PredicateObligation<'tcx> {
-    let trait_ref =
-        ty::TraitRef { def_id: trait_def_id, substs: tcx.mk_substs_trait(self_ty, params) };
-    predicate_for_trait_ref(cause, param_env, trait_ref, recursion_depth)
-}
-
-/// Casts a trait reference into a reference to one of its super
-/// traits; returns `None` if `target_trait_def_id` is not a
-/// supertrait.
-pub fn upcast_choices(
-    tcx: TyCtxt<'tcx>,
-    source_trait_ref: ty::PolyTraitRef<'tcx>,
-    target_trait_def_id: DefId,
-) -> Vec<ty::PolyTraitRef<'tcx>> {
-    if source_trait_ref.def_id() == target_trait_def_id {
-        return vec![source_trait_ref]; // Shortcut the most common case.
-    }
-
-    supertraits(tcx, source_trait_ref).filter(|r| r.def_id() == target_trait_def_id).collect()
-}
-
-/// Given a trait `trait_ref`, returns the number of vtable entries
-/// that come from `trait_ref`, excluding its supertraits. Used in
-/// computing the vtable base for an upcast trait of a trait object.
-pub fn count_own_vtable_entries(tcx: TyCtxt<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>) -> usize {
-    let mut entries = 0;
-    // Count number of methods and add them to the total offset.
-    // Skip over associated types and constants.
-    for trait_item in tcx.associated_items(trait_ref.def_id()).in_definition_order() {
-        if trait_item.kind == ty::AssocKind::Method {
-            entries += 1;
-        }
-    }
-    entries
-}
-
-/// Given an upcast trait object described by `object`, returns the
-/// index of the method `method_def_id` (which should be part of
-/// `object.upcast_trait_ref`) within the vtable for `object`.
-pub fn get_vtable_index_of_object_method<N>(
-    tcx: TyCtxt<'tcx>,
-    object: &super::VtableObjectData<'tcx, N>,
-    method_def_id: DefId,
-) -> usize {
-    // Count number of methods preceding the one we are selecting and
-    // add them to the total offset.
-    // Skip over associated types and constants.
-    let mut entries = object.vtable_base;
-    for trait_item in tcx.associated_items(object.upcast_trait_ref.def_id()).in_definition_order() {
-        if trait_item.def_id == method_def_id {
-            // The item with the ID we were given really ought to be a method.
-            assert_eq!(trait_item.kind, ty::AssocKind::Method);
-            return entries;
-        }
-        if trait_item.kind == ty::AssocKind::Method {
-            entries += 1;
-        }
-    }
-
-    bug!("get_vtable_index_of_object_method: {:?} was not found", method_def_id);
-}
-
-pub fn closure_trait_ref_and_return_type(
-    tcx: TyCtxt<'tcx>,
-    fn_trait_def_id: DefId,
-    self_ty: Ty<'tcx>,
-    sig: ty::PolyFnSig<'tcx>,
-    tuple_arguments: TupleArgumentsFlag,
-) -> ty::Binder<(ty::TraitRef<'tcx>, Ty<'tcx>)> {
-    let arguments_tuple = match tuple_arguments {
-        TupleArgumentsFlag::No => sig.skip_binder().inputs()[0],
-        TupleArgumentsFlag::Yes => tcx.intern_tup(sig.skip_binder().inputs()),
-    };
-    let trait_ref = ty::TraitRef {
-        def_id: fn_trait_def_id,
-        substs: tcx.mk_substs_trait(self_ty, &[arguments_tuple.into()]),
-    };
-    ty::Binder::bind((trait_ref, sig.skip_binder().output()))
-}
-
-pub fn generator_trait_ref_and_outputs(
-    tcx: TyCtxt<'tcx>,
-    fn_trait_def_id: DefId,
-    self_ty: Ty<'tcx>,
-    sig: ty::PolyGenSig<'tcx>,
-) -> ty::Binder<(ty::TraitRef<'tcx>, Ty<'tcx>, Ty<'tcx>)> {
-    let trait_ref = ty::TraitRef {
-        def_id: fn_trait_def_id,
-        substs: tcx.mk_substs_trait(self_ty, &[sig.skip_binder().resume_ty.into()]),
-    };
-    ty::Binder::bind((trait_ref, sig.skip_binder().yield_ty, sig.skip_binder().return_ty))
-}
-
-pub fn impl_is_default(tcx: TyCtxt<'_>, node_item_def_id: DefId) -> bool {
-    match tcx.hir().as_local_hir_id(node_item_def_id) {
-        Some(hir_id) => {
-            let item = tcx.hir().expect_item(hir_id);
-            if let hir::ItemKind::Impl { defaultness, .. } = item.kind {
-                defaultness.is_default()
-            } else {
-                false
-            }
-        }
-        None => tcx.impl_defaultness(node_item_def_id).is_default(),
-    }
-}
-
-pub fn impl_item_is_final(tcx: TyCtxt<'_>, assoc_item: &ty::AssocItem) -> bool {
-    assoc_item.defaultness.is_final() && !impl_is_default(tcx, assoc_item.container.id())
-}
-
-pub enum TupleArgumentsFlag {
-    Yes,
-    No,
-}
diff --git a/src/librustc_infer/traits/wf.rs b/src/librustc_infer/traits/wf.rs
deleted file mode 100644 (file)
index 980a3f0..0000000
+++ /dev/null
@@ -1,753 +0,0 @@
-use crate::infer::opaque_types::required_region_bounds;
-use crate::infer::InferCtxt;
-use crate::traits::{self, AssocTypeBoundData};
-use rustc::middle::lang_items;
-use rustc::ty::subst::SubstsRef;
-use rustc::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
-use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
-use rustc_span::symbol::{kw, Ident};
-use rustc_span::Span;
-
-/// Returns the set of obligations needed to make `ty` well-formed.
-/// If `ty` contains unresolved inference variables, this may include
-/// further WF obligations. However, if `ty` IS an unresolved
-/// inference variable, returns `None`, because we are not able to
-/// make any progress at all. This is to prevent "livelock" where we
-/// say "$0 is WF if $0 is WF".
-pub fn obligations<'a, 'tcx>(
-    infcx: &InferCtxt<'a, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    body_id: hir::HirId,
-    ty: Ty<'tcx>,
-    span: Span,
-) -> Option<Vec<traits::PredicateObligation<'tcx>>> {
-    let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![], item: None };
-    if wf.compute(ty) {
-        debug!("wf::obligations({:?}, body_id={:?}) = {:?}", ty, body_id, wf.out);
-
-        let result = wf.normalize();
-        debug!("wf::obligations({:?}, body_id={:?}) ~~> {:?}", ty, body_id, result);
-        Some(result)
-    } else {
-        None // no progress made, return None
-    }
-}
-
-/// Returns the obligations that make this trait reference
-/// well-formed.  For example, if there is a trait `Set` defined like
-/// `trait Set<K:Eq>`, then the trait reference `Foo: Set<Bar>` is WF
-/// if `Bar: Eq`.
-pub fn trait_obligations<'a, 'tcx>(
-    infcx: &InferCtxt<'a, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    body_id: hir::HirId,
-    trait_ref: &ty::TraitRef<'tcx>,
-    span: Span,
-    item: Option<&'tcx hir::Item<'tcx>>,
-) -> Vec<traits::PredicateObligation<'tcx>> {
-    let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![], item };
-    wf.compute_trait_ref(trait_ref, Elaborate::All);
-    wf.normalize()
-}
-
-pub fn predicate_obligations<'a, 'tcx>(
-    infcx: &InferCtxt<'a, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    body_id: hir::HirId,
-    predicate: &ty::Predicate<'tcx>,
-    span: Span,
-) -> Vec<traits::PredicateObligation<'tcx>> {
-    let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![], item: None };
-
-    // (*) ok to skip binders, because wf code is prepared for it
-    match *predicate {
-        ty::Predicate::Trait(ref t, _) => {
-            wf.compute_trait_ref(&t.skip_binder().trait_ref, Elaborate::None); // (*)
-        }
-        ty::Predicate::RegionOutlives(..) => {}
-        ty::Predicate::TypeOutlives(ref t) => {
-            wf.compute(t.skip_binder().0);
-        }
-        ty::Predicate::Projection(ref t) => {
-            let t = t.skip_binder(); // (*)
-            wf.compute_projection(t.projection_ty);
-            wf.compute(t.ty);
-        }
-        ty::Predicate::WellFormed(t) => {
-            wf.compute(t);
-        }
-        ty::Predicate::ObjectSafe(_) => {}
-        ty::Predicate::ClosureKind(..) => {}
-        ty::Predicate::Subtype(ref data) => {
-            wf.compute(data.skip_binder().a); // (*)
-            wf.compute(data.skip_binder().b); // (*)
-        }
-        ty::Predicate::ConstEvaluatable(def_id, substs) => {
-            let obligations = wf.nominal_obligations(def_id, substs);
-            wf.out.extend(obligations);
-
-            for ty in substs.types() {
-                wf.compute(ty);
-            }
-        }
-    }
-
-    wf.normalize()
-}
-
-struct WfPredicates<'a, 'tcx> {
-    infcx: &'a InferCtxt<'a, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    body_id: hir::HirId,
-    span: Span,
-    out: Vec<traits::PredicateObligation<'tcx>>,
-    item: Option<&'tcx hir::Item<'tcx>>,
-}
-
-/// Controls whether we "elaborate" supertraits and so forth on the WF
-/// predicates. This is a kind of hack to address #43784. The
-/// underlying problem in that issue was a trait structure like:
-///
-/// ```
-/// trait Foo: Copy { }
-/// trait Bar: Foo { }
-/// impl<T: Bar> Foo for T { }
-/// impl<T> Bar for T { }
-/// ```
-///
-/// Here, in the `Foo` impl, we will check that `T: Copy` holds -- but
-/// we decide that this is true because `T: Bar` is in the
-/// where-clauses (and we can elaborate that to include `T:
-/// Copy`). This wouldn't be a problem, except that when we check the
-/// `Bar` impl, we decide that `T: Foo` must hold because of the `Foo`
-/// impl. And so nowhere did we check that `T: Copy` holds!
-///
-/// To resolve this, we elaborate the WF requirements that must be
-/// proven when checking impls. This means that (e.g.) the `impl Bar
-/// for T` will be forced to prove not only that `T: Foo` but also `T:
-/// Copy` (which it won't be able to do, because there is no `Copy`
-/// impl for `T`).
-#[derive(Debug, PartialEq, Eq, Copy, Clone)]
-enum Elaborate {
-    All,
-    None,
-}
-
-impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
-    fn cause(&mut self, code: traits::ObligationCauseCode<'tcx>) -> traits::ObligationCause<'tcx> {
-        traits::ObligationCause::new(self.span, self.body_id, code)
-    }
-
-    fn normalize(&mut self) -> Vec<traits::PredicateObligation<'tcx>> {
-        let cause = self.cause(traits::MiscObligation);
-        let infcx = &mut self.infcx;
-        let param_env = self.param_env;
-        let mut obligations = Vec::with_capacity(self.out.len());
-        for pred in &self.out {
-            assert!(!pred.has_escaping_bound_vars());
-            let mut selcx = traits::SelectionContext::new(infcx);
-            let i = obligations.len();
-            let value =
-                traits::normalize_to(&mut selcx, param_env, cause.clone(), pred, &mut obligations);
-            obligations.insert(i, value);
-        }
-        obligations
-    }
-
-    /// Pushes the obligations required for `trait_ref` to be WF into `self.out`.
-    fn compute_trait_ref(&mut self, trait_ref: &ty::TraitRef<'tcx>, elaborate: Elaborate) {
-        let tcx = self.infcx.tcx;
-        let obligations = self.nominal_obligations(trait_ref.def_id, trait_ref.substs);
-
-        let cause = self.cause(traits::MiscObligation);
-        let param_env = self.param_env;
-
-        let item = &self.item;
-        let extend_cause_with_original_assoc_item_obligation =
-            |cause: &mut traits::ObligationCause<'_>,
-             pred: &ty::Predicate<'_>,
-             trait_assoc_items: &[ty::AssocItem]| {
-                let trait_item = tcx
-                    .hir()
-                    .as_local_hir_id(trait_ref.def_id)
-                    .and_then(|trait_id| tcx.hir().find(trait_id));
-                let (trait_name, trait_generics) = match trait_item {
-                    Some(hir::Node::Item(hir::Item {
-                        ident,
-                        kind: hir::ItemKind::Trait(.., generics, _, _),
-                        ..
-                    }))
-                    | Some(hir::Node::Item(hir::Item {
-                        ident,
-                        kind: hir::ItemKind::TraitAlias(generics, _),
-                        ..
-                    })) => (Some(ident), Some(generics)),
-                    _ => (None, None),
-                };
-
-                let item_span = item.map(|i| tcx.sess.source_map().def_span(i.span));
-                match pred {
-                    ty::Predicate::Projection(proj) => {
-                        // The obligation comes not from the current `impl` nor the `trait` being
-                        // implemented, but rather from a "second order" obligation, like in
-                        // `src/test/ui/associated-types/point-at-type-on-obligation-failure.rs`:
-                        //
-                        //   error[E0271]: type mismatch resolving `<Foo2 as Bar2>::Ok == ()`
-                        //     --> $DIR/point-at-type-on-obligation-failure.rs:13:5
-                        //      |
-                        //   LL |     type Ok;
-                        //      |          -- associated type defined here
-                        //   ...
-                        //   LL | impl Bar for Foo {
-                        //      | ---------------- in this `impl` item
-                        //   LL |     type Ok = ();
-                        //      |     ^^^^^^^^^^^^^ expected `u32`, found `()`
-                        //      |
-                        //      = note: expected type `u32`
-                        //                 found type `()`
-                        //
-                        // FIXME: we would want to point a span to all places that contributed to this
-                        // obligation. In the case above, it should be closer to:
-                        //
-                        //   error[E0271]: type mismatch resolving `<Foo2 as Bar2>::Ok == ()`
-                        //     --> $DIR/point-at-type-on-obligation-failure.rs:13:5
-                        //      |
-                        //   LL |     type Ok;
-                        //      |          -- associated type defined here
-                        //   LL |     type Sibling: Bar2<Ok=Self::Ok>;
-                        //      |     -------------------------------- obligation set here
-                        //   ...
-                        //   LL | impl Bar for Foo {
-                        //      | ---------------- in this `impl` item
-                        //   LL |     type Ok = ();
-                        //      |     ^^^^^^^^^^^^^ expected `u32`, found `()`
-                        //   ...
-                        //   LL | impl Bar2 for Foo2 {
-                        //      | ---------------- in this `impl` item
-                        //   LL |     type Ok = u32;
-                        //      |     -------------- obligation set here
-                        //      |
-                        //      = note: expected type `u32`
-                        //                 found type `()`
-                        if let Some(hir::ItemKind::Impl { items, .. }) = item.map(|i| &i.kind) {
-                            let trait_assoc_item = tcx.associated_item(proj.projection_def_id());
-                            if let Some(impl_item) =
-                                items.iter().find(|item| item.ident == trait_assoc_item.ident)
-                            {
-                                cause.span = impl_item.span;
-                                cause.code = traits::AssocTypeBound(Box::new(AssocTypeBoundData {
-                                    impl_span: item_span,
-                                    original: trait_assoc_item.ident.span,
-                                    bounds: vec![],
-                                }));
-                            }
-                        }
-                    }
-                    ty::Predicate::Trait(proj, _) => {
-                        // An associated item obligation born out of the `trait` failed to be met.
-                        // Point at the `impl` that failed the obligation, the associated item that
-                        // needed to meet the obligation, and the definition of that associated item,
-                        // which should hold the obligation in most cases. An example can be seen in
-                        // `src/test/ui/associated-types/point-at-type-on-obligation-failure-2.rs`:
-                        //
-                        //   error[E0277]: the trait bound `bool: Bar` is not satisfied
-                        //     --> $DIR/point-at-type-on-obligation-failure-2.rs:8:5
-                        //      |
-                        //   LL |     type Assoc: Bar;
-                        //      |          ----- associated type defined here
-                        //   ...
-                        //   LL | impl Foo for () {
-                        //      | --------------- in this `impl` item
-                        //   LL |     type Assoc = bool;
-                        //      |     ^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `bool`
-                        //
-                        // If the obligation comes from the where clause in the `trait`, we point at it:
-                        //
-                        //   error[E0277]: the trait bound `bool: Bar` is not satisfied
-                        //     --> $DIR/point-at-type-on-obligation-failure-2.rs:8:5
-                        //      |
-                        //      | trait Foo where <Self as Foo>>::Assoc: Bar {
-                        //      |                 -------------------------- restricted in this bound
-                        //   LL |     type Assoc;
-                        //      |          ----- associated type defined here
-                        //   ...
-                        //   LL | impl Foo for () {
-                        //      | --------------- in this `impl` item
-                        //   LL |     type Assoc = bool;
-                        //      |     ^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `bool`
-                        if let (
-                            ty::Projection(ty::ProjectionTy { item_def_id, .. }),
-                            Some(hir::ItemKind::Impl { items, .. }),
-                        ) = (&proj.skip_binder().self_ty().kind, item.map(|i| &i.kind))
-                        {
-                            if let Some((impl_item, trait_assoc_item)) = trait_assoc_items
-                                .iter()
-                                .find(|i| i.def_id == *item_def_id)
-                                .and_then(|trait_assoc_item| {
-                                    items
-                                        .iter()
-                                        .find(|i| i.ident == trait_assoc_item.ident)
-                                        .map(|impl_item| (impl_item, trait_assoc_item))
-                                })
-                            {
-                                let bounds = trait_generics
-                                    .map(|generics| {
-                                        get_generic_bound_spans(
-                                            &generics,
-                                            trait_name,
-                                            trait_assoc_item.ident,
-                                        )
-                                    })
-                                    .unwrap_or_else(Vec::new);
-                                cause.span = impl_item.span;
-                                cause.code = traits::AssocTypeBound(Box::new(AssocTypeBoundData {
-                                    impl_span: item_span,
-                                    original: trait_assoc_item.ident.span,
-                                    bounds,
-                                }));
-                            }
-                        }
-                    }
-                    _ => {}
-                }
-            };
-
-        if let Elaborate::All = elaborate {
-            // FIXME: Make `extend_cause_with_original_assoc_item_obligation` take an iterator
-            // instead of a slice.
-            let trait_assoc_items: Vec<_> =
-                tcx.associated_items(trait_ref.def_id).in_definition_order().copied().collect();
-
-            let predicates = obligations.iter().map(|obligation| obligation.predicate).collect();
-            let implied_obligations = traits::elaborate_predicates(tcx, predicates);
-            let implied_obligations = implied_obligations.map(|pred| {
-                let mut cause = cause.clone();
-                extend_cause_with_original_assoc_item_obligation(
-                    &mut cause,
-                    &pred,
-                    &*trait_assoc_items,
-                );
-                traits::Obligation::new(cause, param_env, pred)
-            });
-            self.out.extend(implied_obligations);
-        }
-
-        self.out.extend(obligations);
-
-        self.out.extend(trait_ref.substs.types().filter(|ty| !ty.has_escaping_bound_vars()).map(
-            |ty| traits::Obligation::new(cause.clone(), param_env, ty::Predicate::WellFormed(ty)),
-        ));
-    }
-
-    /// Pushes the obligations required for `trait_ref::Item` to be WF
-    /// into `self.out`.
-    fn compute_projection(&mut self, data: ty::ProjectionTy<'tcx>) {
-        // A projection is well-formed if (a) the trait ref itself is
-        // WF and (b) the trait-ref holds.  (It may also be
-        // normalizable and be WF that way.)
-        let trait_ref = data.trait_ref(self.infcx.tcx);
-        self.compute_trait_ref(&trait_ref, Elaborate::None);
-
-        if !data.has_escaping_bound_vars() {
-            let predicate = trait_ref.without_const().to_predicate();
-            let cause = self.cause(traits::ProjectionWf(data));
-            self.out.push(traits::Obligation::new(cause, self.param_env, predicate));
-        }
-    }
-
-    /// Pushes the obligations required for an array length to be WF
-    /// into `self.out`.
-    fn compute_array_len(&mut self, constant: ty::Const<'tcx>) {
-        if let ty::ConstKind::Unevaluated(def_id, substs, promoted) = constant.val {
-            assert!(promoted.is_none());
-
-            let obligations = self.nominal_obligations(def_id, substs);
-            self.out.extend(obligations);
-
-            let predicate = ty::Predicate::ConstEvaluatable(def_id, substs);
-            let cause = self.cause(traits::MiscObligation);
-            self.out.push(traits::Obligation::new(cause, self.param_env, predicate));
-        }
-    }
-
-    fn require_sized(&mut self, subty: Ty<'tcx>, cause: traits::ObligationCauseCode<'tcx>) {
-        if !subty.has_escaping_bound_vars() {
-            let cause = self.cause(cause);
-            let trait_ref = ty::TraitRef {
-                def_id: self.infcx.tcx.require_lang_item(lang_items::SizedTraitLangItem, None),
-                substs: self.infcx.tcx.mk_substs_trait(subty, &[]),
-            };
-            self.out.push(traits::Obligation::new(
-                cause,
-                self.param_env,
-                trait_ref.without_const().to_predicate(),
-            ));
-        }
-    }
-
-    /// Pushes new obligations into `out`. Returns `true` if it was able
-    /// to generate all the predicates needed to validate that `ty0`
-    /// is WF. Returns false if `ty0` is an unresolved type variable,
-    /// in which case we are not able to simplify at all.
-    fn compute(&mut self, ty0: Ty<'tcx>) -> bool {
-        let mut subtys = ty0.walk();
-        let param_env = self.param_env;
-        while let Some(ty) = subtys.next() {
-            match ty.kind {
-                ty::Bool
-                | ty::Char
-                | ty::Int(..)
-                | ty::Uint(..)
-                | ty::Float(..)
-                | ty::Error
-                | ty::Str
-                | ty::GeneratorWitness(..)
-                | ty::Never
-                | ty::Param(_)
-                | ty::Bound(..)
-                | ty::Placeholder(..)
-                | ty::Foreign(..) => {
-                    // WfScalar, WfParameter, etc
-                }
-
-                ty::Slice(subty) => {
-                    self.require_sized(subty, traits::SliceOrArrayElem);
-                }
-
-                ty::Array(subty, len) => {
-                    self.require_sized(subty, traits::SliceOrArrayElem);
-                    self.compute_array_len(*len);
-                }
-
-                ty::Tuple(ref tys) => {
-                    if let Some((_last, rest)) = tys.split_last() {
-                        for elem in rest {
-                            self.require_sized(elem.expect_ty(), traits::TupleElem);
-                        }
-                    }
-                }
-
-                ty::RawPtr(_) => {
-                    // simple cases that are WF if their type args are WF
-                }
-
-                ty::Projection(data) => {
-                    subtys.skip_current_subtree(); // subtree handled by compute_projection
-                    self.compute_projection(data);
-                }
-
-                ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
-
-                ty::Adt(def, substs) => {
-                    // WfNominalType
-                    let obligations = self.nominal_obligations(def.did, substs);
-                    self.out.extend(obligations);
-                }
-
-                ty::FnDef(did, substs) => {
-                    let obligations = self.nominal_obligations(did, substs);
-                    self.out.extend(obligations);
-                }
-
-                ty::Ref(r, rty, _) => {
-                    // WfReference
-                    if !r.has_escaping_bound_vars() && !rty.has_escaping_bound_vars() {
-                        let cause = self.cause(traits::ReferenceOutlivesReferent(ty));
-                        self.out.push(traits::Obligation::new(
-                            cause,
-                            param_env,
-                            ty::Predicate::TypeOutlives(ty::Binder::dummy(ty::OutlivesPredicate(
-                                rty, r,
-                            ))),
-                        ));
-                    }
-                }
-
-                ty::Generator(..) => {
-                    // Walk ALL the types in the generator: this will
-                    // include the upvar types as well as the yield
-                    // type. Note that this is mildly distinct from
-                    // the closure case, where we have to be careful
-                    // about the signature of the closure. We don't
-                    // have the problem of implied bounds here since
-                    // generators don't take arguments.
-                }
-
-                ty::Closure(def_id, substs) => {
-                    // Only check the upvar types for WF, not the rest
-                    // of the types within. This is needed because we
-                    // capture the signature and it may not be WF
-                    // without the implied bounds. Consider a closure
-                    // like `|x: &'a T|` -- it may be that `T: 'a` is
-                    // not known to hold in the creator's context (and
-                    // indeed the closure may not be invoked by its
-                    // creator, but rather turned to someone who *can*
-                    // verify that).
-                    //
-                    // The special treatment of closures here really
-                    // ought not to be necessary either; the problem
-                    // is related to #25860 -- there is no way for us
-                    // to express a fn type complete with the implied
-                    // bounds that it is assuming. I think in reality
-                    // the WF rules around fn are a bit messed up, and
-                    // that is the rot problem: `fn(&'a T)` should
-                    // probably always be WF, because it should be
-                    // shorthand for something like `where(T: 'a) {
-                    // fn(&'a T) }`, as discussed in #25860.
-                    //
-                    // Note that we are also skipping the generic
-                    // types. This is consistent with the `outlives`
-                    // code, but anyway doesn't matter: within the fn
-                    // body where they are created, the generics will
-                    // always be WF, and outside of that fn body we
-                    // are not directly inspecting closure types
-                    // 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) {
-                        self.compute(upvar_ty);
-                    }
-                }
-
-                ty::FnPtr(_) => {
-                    // let the loop iterate into the argument/return
-                    // types appearing in the fn signature
-                }
-
-                ty::Opaque(did, substs) => {
-                    // all of the requirements on type parameters
-                    // should've been checked by the instantiation
-                    // of whatever returned this exact `impl Trait`.
-
-                    // for named opaque `impl Trait` types we still need to check them
-                    if ty::is_impl_trait_defn(self.infcx.tcx, did).is_none() {
-                        let obligations = self.nominal_obligations(did, substs);
-                        self.out.extend(obligations);
-                    }
-                }
-
-                ty::Dynamic(data, r) => {
-                    // WfObject
-                    //
-                    // Here, we defer WF checking due to higher-ranked
-                    // regions. This is perhaps not ideal.
-                    self.from_object_ty(ty, data, r);
-
-                    // FIXME(#27579) RFC also considers adding trait
-                    // 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),
-                            )
-                        }));
-                    }
-                }
-
-                // Inference variables are the complicated case, since we don't
-                // know what type they are. We do two things:
-                //
-                // 1. Check if they have been resolved, and if so proceed with
-                //    THAT type.
-                // 2. If not, check whether this is the type that we
-                //    started with (ty0). In that case, we've made no
-                //    progress at all, so return false. Otherwise,
-                //    we've at least simplified things (i.e., we went
-                //    from `Vec<$0>: WF` to `$0: WF`, so we can
-                //    register a pending obligation and keep
-                //    moving. (Goal is that an "inductive hypothesis"
-                //    is satisfied to ensure termination.)
-                ty::Infer(_) => {
-                    let ty = self.infcx.shallow_resolve(ty);
-                    if let ty::Infer(_) = ty.kind {
-                        // not yet resolved...
-                        if ty == ty0 {
-                            // ...this is the type we started from! no progress.
-                            return false;
-                        }
-
-                        let cause = self.cause(traits::MiscObligation);
-                        self.out.push(
-                            // ...not the type we started from, so we made progress.
-                            traits::Obligation::new(
-                                cause,
-                                self.param_env,
-                                ty::Predicate::WellFormed(ty),
-                            ),
-                        );
-                    } else {
-                        // Yes, resolved, proceed with the
-                        // result. Should never return false because
-                        // `ty` is not a Infer.
-                        assert!(self.compute(ty));
-                    }
-                }
-            }
-        }
-
-        // if we made it through that loop above, we made progress!
-        return true;
-    }
-
-    fn nominal_obligations(
-        &mut self,
-        def_id: DefId,
-        substs: SubstsRef<'tcx>,
-    ) -> Vec<traits::PredicateObligation<'tcx>> {
-        let predicates = self.infcx.tcx.predicates_of(def_id).instantiate(self.infcx.tcx, substs);
-        let cause = self.cause(traits::ItemObligation(def_id));
-        predicates
-            .predicates
-            .into_iter()
-            .map(|pred| traits::Obligation::new(cause.clone(), self.param_env, pred))
-            .filter(|pred| !pred.has_escaping_bound_vars())
-            .collect()
-    }
-
-    fn from_object_ty(
-        &mut self,
-        ty: Ty<'tcx>,
-        data: ty::Binder<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>,
-        region: ty::Region<'tcx>,
-    ) {
-        // Imagine a type like this:
-        //
-        //     trait Foo { }
-        //     trait Bar<'c> : 'c { }
-        //
-        //     &'b (Foo+'c+Bar<'d>)
-        //         ^
-        //
-        // In this case, the following relationships must hold:
-        //
-        //     'b <= 'c
-        //     'd <= 'c
-        //
-        // The first conditions is due to the normal region pointer
-        // rules, which say that a reference cannot outlive its
-        // referent.
-        //
-        // The final condition may be a bit surprising. In particular,
-        // you may expect that it would have been `'c <= 'd`, since
-        // usually lifetimes of outer things are conservative
-        // approximations for inner things. However, it works somewhat
-        // differently with trait objects: here the idea is that if the
-        // user specifies a region bound (`'c`, in this case) it is the
-        // "master bound" that *implies* that bounds from other traits are
-        // all met. (Remember that *all bounds* in a type like
-        // `Foo+Bar+Zed` must be met, not just one, hence if we write
-        // `Foo<'x>+Bar<'y>`, we know that the type outlives *both* 'x and
-        // 'y.)
-        //
-        // Note: in fact we only permit builtin traits, not `Bar<'d>`, I
-        // am looking forward to the future here.
-        if !data.has_escaping_bound_vars() && !region.has_escaping_bound_vars() {
-            let implicit_bounds = object_region_bounds(self.infcx.tcx, data);
-
-            let explicit_bound = region;
-
-            self.out.reserve(implicit_bounds.len());
-            for implicit_bound in implicit_bounds {
-                let cause = self.cause(traits::ObjectTypeBound(ty, explicit_bound));
-                let outlives =
-                    ty::Binder::dummy(ty::OutlivesPredicate(explicit_bound, implicit_bound));
-                self.out.push(traits::Obligation::new(
-                    cause,
-                    self.param_env,
-                    outlives.to_predicate(),
-                ));
-            }
-        }
-    }
-}
-
-/// Given an object type like `SomeTrait + Send`, computes the lifetime
-/// bounds that must hold on the elided self type. These are derived
-/// from the declarations of `SomeTrait`, `Send`, and friends -- if
-/// they declare `trait SomeTrait : 'static`, for example, then
-/// `'static` would appear in the list. The hard work is done by
-/// `infer::required_region_bounds`, see that for more information.
-pub fn object_region_bounds<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    existential_predicates: ty::Binder<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>,
-) -> Vec<ty::Region<'tcx>> {
-    // Since we don't actually *know* the self type for an object,
-    // this "open(err)" serves as a kind of dummy standin -- basically
-    // a placeholder type.
-    let open_ty = tcx.mk_ty_infer(ty::FreshTy(0));
-
-    let predicates = existential_predicates
-        .iter()
-        .filter_map(|predicate| {
-            if let ty::ExistentialPredicate::Projection(_) = *predicate.skip_binder() {
-                None
-            } else {
-                Some(predicate.with_self_ty(tcx, open_ty))
-            }
-        })
-        .collect();
-
-    required_region_bounds(tcx, open_ty, predicates)
-}
-
-/// Find the span of a generic bound affecting an associated type.
-fn get_generic_bound_spans(
-    generics: &hir::Generics<'_>,
-    trait_name: Option<&Ident>,
-    assoc_item_name: Ident,
-) -> Vec<Span> {
-    let mut bounds = vec![];
-    for clause in generics.where_clause.predicates.iter() {
-        if let hir::WherePredicate::BoundPredicate(pred) = clause {
-            match &pred.bounded_ty.kind {
-                hir::TyKind::Path(hir::QPath::Resolved(Some(ty), path)) => {
-                    let mut s = path.segments.iter();
-                    if let (a, Some(b), None) = (s.next(), s.next(), s.next()) {
-                        if a.map(|s| &s.ident) == trait_name
-                            && b.ident == assoc_item_name
-                            && is_self_path(&ty.kind)
-                        {
-                            // `<Self as Foo>::Bar`
-                            bounds.push(pred.span);
-                        }
-                    }
-                }
-                hir::TyKind::Path(hir::QPath::TypeRelative(ty, segment)) => {
-                    if segment.ident == assoc_item_name {
-                        if is_self_path(&ty.kind) {
-                            // `Self::Bar`
-                            bounds.push(pred.span);
-                        }
-                    }
-                }
-                _ => {}
-            }
-        }
-    }
-    bounds
-}
-
-fn is_self_path(kind: &hir::TyKind<'_>) -> bool {
-    match kind {
-        hir::TyKind::Path(hir::QPath::Resolved(None, path)) => {
-            let mut s = path.segments.iter();
-            if let (Some(segment), None) = (s.next(), s.next()) {
-                if segment.ident.name == kw::SelfUpper {
-                    // `type(Self)`
-                    return true;
-                }
-            }
-        }
-        _ => {}
-    }
-    false
-}
index b29480a88109f68e7033f3a2fbeed6188a87f376..e84181f1d75e7238512b6b544ab3c40afaeabe03 100644 (file)
@@ -42,6 +42,7 @@ rustc_errors = { path = "../librustc_errors" }
 rustc_plugin_impl = { path = "../librustc_plugin_impl" }
 rustc_privacy = { path = "../librustc_privacy" }
 rustc_resolve = { path = "../librustc_resolve" }
+rustc_trait_selection = { path = "../librustc_trait_selection" }
 rustc_ty = { path = "../librustc_ty" }
 tempfile = "3.0.5"
 once_cell = "1"
index e15217dfa67e60298bfd7df5abc07a72005c12d8..c5ebcf0696fba163a68f8074bd7ba32902ab33b2 100644 (file)
@@ -1,10 +1,6 @@
 pub use crate::passes::BoxedResolver;
 use crate::util;
 
-use rustc::lint;
-use rustc::session::config::{self, ErrorOutputType, Input, OutputFilenames};
-use rustc::session::early_error;
-use rustc::session::{DiagnosticOutput, Session};
 use rustc::ty;
 use rustc::util::common::ErrorReported;
 use rustc_ast::ast::{self, MetaItemKind};
 use rustc_errors::registry::Registry;
 use rustc_lint::LintStore;
 use rustc_parse::new_parser_from_source_str;
+use rustc_session::config::{self, ErrorOutputType, Input, OutputFilenames};
+use rustc_session::early_error;
+use rustc_session::lint;
 use rustc_session::parse::{CrateConfig, ParseSess};
+use rustc_session::{DiagnosticOutput, Session};
 use rustc_span::edition;
 use rustc_span::source_map::{FileLoader, FileName, SourceMap};
 use std::path::PathBuf;
index 1e9b76c3e14d270f7828f3db1d04e6d0016825c7..ee323b204b7a01f28a3b965028d97dfc2f282a36 100644 (file)
@@ -5,14 +5,9 @@
 use log::{info, log_enabled, warn};
 use rustc::arena::Arena;
 use rustc::dep_graph::DepGraph;
-use rustc::hir::map;
-use rustc::lint;
+use rustc::hir::map::Definitions;
 use rustc::middle;
 use rustc::middle::cstore::{CrateStore, MetadataLoader, MetadataLoaderDyn};
-use rustc::session::config::{self, CrateType, Input, OutputFilenames, OutputType};
-use rustc::session::config::{PpMode, PpSourceMode};
-use rustc::session::search_paths::PathKind;
-use rustc::session::Session;
 use rustc::ty::steal::Steal;
 use rustc::ty::{self, GlobalCtxt, ResolverOutputs, TyCtxt};
 use rustc::util::common::ErrorReported;
@@ -27,7 +22,6 @@
 use rustc_expand::base::ExtCtxt;
 use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
 use rustc_hir::Crate;
-use rustc_infer::traits;
 use rustc_lint::LintStore;
 use rustc_mir as mir;
 use rustc_mir_build as mir_build;
 use rustc_passes::{self, hir_stats, layout_test};
 use rustc_plugin_impl as plugin;
 use rustc_resolve::{Resolver, ResolverArenas};
+use rustc_session::config::{self, CrateType, Input, OutputFilenames, OutputType};
+use rustc_session::config::{PpMode, PpSourceMode};
+use rustc_session::lint;
+use rustc_session::search_paths::PathKind;
+use rustc_session::Session;
 use rustc_span::symbol::Symbol;
 use rustc_span::FileName;
+use rustc_trait_selection::traits;
 use rustc_typeck as typeck;
 
 use rustc_serialize::json;
@@ -189,7 +189,7 @@ pub fn register_plugins<'a>(
     }
 
     sess.time("recursion_limit", || {
-        middle::recursion_limit::update_limits(sess, &krate);
+        middle::limits::update_limits(sess, &krate);
     });
 
     let mut lint_store = rustc_lint::new_lint_store(
@@ -210,14 +210,7 @@ pub fn register_plugins<'a>(
     Ok((krate, Lrc::new(lint_store)))
 }
 
-fn configure_and_expand_inner<'a>(
-    sess: &'a Session,
-    lint_store: &'a LintStore,
-    mut krate: ast::Crate,
-    crate_name: &str,
-    resolver_arenas: &'a ResolverArenas<'a>,
-    metadata_loader: &'a MetadataLoaderDyn,
-) -> Result<(ast::Crate, Resolver<'a>)> {
+fn pre_expansion_lint(sess: &Session, lint_store: &LintStore, krate: &ast::Crate) {
     sess.time("pre_AST_expansion_lint_checks", || {
         rustc_lint::check_ast_crate(
             sess,
@@ -228,6 +221,17 @@ fn configure_and_expand_inner<'a>(
             rustc_lint::BuiltinCombinedPreExpansionLintPass::new(),
         );
     });
+}
+
+fn configure_and_expand_inner<'a>(
+    sess: &'a Session,
+    lint_store: &'a LintStore,
+    mut krate: ast::Crate,
+    crate_name: &str,
+    resolver_arenas: &'a ResolverArenas<'a>,
+    metadata_loader: &'a MetadataLoaderDyn,
+) -> Result<(ast::Crate, Resolver<'a>)> {
+    pre_expansion_lint(sess, lint_store, &krate);
 
     let mut resolver = Resolver::new(sess, &krate, crate_name, metadata_loader, &resolver_arenas);
     rustc_builtin_macros::register_builtin_macros(&mut resolver, sess.edition());
@@ -291,7 +295,8 @@ fn configure_and_expand_inner<'a>(
             ..rustc_expand::expand::ExpansionConfig::default(crate_name.to_string())
         };
 
-        let mut ecx = ExtCtxt::new(&sess.parse_sess, cfg, &mut resolver);
+        let extern_mod_loaded = |k: &ast::Crate| pre_expansion_lint(sess, lint_store, k);
+        let mut ecx = ExtCtxt::new(&sess.parse_sess, cfg, &mut resolver, Some(&extern_mod_loaded));
 
         // Expand macros now!
         let krate = sess.time("expand_crate", || ecx.monotonic_expander().expand_crate(krate));
@@ -713,10 +718,7 @@ pub fn create_global_ctxt<'tcx>(
     arena: &'tcx WorkerLocal<Arena<'tcx>>,
 ) -> QueryContext<'tcx> {
     let sess = &compiler.session();
-    let defs = mem::take(&mut resolver_outputs.definitions);
-
-    // Construct the HIR map.
-    let hir_map = map::map_crate(sess, &*resolver_outputs.cstore, krate, dep_graph, defs);
+    let defs: &'tcx Definitions = arena.alloc(mem::take(&mut resolver_outputs.definitions));
 
     let query_result_on_disk_cache = rustc_incremental::load_query_result_cache(sess);
 
@@ -742,7 +744,9 @@ pub fn create_global_ctxt<'tcx>(
                 extern_providers,
                 arena,
                 resolver_outputs,
-                hir_map,
+                krate,
+                defs,
+                dep_graph,
                 query_result_on_disk_cache,
                 &crate_name,
                 &outputs,
@@ -763,6 +767,8 @@ pub fn create_global_ctxt<'tcx>(
 fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> {
     assert_eq!(cnum, LOCAL_CRATE);
 
+    rustc::hir::map::check_crate(tcx);
+
     let sess = tcx.sess;
     let mut entry_point = None;
 
index 426d97cc09b9234d43cf7d0abec0033ce3bdedbe..3514829dca7f777034b4a87c90e073f719195db8 100644 (file)
@@ -3,8 +3,6 @@
 
 use rustc::arena::Arena;
 use rustc::dep_graph::DepGraph;
-use rustc::session::config::{OutputFilenames, OutputType};
-use rustc::session::Session;
 use rustc::ty::steal::Steal;
 use rustc::ty::{GlobalCtxt, ResolverOutputs};
 use rustc::util::common::ErrorReported;
@@ -15,6 +13,8 @@
 use rustc_hir::Crate;
 use rustc_incremental::DepGraphFuture;
 use rustc_lint::LintStore;
+use rustc_session::config::{OutputFilenames, OutputType};
+use rustc_session::Session;
 use std::any::Any;
 use std::cell::{Ref, RefCell, RefMut};
 use std::mem;
index 1b80cf4e3dbc2d7ed15c65a20bf75a19c8dafa5e..db5ada9291435f5b8c9f7b02c1488df1dd6bc419 100644 (file)
@@ -2,16 +2,16 @@
 
 use crate::interface::parse_cfgspecs;
 
-use rustc::lint::Level;
 use rustc::middle::cstore;
-use rustc::session::config::{build_configuration, build_session_options, to_crate_config};
-use rustc::session::config::{rustc_optgroups, ErrorOutputType, ExternLocation, Options, Passes};
-use rustc::session::config::{ExternEntry, LinkerPluginLto, LtoCli, SwitchWithOptPath};
-use rustc::session::config::{Externs, OutputType, OutputTypes, SymbolManglingVersion};
-use rustc::session::search_paths::SearchPath;
-use rustc::session::{build_session, Session};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{emitter::HumanReadableErrorType, registry, ColorConfig};
+use rustc_session::config::{build_configuration, build_session_options, to_crate_config};
+use rustc_session::config::{rustc_optgroups, ErrorOutputType, ExternLocation, Options, Passes};
+use rustc_session::config::{ExternEntry, LinkerPluginLto, LtoCli, SwitchWithOptPath};
+use rustc_session::config::{Externs, OutputType, OutputTypes, SymbolManglingVersion};
+use rustc_session::lint::Level;
+use rustc_session::search_paths::SearchPath;
+use rustc_session::{build_session, Session};
 use rustc_span::edition::{Edition, DEFAULT_EDITION};
 use rustc_span::symbol::sym;
 use rustc_target::spec::{MergeFunctions, PanicStrategy, RelroLevel};
index 10a8c0a63f1882f4bf9da355f93e59320c697d22..5c4de9e7155c63c30f4a34cd86527d771fbb514a 100644 (file)
@@ -1,5 +1,4 @@
 use log::info;
-use rustc::lint;
 use rustc::ty;
 use rustc_ast::ast::{AttrVec, BlockCheckMode};
 use rustc_ast::mut_visit::{visit_clobber, MutVisitor, *};
@@ -18,7 +17,7 @@
 use rustc_resolve::{self, Resolver};
 use rustc_session as session;
 use rustc_session::config::{ErrorOutputType, Input, OutputFilenames};
-use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer};
+use rustc_session::lint::{self, BuiltinLintDiagnostics, LintBuffer};
 use rustc_session::parse::CrateConfig;
 use rustc_session::CrateDisambiguator;
 use rustc_session::{config, early_error, filesearch, DiagnosticOutput, Session};
@@ -49,7 +48,7 @@ pub fn add_configuration(
 
     cfg.extend(codegen_backend.target_features(sess).into_iter().map(|feat| (tf, Some(feat))));
 
-    if sess.crt_static_feature() {
+    if sess.crt_static_feature(None) {
         cfg.insert((tf, Some(Symbol::intern("crt-static"))));
     }
 }
@@ -426,7 +425,7 @@ pub(crate) fn check_attr_crate_type(attrs: &[ast::Attribute], lint_buffer: &mut
     for a in attrs.iter() {
         if a.check_name(sym::crate_type) {
             if let Some(n) = a.value_str() {
-                if let Some(_) = categorize_crate_type(n) {
+                if categorize_crate_type(n).is_some() {
                     return;
                 }
 
@@ -780,7 +779,7 @@ fn block_to_stmt(b: ast::Block, resolver: &mut Resolver<'_>) -> ast::Stmt {
 
     // in general the pretty printer processes unexpanded code, so
     // we override the default `visit_mac` method which panics.
-    fn visit_mac(&mut self, mac: &mut ast::Mac) {
+    fn visit_mac(&mut self, mac: &mut ast::MacCall) {
         noop_visit_mac(mac, self)
     }
 }
index 4f5e03d008c995fa4193585e69bde3fcd023e7d3..c51bf735fa727c0ac6f193ed38329b97d769cf46 100644 (file)
@@ -17,7 +17,7 @@ pub enum EscapeError {
 
     /// Escaped '\' character without continuation.
     LoneSlash,
-    /// Invalid escape characted (e.g. '\z').
+    /// Invalid escape character (e.g. '\z').
     InvalidEscape,
     /// Raw '\r' encountered.
     BareCarriageReturn,
@@ -43,7 +43,7 @@ pub enum EscapeError {
     UnclosedUnicodeEscape,
     /// '\u{_12}'
     LeadingUnderscoreUnicodeEscape,
-    /// More than 6 charactes in '\u{..}', e.g. '\u{10FFFF_FF}'
+    /// More than 6 characters in '\u{..}', e.g. '\u{10FFFF_FF}'
     OverlongUnicodeEscape,
     /// Invalid in-bound unicode character code, e.g. '\u{DFFF}'.
     LoneSurrogateUnicodeEscape,
index 6470d25fe0a2e99e2449b268edab025071f86327..9785af5eab2fd1e91d104357281a00b451691d6f 100644 (file)
@@ -24,3 +24,4 @@ rustc_feature = { path = "../librustc_feature" }
 rustc_index = { path = "../librustc_index" }
 rustc_session = { path = "../librustc_session" }
 rustc_infer = { path = "../librustc_infer" }
+rustc_trait_selection = { path = "../librustc_trait_selection" }
index 3eecd2a54e33e4e1f519f8f4c9beea3fdca45569..408031028b102dac8f11d1e594a81560161e47fd 100644 (file)
@@ -22,7 +22,6 @@
 //! `late_lint_methods!` invocation in `lib.rs`.
 
 use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
-use rustc::hir::map::Map;
 use rustc::lint::LintDiagnosticBuilder;
 use rustc::ty::{self, layout::VariantIdx, Ty, TyCtxt};
 use rustc_ast::ast::{self, Expr};
 use rustc_hir::def_id::DefId;
 use rustc_hir::{GenericParamKind, PatKind};
 use rustc_hir::{HirIdSet, Node};
-use rustc_infer::traits::misc::can_type_implement_copy;
 use rustc_session::lint::FutureIncompatibleInfo;
 use rustc_span::edition::Edition;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::{BytePos, Span};
+use rustc_trait_selection::traits::misc::can_type_implement_copy;
 
 use crate::nonstandard_style::{method_context, MethodLateContext};
 
@@ -399,7 +398,7 @@ fn exit_lint_attrs(&mut self, _: &LateContext<'_, '_>, _attrs: &[ast::Attribute]
     }
 
     fn check_crate(&mut self, cx: &LateContext<'_, '_>, krate: &hir::Crate<'_>) {
-        self.check_missing_docs_attrs(cx, None, &krate.attrs, krate.span, "crate");
+        self.check_missing_docs_attrs(cx, None, &krate.item.attrs, krate.item.span, "crate");
 
         for macro_def in krate.exported_macros {
             let has_doc = macro_def.attrs.iter().any(|a| has_doc(a));
@@ -465,7 +464,7 @@ fn check_trait_item(&mut self, cx: &LateContext<'_, '_>, trait_item: &hir::Trait
 
         let desc = match trait_item.kind {
             hir::TraitItemKind::Const(..) => "an associated constant",
-            hir::TraitItemKind::Method(..) => "a trait method",
+            hir::TraitItemKind::Fn(..) => "a trait method",
             hir::TraitItemKind::Type(..) => "an associated type",
         };
 
@@ -486,7 +485,7 @@ fn check_impl_item(&mut self, cx: &LateContext<'_, '_>, impl_item: &hir::ImplIte
 
         let desc = match impl_item.kind {
             hir::ImplItemKind::Const(..) => "an associated constant",
-            hir::ImplItemKind::Method(..) => "a method",
+            hir::ImplItemKind::Fn(..) => "a method",
             hir::ImplItemKind::TyAlias(_) => "an associated type",
             hir::ImplItemKind::OpaqueTy(_) => "an associated `impl Trait` type",
         };
@@ -775,7 +774,10 @@ fn check_stmt(&mut self, cx: &EarlyContext<'_>, stmt: &ast::Stmt) {
             ast::StmtKind::Local(..) => "statements",
             ast::StmtKind::Item(..) => "inner items",
             // expressions will be reported by `check_expr`.
-            ast::StmtKind::Semi(..) | ast::StmtKind::Expr(..) | ast::StmtKind::Mac(..) => return,
+            ast::StmtKind::Empty
+            | ast::StmtKind::Semi(_)
+            | ast::StmtKind::Expr(_)
+            | ast::StmtKind::MacCall(_) => return,
         };
 
         warn_if_doc(cx, stmt.span, kind, stmt.kind.attrs());
@@ -1068,9 +1070,9 @@ struct WalkAssocTypes<'a, 'db> {
             err: &'a mut DiagnosticBuilder<'db>,
         }
         impl<'a, 'db, 'v> Visitor<'v> for WalkAssocTypes<'a, 'db> {
-            type Map = Map<'v>;
+            type Map = intravisit::ErasedMap<'v>;
 
-            fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> {
+            fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
                 intravisit::NestedVisitorMap::None
             }
 
@@ -1475,7 +1477,7 @@ impl EarlyLintPass for KeywordIdents {
     fn check_mac_def(&mut self, cx: &EarlyContext<'_>, mac_def: &ast::MacroDef, _id: ast::NodeId) {
         self.check_tokens(cx, mac_def.body.inner_tokens());
     }
-    fn check_mac(&mut self, cx: &EarlyContext<'_>, mac: &ast::Mac) {
+    fn check_mac(&mut self, cx: &EarlyContext<'_>, mac: &ast::MacCall) {
         self.check_tokens(cx, mac.args.inner_tokens());
     }
     fn check_ident(&mut self, cx: &EarlyContext<'_>, ident: ast::Ident) {
index 29a6b8c693ff3c5378cf6a547a4ee3b14f664e6f..5b7b73b48ec5bc7cfc31743d67432c0b3819df36 100644 (file)
@@ -335,7 +335,7 @@ pub fn check_lint_name(
             lint_name.to_string()
         };
         // If the lint was scoped with `tool::` check if the tool lint exists
-        if let Some(_) = tool_name {
+        if tool_name.is_some() {
             match self.by_name.get(&complete_name) {
                 None => match self.lint_groups.get(&*complete_name) {
                     None => return CheckLintNameResult::Tool(Err((None, String::new()))),
@@ -369,7 +369,7 @@ pub fn check_lint_name(
                         return if *silent {
                             CheckLintNameResult::Ok(&lint_ids)
                         } else {
-                            CheckLintNameResult::Tool(Err((Some(&lint_ids), name.to_string())))
+                            CheckLintNameResult::Tool(Err((Some(&lint_ids), (*name).to_string())))
                         };
                     }
                     CheckLintNameResult::Ok(&lint_ids)
@@ -404,7 +404,7 @@ fn check_tool_name_for_backwards_compat(
                         return if *silent {
                             CheckLintNameResult::Tool(Err((Some(&lint_ids), complete_name)))
                         } else {
-                            CheckLintNameResult::Tool(Err((Some(&lint_ids), name.to_string())))
+                            CheckLintNameResult::Tool(Err((Some(&lint_ids), (*name).to_string())))
                         };
                     }
                     CheckLintNameResult::Tool(Err((Some(&lint_ids), complete_name)))
index ff6e9e000b097457df37cae0ca231978d982c1a7..34da29c9747775b61d47aebb114e80e243ddff56 100644 (file)
@@ -18,7 +18,7 @@
 use crate::passes::{EarlyLintPass, EarlyLintPassObject};
 use rustc_ast::ast;
 use rustc_ast::visit as ast_visit;
-use rustc_session::lint::{LintBuffer, LintPass};
+use rustc_session::lint::{BufferedEarlyLint, LintBuffer, LintPass};
 use rustc_session::Session;
 use rustc_span::Span;
 
@@ -37,13 +37,7 @@ struct EarlyContextAndPass<'a, T: EarlyLintPass> {
 impl<'a, T: EarlyLintPass> EarlyContextAndPass<'a, T> {
     fn check_id(&mut self, id: ast::NodeId) {
         for early_lint in self.context.buffered.take(id) {
-            let rustc_session::lint::BufferedEarlyLint {
-                span,
-                msg,
-                node_id: _,
-                lint_id,
-                diagnostic,
-            } = early_lint;
+            let BufferedEarlyLint { span, msg, node_id: _, lint_id, diagnostic } = early_lint;
             self.context.lookup_with_diagnostics(
                 lint_id.lint,
                 Some(span),
@@ -249,7 +243,7 @@ fn visit_mac_def(&mut self, mac: &'a ast::MacroDef, id: ast::NodeId) {
         self.check_id(id);
     }
 
-    fn visit_mac(&mut self, mac: &'a ast::Mac) {
+    fn visit_mac(&mut self, mac: &'a ast::MacCall) {
         // FIXME(#54110): So, this setup isn't really right. I think
         // that (a) the librustc_ast visitor ought to be doing this as
         // part of `walk_mac`, and (b) we should be calling
@@ -326,11 +320,9 @@ pub fn check_ast_crate<T: EarlyLintPass>(
     lint_buffer: Option<LintBuffer>,
     builtin_lints: T,
 ) {
-    let mut passes: Vec<_> = if pre_expansion {
-        lint_store.pre_expansion_passes.iter().map(|p| (p)()).collect()
-    } else {
-        lint_store.early_passes.iter().map(|p| (p)()).collect()
-    };
+    let passes =
+        if pre_expansion { &lint_store.pre_expansion_passes } else { &lint_store.early_passes };
+    let mut passes: Vec<_> = passes.iter().map(|p| (p)()).collect();
     let mut buffered = lint_buffer.unwrap_or_default();
 
     if !sess.opts.debugging_opts.no_interleave_lints {
index db109aef6eb8f20fc466b108bc8f9ad636887c5c..d8c685f2b22ffe908423d1c428574e353bb02124 100644 (file)
@@ -140,7 +140,7 @@ fn check_ty(&mut self, cx: &LateContext<'_, '_>, ty: &'tcx Ty<'tcx>) {
                 }
             }
             TyKind::Rptr(_, MutTy { ty: inner_ty, mutbl: Mutability::Not }) => {
-                if let Some(impl_did) = cx.tcx.impl_of_method(ty.hir_id.owner_def_id()) {
+                if let Some(impl_did) = cx.tcx.impl_of_method(ty.hir_id.owner.to_def_id()) {
                     if cx.tcx.impl_trait_ref(impl_did).is_some() {
                         return;
                     }
index ee03232a0ce4c8390ebcfd319556d068a19c23b7..d2cc55106035752bbab53f6575eaf576a4288fc6 100644 (file)
@@ -33,7 +33,7 @@
 
 /// Extract the `LintStore` from the query context.
 /// This function exists because we've erased `LintStore` as `dyn Any` in the context.
-crate fn unerased_lint_store<'tcx>(tcx: TyCtxt<'tcx>) -> &'tcx LintStore {
+crate fn unerased_lint_store(tcx: TyCtxt<'_>) -> &LintStore {
     let store: &dyn Any = &*tcx.lint_store;
     store.downcast_ref().unwrap()
 }
@@ -99,8 +99,8 @@ impl<'a, 'tcx, T: LateLintPass<'a, 'tcx>> hir_visit::Visitor<'tcx>
     /// Because lints are scoped lexically, we want to walk nested
     /// items in the context of the outer item, so enable
     /// deep-walking.
-    fn nested_visit_map<'this>(&'this mut self) -> hir_visit::NestedVisitorMap<'this, Self::Map> {
-        hir_visit::NestedVisitorMap::All(&self.context.tcx.hir())
+    fn nested_visit_map(&mut self) -> hir_visit::NestedVisitorMap<Self::Map> {
+        hir_visit::NestedVisitorMap::All(self.context.tcx.hir())
     }
 
     fn visit_nested_body(&mut self, body: hir::BodyId) {
@@ -419,7 +419,7 @@ fn late_lint_pass_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(tcx: TyCtxt<'tc
     let mut cx = LateContextAndPass { context, pass };
 
     // Visit the whole crate.
-    cx.with_lint_attrs(hir::CRATE_HIR_ID, &krate.attrs, |cx| {
+    cx.with_lint_attrs(hir::CRATE_HIR_ID, &krate.item.attrs, |cx| {
         // since the root module isn't visited as an item (because it isn't an
         // item), warn for it here.
         lint_callback!(cx, check_crate, krate);
index 7da69f3ed26f2a516b6ce7c8b61f40f4bc4eb64b..2062f9499aeb96f0e0980e8597a3a3bc7e10d97a 100644 (file)
@@ -29,7 +29,7 @@ fn lint_levels(tcx: TyCtxt<'_>, cnum: CrateNum) -> &LintLevelMap {
     let mut builder = LintLevelMapBuilder { levels, tcx, store };
     let krate = tcx.hir().krate();
 
-    let push = builder.levels.push(&krate.attrs, &store);
+    let push = builder.levels.push(&krate.item.attrs, &store);
     builder.levels.register_id(hir::CRATE_HIR_ID);
     for macro_def in krate.exported_macros {
         builder.levels.register_id(macro_def.hir_id);
@@ -377,10 +377,10 @@ pub fn push(&mut self, attrs: &[ast::Attribute], store: &LintStore) -> BuilderPu
         let prev = self.cur;
         if !specs.is_empty() {
             self.cur = self.sets.list.len() as u32;
-            self.sets.list.push(LintSet::Node { specs: specs, parent: prev });
+            self.sets.list.push(LintSet::Node { specs, parent: prev });
         }
 
-        BuilderPush { prev: prev, changed: prev != self.cur }
+        BuilderPush { prev, changed: prev != self.cur }
     }
 
     /// Called after `push` when the scope of a set of attributes are exited.
@@ -438,8 +438,8 @@ fn with_lint_attrs<F>(&mut self, id: hir::HirId, attrs: &[ast::Attribute], f: F)
 impl<'tcx> intravisit::Visitor<'tcx> for LintLevelMapBuilder<'_, 'tcx> {
     type Map = Map<'tcx>;
 
-    fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, Self::Map> {
-        intravisit::NestedVisitorMap::All(&self.tcx.hir())
+    fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
+        intravisit::NestedVisitorMap::All(self.tcx.hir())
     }
 
     fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) {
index 895c42a84d8e9e1854a90f0709c747060c03a7e3..825ac04bc09201deafccfd913ee8d701bc05f639 100644 (file)
@@ -113,7 +113,7 @@ macro_rules! early_lint_passes {
                 WhileTrue: WhileTrue,
                 NonAsciiIdents: NonAsciiIdents,
                 IncompleteFeatures: IncompleteFeatures,
-                RedundantSemicolon: RedundantSemicolon,
+                RedundantSemicolons: RedundantSemicolons,
                 UnusedDocComment: UnusedDocComment,
             ]
         );
@@ -274,7 +274,8 @@ macro_rules! register_passes {
         UNUSED_EXTERN_CRATES,
         UNUSED_FEATURES,
         UNUSED_LABELS,
-        UNUSED_PARENS
+        UNUSED_PARENS,
+        REDUNDANT_SEMICOLONS
     );
 
     add_lint_group!(
@@ -307,6 +308,7 @@ macro_rules! register_passes {
     store.register_renamed("unused_doc_comment", "unused_doc_comments");
     store.register_renamed("async_idents", "keyword_idents");
     store.register_renamed("exceeding_bitshifts", "arithmetic_overflow");
+    store.register_renamed("redundant_semicolon", "redundant_semicolons");
     store.register_removed("unknown_features", "replaced by an error");
     store.register_removed("unsigned_negation", "replaced by negate_unsigned feature gate");
     store.register_removed("negate_unsigned", "cast a signed value instead");
index b0560dc9fdf9c273e6bb49e691d2263630ab7547..afab55358d93889c33c7dd2639a95b63ea860a1d 100644 (file)
@@ -343,7 +343,7 @@ fn check_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::Item<'_>) {
     }
 
     fn check_trait_item(&mut self, cx: &LateContext<'_, '_>, item: &hir::TraitItem<'_>) {
-        if let hir::TraitItemKind::Method(_, hir::TraitMethod::Required(pnames)) = item.kind {
+        if let hir::TraitItemKind::Fn(_, hir::TraitFn::Required(pnames)) = item.kind {
             self.check_snake_case(cx, "trait method", &item.ident);
             for param_name in pnames {
                 self.check_snake_case(cx, "variable", param_name);
index 813be2a032f8b29ecd9f3258a9e1bcbb53983ddc..ace154714458e4eb0b849ea1a6d740791c2a1f7d 100644 (file)
@@ -198,7 +198,7 @@ fn check_fn_post(
             fn check_path(a: &ast::Path, b: ast::NodeId);
             fn check_attribute(a: &ast::Attribute);
             fn check_mac_def(a: &ast::MacroDef, b: ast::NodeId);
-            fn check_mac(a: &ast::Mac);
+            fn check_mac(a: &ast::MacCall);
 
             /// Called when entering a syntax node that can have lint attributes such
             /// as `#[allow(...)]`. Called with *all* the attributes of that node.
index 0b66fd92430acde676eab745a14cb45ccc847bdb..0f807cd497e56b93fdb8d9ea93fa68b73ddbf6c3 100644 (file)
@@ -1,50 +1,41 @@
 use crate::{EarlyContext, EarlyLintPass, LintContext};
-use rustc_ast::ast::{ExprKind, Stmt, StmtKind};
+use rustc_ast::ast::{Block, StmtKind};
 use rustc_errors::Applicability;
+use rustc_span::Span;
 
 declare_lint! {
-    pub REDUNDANT_SEMICOLON,
+    pub REDUNDANT_SEMICOLONS,
     Warn,
     "detects unnecessary trailing semicolons"
 }
 
-declare_lint_pass!(RedundantSemicolon => [REDUNDANT_SEMICOLON]);
+declare_lint_pass!(RedundantSemicolons => [REDUNDANT_SEMICOLONS]);
 
-impl EarlyLintPass for RedundantSemicolon {
-    fn check_stmt(&mut self, cx: &EarlyContext<'_>, stmt: &Stmt) {
-        if let StmtKind::Semi(expr) = &stmt.kind {
-            if let ExprKind::Tup(ref v) = &expr.kind {
-                if v.is_empty() {
-                    // Strings of excess semicolons are encoded as empty tuple expressions
-                    // during the parsing stage, so we check for empty tuple expressions
-                    // which span only semicolons
-                    if let Ok(source_str) = cx.sess().source_map().span_to_snippet(stmt.span) {
-                        if source_str.chars().all(|c| c == ';') {
-                            let multiple = (stmt.span.hi() - stmt.span.lo()).0 > 1;
-                            let msg = if multiple {
-                                "unnecessary trailing semicolons"
-                            } else {
-                                "unnecessary trailing semicolon"
-                            };
-                            cx.struct_span_lint(REDUNDANT_SEMICOLON, stmt.span, |lint| {
-                                let mut err = lint.build(&msg);
-                                let suggest_msg = if multiple {
-                                    "remove these semicolons"
-                                } else {
-                                    "remove this semicolon"
-                                };
-                                err.span_suggestion(
-                                    stmt.span,
-                                    &suggest_msg,
-                                    String::new(),
-                                    Applicability::MaybeIncorrect,
-                                );
-                                err.emit();
-                            });
-                        }
-                    }
-                }
+impl EarlyLintPass for RedundantSemicolons {
+    fn check_block(&mut self, cx: &EarlyContext<'_>, block: &Block) {
+        let mut seq = None;
+        for stmt in block.stmts.iter() {
+            match (&stmt.kind, &mut seq) {
+                (StmtKind::Empty, None) => seq = Some((stmt.span, false)),
+                (StmtKind::Empty, Some(seq)) => *seq = (seq.0.to(stmt.span), true),
+                (_, seq) => maybe_lint_redundant_semis(cx, seq),
             }
         }
+        maybe_lint_redundant_semis(cx, &mut seq);
+    }
+}
+
+fn maybe_lint_redundant_semis(cx: &EarlyContext<'_>, seq: &mut Option<(Span, bool)>) {
+    if let Some((span, multiple)) = seq.take() {
+        cx.struct_span_lint(REDUNDANT_SEMICOLONS, span, |lint| {
+            let (msg, rem) = if multiple {
+                ("unnecessary trailing semicolons", "remove these semicolons")
+            } else {
+                ("unnecessary trailing semicolon", "remove this semicolon")
+            };
+            lint.build(msg)
+                .span_suggestion(span, rem, String::new(), Applicability::MaybeIncorrect)
+                .emit();
+        });
     }
 }
index 86d93612e993bd0e1609975b50a045e540f8c711..4949c93d45eede1a5fc50469f826c6feda2eb31c 100644 (file)
@@ -165,7 +165,7 @@ fn report_bin_hex_error(
         let mut err = lint.build(&format!("literal out of range for {}", t));
         err.note(&format!(
             "the literal `{}` (decimal `{}`) does not fit into \
-                    an `{}` and will become `{}{}`",
+             the type `{}` and will become `{}{}`",
             repr_str, val, t, actually, t
         ));
         if let Some(sugg_ty) = get_type_suggestion(&cx.tables.node_type(expr.hir_id), val, negative)
@@ -242,7 +242,7 @@ fn lint_int_literal<'a, 'tcx>(
     v: u128,
 ) {
     let int_type = t.normalize(cx.sess().target.ptr_width);
-    let (_, max) = int_ty_range(int_type);
+    let (min, max) = int_ty_range(int_type);
     let max = max as u128;
     let negative = type_limits.negated_expr_id == e.hir_id;
 
@@ -267,7 +267,19 @@ fn lint_int_literal<'a, 'tcx>(
         }
 
         cx.struct_span_lint(OVERFLOWING_LITERALS, e.span, |lint| {
-            lint.build(&format!("literal out of range for `{}`", t.name_str())).emit()
+            lint.build(&format!("literal out of range for `{}`", t.name_str()))
+                .note(&format!(
+                    "the literal `{}` does not fit into the type `{}` whose range is `{}..={}`",
+                    cx.sess()
+                        .source_map()
+                        .span_to_snippet(lit.span)
+                        .ok()
+                        .expect("must get snippet from literal"),
+                    t.name_str(),
+                    min,
+                    max,
+                ))
+                .emit();
         });
     }
 }
@@ -320,7 +332,19 @@ fn lint_uint_literal<'a, 'tcx>(
             return;
         }
         cx.struct_span_lint(OVERFLOWING_LITERALS, e.span, |lint| {
-            lint.build(&format!("literal out of range for `{}`", t.name_str())).emit()
+            lint.build(&format!("literal out of range for `{}`", t.name_str()))
+                .note(&format!(
+                    "the literal `{}` does not fit into the type `{}` whose range is `{}..={}`",
+                    cx.sess()
+                        .source_map()
+                        .span_to_snippet(lit.span)
+                        .ok()
+                        .expect("must get snippet from literal"),
+                    t.name_str(),
+                    min,
+                    max,
+                ))
+                .emit()
         });
     }
 }
@@ -352,7 +376,17 @@ fn lint_literal<'a, 'tcx>(
             };
             if is_infinite == Ok(true) {
                 cx.struct_span_lint(OVERFLOWING_LITERALS, e.span, |lint| {
-                    lint.build(&format!("literal out of range for `{}`", t.name_str())).emit()
+                    lint.build(&format!("literal out of range for `{}`", t.name_str()))
+                        .note(&format!(
+                            "the literal `{}` does not fit into the type `{}` and will be converted to `std::{}::INFINITY`",
+                            cx.sess()
+                                .source_map()
+                                .span_to_snippet(lit.span)
+                                .expect("must get snippet from literal"),
+                            t.name_str(),
+                            t.name_str(),
+                        ))
+                        .emit();
                 });
             }
         }
@@ -998,10 +1032,8 @@ fn check_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::Item<'_>) {
             let ty = cx.tcx.erase_regions(&t);
             let layout = match cx.layout_of(ty) {
                 Ok(layout) => layout,
-                Err(ty::layout::LayoutError::Unknown(_)) => return,
-                Err(err @ ty::layout::LayoutError::SizeOverflow(_)) => {
-                    bug!("failed to get layout for `{}`: {}", t, err);
-                }
+                Err(ty::layout::LayoutError::Unknown(_))
+                | Err(ty::layout::LayoutError::SizeOverflow(_)) => return,
             };
             let (variants, tag) = match layout.variants {
                 layout::Variants::Multiple {
index 02f04b2345932cbe27cceebe415fa92cd9d6fcb0..229740615f707f60da6fa6b355568764d9f58b5d 100644 (file)
@@ -54,7 +54,7 @@ fn check_stmt(&mut self, cx: &LateContext<'_, '_>, s: &hir::Stmt<'_>) {
                 match callee.kind {
                     hir::ExprKind::Path(ref qpath) => {
                         match cx.tables.qpath_res(qpath, callee.hir_id) {
-                            Res::Def(DefKind::Fn, def_id) | Res::Def(DefKind::Method, def_id) => {
+                            Res::Def(DefKind::Fn, def_id) | Res::Def(DefKind::AssocFn, def_id) => {
                                 Some(def_id)
                             }
                             // `Res::Local` if it was a closure, for which we
@@ -124,7 +124,12 @@ fn check_must_use_ty<'tcx>(
             descr_post: &str,
             plural_len: usize,
         ) -> bool {
-            if ty.is_unit() || cx.tcx.is_ty_uninhabited_from(cx.tcx.parent_module(expr.hir_id), ty)
+            if ty.is_unit()
+                || cx.tcx.is_ty_uninhabited_from(
+                    cx.tcx.parent_module(expr.hir_id).to_def_id(),
+                    ty,
+                    cx.param_env,
+                )
             {
                 return true;
             }
@@ -538,7 +543,7 @@ fn check_pat(&mut self, cx: &EarlyContext<'_>, p: &ast::Pat) {
             // Do not lint on `(..)` as that will result in the other arms being useless.
             Paren(_)
             // The other cases do not contain sub-patterns.
-            | Wild | Rest | Lit(..) | Mac(..) | Range(..) | Ident(.., None) | Path(..) => return,
+            | Wild | Rest | Lit(..) | MacCall(..) | Range(..) | Ident(.., None) | Path(..) => return,
             // These are list-like patterns; parens can always be removed.
             TupleStruct(_, ps) | Tuple(ps) | Slice(ps) | Or(ps) => for p in ps {
                 self.check_unused_parens_pat(cx, p, false, false);
index 6362f3c2c49f03929543ff72f9b204768ae75fcf..56b7be2f7e2d531912a1aa88c04a7dbd868dc871 100644 (file)
@@ -51,13 +51,10 @@ enum QueryModifier {
     /// Don't hash the result, instead just mark a query red if it runs
     NoHash,
 
-    /// Don't force the query
-    NoForce,
-
     /// Generate a dep node based on the dependencies of the query
     Anon,
 
-    /// Always evaluate the query, ignoring its depdendencies
+    /// Always evaluate the query, ignoring its dependencies
     EvalAlways,
 }
 
@@ -118,8 +115,6 @@ fn parse(input: ParseStream<'_>) -> Result<Self> {
             Ok(QueryModifier::CycleDelayBug)
         } else if modifier == "no_hash" {
             Ok(QueryModifier::NoHash)
-        } else if modifier == "no_force" {
-            Ok(QueryModifier::NoForce)
         } else if modifier == "anon" {
             Ok(QueryModifier::Anon)
         } else if modifier == "eval_always" {
@@ -222,13 +217,10 @@ struct QueryModifiers {
     /// Don't hash the result, instead just mark a query red if it runs
     no_hash: bool,
 
-    /// Don't force the query
-    no_force: bool,
-
     /// Generate a dep node based on the dependencies of the query
     anon: bool,
 
-    // Always evaluate the query, ignoring its depdendencies
+    // Always evaluate the query, ignoring its dependencies
     eval_always: bool,
 }
 
@@ -241,7 +233,6 @@ fn process_modifiers(query: &mut Query) -> QueryModifiers {
     let mut fatal_cycle = false;
     let mut cycle_delay_bug = false;
     let mut no_hash = false;
-    let mut no_force = false;
     let mut anon = false;
     let mut eval_always = false;
     for modifier in query.modifiers.0.drain(..) {
@@ -288,12 +279,6 @@ fn process_modifiers(query: &mut Query) -> QueryModifiers {
                 }
                 no_hash = true;
             }
-            QueryModifier::NoForce => {
-                if no_force {
-                    panic!("duplicate modifier `no_force` for query `{}`", query.name);
-                }
-                no_force = true;
-            }
             QueryModifier::Anon => {
                 if anon {
                     panic!("duplicate modifier `anon` for query `{}`", query.name);
@@ -316,7 +301,6 @@ fn process_modifiers(query: &mut Query) -> QueryModifiers {
         fatal_cycle,
         cycle_delay_bug,
         no_hash,
-        no_force,
         anon,
         eval_always,
     }
@@ -425,7 +409,6 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
     let mut dep_node_def_stream = quote! {};
     let mut dep_node_force_stream = quote! {};
     let mut try_load_from_on_disk_cache_stream = quote! {};
-    let mut no_force_queries = Vec::new();
     let mut cached_queries = quote! {};
 
     for group in groups.0 {
@@ -444,19 +427,19 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
                 cached_queries.extend(quote! {
                     #name,
                 });
-            }
 
-            if modifiers.cache.is_some() && !modifiers.no_force {
                 try_load_from_on_disk_cache_stream.extend(quote! {
                     DepKind::#name => {
-                        debug_assert!(tcx.dep_graph
-                                         .node_color(self)
-                                         .map(|c| c.is_green())
-                                         .unwrap_or(false));
-
-                        let key = RecoverKey::recover(tcx, self).unwrap();
-                        if queries::#name::cache_on_disk(tcx, key, None) {
-                            let _ = tcx.#name(key);
+                        if <#arg as DepNodeParams>::CAN_RECONSTRUCT_QUERY_KEY {
+                            debug_assert!($tcx.dep_graph
+                                            .node_color($dep_node)
+                                            .map(|c| c.is_green())
+                                            .unwrap_or(false));
+
+                            let key = <#arg as DepNodeParams>::recover($tcx, $dep_node).unwrap();
+                            if queries::#name::cache_on_disk($tcx, key, None) {
+                                let _ = $tcx.#name(key);
+                            }
                         }
                     }
                 });
@@ -501,24 +484,21 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
                 [#attribute_stream] #name(#arg),
             });
 
-            if modifiers.no_force {
-                no_force_queries.push(name.clone());
-            } else {
-                // Add a match arm to force the query given the dep node
-                dep_node_force_stream.extend(quote! {
-                    DepKind::#name => {
-                        if let Some(key) = RecoverKey::recover($tcx, $dep_node) {
+            // Add a match arm to force the query given the dep node
+            dep_node_force_stream.extend(quote! {
+                DepKind::#name => {
+                    if <#arg as DepNodeParams>::CAN_RECONSTRUCT_QUERY_KEY {
+                        if let Some(key) = <#arg as DepNodeParams>::recover($tcx, $dep_node) {
                             $tcx.force_query::<crate::ty::query::queries::#name<'_>>(
                                 key,
                                 DUMMY_SP,
                                 *$dep_node
                             );
-                        } else {
-                            return false;
+                            return true;
                         }
                     }
-                });
-            }
+                }
+            });
 
             add_query_description_impl(&query, modifiers, &mut query_description_stream);
         }
@@ -528,12 +508,6 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
         });
     }
 
-    // Add an arm for the no force queries to panic when trying to force them
-    for query in no_force_queries {
-        dep_node_force_stream.extend(quote! {
-            DepKind::#query |
-        });
-    }
     dep_node_force_stream.extend(quote! {
         DepKind::Null => {
             bug!("Cannot force dep node: {:?}", $dep_node)
@@ -577,14 +551,9 @@ macro_rules! rustc_cached_queries {
 
         #query_description_stream
 
-        impl DepNode {
-            /// Check whether the query invocation corresponding to the given
-            /// DepNode is eligible for on-disk-caching. If so, this is method
-            /// will execute the query corresponding to the given DepNode.
-            /// Also, as a sanity check, it expects that the corresponding query
-            /// invocation has been marked as green already.
-            pub fn try_load_from_on_disk_cache(&self, tcx: TyCtxt<'_>) {
-                match self.kind {
+        macro_rules! rustc_dep_node_try_load_from_on_disk_cache {
+            ($dep_node:expr, $tcx:expr) => {
+                match $dep_node.kind {
                     #try_load_from_on_disk_cache_stream
                     _ => (),
                 }
index feddcd5f994290e2b9a9d30a144efc96609b863d..0f8bc4323070b17a8ed169face61fb55a5f97030 100644 (file)
@@ -103,6 +103,7 @@ pub fn symbols(input: TokenStream) -> TokenStream {
             #value,
         });
         keyword_stream.extend(quote! {
+            #[allow(non_upper_case_globals)]
             pub const #name: Symbol = Symbol::new(#counter);
         });
         counter += 1;
@@ -120,6 +121,8 @@ pub fn symbols(input: TokenStream) -> TokenStream {
             #value,
         });
         symbols_stream.extend(quote! {
+            #[allow(rustc::default_hash_types)]
+            #[allow(non_upper_case_globals)]
             pub const #name: Symbol = Symbol::new(#counter);
         });
         counter += 1;
@@ -149,6 +152,7 @@ macro_rules! symbols {
             () => {
                 #symbols_stream
 
+                #[allow(non_upper_case_globals)]
                 pub const digits_array: &[Symbol; 10] = &[
                     #digits_stream
                 ];
index 8abfb20965e489c74835dc0b0d150075c7af7d1f..088cba83ef998164cb7c1f11fb621709a01a44f6 100644 (file)
@@ -15,7 +15,6 @@ log = "0.4"
 memmap = "0.7"
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
 rustc = { path = "../librustc" }
-rustc_ast_pretty = { path = "../librustc_ast_pretty" }
 rustc_attr = { path = "../librustc_attr" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_errors = { path = "../librustc_errors" }
@@ -26,8 +25,8 @@ rustc_serialize = { path = "../libserialize", package = "serialize" }
 stable_deref_trait = "1.0.0"
 rustc_ast = { path = "../librustc_ast" }
 rustc_expand = { path = "../librustc_expand" }
-rustc_parse = { path = "../librustc_parse" }
 rustc_span = { path = "../librustc_span" }
+rustc_session = { path = "../librustc_session" }
 
 [target.'cfg(windows)'.dependencies]
 winapi = { version = "0.3", features = ["errhandlingapi", "libloaderapi"] }
index 293a353a092d078dc829a4f2620da51a931d97fc..f20cdfcba15ca9b1e77fdb5026f1e93f0630aed1 100644 (file)
@@ -6,19 +6,18 @@
 use rustc::hir::map::Definitions;
 use rustc::middle::cstore::DepKind;
 use rustc::middle::cstore::{CrateSource, ExternCrate, ExternCrateSource, MetadataLoaderDyn};
-use rustc::session::config;
-use rustc::session::search_paths::PathKind;
-use rustc::session::{CrateDisambiguator, Session};
 use rustc::ty::TyCtxt;
-use rustc_ast::ast;
-use rustc_ast::attr;
 use rustc_ast::expand::allocator::{global_allocator_spans, AllocatorKind};
+use rustc_ast::{ast, attr};
 use rustc_data_structures::svh::Svh;
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::struct_span_err;
 use rustc_expand::base::SyntaxExtension;
 use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
 use rustc_index::vec::IndexVec;
+use rustc_session::config;
+use rustc_session::search_paths::PathKind;
+use rustc_session::{CrateDisambiguator, Session};
 use rustc_span::edition::Edition;
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::{Span, DUMMY_SP};
@@ -76,6 +75,21 @@ fn report(self) -> ! {
     }
 }
 
+/// A reference to `CrateMetadata` that can also give access to whole crate store when necessary.
+#[derive(Clone, Copy)]
+crate struct CrateMetadataRef<'a> {
+    pub cdata: &'a CrateMetadata,
+    pub cstore: &'a CStore,
+}
+
+impl std::ops::Deref for CrateMetadataRef<'_> {
+    type Target = CrateMetadata;
+
+    fn deref(&self) -> &Self::Target {
+        self.cdata
+    }
+}
+
 fn dump_crates(cstore: &CStore) {
     info!("resolved crates:");
     cstore.iter_crate_data(|cnum, data| {
@@ -100,10 +114,11 @@ fn alloc_new_crate_num(&mut self) -> CrateNum {
         CrateNum::new(self.metas.len() - 1)
     }
 
-    crate fn get_crate_data(&self, cnum: CrateNum) -> &CrateMetadata {
-        self.metas[cnum]
+    crate fn get_crate_data(&self, cnum: CrateNum) -> CrateMetadataRef<'_> {
+        let cdata = self.metas[cnum]
             .as_ref()
-            .unwrap_or_else(|| panic!("Failed to get crate data for {:?}", cnum))
+            .unwrap_or_else(|| panic!("Failed to get crate data for {:?}", cnum));
+        CrateMetadataRef { cdata, cstore: self }
     }
 
     fn set_crate_data(&mut self, cnum: CrateNum, data: CrateMetadata) {
@@ -217,7 +232,7 @@ fn existing_match(&self, name: Symbol, hash: Option<Svh>, kind: PathKind) -> Opt
             // We're also sure to compare *paths*, not actual byte slices. The
             // `source` stores paths which are normalized which may be different
             // from the strings on the command line.
-            let source = self.cstore.get_crate_data(cnum).source();
+            let source = self.cstore.get_crate_data(cnum).cdata.source();
             if let Some(entry) = self.sess.opts.externs.get(&name.as_str()) {
                 // Only use `--extern crate_name=path` here, not `--extern crate_name`.
                 if let Some(mut files) = entry.files() {
@@ -463,7 +478,7 @@ fn maybe_resolve_crate<'b>(
             self.load(&mut locator)
                 .map(|r| (r, None))
                 .or_else(|| {
-                    dep_kind = DepKind::UnexportedMacrosOnly;
+                    dep_kind = DepKind::MacrosOnly;
                     self.load_proc_macro(&mut locator, path_kind)
                 })
                 .ok_or_else(move || LoadError::LocatorError(locator))?
@@ -473,7 +488,7 @@ fn maybe_resolve_crate<'b>(
             (LoadResult::Previous(cnum), None) => {
                 let data = self.cstore.get_crate_data(cnum);
                 if data.is_proc_macro_crate() {
-                    dep_kind = DepKind::UnexportedMacrosOnly;
+                    dep_kind = DepKind::MacrosOnly;
                 }
                 data.update_dep_kind(|data_dep_kind| cmp::max(data_dep_kind, dep_kind));
                 Ok(cnum)
@@ -547,9 +562,6 @@ fn resolve_crate_deps(
                     "resolving dep crate {} hash: `{}` extra filename: `{}`",
                     dep.name, dep.hash, dep.extra_filename
                 );
-                if dep.kind == DepKind::UnexportedMacrosOnly {
-                    return krate;
-                }
                 let dep_kind = match dep_kind {
                     DepKind::MacrosOnly => DepKind::MacrosOnly,
                     _ => dep.kind,
@@ -850,7 +862,7 @@ pub fn process_extern_crate(
                     None => item.ident.name,
                 };
                 let dep_kind = if attr::contains_name(&item.attrs, sym::no_link) {
-                    DepKind::UnexportedMacrosOnly
+                    DepKind::MacrosOnly
                 } else {
                     DepKind::Explicit
                 };
@@ -858,11 +870,11 @@ pub fn process_extern_crate(
                 let cnum = self.resolve_crate(name, item.span, dep_kind, None);
 
                 let def_id = definitions.opt_local_def_id(item.id).unwrap();
-                let path_len = definitions.def_path(def_id.index).data.len();
+                let path_len = definitions.def_path(def_id).data.len();
                 self.update_extern_crate(
                     cnum,
                     ExternCrate {
-                        src: ExternCrateSource::Extern(def_id),
+                        src: ExternCrateSource::Extern(def_id.to_def_id()),
                         span: item.span,
                         path_len,
                         dependency_of: LOCAL_CRATE,
index 9e71839dbfde6a7540e2d5ba869e43befc06de5b..4cfaf03b7a5f63ae59e9a33b41271768695d98ee 100644 (file)
 use rustc::middle::cstore::LinkagePreference::{self, RequireDynamic, RequireStatic};
 use rustc::middle::cstore::{self, DepKind};
 use rustc::middle::dependency_format::{Dependencies, DependencyList, Linkage};
-use rustc::session::config;
 use rustc::ty::TyCtxt;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::def_id::CrateNum;
+use rustc_session::config;
 use rustc_target::spec::PanicStrategy;
 
 crate fn calculate(tcx: TyCtxt<'_>) -> Dependencies {
@@ -97,7 +97,9 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: config::CrateType) -> DependencyList {
 
         // If the global prefer_dynamic switch is turned off, or the final
         // executable will be statically linked, prefer static crate linkage.
-        config::CrateType::Executable if !sess.opts.cg.prefer_dynamic || sess.crt_static() => {
+        config::CrateType::Executable
+            if !sess.opts.cg.prefer_dynamic || sess.crt_static(Some(ty)) =>
+        {
             Linkage::Static
         }
         config::CrateType::Executable => Linkage::Dynamic,
@@ -129,7 +131,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: config::CrateType) -> DependencyList {
         // If any are not found, generate some nice pretty errors.
         if ty == config::CrateType::Staticlib
             || (ty == config::CrateType::Executable
-                && sess.crt_static()
+                && sess.crt_static(Some(ty))
                 && !sess.target.target.options.crt_static_allows_dylibs)
         {
             for &cnum in tcx.crates().iter() {
index d4cc3c32616ac02a88e808eeb9e0a57833af26c7..e401dc0f6e7d49d698c1fd17143f42c219c90a94 100644 (file)
@@ -31,7 +31,7 @@
 pub mod locator;
 
 pub fn validate_crate_name(
-    sess: Option<&rustc::session::Session>,
+    sess: Option<&rustc_session::Session>,
     s: &str,
     sp: Option<rustc_span::Span>,
 ) {
index 8d018b9bb94ddb653ff61a69c4f4bb33de0c5cc1..13668b2423fddf27452bdda804d8b2be7eb7d6e5 100644 (file)
@@ -8,7 +8,7 @@
     let mut collector = Collector { args: Vec::new() };
     tcx.hir().krate().visit_all_item_likes(&mut collector);
 
-    for attr in tcx.hir().krate().attrs.iter() {
+    for attr in tcx.hir().krate().item.attrs.iter() {
         if attr.has_name(sym::link_args) {
             if let Some(linkarg) = attr.value_str() {
                 collector.add_link_args(&linkarg.as_str());
index 2157b8ce15931e836453a7f929994a19d83b487f..1ede629e7ef7dc9af47c52d7aa5427c4df418dfe 100644 (file)
 use crate::rmeta::{rustc_version, MetadataBlob, METADATA_HEADER};
 
 use rustc::middle::cstore::{CrateSource, MetadataLoader};
-use rustc::session::filesearch::{FileDoesntMatch, FileMatches, FileSearch};
-use rustc::session::search_paths::PathKind;
-use rustc::session::{config, CrateDisambiguator, Session};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::svh::Svh;
 use rustc_data_structures::sync::MetadataRef;
 use rustc_errors::{struct_span_err, DiagnosticBuilder};
+use rustc_session::filesearch::{FileDoesntMatch, FileMatches, FileSearch};
+use rustc_session::search_paths::PathKind;
+use rustc_session::{config, CrateDisambiguator, Session};
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
 use rustc_target::spec::{Target, TargetTriple};
@@ -711,7 +711,7 @@ fn extract_one(
         // See also #68149 which provides more detail on why emitting the
         // dependency on the rlib is a bad thing.
         //
-        // We currenty do not verify that these other sources are even in sync,
+        // We currently do not verify that these other sources are even in sync,
         // and this is arguably a bug (see #10786), but because reading metadata
         // is quite slow (especially from dylibs) we currently do not read it
         // from the other crate sources.
index 2fa9cb099dd515e679f1bd2aa7f1f43feb1d35e5..64bbf393ba0f1ca9e4d429703581b52ceb3bd10a 100644 (file)
@@ -1,12 +1,12 @@
 use rustc::middle::cstore::{self, NativeLibrary};
-use rustc::session::parse::feature_err;
-use rustc::session::Session;
 use rustc::ty::TyCtxt;
 use rustc_attr as attr;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
+use rustc_session::parse::feature_err;
+use rustc_session::Session;
 use rustc_span::source_map::Span;
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_target::spec::abi::Abi;
index a72ee0cbe4729bc7b227db568061e6659820f427..2bf74fe272ec97abc5bd5e801f9875b33ccf8de9 100644 (file)
@@ -1,9 +1,10 @@
 // Decoding metadata from a single crate's metadata
 
+use crate::creader::CrateMetadataRef;
 use crate::rmeta::table::{FixedSizeEncoding, Table};
 use crate::rmeta::*;
 
-use rustc::dep_graph::{self, DepNodeIndex};
+use rustc::dep_graph::{self, DepNode, DepNodeIndex};
 use rustc::hir::exports::Export;
 use rustc::hir::map::definitions::DefPathTable;
 use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash};
 use rustc::middle::lang_items;
 use rustc::mir::interpret::{AllocDecodingSession, AllocDecodingState};
 use rustc::mir::{self, interpret, BodyAndCache, Promoted};
-use rustc::session::Session;
 use rustc::ty::codec::TyDecoder;
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::util::common::record_time;
+use rustc_ast::ast::{self, Ident};
+use rustc_attr as attr;
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::svh::Svh;
 use rustc_data_structures::sync::{AtomicCell, Lock, LockGuard, Lrc, Once};
+use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind};
+use rustc_expand::proc_macro::{AttrProcMacro, BangProcMacro, ProcMacroDerive};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
 use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_index::vec::{Idx, IndexVec};
+use rustc_serialize::{opaque, Decodable, Decoder, SpecializedDecoder};
+use rustc_session::Session;
+use rustc_span::source_map::{self, respan, Spanned};
+use rustc_span::symbol::{sym, Symbol};
+use rustc_span::{self, hygiene::MacroKind, BytePos, Pos, Span, DUMMY_SP};
 
+use log::debug;
+use proc_macro::bridge::client::ProcMacro;
 use std::io;
 use std::mem;
 use std::num::NonZeroUsize;
 use std::u32;
 
-use log::debug;
-use proc_macro::bridge::client::ProcMacro;
-use rustc_ast::ast::{self, Ident};
-use rustc_attr as attr;
-use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind};
-use rustc_expand::proc_macro::{AttrProcMacro, BangProcMacro, ProcMacroDerive};
-use rustc_serialize::{opaque, Decodable, Decoder, SpecializedDecoder};
-use rustc_span::source_map::{self, respan, Spanned};
-use rustc_span::symbol::{sym, Symbol};
-use rustc_span::{self, hygiene::MacroKind, BytePos, Pos, Span, DUMMY_SP};
-
 pub use cstore_impl::{provide, provide_extern};
 
 mod cstore_impl;
@@ -125,7 +125,7 @@ struct ImportedSourceFile {
 
 pub(super) struct DecodeContext<'a, 'tcx> {
     opaque: opaque::Decoder<'a>,
-    cdata: Option<&'a CrateMetadata>,
+    cdata: Option<CrateMetadataRef<'a>>,
     sess: Option<&'tcx Session>,
     tcx: Option<TyCtxt<'tcx>>,
 
@@ -141,7 +141,7 @@ pub(super) struct DecodeContext<'a, 'tcx> {
 /// Abstract over the various ways one can create metadata decoders.
 pub(super) trait Metadata<'a, 'tcx>: Copy {
     fn raw_bytes(self) -> &'a [u8];
-    fn cdata(self) -> Option<&'a CrateMetadata> {
+    fn cdata(self) -> Option<CrateMetadataRef<'a>> {
         None
     }
     fn sess(self) -> Option<&'tcx Session> {
@@ -162,7 +162,7 @@ fn decoder(self, pos: usize) -> DecodeContext<'a, 'tcx> {
             lazy_state: LazyState::NoNode,
             alloc_decoding_session: self
                 .cdata()
-                .map(|cdata| cdata.alloc_decoding_state.new_decoding_session()),
+                .map(|cdata| cdata.cdata.alloc_decoding_state.new_decoding_session()),
         }
     }
 }
@@ -185,33 +185,33 @@ fn sess(self) -> Option<&'tcx Session> {
     }
 }
 
-impl<'a, 'tcx> Metadata<'a, 'tcx> for &'a CrateMetadata {
+impl<'a, 'tcx> Metadata<'a, 'tcx> for &'a CrateMetadataRef<'a> {
     fn raw_bytes(self) -> &'a [u8] {
         self.blob.raw_bytes()
     }
-    fn cdata(self) -> Option<&'a CrateMetadata> {
-        Some(self)
+    fn cdata(self) -> Option<CrateMetadataRef<'a>> {
+        Some(*self)
     }
 }
 
-impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadata, &'tcx Session) {
+impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadataRef<'a>, &'tcx Session) {
     fn raw_bytes(self) -> &'a [u8] {
         self.0.raw_bytes()
     }
-    fn cdata(self) -> Option<&'a CrateMetadata> {
-        Some(self.0)
+    fn cdata(self) -> Option<CrateMetadataRef<'a>> {
+        Some(*self.0)
     }
     fn sess(self) -> Option<&'tcx Session> {
         Some(&self.1)
     }
 }
 
-impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadata, TyCtxt<'tcx>) {
+impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadataRef<'a>, TyCtxt<'tcx>) {
     fn raw_bytes(self) -> &'a [u8] {
         self.0.raw_bytes()
     }
-    fn cdata(self) -> Option<&'a CrateMetadata> {
-        Some(self.0)
+    fn cdata(self) -> Option<CrateMetadataRef<'a>> {
+        Some(*self.0)
     }
     fn tcx(self) -> Option<TyCtxt<'tcx>> {
         Some(self.1)
@@ -242,7 +242,7 @@ fn tcx(&self) -> TyCtxt<'tcx> {
         self.tcx.expect("missing TyCtxt in DecodeContext")
     }
 
-    fn cdata(&self) -> &'a CrateMetadata {
+    fn cdata(&self) -> CrateMetadataRef<'a> {
         self.cdata.expect("missing CrateMetadata in DecodeContext")
     }
 
@@ -364,7 +364,7 @@ fn specialized_decode(&mut self) -> Result<DefIndex, Self::Error> {
 impl<'a, 'tcx> SpecializedDecoder<LocalDefId> for DecodeContext<'a, 'tcx> {
     #[inline]
     fn specialized_decode(&mut self) -> Result<LocalDefId, Self::Error> {
-        self.specialized_decode().map(|i| LocalDefId::from_def_id(i))
+        Ok(DefId::decode(self)?.expect_local())
     }
 }
 
@@ -386,7 +386,7 @@ fn specialized_decode(&mut self) -> Result<Span, Self::Error> {
             return Ok(DUMMY_SP);
         }
 
-        debug_assert_eq!(tag, TAG_VALID_SPAN);
+        debug_assert!(tag == TAG_VALID_SPAN_LOCAL || tag == TAG_VALID_SPAN_FOREIGN);
 
         let lo = BytePos::decode(self)?;
         let len = BytePos::decode(self)?;
@@ -398,7 +398,68 @@ fn specialized_decode(&mut self) -> Result<Span, Self::Error> {
             bug!("Cannot decode Span without Session.")
         };
 
-        let imported_source_files = self.cdata().imported_source_files(&sess.source_map());
+        // There are two possibilities here:
+        // 1. This is a 'local span', which is located inside a `SourceFile`
+        // that came from this crate. In this case, we use the source map data
+        // encoded in this crate. This branch should be taken nearly all of the time.
+        // 2. This is a 'foreign span', which is located inside a `SourceFile`
+        // that came from a *different* crate (some crate upstream of the one
+        // whose metadata we're looking at). For example, consider this dependency graph:
+        //
+        // A -> B -> C
+        //
+        // Suppose that we're currently compiling crate A, and start deserializing
+        // metadata from crate B. When we deserialize a Span from crate B's metadata,
+        // there are two posibilites:
+        //
+        // 1. The span references a file from crate B. This makes it a 'local' span,
+        // which means that we can use crate B's serialized source map information.
+        // 2. The span references a file from crate C. This makes it a 'foreign' span,
+        // which means we need to use Crate *C* (not crate B) to determine the source
+        // map information. We only record source map information for a file in the
+        // crate that 'owns' it, so deserializing a Span may require us to look at
+        // a transitive dependency.
+        //
+        // When we encode a foreign span, we adjust its 'lo' and 'high' values
+        // to be based on the *foreign* crate (e.g. crate C), not the crate
+        // we are writing metadata for (e.g. crate B). This allows us to
+        // treat the 'local' and 'foreign' cases almost identically during deserialization:
+        // we can call `imported_source_files` for the proper crate, and binary search
+        // through the returned slice using our span.
+        let imported_source_files = if tag == TAG_VALID_SPAN_LOCAL {
+            self.cdata().imported_source_files(sess.source_map())
+        } else {
+            // FIXME: We don't decode dependencies of proc-macros.
+            // Remove this once #69976 is merged
+            if self.cdata().root.is_proc_macro_crate() {
+                debug!(
+                    "SpecializedDecoder<Span>::specialized_decode: skipping span for proc-macro crate {:?}",
+                    self.cdata().cnum
+                );
+                // Decode `CrateNum` as u32 - using `CrateNum::decode` will ICE
+                // since we don't have `cnum_map` populated.
+                // This advances the decoder position so that we can continue
+                // to read metadata.
+                let _ = u32::decode(self)?;
+                return Ok(DUMMY_SP);
+            }
+            // tag is TAG_VALID_SPAN_FOREIGN, checked by `debug_assert` above
+            let cnum = CrateNum::decode(self)?;
+            debug!(
+                "SpecializedDecoder<Span>::specialized_decode: loading source files from cnum {:?}",
+                cnum
+            );
+
+            // Decoding 'foreign' spans should be rare enough that it's
+            // not worth it to maintain a per-CrateNum cache for `last_source_file_index`.
+            // We just set it to 0, to ensure that we don't try to access something out
+            // of bounds for our initial 'guess'
+            self.last_source_file_index = 0;
+
+            let foreign_data = self.cdata().cstore.get_crate_data(cnum);
+            foreign_data.imported_source_files(sess.source_map())
+        };
+
         let source_file = {
             // Optimize for the case that most spans within a translated item
             // originate from the same source_file.
@@ -412,16 +473,32 @@ fn specialized_decode(&mut self) -> Result<Span, Self::Error> {
                     .binary_search_by_key(&lo, |source_file| source_file.original_start_pos)
                     .unwrap_or_else(|index| index - 1);
 
-                self.last_source_file_index = index;
+                // Don't try to cache the index for foreign spans,
+                // as this would require a map from CrateNums to indices
+                if tag == TAG_VALID_SPAN_LOCAL {
+                    self.last_source_file_index = index;
+                }
                 &imported_source_files[index]
             }
         };
 
         // Make sure our binary search above is correct.
-        debug_assert!(lo >= source_file.original_start_pos && lo <= source_file.original_end_pos);
+        debug_assert!(
+            lo >= source_file.original_start_pos && lo <= source_file.original_end_pos,
+            "Bad binary search: lo={:?} source_file.original_start_pos={:?} source_file.original_end_pos={:?}",
+            lo,
+            source_file.original_start_pos,
+            source_file.original_end_pos
+        );
 
         // Make sure we correctly filtered out invalid spans during encoding
-        debug_assert!(hi >= source_file.original_start_pos && hi <= source_file.original_end_pos);
+        debug_assert!(
+            hi >= source_file.original_start_pos && hi <= source_file.original_end_pos,
+            "Bad binary search: hi={:?} source_file.original_start_pos={:?} source_file.original_end_pos={:?}",
+            hi,
+            source_file.original_start_pos,
+            source_file.original_end_pos
+        );
 
         let lo =
             (lo + source_file.translated_source_file.start_pos) - source_file.original_start_pos;
@@ -504,7 +581,7 @@ fn def_kind(&self) -> Option<DefKind> {
             EntryKind::Struct(_, _) => DefKind::Struct,
             EntryKind::Union(_, _) => DefKind::Union,
             EntryKind::Fn(_) | EntryKind::ForeignFn(_) => DefKind::Fn,
-            EntryKind::Method(_) => DefKind::Method,
+            EntryKind::AssocFn(_) => DefKind::AssocFn,
             EntryKind::Type => DefKind::TyAlias,
             EntryKind::TypeParam => DefKind::TyParam,
             EntryKind::ConstParam => DefKind::ConstParam,
@@ -558,50 +635,7 @@ impl CrateRoot<'_> {
     }
 }
 
-impl<'a, 'tcx> CrateMetadata {
-    crate fn new(
-        sess: &Session,
-        blob: MetadataBlob,
-        root: CrateRoot<'static>,
-        raw_proc_macros: Option<&'static [ProcMacro]>,
-        cnum: CrateNum,
-        cnum_map: CrateNumMap,
-        dep_kind: DepKind,
-        source: CrateSource,
-        private_dep: bool,
-        host_hash: Option<Svh>,
-    ) -> CrateMetadata {
-        let def_path_table = record_time(&sess.perf_stats.decode_def_path_tables_time, || {
-            root.def_path_table.decode((&blob, sess))
-        });
-        let trait_impls = root
-            .impls
-            .decode((&blob, sess))
-            .map(|trait_impls| (trait_impls.trait_id, trait_impls.impls))
-            .collect();
-        let alloc_decoding_state =
-            AllocDecodingState::new(root.interpret_alloc_index.decode(&blob).collect());
-        let dependencies = Lock::new(cnum_map.iter().cloned().collect());
-        CrateMetadata {
-            blob,
-            root,
-            def_path_table,
-            trait_impls,
-            raw_proc_macros,
-            source_map_import_info: Once::new(),
-            alloc_decoding_state,
-            dep_node_index: AtomicCell::new(DepNodeIndex::INVALID),
-            cnum,
-            cnum_map,
-            dependencies,
-            dep_kind: Lock::new(dep_kind),
-            source,
-            private_dep,
-            host_hash,
-            extern_crate: Lock::new(None),
-        }
-    }
-
+impl<'a, 'tcx> CrateMetadataRef<'a> {
     fn is_proc_macro(&self, id: DefIndex) -> bool {
         self.root.proc_macro_data.and_then(|data| data.decode(self).find(|x| *x == id)).is_some()
     }
@@ -622,10 +656,6 @@ fn kind(&self, item_id: DefIndex) -> EntryKind {
         })
     }
 
-    fn local_def_id(&self, index: DefIndex) -> DefId {
-        DefId { krate: self.cnum, index }
-    }
-
     fn raw_proc_macro(&self, id: DefIndex) -> &ProcMacro {
         // DefIndex's in root.proc_macro_data have a one-to-one correspondence
         // with items in 'raw_proc_macros'.
@@ -697,6 +727,7 @@ fn get_trait_def(&self, item_id: DefIndex, sess: &Session) -> ty::TraitDef {
                     data.paren_sugar,
                     data.has_auto_impl,
                     data.is_marker,
+                    data.specialization_kind,
                     self.def_path_table.def_path_hash(item_id),
                 )
             }
@@ -706,6 +737,7 @@ fn get_trait_def(&self, item_id: DefIndex, sess: &Session) -> ty::TraitDef {
                 false,
                 false,
                 false,
+                ty::trait_def::TraitSpecializationKind::None,
                 self.def_path_table.def_path_hash(item_id),
             ),
             _ => bug!("def-index does not refer to trait or trait alias"),
@@ -1113,7 +1145,7 @@ fn get_associated_item(&self, id: DefIndex) -> ty::AssocItem {
 
         let (kind, container, has_self) = match self.kind(id) {
             EntryKind::AssocConst(container, _, _) => (ty::AssocKind::Const, container, false),
-            EntryKind::Method(data) => {
+            EntryKind::AssocFn(data) => {
                 let data = data.decode(self);
                 (ty::AssocKind::Method, data.container, data.has_self)
             }
@@ -1191,18 +1223,6 @@ fn get_struct_field_names(&self, id: DefIndex, sess: &Session) -> Vec<Spanned<as
             .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<DefId> {
-        for (local, &global) in self.cnum_map.iter_enumerated() {
-            if global == did.krate {
-                return Some(DefId { krate: local, index: did.index });
-            }
-        }
-
-        None
-    }
-
     fn get_inherent_implementations_for_type(
         &self,
         tcx: TyCtxt<'tcx>,
@@ -1307,7 +1327,7 @@ fn get_missing_lang_items(&self, tcx: TyCtxt<'tcx>) -> &'tcx [lang_items::LangIt
     fn get_fn_param_names(&self, id: DefIndex) -> Vec<ast::Name> {
         let param_names = match self.kind(id) {
             EntryKind::Fn(data) | EntryKind::ForeignFn(data) => data.decode(self).param_names,
-            EntryKind::Method(data) => data.decode(self).fn_data.param_names,
+            EntryKind::AssocFn(data) => data.decode(self).fn_data.param_names,
             _ => Lazy::empty(),
         };
         param_names.decode(self).collect()
@@ -1333,9 +1353,9 @@ fn get_rendered_const(&self, id: DefIndex) -> String {
         }
     }
 
-    fn get_macro(&self, id: DefIndex) -> MacroDef {
+    fn get_macro(&self, id: DefIndex, sess: &Session) -> MacroDef {
         match self.kind(id) {
-            EntryKind::MacroDef(macro_def) => macro_def.decode(self),
+            EntryKind::MacroDef(macro_def) => macro_def.decode((self, sess)),
             _ => bug!(),
         }
     }
@@ -1344,7 +1364,7 @@ fn get_macro(&self, id: DefIndex) -> MacroDef {
     // don't serialize constness for tuple variant and tuple struct constructors.
     fn is_const_fn_raw(&self, id: DefIndex) -> bool {
         let constness = match self.kind(id) {
-            EntryKind::Method(data) => data.decode(self).fn_data.constness,
+            EntryKind::AssocFn(data) => data.decode(self).fn_data.constness,
             EntryKind::Fn(data) => data.decode(self).constness,
             // Some intrinsics can be const fn. While we could recompute this (at least until we
             // stop having hardcoded whitelists and move to stability attributes), it seems cleaner
@@ -1359,7 +1379,7 @@ fn is_const_fn_raw(&self, id: DefIndex) -> bool {
     fn asyncness(&self, id: DefIndex) -> hir::IsAsync {
         match self.kind(id) {
             EntryKind::Fn(data) => data.decode(self).asyncness,
-            EntryKind::Method(data) => data.decode(self).fn_data.asyncness,
+            EntryKind::AssocFn(data) => data.decode(self).fn_data.asyncness,
             EntryKind::ForeignFn(data) => data.decode(self).asyncness,
             _ => bug!("asyncness: expected function kind"),
         }
@@ -1409,11 +1429,6 @@ fn def_path(&self, id: DefIndex) -> DefPath {
         DefPath::make(self.cnum, id, |parent| self.def_key(parent))
     }
 
-    #[inline]
-    fn def_path_hash(&self, index: DefIndex) -> DefPathHash {
-        self.def_path_table.def_path_hash(index)
-    }
-
     /// Imports the source_map from an external crate into the source_map of the crate
     /// currently being compiled (the "local crate").
     ///
@@ -1440,10 +1455,10 @@ fn def_path_hash(&self, index: DefIndex) -> DefPathHash {
     /// Proc macro crates don't currently export spans, so this function does not have
     /// to work for them.
     fn imported_source_files(
-        &'a self,
+        &self,
         local_source_map: &source_map::SourceMap,
-    ) -> &[ImportedSourceFile] {
-        self.source_map_import_info.init_locking(|| {
+    ) -> &'a [ImportedSourceFile] {
+        self.cdata.source_map_import_info.init_locking(|| {
             let external_source_map = self.root.source_map.decode(self);
 
             external_source_map
@@ -1487,14 +1502,16 @@ fn imported_source_files(
                     let local_version = local_source_map.new_imported_source_file(
                         name,
                         name_was_remapped,
-                        self.cnum.as_u32(),
                         src_hash,
                         name_hash,
                         source_length,
+                        self.cnum,
                         lines,
                         multibyte_chars,
                         non_narrow_chars,
                         normalized_pos,
+                        start_pos,
+                        end_pos,
                     );
                     debug!(
                         "CrateMetaData::imported_source_files alloc \
@@ -1516,29 +1533,50 @@ fn imported_source_files(
                 .collect()
         })
     }
+}
 
-    /// Get the `DepNodeIndex` corresponding this crate. The result of this
-    /// method is cached in the `dep_node_index` field.
-    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(dep_graph::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);
+impl CrateMetadata {
+    crate fn new(
+        sess: &Session,
+        blob: MetadataBlob,
+        root: CrateRoot<'static>,
+        raw_proc_macros: Option<&'static [ProcMacro]>,
+        cnum: CrateNum,
+        cnum_map: CrateNumMap,
+        dep_kind: DepKind,
+        source: CrateSource,
+        private_dep: bool,
+        host_hash: Option<Svh>,
+    ) -> CrateMetadata {
+        let def_path_table = record_time(&sess.perf_stats.decode_def_path_tables_time, || {
+            root.def_path_table.decode((&blob, sess))
+        });
+        let trait_impls = root
+            .impls
+            .decode((&blob, sess))
+            .map(|trait_impls| (trait_impls.trait_id, trait_impls.impls))
+            .collect();
+        let alloc_decoding_state =
+            AllocDecodingState::new(root.interpret_alloc_index.decode(&blob).collect());
+        let dependencies = Lock::new(cnum_map.iter().cloned().collect());
+        CrateMetadata {
+            blob,
+            root,
+            def_path_table,
+            trait_impls,
+            raw_proc_macros,
+            source_map_import_info: Once::new(),
+            alloc_decoding_state,
+            dep_node_index: AtomicCell::new(DepNodeIndex::INVALID),
+            cnum,
+            cnum_map,
+            dependencies,
+            dep_kind: Lock::new(dep_kind),
+            source,
+            private_dep,
+            host_hash,
+            extern_crate: Lock::new(None),
         }
-
-        dep_node_index
     }
 
     crate fn dependencies(&self) -> LockGuard<'_, Vec<CrateNum>> {
@@ -1613,6 +1651,52 @@ fn get_crate_dep_node_index(&self, tcx: TyCtxt<'tcx>) -> DepNodeIndex {
     crate fn hash(&self) -> Svh {
         self.root.hash
     }
+
+    fn local_def_id(&self, index: DefIndex) -> DefId {
+        DefId { krate: self.cnum, index }
+    }
+
+    // Translate a DefId from the current compilation environment to a DefId
+    // for an external crate.
+    fn reverse_translate_def_id(&self, did: DefId) -> Option<DefId> {
+        for (local, &global) in self.cnum_map.iter_enumerated() {
+            if global == did.krate {
+                return Some(DefId { krate: local, index: did.index });
+            }
+        }
+
+        None
+    }
+
+    #[inline]
+    fn def_path_hash(&self, index: DefIndex) -> DefPathHash {
+        self.def_path_table.def_path_hash(index)
+    }
+
+    /// Get the `DepNodeIndex` corresponding this crate. The result of this
+    /// method is cached in the `dep_node_index` field.
+    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 =
+                DepNode::from_def_path_hash(def_path_hash, dep_graph::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
index 50ab3811f523604047c950dcc2d84c889b4c7c8b..cc2bd51f92f3e132889605a34621ec60c6cdf81d 100644 (file)
@@ -7,34 +7,27 @@
 use rustc::hir::exports::Export;
 use rustc::hir::map::definitions::DefPathTable;
 use rustc::hir::map::{DefKey, DefPath, DefPathHash};
-use rustc::middle::cstore::{CrateSource, CrateStore, DepKind, EncodedMetadata, NativeLibraryKind};
+use rustc::middle::cstore::{CrateSource, CrateStore, EncodedMetadata, NativeLibraryKind};
 use rustc::middle::exported_symbols::ExportedSymbol;
 use rustc::middle::stability::DeprecationEntry;
-use rustc::session::{CrateDisambiguator, Session};
 use rustc::ty::query::Providers;
 use rustc::ty::query::QueryConfig;
 use rustc::ty::{self, TyCtxt};
+use rustc_ast::ast;
+use rustc_ast::attr;
+use rustc_ast::expand::allocator::AllocatorKind;
 use rustc_data_structures::svh::Svh;
 use rustc_hir as hir;
 use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE};
-use rustc_parse::parser::emit_unclosed_delims;
-use rustc_parse::source_file_to_stream;
+use rustc_session::{CrateDisambiguator, Session};
+use rustc_span::source_map::{self, Span, Spanned};
+use rustc_span::symbol::Symbol;
 
 use rustc_data_structures::sync::Lrc;
 use smallvec::SmallVec;
 use std::any::Any;
 use std::sync::Arc;
 
-use rustc_ast::ast;
-use rustc_ast::attr;
-use rustc_ast::expand::allocator::AllocatorKind;
-use rustc_ast::ptr::P;
-use rustc_ast::tokenstream::DelimSpan;
-use rustc_span::source_map;
-use rustc_span::source_map::Spanned;
-use rustc_span::symbol::Symbol;
-use rustc_span::{FileName, Span};
-
 macro_rules! provide {
     (<$lt:tt> $tcx:ident, $def_id:ident, $other:ident, $cdata:ident,
       $($name:ident => $compute:block)*) => {
@@ -147,7 +140,7 @@ fn into_args(self) -> (DefId, DefId) {
         cdata.get_deprecation(def_id.index).map(DeprecationEntry::external)
     }
     item_attrs => { cdata.get_item_attrs(def_id.index, tcx.sess) }
-    // FIXME(#38501) We've skipped a `read` on the `HirBody` of
+    // FIXME(#38501) We've skipped a `read` on the `hir_owner_items` of
     // a `fn` when encoding, so the dep-tracking wouldn't work.
     // This is only used by rustdoc anyway, which shouldn't have
     // incremental recompilation ever enabled.
@@ -393,14 +386,6 @@ pub fn provide(providers: &mut Providers<'_>) {
 }
 
 impl CStore {
-    pub fn export_macros_untracked(&self, cnum: CrateNum) {
-        let data = self.get_crate_data(cnum);
-        let mut dep_kind = data.dep_kind.lock();
-        if *dep_kind == DepKind::UnexportedMacrosOnly {
-            *dep_kind = DepKind::MacrosOnly;
-        }
-    }
-
     pub fn struct_field_names_untracked(&self, def: DefId, sess: &Session) -> Vec<Spanned<Symbol>> {
         self.get_crate_data(def.krate).get_struct_field_names(def.index, sess)
     }
@@ -427,15 +412,7 @@ pub fn load_macro_untracked(&self, id: DefId, sess: &Session) -> LoadedMacro {
             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 source_name = FileName::Macros(macro_full_name);
-
-        let source_file = sess.parse_sess.source_map().new_source_file(source_name, def.body);
-        let local_span = Span::with_root_ctxt(source_file.start_pos, source_file.end_pos);
-        let dspan = DelimSpan::from_single(local_span);
-        let (body, mut errors) = source_file_to_stream(&sess.parse_sess, source_file, None);
-        emit_unclosed_delims(&mut errors, &sess.parse_sess);
+        let span = data.get_span(id.index, sess);
 
         // Mark the attrs as used
         let attrs = data.get_item_attrs(id.index, sess);
@@ -443,28 +420,22 @@ pub fn load_macro_untracked(&self, id: DefId, sess: &Session) -> LoadedMacro {
             attr::mark_used(attr);
         }
 
-        let name = data
+        let ident = data
             .def_key(id.index)
             .disambiguated_data
             .data
             .get_opt_name()
+            .map(ast::Ident::with_dummy_span) // FIXME: cross-crate hygiene
             .expect("no name in load_macro");
-        sess.imported_macro_spans
-            .borrow_mut()
-            .insert(local_span, (name.to_string(), data.get_span(id.index, sess)));
 
         LoadedMacro::MacroDef(
             ast::Item {
-                // FIXME: cross-crate hygiene
-                ident: ast::Ident::with_dummy_span(name),
+                ident,
                 id: ast::DUMMY_NODE_ID,
-                span: local_span,
+                span,
                 attrs: attrs.iter().cloned().collect(),
-                kind: ast::ItemKind::MacroDef(ast::MacroDef {
-                    body: P(ast::MacArgs::Delimited(dspan, ast::MacDelimiter::Brace, body)),
-                    legacy: def.legacy,
-                }),
-                vis: source_map::respan(local_span.shrink_to_lo(), ast::VisibilityKind::Inherited),
+                kind: ast::ItemKind::MacroDef(data.get_macro(id.index, sess)),
+                vis: source_map::respan(span.shrink_to_lo(), ast::VisibilityKind::Inherited),
                 tokens: None,
             },
             data.root.edition,
@@ -525,7 +496,7 @@ fn def_path_hash(&self, def: DefId) -> DefPathHash {
     }
 
     fn def_path_table(&self, cnum: CrateNum) -> &DefPathTable {
-        &self.get_crate_data(cnum).def_path_table
+        &self.get_crate_data(cnum).cdata.def_path_table
     }
 
     fn crates_untracked(&self) -> Vec<CrateNum> {
index ea0cc2f0c8bf254c76c0dd3da28c0ab359da16da..6280fd62de9a828617caa8afa206e42443e48f2e 100644 (file)
@@ -1,6 +1,7 @@
 use crate::rmeta::table::FixedSizeEncoding;
 use crate::rmeta::*;
 
+use log::{debug, trace};
 use rustc::hir::map::definitions::DefPathTable;
 use rustc::hir::map::Map;
 use rustc::middle::cstore::{EncodedMetadata, ForeignModule, LinkagePreference, NativeLibrary};
 use rustc::ty::codec::{self as ty_codec, TyEncoder};
 use rustc::ty::layout::VariantIdx;
 use rustc::ty::{self, SymbolName, Ty, TyCtxt};
+use rustc_ast::ast;
+use rustc_ast::attr;
 use rustc_data_structures::fingerprint::Fingerprint;
+use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::stable_hasher::StableHasher;
+use rustc_data_structures::sync::Lrc;
+use rustc_hir as hir;
 use rustc_hir::def::CtorKind;
 use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
+use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_hir::{AnonConst, GenericParamKind};
 use rustc_index::vec::Idx;
-
-use rustc::session::config::{self, CrateType};
-use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::stable_hasher::StableHasher;
-use rustc_data_structures::sync::Lrc;
 use rustc_serialize::{opaque, Encodable, Encoder, SpecializedEncoder};
-
-use log::{debug, trace};
-use rustc_ast::ast;
-use rustc_ast::attr;
+use rustc_session::config::{self, CrateType};
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
-use rustc_span::{self, FileName, SourceFile, Span};
+use rustc_span::{self, ExternalSource, FileName, SourceFile, Span};
 use std::hash::Hash;
 use std::num::NonZeroUsize;
 use std::path::Path;
 use std::u32;
 
-use rustc_hir as hir;
-use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
-use rustc_hir::itemlikevisit::ItemLikeVisitor;
-
 struct EncodeContext<'tcx> {
     opaque: opaque::Encoder,
     tcx: TyCtxt<'tcx>,
@@ -167,20 +164,56 @@ fn specialized_encode(&mut self, span: &Span) -> Result<(), Self::Error> {
             return TAG_INVALID_SPAN.encode(self);
         }
 
-        // HACK(eddyb) there's no way to indicate which crate a Span is coming
-        // from right now, so decoding would fail to find the SourceFile if
-        // it's not local to the crate the Span is found in.
-        if self.source_file_cache.is_imported() {
-            return TAG_INVALID_SPAN.encode(self);
-        }
+        // There are two possible cases here:
+        // 1. This span comes from a 'foreign' crate - e.g. some crate upstream of the
+        // crate we are writing metadata for. When the metadata for *this* crate gets
+        // deserialized, the deserializer will need to know which crate it originally came
+        // from. We use `TAG_VALID_SPAN_FOREIGN` to indicate that a `CrateNum` should
+        // be deserialized after the rest of the span data, which tells the deserializer
+        // which crate contains the source map information.
+        // 2. This span comes from our own crate. No special hamdling is needed - we just
+        // write `TAG_VALID_SPAN_LOCAL` to let the deserializer know that it should use
+        // our own source map information.
+        let (tag, lo, hi) = if self.source_file_cache.is_imported() {
+            // To simplify deserialization, we 'rebase' this span onto the crate it originally came from
+            // (the crate that 'owns' the file it references. These rebased 'lo' and 'hi' values
+            // are relative to the source map information for the 'foreign' crate whose CrateNum
+            // we write into the metadata. This allows `imported_source_files` to binary
+            // search through the 'foreign' crate's source map information, using the
+            // deserialized 'lo' and 'hi' values directly.
+            //
+            // All of this logic ensures that the final result of deserialization is a 'normal'
+            // Span that can be used without any additional trouble.
+            let external_start_pos = {
+                // Introduce a new scope so that we drop the 'lock()' temporary
+                match &*self.source_file_cache.external_src.lock() {
+                    ExternalSource::Foreign { original_start_pos, .. } => *original_start_pos,
+                    src => panic!("Unexpected external source {:?}", src),
+                }
+            };
+            let lo = (span.lo - self.source_file_cache.start_pos) + external_start_pos;
+            let hi = (span.hi - self.source_file_cache.start_pos) + external_start_pos;
 
-        TAG_VALID_SPAN.encode(self)?;
-        span.lo.encode(self)?;
+            (TAG_VALID_SPAN_FOREIGN, lo, hi)
+        } else {
+            (TAG_VALID_SPAN_LOCAL, span.lo, span.hi)
+        };
+
+        tag.encode(self)?;
+        lo.encode(self)?;
 
         // Encode length which is usually less than span.hi and profits more
         // from the variable-length integer encoding that we use.
-        let len = span.hi - span.lo;
-        len.encode(self)
+        let len = hi - lo;
+        len.encode(self)?;
+
+        if tag == TAG_VALID_SPAN_FOREIGN {
+            // This needs to be two lines to avoid holding the `self.source_file_cache`
+            // while calling `cnum.encode(self)`
+            let cnum = self.source_file_cache.cnum;
+            cnum.encode(self)?;
+        }
+        Ok(())
 
         // Don't encode the expansion context.
     }
@@ -331,7 +364,7 @@ fn lazy<T: ?Sized + LazyMeta>(&mut self, value: impl EncodeContentsForLazy<T>) -
     fn encode_info_for_items(&mut self) {
         let krate = self.tcx.hir().krate();
         let vis = Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Public };
-        self.encode_info_for_mod(hir::CRATE_HIR_ID, &krate.module, &krate.attrs, &vis);
+        self.encode_info_for_mod(hir::CRATE_HIR_ID, &krate.item.module, &krate.item.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);
@@ -493,7 +526,7 @@ fn encode_crate_root(&mut self) -> Lazy<CrateRoot<'tcx>> {
             edition: tcx.sess.edition(),
             has_global_allocator: tcx.has_global_allocator(LOCAL_CRATE),
             has_panic_handler: tcx.has_panic_handler(LOCAL_CRATE),
-            has_default_lib_allocator: has_default_lib_allocator,
+            has_default_lib_allocator,
             plugin_registrar_fn: tcx.plugin_registrar_fn(LOCAL_CRATE).map(|id| id.index),
             proc_macro_decls_static: if is_proc_macro {
                 let id = tcx.proc_macro_decls_static(LOCAL_CRATE).unwrap();
@@ -805,12 +838,12 @@ fn encode_info_for_trait_item(&mut self, def_id: DefId) {
                 )
             }
             ty::AssocKind::Method => {
-                let fn_data = if let hir::TraitItemKind::Method(m_sig, m) = &ast_item.kind {
+                let fn_data = if let hir::TraitItemKind::Fn(m_sig, m) = &ast_item.kind {
                     let param_names = match *m {
-                        hir::TraitMethod::Required(ref names) => {
+                        hir::TraitFn::Required(ref names) => {
                             self.encode_fn_param_names(names)
                         }
-                        hir::TraitMethod::Provided(body) => {
+                        hir::TraitFn::Provided(body) => {
                             self.encode_fn_param_names_for_body(body)
                         }
                     };
@@ -822,7 +855,7 @@ fn encode_info_for_trait_item(&mut self, def_id: DefId) {
                 } else {
                     bug!()
                 };
-                EntryKind::Method(self.lazy(MethodData {
+                EntryKind::AssocFn(self.lazy(AssocFnData {
                     fn_data,
                     container,
                     has_self: trait_item.method_has_self_argument,
@@ -894,7 +927,7 @@ fn encode_info_for_impl_item(&mut self, def_id: DefId) {
                 }
             }
             ty::AssocKind::Method => {
-                let fn_data = if let hir::ImplItemKind::Method(ref sig, body) = ast_item.kind {
+                let fn_data = if let hir::ImplItemKind::Fn(ref sig, body) = ast_item.kind {
                     FnData {
                         asyncness: sig.header.asyncness,
                         constness: sig.header.constness,
@@ -903,7 +936,7 @@ fn encode_info_for_impl_item(&mut self, def_id: DefId) {
                 } else {
                     bug!()
                 };
-                EntryKind::Method(self.lazy(MethodData {
+                EntryKind::AssocFn(self.lazy(AssocFnData {
                     fn_data,
                     container,
                     has_self: impl_item.method_has_self_argument,
@@ -928,7 +961,7 @@ fn encode_info_for_impl_item(&mut self, def_id: DefId) {
         self.encode_inferred_outlives(def_id);
         let mir = match ast_item.kind {
             hir::ImplItemKind::Const(..) => true,
-            hir::ImplItemKind::Method(ref sig, _) => {
+            hir::ImplItemKind::Fn(ref sig, _) => {
                 let generics = self.tcx.generics_of(def_id);
                 let needs_inline = (generics.requires_monomorphization(self.tcx)
                     || tcx.codegen_fn_attrs(def_id).requests_inline())
@@ -1077,12 +1110,13 @@ fn encode_info_for_item(&mut self, def_id: DefId, item: &'tcx hir::Item<'tcx>) {
                 let polarity = self.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| {
-                        match node {
-                            specialization_graph::Node::Impl(parent) => Some(parent),
-                            _ => None,
-                        }
-                    })
+                    trait_def.ancestors(self.tcx, def_id).ok()
+                        .and_then(|mut an| an.nth(1).and_then(|node| {
+                            match node {
+                                specialization_graph::Node::Impl(parent) => Some(parent),
+                                _ => None,
+                            }
+                        }))
                 } else {
                     None
                 };
@@ -1114,6 +1148,7 @@ fn encode_info_for_item(&mut self, def_id: DefId, item: &'tcx hir::Item<'tcx>) {
                     paren_sugar: trait_def.paren_sugar,
                     has_auto_impl: self.tcx.trait_is_auto(def_id),
                     is_marker: trait_def.is_marker,
+                    specialization_kind: trait_def.specialization_kind,
                 };
 
                 EntryKind::Trait(self.lazy(data))
@@ -1235,12 +1270,8 @@ fn encode_info_for_item(&mut self, def_id: DefId, item: &'tcx hir::Item<'tcx>) {
 
     /// Serialize the text of exported macros
     fn encode_info_for_macro_def(&mut self, macro_def: &hir::MacroDef<'_>) {
-        use rustc_ast_pretty::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.kind[def_id] <- EntryKind::MacroDef(self.lazy(macro_def.ast.clone())));
         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] <- macro_def.attrs);
@@ -1319,7 +1350,7 @@ fn encode_proc_macros(&mut self) -> Option<Lazy<[DefIndex]>> {
         let is_proc_macro = self.tcx.sess.crate_types.borrow().contains(&CrateType::ProcMacro);
         if is_proc_macro {
             let tcx = self.tcx;
-            Some(self.lazy(tcx.hir().krate().proc_macros.iter().map(|p| p.owner)))
+            Some(self.lazy(tcx.hir().krate().proc_macros.iter().map(|p| p.owner.local_def_index)))
         } else {
             None
         }
@@ -1407,8 +1438,8 @@ fn encode_impls(&mut self) -> Lazy<[TraitImpls]> {
             .into_iter()
             .map(|(trait_def_id, mut impls)| {
                 // Bring everything into deterministic order for hashing
-                impls.sort_by_cached_key(|&def_index| {
-                    tcx.hir().definitions().def_path_hash(def_index)
+                impls.sort_by_cached_key(|&index| {
+                    tcx.hir().definitions().def_path_hash(LocalDefId { local_def_index: index })
                 });
 
                 TraitImpls {
@@ -1506,8 +1537,8 @@ fn encode_info_for_foreign_item(&mut self, def_id: DefId, nitem: &hir::ForeignIt
 impl Visitor<'tcx> for EncodeContext<'tcx> {
     type Map = Map<'tcx>;
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
-        NestedVisitorMap::OnlyBodies(&self.tcx.hir())
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::OnlyBodies(self.tcx.hir())
     }
     fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
         intravisit::walk_expr(self, ex);
index 9b05fd4734ca35cb8e7e749635a5d9a4fe8f1b77..05d834e5dee12b04097f253edf3fd785136c76ac 100644 (file)
@@ -7,10 +7,8 @@
 use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
 use rustc::middle::lang_items;
 use rustc::mir;
-use rustc::session::config::SymbolManglingVersion;
-use rustc::session::CrateDisambiguator;
 use rustc::ty::{self, ReprOptions, Ty};
-use rustc_ast::ast;
+use rustc_ast::ast::{self, MacroDef};
 use rustc_attr as attr;
 use rustc_data_structures::svh::Svh;
 use rustc_data_structures::sync::MetadataRef;
@@ -19,6 +17,8 @@
 use rustc_hir::def_id::{DefId, DefIndex};
 use rustc_index::vec::IndexVec;
 use rustc_serialize::opaque::Encoder;
+use rustc_session::config::SymbolManglingVersion;
+use rustc_session::CrateDisambiguator;
 use rustc_span::edition::Edition;
 use rustc_span::symbol::Symbol;
 use rustc_span::{self, Span};
@@ -201,7 +201,7 @@ macro_rules! Lazy {
 
     per_def: LazyPerDefTables<'tcx>,
 
-    /// The DefIndex's of any proc macros delcared by this crate.
+    /// The DefIndex's of any proc macros declared by this crate.
     proc_macro_data: Option<Lazy<[DefIndex]>>,
 
     compiler_builtins: bool,
@@ -305,7 +305,7 @@ enum EntryKind {
     Generator(hir::GeneratorKind),
     Trait(Lazy<TraitData>),
     Impl(Lazy<ImplData>),
-    Method(Lazy<MethodData>),
+    AssocFn(Lazy<AssocFnData>),
     AssocType(AssocContainer),
     AssocOpaqueTy(AssocContainer),
     AssocConst(AssocContainer, mir::ConstQualifs, Lazy<RenderedConst>),
@@ -322,12 +322,6 @@ struct ModData {
     reexports: Lazy<[Export<hir::HirId>]>,
 }
 
-#[derive(RustcEncodable, RustcDecodable)]
-struct MacroDef {
-    body: String,
-    legacy: bool,
-}
-
 #[derive(RustcEncodable, RustcDecodable)]
 struct FnData {
     asyncness: hir::IsAsync,
@@ -349,6 +343,7 @@ struct TraitData {
     paren_sugar: bool,
     has_auto_impl: bool,
     is_marker: bool,
+    specialization_kind: ty::trait_def::TraitSpecializationKind,
 }
 
 #[derive(RustcEncodable, RustcDecodable)]
@@ -398,7 +393,7 @@ fn defaultness(&self) -> hir::Defaultness {
 }
 
 #[derive(RustcEncodable, RustcDecodable)]
-struct MethodData {
+struct AssocFnData {
     fn_data: FnData,
     container: AssocContainer,
     has_self: bool,
@@ -410,5 +405,6 @@ struct GeneratorData<'tcx> {
 }
 
 // Tags used for encoding Spans:
-const TAG_VALID_SPAN: u8 = 0;
-const TAG_INVALID_SPAN: u8 = 1;
+const TAG_VALID_SPAN_LOCAL: u8 = 0;
+const TAG_VALID_SPAN_FOREIGN: u8 = 1;
+const TAG_INVALID_SPAN: u8 = 2;
index 6e606230b6371c27093e04c12f0cf08e4800fdda..256a80076b92338ddc61f89859f2fdccf4e51e7e 100644 (file)
@@ -15,7 +15,7 @@ dot = { path = "../libgraphviz", package = "graphviz" }
 itertools = "0.8"
 log = "0.4"
 log_settings = "0.1.1"
-polonius-engine = "0.11.0"
+polonius-engine = "0.12.0"
 rustc = { path = "../librustc" }
 rustc_ast_pretty = { path = "../librustc_ast_pretty" }
 rustc_attr = { path = "../librustc_attr" }
@@ -27,7 +27,9 @@ rustc_infer = { path = "../librustc_infer" }
 rustc_lexer = { path = "../librustc_lexer" }
 rustc_macros = { path = "../librustc_macros" }
 rustc_serialize = { path = "../libserialize", package = "serialize" }
+rustc_session = { path = "../librustc_session" }
 rustc_target = { path = "../librustc_target" }
+rustc_trait_selection = { path = "../librustc_trait_selection" }
 rustc_ast = { path = "../librustc_ast" }
 rustc_span = { path = "../librustc_span" }
 rustc_apfloat = { path = "../librustc_apfloat" }
index ca51d16f9f269fd55f744c6cd90e5b7b27930d48..e895eec5d52af45752284c2cfccab48391defe94 100644 (file)
@@ -10,9 +10,9 @@
 use rustc_hir::def_id::DefId;
 use rustc_hir::{AsyncGeneratorKind, GeneratorKind};
 use rustc_index::vec::Idx;
-use rustc_infer::traits::error_reporting::suggest_constraining_type_param;
 use rustc_span::source_map::DesugaringKind;
 use rustc_span::Span;
+use rustc_trait_selection::traits::error_reporting::suggest_constraining_type_param;
 
 use crate::dataflow::drop_flag_effects;
 use crate::dataflow::indexes::{MoveOutIndex, MovePathIndex};
@@ -51,7 +51,7 @@ pub(in crate::borrow_check) fn report_use_of_moved_or_uninitialized(
         &mut self,
         location: Location,
         desired_action: InitializationRequiringAction,
-        (moved_place, used_place, span): (PlaceRef<'cx, 'tcx>, PlaceRef<'cx, 'tcx>, Span),
+        (moved_place, used_place, span): (PlaceRef<'tcx>, PlaceRef<'tcx>, Span),
         mpi: MovePathIndex,
     ) {
         debug!(
@@ -647,7 +647,7 @@ pub(in crate::borrow_check) fn describe_place_for_conflicting_borrow(
                 // borrowed place and look for a access to a different field of the same union.
                 let Place { local, projection } = second_borrowed_place;
 
-                let mut cursor = projection.as_ref();
+                let mut cursor = &projection[..];
                 while let [proj_base @ .., elem] = cursor {
                     cursor = proj_base;
 
@@ -1231,7 +1231,7 @@ fn report_escaping_closure_capture(
                 GeneratorKind::Async(async_kind) => match async_kind {
                     AsyncGeneratorKind::Block => "async block",
                     AsyncGeneratorKind::Closure => "async closure",
-                    _ => bug!("async block/closure expected, but async funtion found."),
+                    _ => bug!("async block/closure expected, but async function found."),
                 },
                 GeneratorKind::Gen => "generator",
             },
@@ -1521,7 +1521,7 @@ pub(in crate::borrow_check) fn report_illegal_reassignment(
         err.buffer(&mut self.errors_buffer);
     }
 
-    fn classify_drop_access_kind(&self, place: PlaceRef<'cx, 'tcx>) -> StorageDeadOrDrop<'tcx> {
+    fn classify_drop_access_kind(&self, place: PlaceRef<'tcx>) -> StorageDeadOrDrop<'tcx> {
         let tcx = self.infcx.tcx;
         match place.projection {
             [] => StorageDeadOrDrop::LocalStorageDead,
index cd6834a5a4d00b10ecfaf358c506e2fab2337bb5..7110a4a3058a65f93d24a238ca96f833bb7ae326 100644 (file)
@@ -51,7 +51,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     pub(super) fn add_moved_or_invoked_closure_note(
         &self,
         location: Location,
-        place: PlaceRef<'cx, 'tcx>,
+        place: PlaceRef<'tcx>,
         diag: &mut DiagnosticBuilder<'_>,
     ) {
         debug!("add_moved_or_invoked_closure_note: location={:?} place={:?}", location, place);
@@ -139,7 +139,7 @@ pub(super) fn add_moved_or_invoked_closure_note(
 
     /// End-user visible description of `place` if one can be found. If the
     /// place is a temporary for instance, None will be returned.
-    pub(super) fn describe_place(&self, place_ref: PlaceRef<'cx, 'tcx>) -> Option<String> {
+    pub(super) fn describe_place(&self, place_ref: PlaceRef<'tcx>) -> Option<String> {
         self.describe_place_with_options(place_ref, IncludingDowncast(false))
     }
 
@@ -149,7 +149,7 @@ pub(super) fn describe_place(&self, place_ref: PlaceRef<'cx, 'tcx>) -> Option<St
     /// `Downcast` and `IncludingDowncast` is true
     pub(super) fn describe_place_with_options(
         &self,
-        place: PlaceRef<'cx, 'tcx>,
+        place: PlaceRef<'tcx>,
         including_downcast: IncludingDowncast,
     ) -> Option<String> {
         let mut buf = String::new();
@@ -162,7 +162,7 @@ pub(super) fn describe_place_with_options(
     /// Appends end-user visible description of `place` to `buf`.
     fn append_place_to_string(
         &self,
-        place: PlaceRef<'cx, 'tcx>,
+        place: PlaceRef<'tcx>,
         buf: &mut String,
         mut autoderef: bool,
         including_downcast: &IncludingDowncast,
@@ -175,7 +175,7 @@ fn append_place_to_string(
                 if self.body.local_decls[local].is_ref_for_guard() =>
             {
                 self.append_place_to_string(
-                    PlaceRef { local: local, projection: &[] },
+                    PlaceRef { local, projection: &[] },
                     buf,
                     autoderef,
                     &including_downcast,
@@ -303,7 +303,7 @@ fn append_local_to_string(&self, local: Local, buf: &mut String) -> Result<(), (
     }
 
     /// End-user visible description of the `field`nth field of `base`
-    fn describe_field(&self, place: PlaceRef<'cx, 'tcx>, field: Field) -> String {
+    fn describe_field(&self, place: PlaceRef<'tcx>, field: Field) -> String {
         // FIXME Place2 Make this work iteratively
         match place {
             PlaceRef { local, projection: [] } => {
@@ -399,7 +399,7 @@ pub(super) fn note_type_does_not_implement_copy(
 
     pub(super) fn borrowed_content_source(
         &self,
-        deref_base: PlaceRef<'cx, 'tcx>,
+        deref_base: PlaceRef<'tcx>,
     ) -> BorrowedContentSource<'tcx> {
         let tcx = self.infcx.tcx;
 
@@ -694,7 +694,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     /// Finds the spans associated to a move or copy of move_place at location.
     pub(super) fn move_spans(
         &self,
-        moved_place: PlaceRef<'cx, 'tcx>, // Could also be an upvar.
+        moved_place: PlaceRef<'tcx>, // Could also be an upvar.
         location: Location,
     ) -> UseSpans {
         use self::UseSpans::*;
@@ -782,7 +782,7 @@ pub(super) fn borrow_spans(&self, use_span: Span, location: Location) -> UseSpan
     fn closure_span(
         &self,
         def_id: DefId,
-        target_place: PlaceRef<'cx, 'tcx>,
+        target_place: PlaceRef<'tcx>,
         places: &Vec<Operand<'tcx>>,
     ) -> Option<(Span, Option<GeneratorKind>, Span)> {
         debug!(
index d91f6edc9800c3063c3e13ad83fcc704227e488e..c462f93414874150d7adc17b628d9759afcbeaf6 100644 (file)
@@ -23,7 +23,7 @@ pub(crate) fn report_mutability_error(
         &mut self,
         access_place: &Place<'tcx>,
         span: Span,
-        the_place_err: PlaceRef<'cx, 'tcx>,
+        the_place_err: PlaceRef<'tcx>,
         error_access: AccessKind,
         location: Location,
     ) {
@@ -329,40 +329,6 @@ pub(crate) fn report_mutability_error(
                 if self.body.local_decls[local].is_user_variable() =>
             {
                 let local_decl = &self.body.local_decls[local];
-                let suggestion = match local_decl.local_info {
-                    LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::ImplicitSelf(_))) => {
-                        Some(suggest_ampmut_self(self.infcx.tcx, local_decl))
-                    }
-
-                    LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::Var(
-                        mir::VarBindingForm {
-                            binding_mode: ty::BindingMode::BindByValue(_),
-                            opt_ty_info,
-                            ..
-                        },
-                    ))) => Some(suggest_ampmut(
-                        self.infcx.tcx,
-                        self.body,
-                        local,
-                        local_decl,
-                        opt_ty_info,
-                    )),
-
-                    LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::Var(
-                        mir::VarBindingForm {
-                            binding_mode: ty::BindingMode::BindByReference(_),
-                            ..
-                        },
-                    ))) => {
-                        let pattern_span = local_decl.source_info.span;
-                        suggest_ref_mut(self.infcx.tcx, pattern_span)
-                            .map(|replacement| (pattern_span, replacement))
-                    }
-
-                    LocalInfo::User(ClearCrossCrate::Clear) => bug!("saw cleared local state"),
-
-                    _ => unreachable!(),
-                };
 
                 let (pointer_sigil, pointer_desc) = if local_decl.ty.is_region_ptr() {
                     ("&", "reference")
@@ -370,17 +336,53 @@ pub(crate) fn report_mutability_error(
                     ("*const", "pointer")
                 };
 
-                if let Some((err_help_span, suggested_code)) = suggestion {
-                    err.span_suggestion(
-                        err_help_span,
-                        &format!("consider changing this to be a mutable {}", pointer_desc),
-                        suggested_code,
-                        Applicability::MachineApplicable,
-                    );
-                }
-
                 match self.local_names[local] {
                     Some(name) if !local_decl.from_compiler_desugaring() => {
+                        let suggestion = match local_decl.local_info {
+                            LocalInfo::User(ClearCrossCrate::Set(
+                                mir::BindingForm::ImplicitSelf(_),
+                            )) => Some(suggest_ampmut_self(self.infcx.tcx, local_decl)),
+
+                            LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::Var(
+                                mir::VarBindingForm {
+                                    binding_mode: ty::BindingMode::BindByValue(_),
+                                    opt_ty_info,
+                                    ..
+                                },
+                            ))) => Some(suggest_ampmut(
+                                self.infcx.tcx,
+                                self.body,
+                                local,
+                                local_decl,
+                                opt_ty_info,
+                            )),
+
+                            LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::Var(
+                                mir::VarBindingForm {
+                                    binding_mode: ty::BindingMode::BindByReference(_),
+                                    ..
+                                },
+                            ))) => {
+                                let pattern_span = local_decl.source_info.span;
+                                suggest_ref_mut(self.infcx.tcx, pattern_span)
+                                    .map(|replacement| (pattern_span, replacement))
+                            }
+
+                            LocalInfo::User(ClearCrossCrate::Clear) => {
+                                bug!("saw cleared local state")
+                            }
+
+                            _ => unreachable!(),
+                        };
+
+                        if let Some((err_help_span, suggested_code)) = suggestion {
+                            err.span_suggestion(
+                                err_help_span,
+                                &format!("consider changing this to be a mutable {}", pointer_desc),
+                                suggested_code,
+                                Applicability::MachineApplicable,
+                            );
+                        }
                         err.span_label(
                             span,
                             format!(
@@ -445,7 +447,7 @@ pub(crate) fn report_mutability_error(
         err.buffer(&mut self.errors_buffer);
     }
 
-    /// Targetted error when encountering an `FnMut` closure where an `Fn` closure was expected.
+    /// Targeted error when encountering an `FnMut` closure where an `Fn` closure was expected.
     fn expected_fn_found_fn_mut_call(&self, err: &mut DiagnosticBuilder<'_>, sp: Span, act: &str) {
         err.span_label(sp, format!("cannot {}", act));
 
@@ -478,12 +480,12 @@ fn expected_fn_found_fn_mut_call(&self, err: &mut DiagnosticBuilder<'_>, sp: Spa
                         }))
                         | Some(hir::Node::TraitItem(hir::TraitItem {
                             ident,
-                            kind: hir::TraitItemKind::Method(sig, _),
+                            kind: hir::TraitItemKind::Fn(sig, _),
                             ..
                         }))
                         | Some(hir::Node::ImplItem(hir::ImplItem {
                             ident,
-                            kind: hir::ImplItemKind::Method(sig, _),
+                            kind: hir::ImplItemKind::Fn(sig, _),
                             ..
                         })) => Some(
                             arg_pos
@@ -520,12 +522,12 @@ fn expected_fn_found_fn_mut_call(&self, err: &mut DiagnosticBuilder<'_>, sp: Spa
                 hir::Node::Item(hir::Item { ident, kind: hir::ItemKind::Fn(sig, ..), .. })
                 | hir::Node::TraitItem(hir::TraitItem {
                     ident,
-                    kind: hir::TraitItemKind::Method(sig, _),
+                    kind: hir::TraitItemKind::Fn(sig, _),
                     ..
                 })
                 | hir::Node::ImplItem(hir::ImplItem {
                     ident,
-                    kind: hir::ImplItemKind::Method(sig, _),
+                    kind: hir::ImplItemKind::Fn(sig, _),
                     ..
                 }) => {
                     err.span_label(ident.span, "");
index 8cd75d4a2fd27a085c7328882590c410ea407c16..494b6421fd5d49bcf9e9eae433e76813650b0b58 100644 (file)
@@ -4,7 +4,8 @@
 use rustc::ty::{self, RegionVid, Ty};
 use rustc_errors::{Applicability, DiagnosticBuilder};
 use rustc_infer::infer::{
-    error_reporting::nice_region_error::NiceRegionError, opaque_types, NLLRegionVariableOrigin,
+    error_reporting::nice_region_error::NiceRegionError,
+    error_reporting::unexpected_hidden_region_diagnostic, NLLRegionVariableOrigin,
 };
 use rustc_span::symbol::kw;
 use rustc_span::Span;
@@ -197,7 +198,7 @@ pub(in crate::borrow_check) fn report_region_errors(&mut self, nll_errors: Regio
                     let region_scope_tree = &self.infcx.tcx.region_scope_tree(self.mir_def_id);
                     let named_ty = self.regioncx.name_regions(self.infcx.tcx, hidden_ty);
                     let named_region = self.regioncx.name_regions(self.infcx.tcx, member_region);
-                    opaque_types::unexpected_hidden_region_diagnostic(
+                    unexpected_hidden_region_diagnostic(
                         self.infcx.tcx,
                         Some(region_scope_tree),
                         span,
@@ -283,8 +284,7 @@ pub(in crate::borrow_check) fn report_region_error(
         debug!("report_region_error: category={:?} {:?}", category, span);
         // Check if we can use one of the "nice region errors".
         if let (Some(f), Some(o)) = (self.to_error_region(fr), self.to_error_region(outlived_fr)) {
-            let tables = self.infcx.tcx.typeck_tables_of(self.mir_def_id);
-            let nice = NiceRegionError::new_from_span(self.infcx, span, o, f, Some(tables));
+            let nice = NiceRegionError::new_from_span(self.infcx, span, o, f);
             if let Some(diag) = nice.try_report_from_nll() {
                 diag.buffer(&mut self.errors_buffer);
                 return;
index 01ace74287622c1175cc7fd3b9a1c407b6371ee8..7103fc596c92269c4bda1121550c1a41f8e87353 100644 (file)
@@ -651,7 +651,7 @@ fn give_name_if_anonymous_region_appears_in_output(&self, fr: RegionVid) -> Opti
                 if gen_move.is_some() { " of generator" } else { " of closure" },
             ),
             hir::Node::ImplItem(hir::ImplItem {
-                kind: hir::ImplItemKind::Method(method_sig, _),
+                kind: hir::ImplItemKind::Fn(method_sig, _),
                 ..
             }) => (method_sig.decl.output.span(), ""),
             _ => (self.body.span, ""),
index 827ccb1c85733badb2a585cdb9dc897f18820d33..cd8139b17b48d373679b6a3402541151637c9178 100644 (file)
@@ -71,16 +71,16 @@ macro_rules! write_facts_to_path {
                 killed,
                 outlives,
                 invalidates,
-                var_used,
-                var_defined,
-                var_drop_used,
-                var_uses_region,
-                var_drops_region,
-                child,
-                path_belongs_to_var,
-                initialized_at,
-                moved_out_at,
-                path_accessed_at,
+                var_used_at,
+                var_defined_at,
+                var_dropped_at,
+                use_of_var_derefs_origin,
+                drop_of_var_derefs_origin,
+                child_path,
+                path_is_var,
+                path_assigned_at_base,
+                path_moved_at_base,
+                path_accessed_at_base,
                 known_subset,
             ])
         }
index 0bead27050ce642cb6830199f7e8e41db7a5fee4..d33639aa9d9a080009a6261ac2c95bf5af25a583 100644 (file)
@@ -63,7 +63,7 @@ fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
                 self.mutate_place(location, lhs, Shallow(None), JustWrite);
             }
             StatementKind::FakeRead(_, _) => {
-                // Only relavent for initialized/liveness/safety checks.
+                // Only relevant for initialized/liveness/safety checks.
             }
             StatementKind::SetDiscriminant { ref place, variant_index: _ } => {
                 self.mutate_place(location, place, Shallow(None), JustWrite);
index aeb29d2e11eb0205c04a311069e884053471e32f..4323e2db844766697c58287a83da20b2ca67e7e2 100644 (file)
@@ -125,7 +125,7 @@ impl<R1> MemberConstraintSet<'tcx, R1>
         // wind up mapped to the same key `S`, we would append the
         // linked list for `Ra` onto the end of the linked list for
         // `Rb` (or vice versa) -- this basically just requires
-        // rewriting the final link from one list to point at the othe
+        // rewriting the final link from one list to point at the other
         // other (see `append_list`).
 
         let MemberConstraintSet { first_constraints, mut constraints, choice_regions } = self;
index 28974dcd08bf6e883ed199dfdca687d621f87ebf..6c1901455fda95f4868f550e6c65862af19c59e3 100644 (file)
@@ -1,7 +1,5 @@
 //! This query borrow-checks the MIR to (further) ensure it is not broken.
 
-use rustc::lint::builtin::MUTABLE_BORROW_RESERVATION_CONFLICT;
-use rustc::lint::builtin::UNUSED_MUT;
 use rustc::mir::{
     read_only, traversal, Body, BodyAndCache, ClearCrossCrate, Local, Location, Mutability,
     Operand, Place, PlaceElem, PlaceRef, ReadOnlyBodyAndCache,
@@ -11,7 +9,7 @@
 use rustc::mir::{Terminator, TerminatorKind};
 use rustc::ty::query::Providers;
 use rustc::ty::{self, RegionVid, TyCtxt};
-
+use rustc_ast::ast::Name;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::graph::dominators::Dominators;
 use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder};
@@ -20,6 +18,8 @@
 use rustc_index::bit_set::BitSet;
 use rustc_index::vec::IndexVec;
 use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
+use rustc_session::lint::builtin::{MUTABLE_BORROW_RESERVATION_CONFLICT, UNUSED_MUT};
+use rustc_span::{Span, DUMMY_SP};
 
 use either::Either;
 use smallvec::SmallVec;
@@ -28,9 +28,6 @@
 use std::mem;
 use std::rc::Rc;
 
-use rustc_ast::ast::Name;
-use rustc_span::{Span, DUMMY_SP};
-
 use crate::dataflow;
 use crate::dataflow::generic::{Analysis, BorrowckFlowState as Flows, BorrowckResults};
 use crate::dataflow::indexes::{BorrowIndex, InitIndex, MoveOutIndex, MovePathIndex};
@@ -86,6 +83,8 @@
     mutability: Mutability,
 }
 
+const DEREF_PROJECTION: &[PlaceElem<'_>; 1] = &[ProjectionElem::Deref];
+
 pub fn provide(providers: &mut Providers<'_>) {
     *providers = Providers { mir_borrowck, ..*providers };
 }
@@ -452,7 +451,7 @@ fn do_mir_borrowck<'a, 'tcx>(
     /// for the activation of the borrow.
     reservation_warnings:
         FxHashMap<BorrowIndex, (Place<'tcx>, Span, Location, BorrowKind, BorrowData<'tcx>)>,
-    /// This field keeps track of move errors that are to be reported for given move indicies.
+    /// This field keeps track of move errors that are to be reported for given move indices.
     ///
     /// There are situations where many errors can be reported for a single move out (see #53807)
     /// and we want only the best of those errors.
@@ -466,10 +465,10 @@ fn do_mir_borrowck<'a, 'tcx>(
     /// `BTreeMap` is used to preserve the order of insertions when iterating. This is necessary
     /// when errors in the map are being re-added to the error buffer so that errors with the
     /// same primary span come out in a consistent order.
-    move_error_reported: BTreeMap<Vec<MoveOutIndex>, (PlaceRef<'cx, 'tcx>, DiagnosticBuilder<'cx>)>,
+    move_error_reported: BTreeMap<Vec<MoveOutIndex>, (PlaceRef<'tcx>, DiagnosticBuilder<'cx>)>,
     /// This field keeps track of errors reported in the checking of uninitialized variables,
     /// so that we don't report seemingly duplicate errors.
-    uninitialized_error_reported: FxHashSet<PlaceRef<'cx, 'tcx>>,
+    uninitialized_error_reported: FxHashSet<PlaceRef<'tcx>>,
     /// Errors to be reported buffer
     errors_buffer: Vec<Diagnostic>,
     /// This field keeps track of all the local variables that are declared mut and are mutated.
@@ -841,9 +840,9 @@ enum InitializationRequiringAction {
     PartialAssignment,
 }
 
-struct RootPlace<'d, 'tcx> {
+struct RootPlace<'tcx> {
     place_local: Local,
-    place_projection: &'d [PlaceElem<'tcx>],
+    place_projection: &'tcx [PlaceElem<'tcx>],
     is_local_mutation_allowed: LocalMutationIsAllowed,
 }
 
@@ -1413,7 +1412,6 @@ fn check_for_invalidation_at_exit(
     ) {
         debug!("check_for_invalidation_at_exit({:?})", borrow);
         let place = &borrow.borrowed_place;
-        let deref = [ProjectionElem::Deref];
         let mut root_place = PlaceRef { local: place.local, projection: &[] };
 
         // FIXME(nll-rfc#40): do more precise destructor tracking here. For now
@@ -1427,7 +1425,7 @@ fn check_for_invalidation_at_exit(
                 // Thread-locals might be dropped after the function exits
                 // We have to dereference the outer reference because
                 // borrows don't conflict behind shared references.
-                root_place.projection = &deref;
+                root_place.projection = DEREF_PROJECTION;
                 (true, true)
             } else {
                 (false, self.locals_are_invalidated_at_exit)
@@ -1526,7 +1524,7 @@ fn check_if_full_path_is_moved(
         &mut self,
         location: Location,
         desired_action: InitializationRequiringAction,
-        place_span: (PlaceRef<'cx, 'tcx>, Span),
+        place_span: (PlaceRef<'tcx>, Span),
         flow_state: &Flows<'cx, 'tcx>,
     ) {
         let maybe_uninits = &flow_state.uninits;
@@ -1592,7 +1590,7 @@ fn check_if_subslice_element_is_moved(
         &mut self,
         location: Location,
         desired_action: InitializationRequiringAction,
-        place_span: (PlaceRef<'cx, 'tcx>, Span),
+        place_span: (PlaceRef<'tcx>, Span),
         maybe_uninits: &BitSet<MovePathIndex>,
         from: u32,
         to: u32,
@@ -1631,7 +1629,7 @@ fn check_if_path_or_subpath_is_moved(
         &mut self,
         location: Location,
         desired_action: InitializationRequiringAction,
-        place_span: (PlaceRef<'cx, 'tcx>, Span),
+        place_span: (PlaceRef<'tcx>, Span),
         flow_state: &Flows<'cx, 'tcx>,
     ) {
         let maybe_uninits = &flow_state.uninits;
@@ -1709,10 +1707,7 @@ fn check_if_path_or_subpath_is_moved(
     /// An Err result includes a tag indicated why the search failed.
     /// Currently this can only occur if the place is built off of a
     /// static variable, as we do not track those in the MoveData.
-    fn move_path_closest_to(
-        &mut self,
-        place: PlaceRef<'_, 'tcx>,
-    ) -> (PlaceRef<'cx, 'tcx>, MovePathIndex) {
+    fn move_path_closest_to(&mut self, place: PlaceRef<'tcx>) -> (PlaceRef<'tcx>, MovePathIndex) {
         match self.move_data.rev_lookup.find(place) {
             LookupResult::Parent(Some(mpi)) | LookupResult::Exact(mpi) => {
                 (self.move_data.move_paths[mpi].place.as_ref(), mpi)
@@ -1721,7 +1716,7 @@ fn move_path_closest_to(
         }
     }
 
-    fn move_path_for_place(&mut self, place: PlaceRef<'_, 'tcx>) -> Option<MovePathIndex> {
+    fn move_path_for_place(&mut self, place: PlaceRef<'tcx>) -> Option<MovePathIndex> {
         // If returns None, then there is no move path corresponding
         // to a direct owner of `place` (which means there is nothing
         // that borrowck tracks for its analysis).
@@ -1816,7 +1811,7 @@ fn check_if_assigned_path_is_moved(
         fn check_parent_of_field<'cx, 'tcx>(
             this: &mut MirBorrowckCtxt<'cx, 'tcx>,
             location: Location,
-            base: PlaceRef<'cx, 'tcx>,
+            base: PlaceRef<'tcx>,
             span: Span,
             flow_state: &Flows<'cx, 'tcx>,
         ) {
@@ -2029,7 +2024,7 @@ fn is_local_ever_initialized(
     }
 
     /// Adds the place into the used mutable variables set
-    fn add_used_mut<'d>(&mut self, root_place: RootPlace<'d, 'tcx>, flow_state: &Flows<'cx, 'tcx>) {
+    fn add_used_mut(&mut self, root_place: RootPlace<'tcx>, flow_state: &Flows<'cx, 'tcx>) {
         match root_place {
             RootPlace { place_local: local, place_projection: [], is_local_mutation_allowed } => {
                 // If the local may have been initialized, and it is now currently being
@@ -2063,11 +2058,11 @@ fn add_used_mut<'d>(&mut self, root_place: RootPlace<'d, 'tcx>, flow_state: &Flo
 
     /// Whether this value can be written or borrowed mutably.
     /// Returns the root place if the place passed in is a projection.
-    fn is_mutable<'d>(
+    fn is_mutable(
         &self,
-        place: PlaceRef<'d, 'tcx>,
+        place: PlaceRef<'tcx>,
         is_local_mutation_allowed: LocalMutationIsAllowed,
-    ) -> Result<RootPlace<'d, 'tcx>, PlaceRef<'d, 'tcx>> {
+    ) -> Result<RootPlace<'tcx>, PlaceRef<'tcx>> {
         match place {
             PlaceRef { local, projection: [] } => {
                 let local = &self.body.local_decls[local];
@@ -2218,7 +2213,7 @@ fn is_mutable<'d>(
     /// then returns the index of the field being projected. Note that this closure will always
     /// be `self` in the current MIR, because that is the only time we directly access the fields
     /// of a closure type.
-    pub fn is_upvar_field_projection(&self, place_ref: PlaceRef<'cx, 'tcx>) -> Option<Field> {
+    pub fn is_upvar_field_projection(&self, place_ref: PlaceRef<'tcx>) -> Option<Field> {
         let mut place_projection = place_ref.projection;
         let mut by_ref = false;
 
index 2201abe4b92f998159064c68802982e2589ea261..077ed49ed2cacc8fc248a8e1f5c3ed561b36536f 100644 (file)
@@ -86,15 +86,18 @@ fn populate_polonius_move_facts(
     body: &Body<'_>,
 ) {
     all_facts
-        .path_belongs_to_var
+        .path_is_var
         .extend(move_data.rev_lookup.iter_locals_enumerated().map(|(v, &m)| (m, v)));
 
     for (child, move_path) in move_data.move_paths.iter_enumerated() {
-        all_facts
-            .child
-            .extend(move_path.parents(&move_data.move_paths).map(|(parent, _)| (child, parent)));
+        if let Some(parent) = move_path.parent {
+            all_facts.child_path.push((child, parent));
+        }
     }
 
+    let fn_entry_start = location_table
+        .start_index(Location { block: BasicBlock::from_u32(0u32), statement_index: 0 });
+
     // initialized_at
     for init in move_data.inits.iter() {
         match init.location {
@@ -115,28 +118,37 @@ fn populate_polonius_move_facts(
                         // the successors, but not in the unwind block.
                         let first_statement = Location { block: successor, statement_index: 0 };
                         all_facts
-                            .initialized_at
+                            .path_assigned_at_base
                             .push((init.path, location_table.start_index(first_statement)));
                     }
                 } else {
                     // In all other cases, the initialization just happens at the
                     // midpoint, like any other effect.
-                    all_facts.initialized_at.push((init.path, location_table.mid_index(location)));
+                    all_facts
+                        .path_assigned_at_base
+                        .push((init.path, location_table.mid_index(location)));
                 }
             }
             // Arguments are initialized on function entry
             InitLocation::Argument(local) => {
                 assert!(body.local_kind(local) == LocalKind::Arg);
-                let fn_entry = Location { block: BasicBlock::from_u32(0u32), statement_index: 0 };
-                all_facts.initialized_at.push((init.path, location_table.start_index(fn_entry)));
+                all_facts.path_assigned_at_base.push((init.path, fn_entry_start));
             }
         }
     }
 
+    for (local, &path) in move_data.rev_lookup.iter_locals_enumerated() {
+        if body.local_kind(local) != LocalKind::Arg {
+            // Non-arguments start out deinitialised; we simulate this with an
+            // initial move:
+            all_facts.path_moved_at_base.push((path, fn_entry_start));
+        }
+    }
+
     // moved_out_at
     // deinitialisation is assumed to always happen!
     all_facts
-        .moved_out_at
+        .path_moved_at_base
         .extend(move_data.moves.iter().map(|mo| (mo.path, location_table.mid_index(mo.source))));
 }
 
@@ -260,7 +272,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>(
     // Dump facts if requested.
     let polonius_output = all_facts.and_then(|all_facts| {
         if infcx.tcx.sess.opts.debugging_opts.nll_facts {
-            let def_path = infcx.tcx.hir().def_path(def_id);
+            let def_path = infcx.tcx.def_path(def_id);
             let dir_path =
                 PathBuf::from("nll-facts").join(def_path.to_filename_friendly_no_crate());
             all_facts.write_to_dir(dir_path, location_table).unwrap();
index 984de021ca11276da6b3648c87a3ac3d76053d8b..767ffa50fedb4cd23f30434c70ae559308e9a95c 100644 (file)
@@ -48,7 +48,7 @@ pub(super) fn borrow_conflicts_with_place<'tcx>(
     body: &Body<'tcx>,
     borrow_place: &Place<'tcx>,
     borrow_kind: BorrowKind,
-    access_place: PlaceRef<'_, 'tcx>,
+    access_place: PlaceRef<'tcx>,
     access: AccessDepth,
     bias: PlaceConflictBias,
 ) -> bool {
@@ -73,7 +73,7 @@ fn place_components_conflict<'tcx>(
     body: &Body<'tcx>,
     borrow_place: &Place<'tcx>,
     borrow_kind: BorrowKind,
-    access_place: PlaceRef<'_, 'tcx>,
+    access_place: PlaceRef<'tcx>,
     access: AccessDepth,
     bias: PlaceConflictBias,
 ) -> bool {
index 31bee460fa0113f4a9be55e61c87062f0f4c0aad..c64e8c363af54c9777c6279122733b3b8592d0d1 100644 (file)
 use rustc::ty::{self, TyCtxt};
 use rustc_hir as hir;
 
-pub trait IsPrefixOf<'cx, 'tcx> {
-    fn is_prefix_of(&self, other: PlaceRef<'cx, 'tcx>) -> bool;
+pub trait IsPrefixOf<'tcx> {
+    fn is_prefix_of(&self, other: PlaceRef<'tcx>) -> bool;
 }
 
-impl<'cx, 'tcx> IsPrefixOf<'cx, 'tcx> for PlaceRef<'cx, 'tcx> {
-    fn is_prefix_of(&self, other: PlaceRef<'cx, 'tcx>) -> bool {
+impl<'tcx> IsPrefixOf<'tcx> for PlaceRef<'tcx> {
+    fn is_prefix_of(&self, other: PlaceRef<'tcx>) -> bool {
         self.local == other.local
             && self.projection.len() <= other.projection.len()
             && self.projection == &other.projection[..self.projection.len()]
@@ -29,7 +29,7 @@ pub(super) struct Prefixes<'cx, 'tcx> {
     body: ReadOnlyBodyAndCache<'cx, 'tcx>,
     tcx: TyCtxt<'tcx>,
     kind: PrefixSet,
-    next: Option<PlaceRef<'cx, 'tcx>>,
+    next: Option<PlaceRef<'tcx>>,
 }
 
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
@@ -50,7 +50,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     /// terminating the iteration early based on `kind`.
     pub(super) fn prefixes(
         &self,
-        place_ref: PlaceRef<'cx, 'tcx>,
+        place_ref: PlaceRef<'tcx>,
         kind: PrefixSet,
     ) -> Prefixes<'cx, 'tcx> {
         Prefixes { next: Some(place_ref), kind, body: self.body, tcx: self.infcx.tcx }
@@ -58,7 +58,7 @@ pub(super) fn prefixes(
 }
 
 impl<'cx, 'tcx> Iterator for Prefixes<'cx, 'tcx> {
-    type Item = PlaceRef<'cx, 'tcx>;
+    type Item = PlaceRef<'tcx>;
     fn next(&mut self) -> Option<Self::Item> {
         let mut cursor = self.next?;
 
index 144f655420b36541571ab5907c65fcc585070bfc..fe96b3e34a2a875913ba40c3fdf1c51adeccd575 100644 (file)
@@ -7,6 +7,7 @@
 };
 use rustc::ty::{self, subst::SubstsRef, RegionVid, Ty, TyCtxt, TypeFoldable};
 use rustc_data_structures::binary_search_util;
+use rustc_data_structures::frozen::Frozen;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::graph::scc::Sccs;
 use rustc_hir::def_id::DefId;
@@ -54,12 +55,12 @@ pub struct RegionInferenceContext<'tcx> {
     liveness_constraints: LivenessValues<RegionVid>,
 
     /// The outlives constraints computed by the type-check.
-    constraints: Rc<OutlivesConstraintSet>,
+    constraints: Frozen<OutlivesConstraintSet>,
 
     /// The constraint-set, but in graph form, making it easy to traverse
     /// the constraints adjacent to a particular region. Used to construct
     /// the SCC (see `constraint_sccs`) and for error reporting.
-    constraint_graph: Rc<NormalConstraintGraph>,
+    constraint_graph: Frozen<NormalConstraintGraph>,
 
     /// The SCC computed from `constraints` and the constraint
     /// graph. We have an edge from SCC A to SCC B if `A: B`. Used to
@@ -112,7 +113,7 @@ pub struct RegionInferenceContext<'tcx> {
 
     /// Information about how the universally quantified regions in
     /// scope on this function relate to one another.
-    universal_region_relations: Rc<UniversalRegionRelations<'tcx>>,
+    universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
 }
 
 /// Each time that `apply_member_constraint` is successful, it appends
@@ -242,11 +243,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     ///
     /// The `outlives_constraints` and `type_tests` are an initial set
     /// of constraints produced by the MIR type check.
-    pub(crate) fn new(
+    pub(in crate::borrow_check) fn new(
         var_infos: VarInfos,
         universal_regions: Rc<UniversalRegions<'tcx>>,
         placeholder_indices: Rc<PlaceholderIndices>,
-        universal_region_relations: Rc<UniversalRegionRelations<'tcx>>,
+        universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
         outlives_constraints: OutlivesConstraintSet,
         member_constraints_in: MemberConstraintSet<'tcx, RegionVid>,
         closure_bounds_mapping: FxHashMap<
@@ -263,8 +264,8 @@ pub(crate) fn new(
             .map(|info| RegionDefinition::new(info.universe, info.origin))
             .collect();
 
-        let constraints = Rc::new(outlives_constraints); // freeze constraints
-        let constraint_graph = Rc::new(constraints.graph(definitions.len()));
+        let constraints = Frozen::freeze(outlives_constraints);
+        let constraint_graph = Frozen::freeze(constraints.graph(definitions.len()));
         let fr_static = universal_regions.fr_static;
         let constraint_sccs = Rc::new(constraints.compute_sccs(&constraint_graph, fr_static));
 
index 15bbc5677daddbbaa80680476c5b758bd050348f..49b494373284712802a2c0e5e1f13654dba553b2 100644 (file)
@@ -3,6 +3,7 @@
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::InferCtxt;
 use rustc_span::Span;
+use rustc_trait_selection::opaque_types::InferCtxtExt;
 
 use super::RegionInferenceContext;
 
index 3126d44014b4ea3d0943c3497794c6a38e7dec9b..675463cb1c1f98ab85916b4ea8f27554289c20be 100644 (file)
@@ -140,7 +140,7 @@ impl<N: Idx> LivenessValues<N> {
     /// Each of the regions in num_region_variables will be initialized with an
     /// empty set of points and no causal information.
     crate fn new(elements: Rc<RegionValueElements>) -> Self {
-        Self { points: SparseBitMatrix::new(elements.num_points), elements: elements }
+        Self { points: SparseBitMatrix::new(elements.num_points), elements }
     }
 
     /// Iterate through each region that has a value in this set.
index 137216531a369e69b8eaaf89846bbe70edf91540..86951f93f0e7e963ed06a1f52d4cb28942e934b9 100644 (file)
@@ -1,13 +1,15 @@
 use rustc::mir::ConstraintCategory;
+use rustc::traits::query::OutlivesBound;
 use rustc::ty::free_region_map::FreeRegionRelations;
 use rustc::ty::{self, RegionVid, Ty, TyCtxt};
+use rustc_data_structures::frozen::Frozen;
 use rustc_data_structures::transitive_relation::TransitiveRelation;
 use rustc_infer::infer::canonical::QueryRegionConstraints;
+use rustc_infer::infer::outlives;
 use rustc_infer::infer::region_constraints::GenericKind;
 use rustc_infer::infer::InferCtxt;
-use rustc_infer::traits::query::outlives_bounds::{self, OutlivesBound};
-use rustc_infer::traits::query::type_op::{self, TypeOp};
 use rustc_span::DUMMY_SP;
+use rustc_trait_selection::traits::query::type_op::{self, TypeOp};
 use std::rc::Rc;
 
 use crate::borrow_check::{
@@ -52,7 +54,7 @@
 type NormalizedInputsAndOutput<'tcx> = Vec<Ty<'tcx>>;
 
 crate struct CreateResult<'tcx> {
-    crate universal_region_relations: Rc<UniversalRegionRelations<'tcx>>,
+    pub(in crate::borrow_check) universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
     crate region_bound_pairs: RegionBoundPairs<'tcx>,
     crate normalized_inputs_and_output: NormalizedInputsAndOutput<'tcx>,
 }
@@ -266,7 +268,7 @@ impl UniversalRegionRelationsBuilder<'cx, 'tcx> {
 
         // Insert the facts we know from the predicates. Why? Why not.
         let param_env = self.param_env;
-        self.add_outlives_bounds(outlives_bounds::explicit_outlives_bounds(param_env));
+        self.add_outlives_bounds(outlives::explicit_outlives_bounds(param_env));
 
         // Finally:
         // - outlives is reflexive, so `'r: 'r` for every region `'r`
@@ -297,7 +299,7 @@ impl UniversalRegionRelationsBuilder<'cx, 'tcx> {
         }
 
         CreateResult {
-            universal_region_relations: Rc::new(self.relations),
+            universal_region_relations: Frozen::freeze(self.relations),
             region_bound_pairs: self.region_bound_pairs,
             normalized_inputs_and_output,
         }
index 37cf77b7095c6c70334c8f121f52e0bfd39bdedf..f2194c77c8991aee23f6bf65bb12bd101bc741aa 100644 (file)
@@ -64,13 +64,16 @@ pub(super) fn equate_inputs_and_outputs(
             }
         };
 
+        debug!(
+            "equate_inputs_and_outputs: normalized_input_tys = {:?}, local_decls = {:?}",
+            normalized_input_tys, body.local_decls
+        );
+
         // Equate expected input tys with those in the MIR.
         for (&normalized_input_ty, argument_index) in normalized_input_tys.iter().zip(0..) {
             // In MIR, argument N is stored in local N+1.
             let local = Local::new(argument_index + 1);
 
-            debug!("equate_inputs_and_outputs: normalized_input_ty = {:?}", normalized_input_ty);
-
             let mir_input_ty = body.local_decls[local].ty;
             let mir_input_span = body.local_decls[local].source_info.span;
             self.equate_normalized_input_or_output(
index 055415f28722289a3b41b309564c8b86458dbe3e..407e0628b6eb8ba6a78a34aaf93fc433d7f2f52b 100644 (file)
 type PathPointRelation = Vec<(MovePathIndex, LocationIndex)>;
 
 struct UseFactsExtractor<'me> {
-    var_defined: &'me mut VarPointRelation,
-    var_used: &'me mut VarPointRelation,
+    var_defined_at: &'me mut VarPointRelation,
+    var_used_at: &'me mut VarPointRelation,
     location_table: &'me LocationTable,
-    var_drop_used: &'me mut Vec<(Local, Location)>,
+    var_dropped_at: &'me mut VarPointRelation,
     move_data: &'me MoveData<'me>,
-    path_accessed_at: &'me mut PathPointRelation,
+    path_accessed_at_base: &'me mut PathPointRelation,
 }
 
 // A Visitor to walk through the MIR and extract point-wise facts
@@ -28,22 +28,22 @@ fn location_to_index(&self, location: Location) -> LocationIndex {
 
     fn insert_def(&mut self, local: Local, location: Location) {
         debug!("UseFactsExtractor::insert_def()");
-        self.var_defined.push((local, self.location_to_index(location)));
+        self.var_defined_at.push((local, self.location_to_index(location)));
     }
 
     fn insert_use(&mut self, local: Local, location: Location) {
         debug!("UseFactsExtractor::insert_use()");
-        self.var_used.push((local, self.location_to_index(location)));
+        self.var_used_at.push((local, self.location_to_index(location)));
     }
 
     fn insert_drop_use(&mut self, local: Local, location: Location) {
         debug!("UseFactsExtractor::insert_drop_use()");
-        self.var_drop_used.push((local, location));
+        self.var_dropped_at.push((local, self.location_to_index(location)));
     }
 
     fn insert_path_access(&mut self, path: MovePathIndex, location: Location) {
         debug!("UseFactsExtractor::insert_path_access({:?}, {:?})", path, location);
-        self.path_accessed_at.push((path, self.location_to_index(location)));
+        self.path_accessed_at_base.push((path, self.location_table.start_index(location)));
     }
 
     fn place_to_mpi(&self, place: &Place<'_>) -> Option<MovePathIndex> {
@@ -88,51 +88,54 @@ pub(super) fn populate_access_facts(
     body: ReadOnlyBodyAndCache<'_, 'tcx>,
     location_table: &LocationTable,
     move_data: &MoveData<'_>,
-    drop_used: &mut Vec<(Local, Location)>,
+    dropped_at: &mut Vec<(Local, Location)>,
 ) {
     debug!("populate_access_facts()");
 
     if let Some(facts) = typeck.borrowck_context.all_facts.as_mut() {
         let mut extractor = UseFactsExtractor {
-            var_defined: &mut facts.var_defined,
-            var_used: &mut facts.var_used,
-            var_drop_used: drop_used,
-            path_accessed_at: &mut facts.path_accessed_at,
+            var_defined_at: &mut facts.var_defined_at,
+            var_used_at: &mut facts.var_used_at,
+            var_dropped_at: &mut facts.var_dropped_at,
+            path_accessed_at_base: &mut facts.path_accessed_at_base,
             location_table,
             move_data,
         };
         extractor.visit_body(body);
 
-        facts.var_drop_used.extend(
-            drop_used.iter().map(|&(local, location)| (local, location_table.mid_index(location))),
+        facts.var_dropped_at.extend(
+            dropped_at.iter().map(|&(local, location)| (local, location_table.mid_index(location))),
         );
 
         for (local, local_decl) in body.local_decls.iter_enumerated() {
-            debug!("add var_uses_regions facts - local={:?}, type={:?}", local, local_decl.ty);
+            debug!(
+                "add use_of_var_derefs_origin facts - local={:?}, type={:?}",
+                local, local_decl.ty
+            );
             let _prof_timer = typeck.infcx.tcx.prof.generic_activity("polonius_fact_generation");
             let universal_regions = &typeck.borrowck_context.universal_regions;
             typeck.infcx.tcx.for_each_free_region(&local_decl.ty, |region| {
                 let region_vid = universal_regions.to_region_vid(region);
-                facts.var_uses_region.push((local, region_vid));
+                facts.use_of_var_derefs_origin.push((local, region_vid));
             });
         }
     }
 }
 
 // For every potentially drop()-touched region `region` in `local`'s type
-// (`kind`), emit a Polonius `var_drops_region(local, region)` fact.
-pub(super) fn add_var_drops_regions(
+// (`kind`), emit a Polonius `use_of_var_derefs_origin(local, origin)` fact.
+pub(super) fn add_drop_of_var_derefs_origin(
     typeck: &mut TypeChecker<'_, 'tcx>,
     local: Local,
     kind: &GenericArg<'tcx>,
 ) {
-    debug!("add_var_drops_region(local={:?}, kind={:?}", local, kind);
+    debug!("add_drop_of_var_derefs_origin(local={:?}, kind={:?}", local, kind);
     if let Some(facts) = typeck.borrowck_context.all_facts.as_mut() {
         let _prof_timer = typeck.infcx.tcx.prof.generic_activity("polonius_fact_generation");
         let universal_regions = &typeck.borrowck_context.universal_regions;
         typeck.infcx.tcx.for_each_free_region(kind, |drop_live_region| {
             let region_vid = universal_regions.to_region_vid(drop_live_region);
-            facts.var_drops_region.push((local, region_vid));
+            facts.drop_of_var_derefs_origin.push((local, region_vid));
         });
     }
 }
index 4c8deb0ecf84a547bd52d4d8c591be1b2c34d53a..0c49ee44f9a5025ad6f63f779d74f62e1245f672 100644 (file)
@@ -3,9 +3,9 @@
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_index::bit_set::HybridBitSet;
 use rustc_infer::infer::canonical::QueryRegionConstraints;
-use rustc_infer::traits::query::dropck_outlives::DropckOutlivesResult;
-use rustc_infer::traits::query::type_op::outlives::DropckOutlives;
-use rustc_infer::traits::query::type_op::TypeOp;
+use rustc_trait_selection::traits::query::dropck_outlives::DropckOutlivesResult;
+use rustc_trait_selection::traits::query::type_op::outlives::DropckOutlives;
+use rustc_trait_selection::traits::query::type_op::TypeOp;
 use std::rc::Rc;
 
 use crate::dataflow::generic::ResultsCursor;
@@ -484,7 +484,7 @@ fn add_drop_live_facts_for(
         for &kind in &drop_data.dropck_result.kinds {
             Self::make_all_regions_live(self.elements, &mut self.typeck, kind, live_at);
 
-            polonius::add_var_drops_regions(&mut self.typeck, dropped_local, &kind);
+            polonius::add_drop_of_var_derefs_origin(&mut self.typeck, dropped_local, &kind);
         }
     }
 
index f4e1bce462f55bee6345d6b817d892cd4e2a471e..05d4fc8880e406dc8fb6194353e504e1c90041ac 100644 (file)
     self, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, RegionVid, ToPolyTraitRef, Ty,
     TyCtxt, UserType, UserTypeAnnotationIndex,
 };
+use rustc_data_structures::frozen::Frozen;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_infer::infer::canonical::QueryRegionConstraints;
-use rustc_infer::infer::opaque_types::GenerateMemberConstraints;
 use rustc_infer::infer::outlives::env::RegionBoundPairs;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_infer::infer::{
     InferCtxt, InferOk, LateBoundRegionConversionTime, NLLRegionVariableOrigin,
 };
-use rustc_infer::traits::query::type_op;
-use rustc_infer::traits::query::type_op::custom::CustomTypeOp;
-use rustc_infer::traits::query::{Fallible, NoSolution};
-use rustc_infer::traits::{self, ObligationCause, PredicateObligations};
 use rustc_span::{Span, DUMMY_SP};
+use rustc_trait_selection::infer::InferCtxtExt as _;
+use rustc_trait_selection::opaque_types::{GenerateMemberConstraints, InferCtxtExt};
+use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
+use rustc_trait_selection::traits::query::type_op;
+use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp;
+use rustc_trait_selection::traits::query::{Fallible, NoSolution};
+use rustc_trait_selection::traits::{self, ObligationCause, PredicateObligations};
 
 use crate::dataflow::generic::ResultsCursor;
 use crate::dataflow::move_paths::MoveData;
@@ -579,7 +582,7 @@ fn sanitize_promoted(
             | ConstraintCategory::UseAsConst
             | ConstraintCategory::UseAsStatic = constraint.category
             {
-                // "Returning" from a promoted is an assigment to a
+                // "Returning" from a promoted is an assignment to a
                 // temporary from the user's point of view.
                 constraint.category = ConstraintCategory::Boring;
             }
@@ -828,7 +831,7 @@ struct BorrowCheckContext<'a, 'tcx> {
 
 crate struct MirTypeckResults<'tcx> {
     crate constraints: MirTypeckRegionConstraints<'tcx>,
-    crate universal_region_relations: Rc<UniversalRegionRelations<'tcx>>,
+    pub(in crate::borrow_check) universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
     crate opaque_type_values: FxHashMap<DefId, ty::ResolvedOpaqueTy<'tcx>>,
 }
 
@@ -1905,7 +1908,7 @@ fn ensure_place_sized(&mut self, ty: Ty<'tcx>, span: Span) {
             // expressions evaluate through `as_temp` or `into` a return
             // slot or local, so to find all unsized rvalues it is enough
             // to check all temps, return slots and locals.
-            if let None = self.reported_errors.replace((ty, span)) {
+            if self.reported_errors.replace((ty, span)).is_none() {
                 let mut diag = struct_span_err!(
                     self.tcx().sess,
                     span,
@@ -2005,7 +2008,9 @@ fn check_rvalue(
                                 &traits::Obligation::new(
                                     ObligationCause::new(
                                         span,
-                                        self.tcx().hir().def_index_to_hir_id(self.mir_def_id.index),
+                                        self.tcx()
+                                            .hir()
+                                            .local_def_id_to_hir_id(self.mir_def_id.expect_local()),
                                         traits::ObligationCauseCode::RepeatVec(should_suggest),
                                     ),
                                     self.param_env,
index 31507a184d8f914d0898ee844adbf53ff7bf27b2..ebaafd40262705a00a8a088503c575919ab0bdc6 100644 (file)
@@ -3,8 +3,8 @@
 use rustc::ty::{self, Ty};
 use rustc_infer::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRelatingDelegate};
 use rustc_infer::infer::{InferCtxt, NLLRegionVariableOrigin};
-use rustc_infer::traits::query::Fallible;
-use rustc_infer::traits::DomainGoal;
+use rustc_trait_selection::traits::query::Fallible;
+use rustc_trait_selection::traits::DomainGoal;
 
 use crate::borrow_check::constraints::OutlivesConstraint;
 use crate::borrow_check::type_check::{BorrowCheckContext, Locations};
@@ -64,7 +64,7 @@ fn create_next_universe(&mut self) -> ty::UniverseIndex {
     }
 
     fn next_existential_region_var(&mut self, from_forall: bool) -> ty::Region<'tcx> {
-        if let Some(_) = &mut self.borrowck_context {
+        if self.borrowck_context.is_some() {
             let origin = NLLRegionVariableOrigin::Existential { from_forall };
             self.infcx.next_nll_region_var(origin)
         } else {
index af4ea759f4f8b808adb054bf851d6f323fe9a2a3..c1acd5bd9a691510020bc1c405c24ab23d787829 100644 (file)
@@ -486,7 +486,7 @@ fn build(self) -> UniversalRegions<'tcx> {
             defining_ty,
             unnormalized_output_ty,
             unnormalized_input_tys,
-            yield_ty: yield_ty,
+            yield_ty,
         }
     }
 
@@ -774,9 +774,9 @@ fn for_each_late_bound_region_defined_on<'tcx>(
     fn_def_id: DefId,
     mut f: impl FnMut(ty::Region<'tcx>),
 ) {
-    if let Some(late_bounds) = tcx.is_late_bound_map(fn_def_id.index) {
+    if let Some(late_bounds) = tcx.is_late_bound_map(fn_def_id.expect_local()) {
         for late_bound in late_bounds.iter() {
-            let hir_id = HirId { owner: fn_def_id.index, local_id: *late_bound };
+            let hir_id = HirId { owner: fn_def_id.expect_local(), local_id: *late_bound };
             let name = tcx.hir().name(hir_id);
             let region_def_id = tcx.hir().local_def_id(hir_id);
             let liberated_region = tcx.mk_region(ty::ReFree(ty::FreeRegion {
index 4d5464f774ff54dc2871cd731591a3b2dd0a4617..ffbff00cf376005a6b983d0ddc9c247b1ad67383 100644 (file)
@@ -89,7 +89,7 @@ pub(super) fn mk_eval_cx<'mir, 'tcx>(
     InterpCx::new(
         tcx.at(span),
         param_env,
-        CompileTimeInterpreter::new(),
+        CompileTimeInterpreter::new(*tcx.sess.const_eval_limit.get()),
         MemoryExtra { can_access_statics },
     )
 }
@@ -186,7 +186,12 @@ fn validate_and_turn_into_const<'tcx>(
         if cid.promoted.is_none() {
             let mut ref_tracking = RefTracking::new(mplace);
             while let Some((mplace, path)) = ref_tracking.todo.pop() {
-                ecx.validate_operand(mplace.into(), path, Some(&mut ref_tracking))?;
+                ecx.const_validate_operand(
+                    mplace.into(),
+                    path,
+                    &mut ref_tracking,
+                    /*may_ref_to_static*/ is_static,
+                )?;
             }
         }
         // Now that we validated, turn this into a proper constant.
@@ -226,7 +231,7 @@ pub fn const_eval_validated_provider<'tcx>(
         match tcx.const_eval_validated(key) {
             // try again with reveal all as requested
             Err(ErrorHandled::TooGeneric) => {}
-            // dedupliate calls
+            // deduplicate calls
             other => return other,
         }
     }
@@ -267,7 +272,7 @@ pub fn const_eval_raw_provider<'tcx>(
         match tcx.const_eval_raw(key) {
             // try again with reveal all as requested
             Err(ErrorHandled::TooGeneric) => {}
-            // dedupliate calls
+            // deduplicate calls
             other => return other,
         }
     }
@@ -297,7 +302,7 @@ pub fn const_eval_raw_provider<'tcx>(
     let mut ecx = InterpCx::new(
         tcx.at(span),
         key.param_env,
-        CompileTimeInterpreter::new(),
+        CompileTimeInterpreter::new(*tcx.sess.const_eval_limit.get()),
         MemoryExtra { can_access_statics: is_static },
     );
 
index 27efcd508414af0e557eae07e995f42dd73ba53c..470e4e7ed25c1fe1adfe0afa796628d55cf64822 100644 (file)
@@ -85,7 +85,7 @@ pub fn is_min_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
 pub fn is_parent_const_impl_raw(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> bool {
     let parent_id = tcx.hir().get_parent_did(hir_id);
     if !parent_id.is_top_level_module() {
-        is_const_impl_raw(tcx, LocalDefId::from_def_id(parent_id))
+        is_const_impl_raw(tcx, parent_id.expect_local())
     } else {
         false
     }
@@ -171,7 +171,7 @@ fn const_fn_is_allowed_fn_ptr(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
 pub fn provide(providers: &mut Providers<'_>) {
     *providers = Providers {
         is_const_fn_raw,
-        is_const_impl_raw: |tcx, def_id| is_const_impl_raw(tcx, LocalDefId::from_def_id(def_id)),
+        is_const_impl_raw: |tcx, def_id| is_const_impl_raw(tcx, def_id.expect_local()),
         is_promotable_const_fn,
         const_fn_is_allowed_fn_ptr,
         ..*providers
index e40436ccf0b4b546e37a8ae616b0774df8ecbe99..28889486c383b55150ced9e80d4c73fc60b31f21 100644 (file)
@@ -1,9 +1,9 @@
 use rustc::mir;
 use rustc::ty::layout::HasTyCtxt;
-use rustc::ty::{self, Ty, TyCtxt};
-use rustc_hir::def_id::DefId;
+use rustc::ty::{self, Ty};
 use std::borrow::{Borrow, Cow};
 use std::collections::hash_map::Entry;
+use std::convert::TryFrom;
 use std::hash::Hash;
 
 use rustc_data_structures::fx::FxHashMap;
@@ -86,9 +86,6 @@ fn hook_panic_fn(
     }
 }
 
-/// Number of steps until the detector even starts doing anything.
-/// Also, a warning is shown to the user when this number is reached.
-const STEPS_UNTIL_DETECTOR_ENABLED: isize = 1_000_000;
 /// The number of steps between loop detector snapshots.
 /// Should be a power of two for performance reasons.
 const DETECTOR_SNAPSHOT_PERIOD: isize = 256;
@@ -101,6 +98,8 @@ pub struct CompileTimeInterpreter<'mir, 'tcx> {
     /// detector period.
     pub(super) steps_since_detector_enabled: isize,
 
+    pub(super) is_detector_enabled: bool,
+
     /// Extra state to detect loops.
     pub(super) loop_detector: snapshot::InfiniteLoopDetector<'mir, 'tcx>,
 }
@@ -112,10 +111,14 @@ pub struct MemoryExtra {
 }
 
 impl<'mir, 'tcx> CompileTimeInterpreter<'mir, 'tcx> {
-    pub(super) fn new() -> Self {
+    pub(super) fn new(const_eval_limit: usize) -> Self {
+        let steps_until_detector_enabled =
+            isize::try_from(const_eval_limit).unwrap_or(std::isize::MAX);
+
         CompileTimeInterpreter {
             loop_detector: Default::default(),
-            steps_since_detector_enabled: -STEPS_UNTIL_DETECTOR_ENABLED,
+            steps_since_detector_enabled: -steps_until_detector_enabled,
+            is_detector_enabled: const_eval_limit != 0,
         }
     }
 }
@@ -237,7 +240,8 @@ fn find_mir_or_eval_fn(
         Ok(Some(match ecx.load_mir(instance.def, None) {
             Ok(body) => *body,
             Err(err) => {
-                if let err_unsup!(NoMirFor(ref path)) = err.kind {
+                if let err_unsup!(NoMirFor(did)) = err.kind {
+                    let path = ecx.tcx.def_path_str(did);
                     return Err(ConstEvalErrKind::NeedsRfc(format!(
                         "calling extern function `{}`",
                         path
@@ -277,7 +281,6 @@ fn call_intrinsic(
 
     fn assert_panic(
         ecx: &mut InterpCx<'mir, 'tcx, Self>,
-        _span: Span,
         msg: &AssertMessage<'tcx>,
         _unwind: Option<mir::BasicBlock>,
     ) -> InterpResult<'tcx> {
@@ -320,13 +323,6 @@ fn binary_ptr_op(
         Err(ConstEvalErrKind::NeedsRfc("pointer arithmetic or comparison".to_string()).into())
     }
 
-    fn find_foreign_static(
-        _tcx: TyCtxt<'tcx>,
-        _def_id: DefId,
-    ) -> InterpResult<'tcx, Cow<'tcx, Allocation<Self::PointerTag>>> {
-        throw_unsup!(ReadForeignStatic)
-    }
-
     #[inline(always)]
     fn init_allocation_extra<'b>(
         _memory_extra: &MemoryExtra,
@@ -351,6 +347,10 @@ fn box_alloc(
     }
 
     fn before_terminator(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
+        if !ecx.machine.is_detector_enabled {
+            return Ok(());
+        }
+
         {
             let steps = &mut ecx.machine.steps_since_detector_enabled;
 
index cb6583976258bd4da1f435b1a864993893efdd45..605091d6c7d415b88fc8b3c602c1f96528a75b91 100644 (file)
@@ -43,7 +43,7 @@ pub(crate) fn const_field<'tcx>(
     op_to_const(&ecx, field)
 }
 
-pub(crate) fn const_caller_location<'tcx>(
+pub(crate) fn const_caller_location(
     tcx: TyCtxt<'tcx>,
     (file, line, col): (Symbol, u32, u32),
 ) -> ConstValue<'tcx> {
index 8c0ab1505284a0d5014e98ad7674bc1bfd10a1b1..170157aca5ddd678391efc9083286821b27898d8 100644 (file)
@@ -2,7 +2,7 @@
 
 use std::borrow::Borrow;
 
-use rustc::mir::{self, BasicBlock, Location};
+use rustc::mir::{self, BasicBlock, Location, TerminatorKind};
 use rustc_index::bit_set::BitSet;
 
 use super::{Analysis, Results};
@@ -29,14 +29,14 @@ pub struct ResultsCursor<'mir, 'tcx, A, R = Results<'tcx, A>>
 
     pos: CursorPosition,
 
-    /// When this flag is set, the cursor is pointing at a `Call` terminator whose call return
-    /// effect has been applied to `state`.
+    /// When this flag is set, the cursor is pointing at a `Call` or `Yield` terminator whose call
+    /// return or resume effect has been applied to `state`.
     ///
-    /// This flag helps to ensure that multiple calls to `seek_after_assume_call_returns` with the
+    /// This flag helps to ensure that multiple calls to `seek_after_assume_success` with the
     /// same target will result in exactly one invocation of `apply_call_return_effect`. It is
     /// sufficient to clear this only in `seek_to_block_start`, since seeking away from a
     /// terminator will always require a cursor reset.
-    call_return_effect_applied: bool,
+    success_effect_applied: bool,
 }
 
 impl<'mir, 'tcx, A, R> ResultsCursor<'mir, 'tcx, A, R>
@@ -50,7 +50,7 @@ pub fn new(body: &'mir mir::Body<'tcx>, results: R) -> Self {
             body,
             pos: CursorPosition::BlockStart(mir::START_BLOCK),
             state: results.borrow().entry_sets[mir::START_BLOCK].clone(),
-            call_return_effect_applied: false,
+            success_effect_applied: false,
             results,
         }
     }
@@ -76,14 +76,14 @@ pub fn contains(&self, elem: A::Idx) -> bool {
     pub fn seek_to_block_start(&mut self, block: BasicBlock) {
         self.state.overwrite(&self.results.borrow().entry_sets[block]);
         self.pos = CursorPosition::BlockStart(block);
-        self.call_return_effect_applied = false;
+        self.success_effect_applied = false;
     }
 
     /// Advances the cursor to hold all effects up to and including to the "before" effect of the
     /// statement (or terminator) at the given location.
     ///
     /// If you wish to observe the full effect of a statement or terminator, not just the "before"
-    /// effect, use `seek_after` or `seek_after_assume_call_returns`.
+    /// effect, use `seek_after` or `seek_after_assume_success`.
     pub fn seek_before(&mut self, target: Location) {
         assert!(target <= self.body.terminator_loc(target.block));
         self.seek_(target, false);
@@ -93,7 +93,7 @@ pub fn seek_before(&mut self, target: Location) {
     /// terminators) up to and including the `target`.
     ///
     /// If the `target` is a `Call` terminator, any call return effect for that terminator will
-    /// **not** be observed. Use `seek_after_assume_call_returns` if you wish to observe the call
+    /// **not** be observed. Use `seek_after_assume_success` if you wish to observe the call
     /// return effect.
     pub fn seek_after(&mut self, target: Location) {
         assert!(target <= self.body.terminator_loc(target.block));
@@ -101,7 +101,7 @@ pub fn seek_after(&mut self, target: Location) {
         // If we have already applied the call return effect, we are currently pointing at a `Call`
         // terminator. Unconditionally reset the dataflow cursor, since there is no way to "undo"
         // the call return effect.
-        if self.call_return_effect_applied {
+        if self.success_effect_applied {
             self.seek_to_block_start(target.block);
         }
 
@@ -111,25 +111,25 @@ pub fn seek_after(&mut self, target: Location) {
     /// Advances the cursor to hold all effects up to and including of the statement (or
     /// terminator) at the given location.
     ///
-    /// If the `target` is a `Call` terminator, any call return effect for that terminator will
-    /// be observed. Use `seek_after` if you do **not** wish to observe the call return effect.
-    pub fn seek_after_assume_call_returns(&mut self, target: Location) {
+    /// If the `target` is a `Call` or `Yield` terminator, any call return or resume effect for that
+    /// terminator will be observed. Use `seek_after` if you do **not** wish to observe the
+    /// "success" effect.
+    pub fn seek_after_assume_success(&mut self, target: Location) {
         let terminator_loc = self.body.terminator_loc(target.block);
         assert!(target.statement_index <= terminator_loc.statement_index);
 
         self.seek_(target, true);
 
-        if target != terminator_loc {
+        if target != terminator_loc || self.success_effect_applied {
             return;
         }
 
+        // Apply the effect of the "success" path of the terminator.
+
+        self.success_effect_applied = true;
         let terminator = self.body.basic_blocks()[target.block].terminator();
-        if let mir::TerminatorKind::Call {
-            destination: Some((return_place, _)), func, args, ..
-        } = &terminator.kind
-        {
-            if !self.call_return_effect_applied {
-                self.call_return_effect_applied = true;
+        match &terminator.kind {
+            TerminatorKind::Call { destination: Some((return_place, _)), func, args, .. } => {
                 self.results.borrow().analysis.apply_call_return_effect(
                     &mut self.state,
                     target.block,
@@ -138,6 +138,14 @@ pub fn seek_after_assume_call_returns(&mut self, target: Location) {
                     return_place,
                 );
             }
+            TerminatorKind::Yield { resume, resume_arg, .. } => {
+                self.results.borrow().analysis.apply_yield_resume_effect(
+                    &mut self.state,
+                    *resume,
+                    resume_arg,
+                );
+            }
+            _ => {}
         }
     }
 
@@ -172,7 +180,7 @@ fn seek_(&mut self, target: Location, apply_after_effect_at_target: bool) {
                 self.seek_to_block_start(target.block)
             }
 
-            // N.B., `call_return_effect_applied` is checked in `seek_after`, not here.
+            // N.B., `success_effect_applied` is checked in `seek_after`, not here.
             _ => (),
         }
 
index 1487129f6c77c2a10473223681a96b4bde3e2ad0..d32072125b3b9fcd101dfbc5bea2de536a0382e3 100644 (file)
@@ -218,15 +218,18 @@ fn propagate_bits_into_graph_successors_of(
 
             Goto { target }
             | Assert { target, cleanup: None, .. }
-            | Yield { resume: target, drop: None, .. }
             | Drop { target, location: _, unwind: None }
             | DropAndReplace { target, value: _, location: _, unwind: None } => {
                 self.propagate_bits_into_entry_set_for(in_out, target, dirty_list)
             }
 
-            Yield { resume: target, drop: Some(drop), .. } => {
+            Yield { resume: target, drop, resume_arg, .. } => {
+                if let Some(drop) = drop {
+                    self.propagate_bits_into_entry_set_for(in_out, drop, dirty_list);
+                }
+
+                self.analysis.apply_yield_resume_effect(in_out, target, &resume_arg);
                 self.propagate_bits_into_entry_set_for(in_out, target, dirty_list);
-                self.propagate_bits_into_entry_set_for(in_out, drop, dirty_list);
             }
 
             Assert { target, cleanup: Some(unwind), .. }
@@ -239,23 +242,26 @@ fn propagate_bits_into_graph_successors_of(
             }
 
             SwitchInt { ref targets, ref values, ref discr, .. } => {
-                // If this is a switch on an enum discriminant, a custom effect may be applied
-                // along each outgoing edge.
-                if let Some(place) = discr.place() {
-                    let enum_def = switch_on_enum_discriminant(self.tcx, self.body, bb_data, place);
-                    if let Some(enum_def) = enum_def {
+                let Engine { tcx, body, .. } = *self;
+                let enum_ = discr
+                    .place()
+                    .and_then(|discr| switch_on_enum_discriminant(tcx, body, bb_data, discr));
+                match enum_ {
+                    // If this is a switch on an enum discriminant, a custom effect may be applied
+                    // along each outgoing edge.
+                    Some((enum_place, enum_def)) => {
                         self.propagate_bits_into_enum_discriminant_switch_successors(
-                            in_out, bb, enum_def, place, dirty_list, &*values, &*targets,
+                            in_out, bb, enum_def, enum_place, dirty_list, &*values, &*targets,
                         );
-
-                        return;
                     }
-                }
 
-                // Otherwise, it's just a normal `SwitchInt`, and every successor sees the same
-                // exit state.
-                for target in targets.iter().copied() {
-                    self.propagate_bits_into_entry_set_for(&in_out, target, dirty_list);
+                    // Otherwise, it's just a normal `SwitchInt`, and every successor sees the same
+                    // exit state.
+                    None => {
+                        for target in targets.iter().copied() {
+                            self.propagate_bits_into_entry_set_for(&in_out, target, dirty_list);
+                        }
+                    }
                 }
             }
 
@@ -342,22 +348,27 @@ fn propagate_bits_into_enum_discriminant_switch_successors(
     }
 }
 
-/// Look at the last statement of a block that ends with  to see if it is an assignment of an enum
-/// discriminant to the local that determines the target of a `SwitchInt` like so:
-///   _42 = discriminant(..)
+/// Inspect a `SwitchInt`-terminated basic block to see if the condition of that `SwitchInt` is
+/// an enum discriminant.
+///
+/// We expect such blocks to have a call to `discriminant` as their last statement like so:
+///   _42 = discriminant(_1)
 ///   SwitchInt(_42, ..)
+///
+/// If the basic block matches this pattern, this function returns the place corresponding to the
+/// enum (`_1` in the example above) as well as the `AdtDef` of that enum.
 fn switch_on_enum_discriminant(
     tcx: TyCtxt<'tcx>,
-    body: &mir::Body<'tcx>,
-    block: &mir::BasicBlockData<'tcx>,
+    body: &'mir mir::Body<'tcx>,
+    block: &'mir mir::BasicBlockData<'tcx>,
     switch_on: &mir::Place<'tcx>,
-) -> Option<&'tcx ty::AdtDef> {
+) -> Option<(&'mir mir::Place<'tcx>, &'tcx ty::AdtDef)> {
     match block.statements.last().map(|stmt| &stmt.kind) {
         Some(mir::StatementKind::Assign(box (lhs, mir::Rvalue::Discriminant(discriminated))))
             if lhs == switch_on =>
         {
             match &discriminated.ty(body, tcx).ty.kind {
-                ty::Adt(def, _) => Some(def),
+                ty::Adt(def, _) => Some((discriminated, def)),
 
                 // `Rvalue::Discriminant` is also used to get the active yield point for a
                 // generator, but we do not need edge-specific effects in that case. This may
index 157526d3c51adc6b5f262322f8a032bee13a167f..36decf7f5a9c3d6e73b37f652b90b56b0f0a105e 100644 (file)
@@ -241,7 +241,7 @@ fn write_node_label(
                     )?;
 
                     let state_on_unwind = this.results.get().clone();
-                    this.results.seek_after_assume_call_returns(terminator_loc);
+                    this.results.seek_after_assume_success(terminator_loc);
                     write_diff(w, this.results.analysis(), &state_on_unwind, this.results.get())?;
 
                     write!(w, "</td>")
@@ -604,8 +604,8 @@ fn write_diff<A: Analysis<'tcx>>(
     Ok(())
 }
 
-const BR_LEFT: &'static str = r#"<br align="left"/>"#;
-const BR_LEFT_SPACE: &'static str = r#"<br align="left"/> "#;
+const BR_LEFT: &str = r#"<br align="left"/>"#;
+const BR_LEFT_SPACE: &str = r#"<br align="left"/> "#;
 
 /// Line break policy that breaks at 40 characters and starts the next line with a single space.
 const LIMIT_30_ALIGN_1: Option<LineBreak> = Some(LineBreak { sequence: BR_LEFT_SPACE, limit: 30 });
index 9a102c9a3d06f0b9e75b51f27eba4d2719580860..fb4b7b9c5be315b276c29eb249c178dc5a0ed00b 100644 (file)
@@ -191,6 +191,20 @@ fn apply_call_return_effect(
         return_place: &mir::Place<'tcx>,
     );
 
+    /// Updates the current dataflow state with the effect of resuming from a `Yield` terminator.
+    ///
+    /// This is similar to `apply_call_return_effect` in that it only takes place after the
+    /// generator is resumed, not when it is dropped.
+    ///
+    /// By default, no effects happen.
+    fn apply_yield_resume_effect(
+        &self,
+        _state: &mut BitSet<Self::Idx>,
+        _resume_block: BasicBlock,
+        _resume_place: &mir::Place<'tcx>,
+    ) {
+    }
+
     /// Updates the current dataflow state with the effect of taking a particular branch in a
     /// `SwitchInt` terminator.
     ///
@@ -284,6 +298,15 @@ fn call_return_effect(
         return_place: &mir::Place<'tcx>,
     );
 
+    /// See `Analysis::apply_yield_resume_effect`.
+    fn yield_resume_effect(
+        &self,
+        _trans: &mut BitSet<Self::Idx>,
+        _resume_block: BasicBlock,
+        _resume_place: &mir::Place<'tcx>,
+    ) {
+    }
+
     /// See `Analysis::apply_discriminant_switch_effect`.
     fn discriminant_switch_effect(
         &self,
@@ -347,6 +370,15 @@ fn apply_call_return_effect(
         self.call_return_effect(state, block, func, args, return_place);
     }
 
+    fn apply_yield_resume_effect(
+        &self,
+        state: &mut BitSet<Self::Idx>,
+        resume_block: BasicBlock,
+        resume_place: &mir::Place<'tcx>,
+    ) {
+        self.yield_resume_effect(state, resume_block, resume_place);
+    }
+
     fn apply_discriminant_switch_effect(
         &self,
         state: &mut BitSet<Self::Idx>,
index 50d4bdb67f755bfdc15ff68f31e61798129d57c8..8f07a10e1b01ce11734a44859e60faceea5fe0be 100644 (file)
@@ -294,7 +294,7 @@ fn cursor_seek() {
 
     cursor.seek_after(call_terminator_loc);
     assert!(!cursor.get().contains(call_return_effect));
-    cursor.seek_after_assume_call_returns(call_terminator_loc);
+    cursor.seek_after_assume_success(call_terminator_loc);
     assert!(cursor.get().contains(call_return_effect));
 
     let every_target = || {
@@ -310,7 +310,7 @@ fn cursor_seek() {
             BlockStart(block) => cursor.seek_to_block_start(block),
             Before(loc) => cursor.seek_before(loc),
             After(loc) => cursor.seek_after(loc),
-            AfterAssumeCallReturns(loc) => cursor.seek_after_assume_call_returns(loc),
+            AfterAssumeCallReturns(loc) => cursor.seek_after_assume_success(loc),
         }
 
         assert_eq!(cursor.get(), &cursor.analysis().expected_state_at_target(targ));
index 5bad8c61a0cd7068d8e8b3f016cf50ece8318d0f..6e1513bcd1dd0beb042e6d673cb0f0e9c49c9a12 100644 (file)
@@ -22,20 +22,20 @@ pub fn visit_results<F>(
             let loc = Location { block, statement_index };
 
             results.reconstruct_before_statement_effect(&mut state, stmt, loc);
-            vis.visit_statement(&mut state, stmt, loc);
+            vis.visit_statement(&state, stmt, loc);
 
             results.reconstruct_statement_effect(&mut state, stmt, loc);
-            vis.visit_statement_exit(&mut state, stmt, loc);
+            vis.visit_statement_exit(&state, stmt, loc);
         }
 
         let loc = body.terminator_loc(block);
         let term = block_data.terminator();
 
         results.reconstruct_before_terminator_effect(&mut state, term, loc);
-        vis.visit_terminator(&mut state, term, loc);
+        vis.visit_terminator(&state, term, loc);
 
         results.reconstruct_terminator_effect(&mut state, term, loc);
-        vis.visit_terminator_exit(&mut state, term, loc);
+        vis.visit_terminator_exit(&state, term, loc);
     }
 }
 
index 45d2b1a71f0f2298530ef54e9f506da6869a0324..a9ef7ef6c528a2a93aa79472e0de2de4470a6b33 100644 (file)
@@ -72,7 +72,7 @@ pub struct Edge {
 
 fn outgoing(body: &Body<'_>, bb: BasicBlock) -> Vec<Edge> {
     (0..body[bb].terminator().successors().count())
-        .map(|index| Edge { source: bb, index: index })
+        .map(|index| Edge { source: bb, index })
         .collect()
 }
 
index fabe562e68a590efe645d925ec4e1e7d16408042..5341d661b1db62379e1fc424fdbbe36fedbb3254 100644 (file)
@@ -161,11 +161,16 @@ fn before_terminator_effect(
         self.borrowed_locals.borrow().analysis().terminator_effect(trans, terminator, loc);
 
         match &terminator.kind {
-            TerminatorKind::Call { destination: Some((place, _)), .. }
-            | TerminatorKind::Yield { resume_arg: place, .. } => {
+            TerminatorKind::Call { destination: Some((place, _)), .. } => {
                 trans.gen(place.local);
             }
 
+            // Note that we do *not* gen the `resume_arg` of `Yield` terminators. The reason for
+            // that is that a `yield` will return from the function, and `resume_arg` is written
+            // only when the generator is later resumed. Unlike `Call`, this doesn't require the
+            // place to have storage *before* the yield, only after.
+            TerminatorKind::Yield { .. } => {}
+
             // Nothing to do for these. Match exhaustively so this fails to compile when new
             // variants are added.
             TerminatorKind::Call { destination: None, .. }
@@ -230,6 +235,15 @@ fn call_return_effect(
     ) {
         trans.gen(return_place.local);
     }
+
+    fn yield_resume_effect(
+        &self,
+        trans: &mut BitSet<Self::Idx>,
+        _resume_block: BasicBlock,
+        resume_place: &mir::Place<'tcx>,
+    ) {
+        trans.gen(resume_place.local);
+    }
 }
 
 impl<'mir, 'tcx> MaybeRequiresStorage<'mir, 'tcx> {
index 25463f31867dfe3a02f2f9a2a8c9dfb40aa227d9..dd0f9ff75b9fe45627ad10c2af088b1b927d3aa7 100644 (file)
@@ -1,22 +1,19 @@
+use rustc::mir::traversal;
+use rustc::mir::{self, BasicBlock, BasicBlockData, Body, Location, Statement, Terminator};
+use rustc::ty::{self, TyCtxt};
 use rustc_ast::ast::{self, MetaItem};
 use rustc_ast_pretty::pprust;
-use rustc_span::symbol::{sym, Symbol};
-
 use rustc_data_structures::work_queue::WorkQueue;
+use rustc_hir::def_id::DefId;
 use rustc_index::bit_set::{BitSet, HybridBitSet};
 use rustc_index::vec::Idx;
-
-use rustc::mir::traversal;
-use rustc::mir::{self, BasicBlock, BasicBlockData, Body, Location, Statement, Terminator};
-use rustc::session::Session;
-use rustc::ty::{self, TyCtxt};
-use rustc_hir::def_id::DefId;
+use rustc_session::Session;
+use rustc_span::symbol::{sym, Symbol};
 
 use std::borrow::Borrow;
 use std::fmt;
 use std::io;
 use std::path::PathBuf;
-use std::usize;
 
 pub use self::at_location::{FlowAtLocation, FlowsAtLocation};
 pub(crate) use self::drop_flag_effects::*;
index 57aa5de7f7a318de09ab76bf2534e5f572ea601f..7c449ad119796fb165376d9161b960c1c5862fbe 100644 (file)
@@ -474,7 +474,7 @@ fn gather_move(&mut self, place: &Place<'tcx>) {
     }
 
     fn record_move(&mut self, place: &Place<'tcx>, path: MovePathIndex) {
-        let move_out = self.builder.data.moves.push(MoveOut { path: path, source: self.loc });
+        let move_out = self.builder.data.moves.push(MoveOut { path, source: self.loc });
         debug!(
             "gather_move({:?}, {:?}): adding move {:?} of {:?}",
             self.loc, place, move_out, path
@@ -483,7 +483,7 @@ fn record_move(&mut self, place: &Place<'tcx>, path: MovePathIndex) {
         self.builder.data.loc_map[self.loc].push(move_out);
     }
 
-    fn gather_init(&mut self, place: PlaceRef<'cx, 'tcx>, kind: InitKind) {
+    fn gather_init(&mut self, place: PlaceRef<'tcx>, kind: InitKind) {
         debug!("gather_init({:?}, {:?})", self.loc, place);
 
         let mut place = place;
index 6f6ba7dc27128adda533997dec7ab5f10173b76b..593952bfa7c809609195eb29c51153dba8e2a5f6 100644 (file)
@@ -312,7 +312,7 @@ impl MovePathLookup {
     // alternative will *not* create a MovePath on the fly for an
     // unknown place, but will rather return the nearest available
     // parent.
-    pub fn find(&self, place: PlaceRef<'_, '_>) -> LookupResult {
+    pub fn find(&self, place: PlaceRef<'_>) -> LookupResult {
         let mut result = self.locals[place.local];
 
         for elem in place.projection.iter() {
index 1a0be582ce67f4a9572933b7b4c70c56e0d2b845..3cbb0667ff3923f051c45ac051c2eb995b5e0254 100644 (file)
@@ -202,7 +202,7 @@ fn cast_from_int(
 
             Char => {
                 // `u8` to `char` cast
-                debug_assert_eq!(v as u8 as u128, v);
+                assert_eq!(v as u8 as u128, v);
                 Ok(Scalar::from_uint(v, Size::from_bytes(4)))
             }
 
index 7a3f09ac80b3d99a24721e8609a8aff386981a13..68a893dc4be5d7f8748ff8e7b5e5dc05eee66903 100644 (file)
@@ -21,7 +21,7 @@
 
 use super::{
     Immediate, MPlaceTy, Machine, MemPlace, MemPlaceMeta, Memory, OpTy, Operand, Place, PlaceTy,
-    ScalarMaybeUndef, StackPopInfo,
+    ScalarMaybeUndef, StackPopJump,
 };
 
 pub struct InterpCx<'mir, 'tcx, M: Machine<'mir, 'tcx>> {
@@ -98,10 +98,10 @@ 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
     /// we can validate it at that layout.
-    /// `ret` stores the block we jump to on a normal return, while 'unwind'
-    /// stores the block used for cleanup during unwinding
+    /// `ret` stores the block we jump to on a normal return, while `unwind`
+    /// stores the block used for cleanup during unwinding.
     Goto { ret: Option<mir::BasicBlock>, unwind: Option<mir::BasicBlock> },
-    /// Just do nohing: Used by Main and for the box_alloc hook in miri.
+    /// Just do nothing: Used by Main and for the `box_alloc` hook in miri.
     /// `cleanup` says whether locals are deallocated. Static computation
     /// wants them leaked to intern what they need (and just throw away
     /// the entire `ecx` when it is done).
@@ -138,7 +138,7 @@ pub enum LocalValue<Tag = (), Id = AllocId> {
 impl<'tcx, Tag: Copy + 'static> LocalState<'tcx, Tag> {
     pub fn access(&self) -> InterpResult<'tcx, Operand<Tag>> {
         match self.value {
-            LocalValue::Dead => throw_unsup!(DeadLocal),
+            LocalValue::Dead => throw_ub!(DeadLocal),
             LocalValue::Uninitialized => {
                 bug!("The type checker should prevent reading from a never-written local")
             }
@@ -152,7 +152,7 @@ pub fn access_mut(
         &mut self,
     ) -> InterpResult<'tcx, Result<&mut LocalValue<Tag>, MemPlace<Tag>>> {
         match self.value {
-            LocalValue::Dead => throw_unsup!(DeadLocal),
+            LocalValue::Dead => throw_ub!(DeadLocal),
             LocalValue::Live(Operand::Indirect(mplace)) => Ok(Err(mplace)),
             ref mut local @ LocalValue::Live(Operand::Immediate(_))
             | ref mut local @ LocalValue::Uninitialized => Ok(Ok(local)),
@@ -326,7 +326,7 @@ pub fn load_mir(
                 if self.tcx.is_mir_available(did) {
                     Ok(self.tcx.optimized_mir(did).unwrap_read_only())
                 } else {
-                    throw_unsup!(NoMirFor(self.tcx.def_path_str(def_id)))
+                    throw_unsup!(NoMirFor(def_id))
                 }
             }
             _ => Ok(self.tcx.instance_mir(instance)),
@@ -335,15 +335,25 @@ pub fn load_mir(
 
     /// Call this on things you got out of the MIR (so it is as generic as the current
     /// stack frame), to bring it into the proper environment for this interpreter.
+    pub(super) fn subst_from_current_frame_and_normalize_erasing_regions<T: TypeFoldable<'tcx>>(
+        &self,
+        value: T,
+    ) -> T {
+        self.subst_from_frame_and_normalize_erasing_regions(self.frame(), value)
+    }
+
+    /// Call this on things you got out of the MIR (so it is as generic as the provided
+    /// stack frame), to bring it into the proper environment for this interpreter.
     pub(super) fn subst_from_frame_and_normalize_erasing_regions<T: TypeFoldable<'tcx>>(
         &self,
+        frame: &Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>,
         value: T,
     ) -> T {
-        self.tcx.subst_and_normalize_erasing_regions(
-            self.frame().instance.substs,
-            self.param_env,
-            &value,
-        )
+        if let Some(substs) = frame.instance.substs_for_mir_body() {
+            self.tcx.subst_and_normalize_erasing_regions(substs, self.param_env, &value)
+        } else {
+            self.tcx.normalize_erasing_regions(self.param_env, value)
+        }
     }
 
     /// The `substs` are assumed to already be in our interpreter "universe" (param_env).
@@ -371,11 +381,8 @@ pub fn layout_of_local(
             None => {
                 let layout = crate::interpret::operand::from_known_layout(layout, || {
                     let local_ty = frame.body.local_decls[local].ty;
-                    let local_ty = self.tcx.subst_and_normalize_erasing_regions(
-                        frame.instance.substs,
-                        self.param_env,
-                        &local_ty,
-                    );
+                    let local_ty =
+                        self.subst_from_frame_and_normalize_erasing_regions(frame, local_ty);
                     self.layout_of(local_ty)
                 })?;
                 if let Some(state) = frame.locals.get(local) {
@@ -457,10 +464,7 @@ pub(super) fn size_and_align_of(
 
                 // Check if this brought us over the size limit.
                 if size.bytes() >= self.tcx.data_layout().obj_size_bound() {
-                    throw_ub_format!(
-                        "wide pointer metadata contains invalid information: \
-                        total size is bigger than largest supported object"
-                    );
+                    throw_ub!(InvalidMeta("total size is bigger than largest supported object"));
                 }
                 Ok(Some((size, align)))
             }
@@ -476,10 +480,7 @@ pub(super) fn size_and_align_of(
 
                 // Make sure the slice is not too big.
                 let size = elem.size.checked_mul(len, &*self.tcx).ok_or_else(|| {
-                    err_ub_format!(
-                        "invalid slice: \
-                        total size is bigger than largest supported object"
-                    )
+                    err_ub!(InvalidMeta("slice is bigger than largest supported object"))
                 })?;
                 Ok(Some((size, elem.align.abi)))
             }
@@ -629,23 +630,15 @@ pub(super) fn pop_stack_frame(&mut self, unwinding: bool) -> InterpResult<'tcx>
 
         ::log_settings::settings().indentation -= 1;
         let frame = self.stack.pop().expect("tried to pop a stack frame, but there were none");
-        let stack_pop_info = M::stack_pop(self, frame.extra, unwinding)?;
-        if let (false, StackPopInfo::StopUnwinding) = (unwinding, stack_pop_info) {
-            bug!("Attempted to stop unwinding while there is no unwinding!");
-        }
 
         // Now where do we jump next?
 
-        // Determine if we leave this function normally or via unwinding.
-        let cur_unwinding =
-            if let StackPopInfo::StopUnwinding = stack_pop_info { false } else { unwinding };
-
         // Usually we want to clean up (deallocate locals), but in a few rare cases we don't.
         // In that case, we return early. We also avoid validation in that case,
         // because this is CTFE and the final value will be thoroughly validated anyway.
         let (cleanup, next_block) = match frame.return_to_block {
             StackPopCleanup::Goto { ret, unwind } => {
-                (true, Some(if cur_unwinding { unwind } else { ret }))
+                (true, Some(if unwinding { unwind } else { ret }))
             }
             StackPopCleanup::None { cleanup, .. } => (cleanup, None),
         };
@@ -653,7 +646,8 @@ pub(super) fn pop_stack_frame(&mut self, unwinding: bool) -> InterpResult<'tcx>
         if !cleanup {
             assert!(self.stack.is_empty(), "only the topmost frame should ever be leaked");
             assert!(next_block.is_none(), "tried to skip cleanup when we have a next block!");
-            // Leak the locals, skip validation.
+            assert!(!unwinding, "tried to skip cleanup during unwinding");
+            // Leak the locals, skip validation, skip machine hook.
             return Ok(());
         }
 
@@ -662,15 +656,15 @@ pub(super) fn pop_stack_frame(&mut self, unwinding: bool) -> InterpResult<'tcx>
             self.deallocate_local(local.value)?;
         }
 
-        trace!(
-            "StackPopCleanup: {:?} StackPopInfo: {:?} cur_unwinding = {:?}",
-            frame.return_to_block,
-            stack_pop_info,
-            cur_unwinding
-        );
-        if cur_unwinding {
+        if M::stack_pop(self, frame.extra, unwinding)? == StackPopJump::NoJump {
+            // The hook already did everything.
+            // We want to skip the `info!` below, hence early return.
+            return Ok(());
+        }
+        // Normal return.
+        if unwinding {
             // Follow the unwind edge.
-            let unwind = next_block.expect("Encounted StackPopCleanup::None when unwinding!");
+            let unwind = next_block.expect("Encountered StackPopCleanup::None when unwinding!");
             self.unwind_to_block(unwind);
         } else {
             // Follow the normal return edge.
@@ -685,7 +679,7 @@ pub(super) fn pop_stack_frame(&mut self, unwinding: bool) -> InterpResult<'tcx>
                     // invariant -- that is, unless a function somehow has a ptr to
                     // its return place... but the way MIR is currently generated, the
                     // return place is always a local and then this cannot happen.
-                    self.validate_operand(self.place_to_op(return_place)?, vec![], None)?;
+                    self.validate_operand(self.place_to_op(return_place)?)?;
                 }
             } else {
                 // Uh, that shouldn't happen... the function did not intend to return
@@ -703,7 +697,7 @@ pub(super) fn pop_stack_frame(&mut self, unwinding: bool) -> InterpResult<'tcx>
                 "CONTINUING({}) {} (unwinding = {})",
                 self.cur_frame(),
                 self.frame().instance,
-                cur_unwinding
+                unwinding
             );
         }
 
index 747b2dd4aa007695319fa08a23e1c934fbd1c35a..90b8a4932991e2b44499c2a4105a257c4ecb1dba 100644 (file)
@@ -187,7 +187,7 @@ fn visit_aggregate(
         self.walk_aggregate(mplace, fields)
     }
 
-    fn visit_primitive(&mut self, mplace: MPlaceTy<'tcx>) -> InterpResult<'tcx> {
+    fn visit_value(&mut self, mplace: MPlaceTy<'tcx>) -> InterpResult<'tcx> {
         // Handle Reference types, as these are the only relocations supported by const eval.
         // Raw pointers (and boxes) are handled by the `leftover_relocations` logic.
         let ty = mplace.layout.ty;
@@ -263,8 +263,11 @@ fn visit_primitive(&mut self, mplace: MPlaceTy<'tcx>) -> InterpResult<'tcx> {
                     None => self.ref_tracking.track((mplace, mutability, mode), || ()),
                 }
             }
+            Ok(())
+        } else {
+            // Not a reference -- proceed recursively.
+            self.walk_value(mplace)
         }
-        Ok(())
     }
 }
 
@@ -324,7 +327,7 @@ pub fn intern_const_alloc_recursive<M: CompileTimeMachine<'mir, 'tcx>>(
         if let Err(error) = interned {
             // This can happen when e.g. the tag of an enum is not a valid discriminant. We do have
             // to read enum discriminants in order to find references in enum variant fields.
-            if let err_unsup!(ValidationFailure(_)) = error.kind {
+            if let err_ub!(ValidationFailure(_)) = error.kind {
                 let err = crate::const_eval::error_to_const_error(&ecx, error);
                 match err.struct_error(
                     ecx.tcx,
@@ -387,7 +390,7 @@ pub fn intern_const_alloc_recursive<M: CompileTimeMachine<'mir, 'tcx>>(
             }
         } else if ecx.memory.dead_alloc_map.contains_key(&alloc_id) {
             // dangling pointer
-            throw_unsup!(ValidationFailure("encountered dangling pointer in final constant".into()))
+            throw_ub_format!("encountered dangling pointer in final constant")
         } else if ecx.tcx.alloc_map.lock().get(alloc_id).is_none() {
             // We have hit an `AllocId` that is neither in local or global memory and isn't marked
             // as dangling by local memory.
index cd06cf01bfa8111a1537fb2acd6da72820cbbe21..03aedad0d988da39935fa9682b6d2aa807ea358b 100644 (file)
@@ -84,14 +84,15 @@ pub fn emulate_intrinsic(
         let substs = instance.substs;
         let intrinsic_name = self.tcx.item_name(instance.def_id());
 
-        // We currently do not handle any intrinsics that are *allowed* to diverge,
-        // but `transmute` could lack a return place in case of UB.
+        // First handle intrinsics without return place.
         let (dest, ret) = match ret {
-            Some(p) => p,
             None => match intrinsic_name {
-                sym::transmute => throw_ub!(Unreachable),
+                sym::transmute => throw_ub_format!("transmuting to uninhabited type"),
+                sym::abort => M::abort(self)?,
+                // Unsupported diverging intrinsic.
                 _ => return Ok(false),
             },
+            Some(p) => p,
         };
 
         // Keep the patterns in this match ordered the same as the list in
@@ -134,7 +135,7 @@ pub fn emulate_intrinsic(
                 let bits = self.force_bits(val, layout_of.size)?;
                 let kind = match layout_of.abi {
                     ty::layout::Abi::Scalar(ref scalar) => scalar.value,
-                    _ => throw_unsup!(TypeNotPrimitive(ty)),
+                    _ => bug!("{} called on invalid type {:?}", intrinsic_name, ty),
                 };
                 let (nonzero, intrinsic_name) = match intrinsic_name {
                     sym::cttz_nonzero => (true, sym::cttz),
@@ -203,7 +204,7 @@ pub fn emulate_intrinsic(
                         if is_add {
                             // max unsigned
                             Scalar::from_uint(
-                                u128::max_value() >> (128 - num_bits),
+                                u128::MAX >> (128 - num_bits),
                                 Size::from_bits(num_bits),
                             )
                         } else {
@@ -216,6 +217,11 @@ pub fn emulate_intrinsic(
                 };
                 self.write_scalar(val, dest)?;
             }
+            sym::discriminant_value => {
+                let place = self.deref_operand(args[0])?;
+                let discr_val = self.read_discriminant(place.into())?.0;
+                self.write_scalar(Scalar::from_uint(discr_val, dest.layout.size), dest)?;
+            }
             sym::unchecked_shl
             | sym::unchecked_shr
             | sym::unchecked_add
@@ -240,9 +246,9 @@ pub fn emulate_intrinsic(
                     let layout = self.layout_of(substs.type_at(0))?;
                     let r_val = self.force_bits(r.to_scalar()?, layout.size)?;
                     if let sym::unchecked_shl | sym::unchecked_shr = intrinsic_name {
-                        throw_ub_format!("Overflowing shift by {} in `{}`", r_val, intrinsic_name);
+                        throw_ub_format!("overflowing shift by {} in `{}`", r_val, intrinsic_name);
                     } else {
-                        throw_ub_format!("Overflow executing `{}`", intrinsic_name);
+                        throw_ub_format!("overflow executing `{}`", intrinsic_name);
                     }
                 }
                 self.write_scalar(val, dest)?;
@@ -381,11 +387,11 @@ pub fn exact_div(
         dest: PlaceTy<'tcx, M::PointerTag>,
     ) -> InterpResult<'tcx> {
         // Performs an exact division, resulting in undefined behavior where
-        // `x % y != 0` or `y == 0` or `x == T::min_value() && y == -1`.
+        // `x % y != 0` or `y == 0` or `x == T::MIN && y == -1`.
         // First, check x % y != 0 (or if that computation overflows).
         let (res, overflow, _ty) = self.overflowing_binary_op(BinOp::Rem, a, b)?;
-        if overflow || res.to_bits(a.layout.size)? != 0 {
-            // Then, check if `b` is -1, which is the "min_value / -1" case.
+        if overflow || res.assert_bits(a.layout.size) != 0 {
+            // Then, check if `b` is -1, which is the "MIN / -1" case.
             let minus1 = Scalar::from_int(-1, dest.layout.size);
             let b_scalar = b.to_scalar().unwrap();
             if b_scalar == minus1 {
index cd8bf7085d1b1c4fb8c383e730373027caeb3e08..677dc69773516e6687af9a0fb1308a9798ea217c 100644 (file)
@@ -157,6 +157,7 @@ fn path_generic_args(
         }
     }
 }
+
 impl PrettyPrinter<'tcx> for AbsolutePathPrinter<'tcx> {
     fn region_should_not_be_omitted(&self, _region: ty::Region<'_>) -> bool {
         false
index 5291000d10b3fa775d18135084d1b3d727ac41e8..c9d32f6240037ee43691a0a5f568679bc98a1357 100644 (file)
@@ -6,8 +6,7 @@
 use std::hash::Hash;
 
 use rustc::mir;
-use rustc::ty::{self, Ty, TyCtxt};
-use rustc_hir::def_id::DefId;
+use rustc::ty::{self, Ty};
 use rustc_span::Span;
 
 use super::{
 /// Data returned by Machine::stack_pop,
 /// to provide further control over the popping of the stack frame
 #[derive(Eq, PartialEq, Debug, Copy, Clone)]
-pub enum StackPopInfo {
+pub enum StackPopJump {
     /// Indicates that no special handling should be
     /// done - we'll either return normally or unwind
     /// based on the terminator for the function
     /// we're leaving.
     Normal,
 
-    /// Indicates that we should stop unwinding,
-    /// as we've reached a catch frame
-    StopUnwinding,
+    /// Indicates that we should *not* jump to the return/unwind address, as the callback already
+    /// took care of everything.
+    NoJump,
 }
 
 /// Whether this kind of memory is allowed to leak
@@ -123,10 +122,6 @@ pub trait Machine<'mir, 'tcx>: Sized {
     /// Whether to enforce the validity invariant
     fn enforce_validity(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool;
 
-    /// Called before a basic block terminator is executed.
-    /// You can use this to detect endlessly running programs.
-    fn before_terminator(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx>;
-
     /// Entry point to all function calls.
     ///
     /// Returns either the mir to use for the call, or `None` if execution should
@@ -170,22 +165,14 @@ fn call_intrinsic(
     /// Called to evaluate `Assert` MIR terminators that trigger a panic.
     fn assert_panic(
         ecx: &mut InterpCx<'mir, 'tcx, Self>,
-        span: Span,
         msg: &mir::AssertMessage<'tcx>,
         unwind: Option<mir::BasicBlock>,
     ) -> InterpResult<'tcx>;
 
-    /// Called for read access to a foreign static item.
-    ///
-    /// This will only be called once per static and machine; the result is cached in
-    /// the machine memory. (This relies on `AllocMap::get_or` being able to add the
-    /// owned allocation to the map even when the map is shared.)
-    ///
-    /// This allocation will then be fed to `tag_allocation` to initialize the "extra" state.
-    fn find_foreign_static(
-        tcx: TyCtxt<'tcx>,
-        def_id: DefId,
-    ) -> InterpResult<'tcx, Cow<'tcx, Allocation>>;
+    /// Called to evaluate `Abort` MIR terminator.
+    fn abort(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx, !> {
+        throw_unsup_format!("aborting execution is not supported");
+    }
 
     /// Called for all binary operations where the LHS has pointer type.
     ///
@@ -204,6 +191,7 @@ fn box_alloc(
     ) -> InterpResult<'tcx>;
 
     /// Called to read the specified `local` from the `frame`.
+    #[inline]
     fn access_local(
         _ecx: &InterpCx<'mir, 'tcx, Self>,
         frame: &Frame<'mir, 'tcx, Self::PointerTag, Self::FrameExtra>,
@@ -212,7 +200,15 @@ fn access_local(
         frame.locals[local].access()
     }
 
+    /// Called before a basic block terminator is executed.
+    /// You can use this to detect endlessly running programs.
+    #[inline]
+    fn before_terminator(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
+        Ok(())
+    }
+
     /// Called before a `Static` value is accessed.
+    #[inline]
     fn before_access_static(
         _memory_extra: &Self::MemoryExtra,
         _allocation: &Allocation,
@@ -220,11 +216,22 @@ fn before_access_static(
         Ok(())
     }
 
+    /// Called for *every* memory access to determine the real ID of the given allocation.
+    /// This provides a way for the machine to "redirect" certain allocations as it sees fit.
+    ///
+    /// This is used by Miri to redirect extern statics to real allocations.
+    ///
+    /// This function must be idempotent.
+    #[inline]
+    fn canonical_alloc_id(_mem: &Memory<'mir, 'tcx, Self>, id: AllocId) -> AllocId {
+        id
+    }
+
     /// Called to initialize the "extra" state of an allocation and make the pointers
     /// it contains (in relocations) tagged.  The way we construct allocations is
     /// to always first construct it without extra and then add the extra.
     /// This keeps uniform code paths for handling both allocations created by CTFE
-    /// for statics, and allocations ceated by Miri during evaluation.
+    /// for statics, and allocations created by Miri during evaluation.
     ///
     /// `kind` is the kind of the allocation being tagged; it can be `None` when
     /// it's a static and `STATIC_KIND` is `None`.
@@ -247,6 +254,8 @@ fn init_allocation_extra<'b>(
     /// Return the "base" tag for the given *static* allocation: the one that is used for direct
     /// accesses to this static/const/fn allocation. If `id` is not a static allocation,
     /// this will return an unusable tag (i.e., accesses will be UB)!
+    ///
+    /// Expects `id` to be already canonical, if needed.
     fn tag_static_base_pointer(memory_extra: &Self::MemoryExtra, id: AllocId) -> Self::PointerTag;
 
     /// Executes a retagging operation
@@ -259,7 +268,7 @@ fn retag(
         Ok(())
     }
 
-    /// Called immediately before a new stack frame got pushed
+    /// Called immediately before a new stack frame got pushed.
     fn stack_push(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx, Self::FrameExtra>;
 
     /// Called immediately after a stack frame gets popped
@@ -267,9 +276,9 @@ fn stack_pop(
         _ecx: &mut InterpCx<'mir, 'tcx, Self>,
         _extra: Self::FrameExtra,
         _unwinding: bool,
-    ) -> InterpResult<'tcx, StackPopInfo> {
+    ) -> InterpResult<'tcx, StackPopJump> {
         // By default, we do not support unwinding from panics
-        Ok(StackPopInfo::Normal)
+        Ok(StackPopJump::Normal)
     }
 
     fn int_to_ptr(
@@ -277,8 +286,10 @@ fn int_to_ptr(
         int: u64,
     ) -> InterpResult<'tcx, Pointer<Self::PointerTag>> {
         Err((if int == 0 {
-            err_unsup!(InvalidNullPointerUsage)
+            // This is UB, seriously.
+            err_ub!(InvalidIntPointerUsage(0))
         } else {
+            // This is just something we cannot support during const-eval.
             err_unsup!(ReadBytesAsPointer)
         })
         .into())
index 032a4bd58506d6e2e584e58e534d19590c6187e4..5b2cd89a122845f13cd512465cdb60f8806e4968 100644 (file)
@@ -150,7 +150,8 @@ pub fn new(tcx: TyCtxtAt<'tcx>, extra: M::MemoryExtra) -> Self {
     /// through a pointer that was created by the program.
     #[inline]
     pub fn tag_static_base_pointer(&self, ptr: Pointer) -> Pointer<M::PointerTag> {
-        ptr.with_tag(M::tag_static_base_pointer(&self.extra, ptr.alloc_id))
+        let id = M::canonical_alloc_id(self, ptr.alloc_id);
+        ptr.with_tag(M::tag_static_base_pointer(&self.extra, id))
     }
 
     pub fn create_fn_alloc(
@@ -214,7 +215,10 @@ pub fn reallocate(
         kind: MemoryKind<M::MemoryKinds>,
     ) -> InterpResult<'tcx, Pointer<M::PointerTag>> {
         if ptr.offset.bytes() != 0 {
-            throw_unsup!(ReallocateNonBasePtr)
+            throw_ub_format!(
+                "reallocating {:?} which does not point to the beginning of an object",
+                ptr
+            );
         }
 
         // For simplicities' sake, we implement reallocate as "alloc, copy, dealloc".
@@ -250,7 +254,10 @@ pub fn deallocate(
         trace!("deallocating: {}", ptr.alloc_id);
 
         if ptr.offset.bytes() != 0 {
-            throw_unsup!(DeallocateNonBasePtr)
+            throw_ub_format!(
+                "deallocating {:?} which does not point to the beginning of an object",
+                ptr
+            );
         }
 
         let (alloc_kind, mut alloc) = match self.alloc_map.remove(&ptr.alloc_id) {
@@ -258,29 +265,32 @@ pub fn deallocate(
             None => {
                 // Deallocating static memory -- always an error
                 return Err(match self.tcx.alloc_map.lock().get(ptr.alloc_id) {
-                    Some(GlobalAlloc::Function(..)) => err_unsup!(DeallocatedWrongMemoryKind(
-                        "function".to_string(),
-                        format!("{:?}", kind),
-                    )),
-                    Some(GlobalAlloc::Static(..)) | Some(GlobalAlloc::Memory(..)) => err_unsup!(
-                        DeallocatedWrongMemoryKind("static".to_string(), format!("{:?}", kind))
-                    ),
-                    None => err_unsup!(DoubleFree),
+                    Some(GlobalAlloc::Function(..)) => err_ub_format!("deallocating a function"),
+                    Some(GlobalAlloc::Static(..)) | Some(GlobalAlloc::Memory(..)) => {
+                        err_ub_format!("deallocating static memory")
+                    }
+                    None => err_ub!(PointerUseAfterFree(ptr.alloc_id)),
                 }
                 .into());
             }
         };
 
         if alloc_kind != kind {
-            throw_unsup!(DeallocatedWrongMemoryKind(
-                format!("{:?}", alloc_kind),
-                format!("{:?}", kind),
-            ))
+            throw_ub_format!(
+                "deallocating `{:?}` memory using `{:?}` deallocation operation",
+                alloc_kind,
+                kind
+            );
         }
         if let Some((size, align)) = old_size_and_align {
             if size != alloc.size || align != alloc.align {
-                let bytes = alloc.size;
-                throw_unsup!(IncorrectAllocationInformation(size, bytes, align, alloc.align))
+                throw_ub_format!(
+                    "incorrect layout on deallocation: allocation has size {} and alignment {}, but gave size {} and alignment {}",
+                    alloc.size.bytes(),
+                    alloc.align.bytes(),
+                    size.bytes(),
+                    align.bytes(),
+                )
             }
         }
 
@@ -337,7 +347,7 @@ fn check_offset_align(offset: u64, align: Align) -> InterpResult<'static> {
             } else {
                 // The biggest power of two through which `offset` is divisible.
                 let offset_pow2 = 1 << offset.trailing_zeros();
-                throw_unsup!(AlignmentCheckFailed {
+                throw_ub!(AlignmentCheckFailed {
                     has: Align::from_bytes(offset_pow2).unwrap(),
                     required: align,
                 })
@@ -359,7 +369,7 @@ fn check_offset_align(offset: u64, align: Align) -> InterpResult<'static> {
                 assert!(size.bytes() == 0);
                 // Must be non-NULL.
                 if bits == 0 {
-                    throw_unsup!(InvalidNullPointerUsage)
+                    throw_ub!(InvalidIntPointerUsage(0))
                 }
                 // Must be aligned.
                 if let Some(align) = align {
@@ -374,7 +384,10 @@ fn check_offset_align(offset: u64, align: Align) -> InterpResult<'static> {
                 // It is sufficient to check this for the end pointer. The addition
                 // checks for overflow.
                 let end_ptr = ptr.offset(size, self)?;
-                end_ptr.check_inbounds_alloc(allocation_size, msg)?;
+                if end_ptr.offset > allocation_size {
+                    // equal is okay!
+                    throw_ub!(PointerOutOfBounds { ptr: end_ptr.erase_tag(), msg, allocation_size })
+                }
                 // Test align. Check this last; if both bounds and alignment are violated
                 // we want the error to be about the bounds.
                 if let Some(align) = align {
@@ -384,7 +397,7 @@ fn check_offset_align(offset: u64, align: Align) -> InterpResult<'static> {
                         // got picked we might be aligned even if this check fails.
                         // We instead have to fall back to converting to an integer and checking
                         // the "real" alignment.
-                        throw_unsup!(AlignmentCheckFailed { has: alloc_align, required: align });
+                        throw_ub!(AlignmentCheckFailed { has: alloc_align, required: align });
                     }
                     check_offset_align(ptr.offset.bytes(), align)?;
                 }
@@ -401,7 +414,9 @@ pub fn ptr_may_be_null(&self, ptr: Pointer<M::PointerTag>) -> bool {
         let (size, _align) = self
             .get_size_and_align(ptr.alloc_id, AllocCheck::MaybeDead)
             .expect("alloc info with MaybeDead cannot fail");
-        ptr.check_inbounds_alloc(size, CheckInAllocMsg::NullPointerTest).is_err()
+        // If the pointer is out-of-bounds, it may be null.
+        // Note that one-past-the-end (offset == size) is still inbounds, and never null.
+        ptr.offset > size
     }
 }
 
@@ -421,6 +436,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
     /// The `GlobalAlloc::Memory` branch here is still reachable though; when a static
     /// contains a reference to memory that was created during its evaluation (i.e., not to
     /// another static), those inner references only exist in "resolved" form.
+    ///
+    /// Assumes `id` is already canonical.
     fn get_static_alloc(
         memory_extra: &M::MemoryExtra,
         tcx: TyCtxtAt<'tcx>,
@@ -429,36 +446,35 @@ fn get_static_alloc(
         let alloc = tcx.alloc_map.lock().get(id);
         let alloc = match alloc {
             Some(GlobalAlloc::Memory(mem)) => Cow::Borrowed(mem),
-            Some(GlobalAlloc::Function(..)) => throw_unsup!(DerefFunctionPointer),
-            None => throw_unsup!(DanglingPointerDeref),
+            Some(GlobalAlloc::Function(..)) => throw_ub!(DerefFunctionPointer(id)),
+            None => throw_ub!(PointerUseAfterFree(id)),
             Some(GlobalAlloc::Static(def_id)) => {
                 // We got a "lazy" static that has not been computed yet.
                 if tcx.is_foreign_item(def_id) {
-                    trace!("static_alloc: foreign item {:?}", def_id);
-                    M::find_foreign_static(tcx.tcx, def_id)?
-                } else {
-                    trace!("static_alloc: Need to compute {:?}", def_id);
-                    let instance = Instance::mono(tcx.tcx, def_id);
-                    let gid = GlobalId { instance, promoted: None };
-                    // use the raw query here to break validation cycles. Later uses of the static
-                    // will call the full query anyway
-                    let raw_const =
-                        tcx.const_eval_raw(ty::ParamEnv::reveal_all().and(gid)).map_err(|err| {
-                            // no need to report anything, the const_eval call takes care of that
-                            // for statics
-                            assert!(tcx.is_static(def_id));
-                            match err {
-                                ErrorHandled::Reported => err_inval!(ReferencedConstant),
-                                ErrorHandled::TooGeneric => err_inval!(TooGeneric),
-                            }
-                        })?;
-                    // Make sure we use the ID of the resolved memory, not the lazy one!
-                    let id = raw_const.alloc_id;
-                    let allocation = tcx.alloc_map.lock().unwrap_memory(id);
-
-                    M::before_access_static(memory_extra, allocation)?;
-                    Cow::Borrowed(allocation)
+                    trace!("get_static_alloc: foreign item {:?}", def_id);
+                    throw_unsup!(ReadForeignStatic(def_id))
                 }
+                trace!("get_static_alloc: Need to compute {:?}", def_id);
+                let instance = Instance::mono(tcx.tcx, def_id);
+                let gid = GlobalId { instance, promoted: None };
+                // use the raw query here to break validation cycles. Later uses of the static
+                // will call the full query anyway
+                let raw_const =
+                    tcx.const_eval_raw(ty::ParamEnv::reveal_all().and(gid)).map_err(|err| {
+                        // no need to report anything, the const_eval call takes care of that
+                        // for statics
+                        assert!(tcx.is_static(def_id));
+                        match err {
+                            ErrorHandled::Reported => err_inval!(ReferencedConstant),
+                            ErrorHandled::TooGeneric => err_inval!(TooGeneric),
+                        }
+                    })?;
+                // Make sure we use the ID of the resolved memory, not the lazy one!
+                let id = raw_const.alloc_id;
+                let allocation = tcx.alloc_map.lock().unwrap_memory(id);
+
+                M::before_access_static(memory_extra, allocation)?;
+                Cow::Borrowed(allocation)
             }
         };
         // We got tcx memory. Let the machine initialize its "extra" stuff.
@@ -478,6 +494,7 @@ pub fn get_raw(
         &self,
         id: AllocId,
     ) -> InterpResult<'tcx, &Allocation<M::PointerTag, M::AllocExtra>> {
+        let id = M::canonical_alloc_id(self, id);
         // The error type of the inner closure here is somewhat funny.  We have two
         // ways of "erroring": An actual error, or because we got a reference from
         // `get_static_alloc` that we can actually use directly without inserting anything anywhere.
@@ -513,6 +530,7 @@ pub fn get_raw_mut(
         &mut self,
         id: AllocId,
     ) -> InterpResult<'tcx, &mut Allocation<M::PointerTag, M::AllocExtra>> {
+        let id = M::canonical_alloc_id(self, id);
         let tcx = self.tcx;
         let memory_extra = &self.extra;
         let a = self.alloc_map.get_mut_or(id, || {
@@ -520,7 +538,7 @@ pub fn get_raw_mut(
             // to give us a cheap reference.
             let alloc = Self::get_static_alloc(memory_extra, tcx, id)?;
             if alloc.mutability == Mutability::Not {
-                throw_unsup!(ModifiedConstantMemory)
+                throw_ub!(WriteToReadOnly(id))
             }
             match M::STATIC_KIND {
                 Some(kind) => Ok((MemoryKind::Machine(kind), alloc.into_owned())),
@@ -534,7 +552,7 @@ pub fn get_raw_mut(
             Ok(a) => {
                 let a = &mut a.1;
                 if a.mutability == Mutability::Not {
-                    throw_unsup!(ModifiedConstantMemory)
+                    throw_ub!(WriteToReadOnly(id))
                 }
                 Ok(a)
             }
@@ -550,6 +568,7 @@ pub fn get_size_and_align(
         id: AllocId,
         liveness: AllocCheck,
     ) -> InterpResult<'static, (Size, Align)> {
+        let id = M::canonical_alloc_id(self, id);
         // # Regular allocations
         // Don't use `self.get_raw` here as that will
         // a) cause cycles in case `id` refers to a static
@@ -560,10 +579,10 @@ pub fn get_size_and_align(
 
         // # Function pointers
         // (both global from `alloc_map` and local from `extra_fn_ptr_map`)
-        if let Some(_) = self.get_fn_alloc(id) {
+        if self.get_fn_alloc(id).is_some() {
             return if let AllocCheck::Dereferenceable = liveness {
                 // The caller requested no function pointers.
-                throw_unsup!(DerefFunctionPointer)
+                throw_ub!(DerefFunctionPointer(id))
             } else {
                 Ok((Size::ZERO, Align::from_bytes(1).unwrap()))
             };
@@ -591,17 +610,18 @@ pub fn get_size_and_align(
                 if let AllocCheck::MaybeDead = liveness {
                     // Deallocated pointers are allowed, we should be able to find
                     // them in the map.
-                    Ok(*self.dead_alloc_map.get(&id).expect(
-                        "deallocated pointers should all be recorded in \
-                            `dead_alloc_map`",
-                    ))
+                    Ok(*self
+                        .dead_alloc_map
+                        .get(&id)
+                        .expect("deallocated pointers should all be recorded in `dead_alloc_map`"))
                 } else {
-                    throw_unsup!(DanglingPointerDeref)
+                    throw_ub!(PointerUseAfterFree(id))
                 }
             }
         }
     }
 
+    /// Assumes `id` is already canonical.
     fn get_fn_alloc(&self, id: AllocId) -> Option<FnVal<'tcx, M::ExtraFnVal>> {
         trace!("reading fn ptr: {}", id);
         if let Some(extra) = self.extra_fn_ptr_map.get(&id) {
@@ -620,9 +640,10 @@ pub fn get_fn(
     ) -> InterpResult<'tcx, FnVal<'tcx, M::ExtraFnVal>> {
         let ptr = self.force_ptr(ptr)?; // We definitely need a pointer value.
         if ptr.offset.bytes() != 0 {
-            throw_unsup!(InvalidFunctionPointer)
+            throw_ub!(InvalidFunctionPointer(ptr.erase_tag()))
         }
-        self.get_fn_alloc(ptr.alloc_id).ok_or_else(|| err_unsup!(ExecuteMemory).into())
+        let id = M::canonical_alloc_id(self, ptr.alloc_id);
+        self.get_fn_alloc(id).ok_or_else(|| err_ub!(InvalidFunctionPointer(ptr.erase_tag())).into())
     }
 
     pub fn mark_immutable(&mut self, id: AllocId) -> InterpResult<'tcx> {
@@ -791,6 +812,33 @@ pub fn read_c_str(&self, ptr: Scalar<M::PointerTag>) -> InterpResult<'tcx, &[u8]
         self.get_raw(ptr.alloc_id)?.read_c_str(self, ptr)
     }
 
+    /// Reads a 0x0000-terminated u16-sequence from memory. Returns them as a Vec<u16>.
+    /// Terminator 0x0000 is not included in the returned Vec<u16>.
+    ///
+    /// Performs appropriate bounds checks.
+    pub fn read_wide_str(&self, ptr: Scalar<M::PointerTag>) -> InterpResult<'tcx, Vec<u16>> {
+        let size_2bytes = Size::from_bytes(2);
+        let align_2bytes = Align::from_bytes(2).unwrap();
+        // We need to read at least 2 bytes, so we *need* a ptr.
+        let mut ptr = self.force_ptr(ptr)?;
+        let allocation = self.get_raw(ptr.alloc_id)?;
+        let mut u16_seq = Vec::new();
+
+        loop {
+            ptr = self
+                .check_ptr_access(ptr.into(), size_2bytes, align_2bytes)?
+                .expect("cannot be a ZST");
+            let single_u16 = allocation.read_scalar(self, ptr, size_2bytes)?.to_u16()?;
+            if single_u16 != 0x0000 {
+                u16_seq.push(single_u16);
+                ptr = ptr.offset(size_2bytes, self)?;
+            } else {
+                break;
+            }
+        }
+        Ok(u16_seq)
+    }
+
     /// Writes the given stream of bytes into memory.
     ///
     /// Performs appropriate bounds checks.
index a519f38e712087dc9215a0aa79a71a77c9dc09f6..c3fd968276577241207408783545216fca5fe308 100644 (file)
@@ -24,7 +24,7 @@
 
 pub use self::memory::{AllocCheck, FnVal, Memory, MemoryKind};
 
-pub use self::machine::{AllocMap, Machine, MayLeak, StackPopInfo};
+pub use self::machine::{AllocMap, Machine, MayLeak, StackPopJump};
 
 pub use self::operand::{ImmTy, Immediate, OpTy, Operand, ScalarMaybeUndef};
 
index df4b9b1618619bb7ce1b692f8f216de07ae75467..b39058405f5cbf2094b483324afd4e4938291afc 100644 (file)
@@ -3,18 +3,20 @@
 
 use std::convert::{TryFrom, TryInto};
 
-use rustc::ty::layout::{
-    self, HasDataLayout, IntegerExt, LayoutOf, PrimitiveExt, Size, TyLayout, VariantIdx,
-};
-use rustc::{mir, ty};
-
 use super::{InterpCx, MPlaceTy, Machine, MemPlace, Place, PlaceTy};
 pub use rustc::mir::interpret::ScalarMaybeUndef;
 use rustc::mir::interpret::{
     sign_extend, truncate, AllocId, ConstValue, GlobalId, InterpResult, Pointer, Scalar,
 };
-use rustc_ast::ast;
+use rustc::ty::layout::{
+    self, HasDataLayout, IntegerExt, LayoutOf, PrimitiveExt, Size, TyLayout, VariantIdx,
+};
+use rustc::ty::print::{FmtPrinter, PrettyPrinter, Printer};
+use rustc::ty::Ty;
+use rustc::{mir, ty};
+use rustc_hir::def::Namespace;
 use rustc_macros::HashStable;
+use std::fmt::Write;
 
 /// An `Immediate` represents a single immediate self-contained Rust value.
 ///
@@ -92,47 +94,44 @@ pub struct ImmTy<'tcx, Tag = ()> {
     pub layout: TyLayout<'tcx>,
 }
 
-// `Tag: Copy` because some methods on `Scalar` consume them by value
 impl<Tag: Copy> std::fmt::Display for ImmTy<'tcx, Tag> {
-    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        match &self.imm {
-            Immediate::Scalar(ScalarMaybeUndef::Scalar(s)) => match s.to_bits(self.layout.size) {
-                Ok(s) => {
-                    match self.layout.ty.kind {
-                        ty::Int(_) => {
-                            return write!(
-                                fmt,
-                                "{}",
-                                super::sign_extend(s, self.layout.size) as i128,
-                            );
-                        }
-                        ty::Uint(_) => return write!(fmt, "{}", s),
-                        ty::Bool if s == 0 => return fmt.write_str("false"),
-                        ty::Bool if s == 1 => return fmt.write_str("true"),
-                        ty::Char => {
-                            if let Some(c) = u32::try_from(s).ok().and_then(std::char::from_u32) {
-                                return write!(fmt, "{}", c);
-                            }
-                        }
-                        ty::Float(ast::FloatTy::F32) => {
-                            if let Ok(u) = u32::try_from(s) {
-                                return write!(fmt, "{}", f32::from_bits(u));
-                            }
-                        }
-                        ty::Float(ast::FloatTy::F64) => {
-                            if let Ok(u) = u64::try_from(s) {
-                                return write!(fmt, "{}", f64::from_bits(u));
-                            }
-                        }
-                        _ => {}
-                    }
-                    write!(fmt, "{:x}", s)
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        /// Helper function for printing a scalar to a FmtPrinter
+        fn p<'a, 'tcx, F: std::fmt::Write, Tag>(
+            cx: FmtPrinter<'a, 'tcx, F>,
+            s: ScalarMaybeUndef<Tag>,
+            ty: Ty<'tcx>,
+        ) -> Result<FmtPrinter<'a, 'tcx, F>, std::fmt::Error> {
+            match s {
+                ScalarMaybeUndef::Scalar(s) => {
+                    cx.pretty_print_const_scalar(s.erase_tag(), ty, true)
                 }
-                Err(_) => fmt.write_str("{pointer}"),
-            },
-            Immediate::Scalar(ScalarMaybeUndef::Undef) => fmt.write_str("{undef}"),
-            Immediate::ScalarPair(..) => fmt.write_str("{wide pointer or tuple}"),
+                ScalarMaybeUndef::Undef => cx.typed_value(
+                    |mut this| {
+                        this.write_str("{undef ")?;
+                        Ok(this)
+                    },
+                    |this| this.print_type(ty),
+                    " ",
+                ),
+            }
         }
+        ty::tls::with(|tcx| {
+            match self.imm {
+                Immediate::Scalar(s) => {
+                    if let Some(ty) = tcx.lift(&self.layout.ty) {
+                        let cx = FmtPrinter::new(tcx, f, Namespace::ValueNS);
+                        p(cx, s, ty)?;
+                        return Ok(());
+                    }
+                    write!(f, "{:?}: {}", s.erase_tag(), self.layout.ty)
+                }
+                Immediate::ScalarPair(a, b) => {
+                    // FIXME(oli-obk): at least print tuples and slices nicely
+                    write!(f, "({:?}, {:?}): {}", a.erase_tag(), b.erase_tag(), self.layout.ty,)
+                }
+            }
+        })
     }
 }
 
@@ -205,11 +204,6 @@ pub fn try_from_int(i: impl Into<i128>, layout: TyLayout<'tcx>) -> Option<Self>
     pub fn from_int(i: impl Into<i128>, layout: TyLayout<'tcx>) -> Self {
         Self::from_scalar(Scalar::from_int(i, layout.size), layout)
     }
-
-    #[inline]
-    pub fn to_bits(self) -> InterpResult<'tcx, u128> {
-        self.to_scalar()?.to_bits(self.layout.size)
-    }
 }
 
 // Use the existing layout if given (but sanity check in debug mode),
@@ -349,7 +343,7 @@ pub fn read_str(&self, mplace: MPlaceTy<'tcx, M::PointerTag>) -> InterpResult<'t
         let len = mplace.len(self)?;
         let bytes = self.memory.read_bytes(mplace.ptr, Size::from_bytes(len as u64))?;
         let str = ::std::str::from_utf8(bytes)
-            .map_err(|err| err_unsup!(ValidationFailure(err.to_string())))?;
+            .map_err(|err| err_ub_format!("this string is not valid UTF-8: {}", err))?;
         Ok(str)
     }
 
@@ -361,7 +355,7 @@ pub fn operand_field(
     ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
         let base = match op.try_as_mplace(self) {
             Ok(mplace) => {
-                // The easy case
+                // We can reuse the mplace field computation logic for indirect operands.
                 let field = self.mplace_field(mplace, field)?;
                 return Ok(field.into());
             }
@@ -463,7 +457,7 @@ pub fn eval_place_to_op(
         layout: Option<TyLayout<'tcx>>,
     ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
         let base_op = match place.local {
-            mir::RETURN_PLACE => throw_unsup!(ReadFromReturnPointer),
+            mir::RETURN_PLACE => throw_ub!(ReadFromReturnPlace),
             local => {
                 // Do not use the layout passed in as argument if the base we are looking at
                 // here is not the entire place.
@@ -496,7 +490,8 @@ pub fn eval_operand(
             Copy(ref place) | Move(ref place) => self.eval_place_to_op(place, layout)?,
 
             Constant(ref constant) => {
-                let val = self.subst_from_frame_and_normalize_erasing_regions(constant.literal);
+                let val =
+                    self.subst_from_current_frame_and_normalize_erasing_regions(constant.literal);
                 self.eval_const_to_op(val, layout)?
             }
         };
@@ -683,7 +678,7 @@ pub fn read_discriminant(
                             // Then computing the absolute variant idx should not overflow any more.
                             let variant_index = variants_start
                                 .checked_add(variant_index_relative)
-                                .expect("oveflow computing absolute variant idx");
+                                .expect("overflow computing absolute variant idx");
                             let variants_len = rval
                                 .layout
                                 .ty
index cd7a419af9508e5fe0713db13159b0f6c21590d4..f2ee5e047a88e5b3366f93dcbcd2cec366c094d2 100644 (file)
@@ -234,7 +234,7 @@ fn binary_int_op(
             BitXor => (Scalar::from_uint(l ^ r, size), left_layout.ty),
 
             Add | Sub | Mul | Rem | Div => {
-                debug_assert!(!left_layout.abi.is_signed());
+                assert!(!left_layout.abi.is_signed());
                 let op: fn(u128, u128) -> (u128, bool) = match bin_op {
                     Add => u128::overflowing_add,
                     Sub => u128::overflowing_sub,
index 4f96cb698915d25146c45e2bff6d9528bf49e772..5313446c253c848e2864011b352cbfa180c238e4 100644 (file)
@@ -640,14 +640,16 @@ pub fn eval_place(
                         // bail out.
                         None => Place::null(&*self),
                     },
-                    layout: self.layout_of(self.subst_from_frame_and_normalize_erasing_regions(
-                        self.frame().body.return_ty(),
-                    ))?,
+                    layout: self.layout_of(
+                        self.subst_from_current_frame_and_normalize_erasing_regions(
+                            self.frame().body.return_ty(),
+                        ),
+                    )?,
                 }
             }
             local => PlaceTy {
                 // This works even for dead/uninitialized locals; we check further when writing
-                place: Place::Local { frame: self.cur_frame(), local: local },
+                place: Place::Local { frame: self.cur_frame(), local },
                 layout: self.layout_of_local(self.frame(), local, None)?,
             },
         };
@@ -681,7 +683,7 @@ pub fn write_immediate(
 
         if M::enforce_validity(self) {
             // Data got changed, better make sure it matches the type!
-            self.validate_operand(self.place_to_op(dest)?, vec![], None)?;
+            self.validate_operand(self.place_to_op(dest)?)?;
         }
 
         Ok(())
@@ -698,7 +700,7 @@ pub fn write_immediate_to_mplace(
 
         if M::enforce_validity(self) {
             // Data got changed, better make sure it matches the type!
-            self.validate_operand(dest.into(), vec![], None)?;
+            self.validate_operand(dest.into())?;
         }
 
         Ok(())
@@ -835,7 +837,7 @@ pub fn copy_op(
 
         if M::enforce_validity(self) {
             // Data got changed, better make sure it matches the type!
-            self.validate_operand(self.place_to_op(dest)?, vec![], None)?;
+            self.validate_operand(self.place_to_op(dest)?)?;
         }
 
         Ok(())
@@ -918,7 +920,7 @@ pub fn copy_op_transmute(
             // most likey we *are* running `typeck` right now. Investigate whether we can bail out
             // on `typeck_tables().has_errors` at all const eval entry points.
             debug!("Size mismatch when transmuting!\nsrc: {:#?}\ndest: {:#?}", src, dest);
-            throw_unsup!(TransmuteSizeDiff(src.layout.ty, dest.layout.ty));
+            throw_inval!(TransmuteSizeDiff(src.layout.ty, dest.layout.ty));
         }
         // Unsized copies rely on interpreting `src.meta` with `dest.layout`, we want
         // to avoid that here.
@@ -943,7 +945,7 @@ pub fn copy_op_transmute(
 
         if M::enforce_validity(self) {
             // Data got changed, better make sure it matches the type!
-            self.validate_operand(dest.into(), vec![], None)?;
+            self.validate_operand(dest.into())?;
         }
 
         Ok(())
index 2353b74016c2b8de37e85d03e1fd344b5a3e5b23..ee45179fd8b316bd53ad98280f33079d2ed3d063 100644 (file)
@@ -292,7 +292,7 @@ fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
 
         let all_bytes = 0..self.len();
         // This 'inspect' is okay since following access respects undef and relocations. This does
-        // influence interpreter exeuction, but only to detect the error of cycles in evalution
+        // influence interpreter exeuction, but only to detect the error of cycles in evaluation
         // dependencies.
         let bytes = self.inspect_with_undef_and_ptr_outside_interpreter(all_bytes);
 
index 7d59c0181a8f3645ef84163382892ec8d043c7fb..cb11df18378d991fc4bb99157e94d9b21298f542 100644 (file)
@@ -248,7 +248,7 @@ pub fn eval_rvalue_into_place(
             }
 
             NullaryOp(mir::NullOp::SizeOf, ty) => {
-                let ty = self.subst_from_frame_and_normalize_erasing_regions(ty);
+                let ty = self.subst_from_current_frame_and_normalize_erasing_regions(ty);
                 let layout = self.layout_of(ty)?;
                 assert!(
                     !layout.is_unsized(),
@@ -287,7 +287,7 @@ fn terminator(&mut self, terminator: &mir::Terminator<'tcx>) -> InterpResult<'tc
         self.eval_terminator(terminator)?;
         if !self.stack.is_empty() {
             // This should change *something*
-            debug_assert!(self.cur_frame() != old_stack || self.frame().block != old_bb);
+            assert!(self.cur_frame() != old_stack || self.frame().block != old_bb);
             if let Some(block) = self.frame().block {
                 info!("// executing {:?}", block);
             }
index 53e10f86a2cecd511060c7b6ecf0c0ae3624cff2..22a081a9c8e0be9af49b682c8dbe25ad83b560c5 100644 (file)
@@ -95,10 +95,14 @@ pub(super) fn eval_terminator(
                 if expected == cond_val {
                     self.go_to_block(target);
                 } else {
-                    M::assert_panic(self, terminator.source_info.span, msg, cleanup)?;
+                    M::assert_panic(self, msg, cleanup)?;
                 }
             }
 
+            Abort => {
+                M::abort(self)?;
+            }
+
             // When we encounter Resume, we've finished unwinding
             // cleanup for the current stack frame. We pop it in order
             // to continue unwinding the next frame
@@ -114,15 +118,13 @@ pub(super) fn eval_terminator(
             Unreachable => throw_ub!(Unreachable),
 
             // These should never occur for MIR we actually run.
-            DropAndReplace { .. } | FalseEdges { .. } | FalseUnwind { .. } => {
+            DropAndReplace { .. }
+            | FalseEdges { .. }
+            | FalseUnwind { .. }
+            | Yield { .. }
+            | GeneratorDrop => {
                 bug!("{:#?} should have been eliminated by MIR pass", terminator.kind)
             }
-
-            // These are not (yet) supported. It is unclear if they even can occur in
-            // MIR that we actually run.
-            Yield { .. } | GeneratorDrop | Abort => {
-                throw_unsup_format!("Unsupported terminator kind: {:#?}", terminator.kind)
-            }
         }
 
         Ok(())
@@ -170,13 +172,19 @@ fn pass_argument(
             trace!("Skipping callee ZST");
             return Ok(());
         }
-        let caller_arg = caller_arg.next().ok_or_else(|| err_unsup!(FunctionArgCountMismatch))?;
+        let caller_arg = caller_arg.next().ok_or_else(|| {
+            err_ub_format!("calling a function with fewer arguments than it requires")
+        })?;
         if rust_abi {
-            debug_assert!(!caller_arg.layout.is_zst(), "ZSTs must have been already filtered out");
+            assert!(!caller_arg.layout.is_zst(), "ZSTs must have been already filtered out");
         }
         // Now, check
         if !Self::check_argument_compat(rust_abi, caller_arg.layout, callee_arg.layout) {
-            throw_unsup!(FunctionArgMismatch(caller_arg.layout.ty, callee_arg.layout.ty))
+            throw_ub_format!(
+                "calling a function with argument of type {:?} passing data of type {:?}",
+                callee_arg.layout.ty,
+                caller_arg.layout.ty
+            )
         }
         // We allow some transmutes here
         self.copy_op_transmute(caller_arg, callee_arg)
@@ -221,7 +229,11 @@ fn eval_fn_call(
                 abi => abi,
             };
             if normalize_abi(caller_abi) != normalize_abi(callee_abi) {
-                throw_unsup!(FunctionAbiMismatch(caller_abi, callee_abi))
+                throw_ub_format!(
+                    "calling a function with ABI {:?} using caller ABI {:?}",
+                    callee_abi,
+                    caller_abi
+                )
             }
         }
 
@@ -251,111 +263,108 @@ fn eval_fn_call(
                     StackPopCleanup::Goto { ret: ret.map(|p| p.1), unwind },
                 )?;
 
-                // We want to pop this frame again in case there was an error, to put
-                // the blame in the right location.  Until the 2018 edition is used in
-                // the compiler, we have to do this with an immediately invoked function.
-                let res =
-                    (|| {
-                        trace!(
-                            "caller ABI: {:?}, args: {:#?}",
-                            caller_abi,
-                            args.iter()
-                                .map(|arg| (arg.layout.ty, format!("{:?}", **arg)))
-                                .collect::<Vec<_>>()
-                        );
-                        trace!(
-                            "spread_arg: {:?}, locals: {:#?}",
-                            body.spread_arg,
-                            body.args_iter()
-                                .map(|local| (
-                                    local,
-                                    self.layout_of_local(self.frame(), local, None).unwrap().ty
-                                ))
-                                .collect::<Vec<_>>()
-                        );
-
-                        // Figure out how to pass which arguments.
-                        // The Rust ABI is special: ZST get skipped.
-                        let rust_abi = match caller_abi {
-                            Abi::Rust | Abi::RustCall => true,
-                            _ => false,
+                // If an error is raised here, pop the frame again to get an accurate backtrace.
+                // To this end, we wrap it all in a `try` block.
+                let res: InterpResult<'tcx> = try {
+                    trace!(
+                        "caller ABI: {:?}, args: {:#?}",
+                        caller_abi,
+                        args.iter()
+                            .map(|arg| (arg.layout.ty, format!("{:?}", **arg)))
+                            .collect::<Vec<_>>()
+                    );
+                    trace!(
+                        "spread_arg: {:?}, locals: {:#?}",
+                        body.spread_arg,
+                        body.args_iter()
+                            .map(|local| (
+                                local,
+                                self.layout_of_local(self.frame(), local, None).unwrap().ty
+                            ))
+                            .collect::<Vec<_>>()
+                    );
+
+                    // Figure out how to pass which arguments.
+                    // The Rust ABI is special: ZST get skipped.
+                    let rust_abi = match caller_abi {
+                        Abi::Rust | Abi::RustCall => true,
+                        _ => false,
+                    };
+                    // We have two iterators: Where the arguments come from,
+                    // and where they go to.
+
+                    // For where they come from: If the ABI is RustCall, we untuple the
+                    // last incoming argument.  These two iterators do not have the same type,
+                    // so to keep the code paths uniform we accept an allocation
+                    // (for RustCall ABI only).
+                    let caller_args: Cow<'_, [OpTy<'tcx, M::PointerTag>]> =
+                        if caller_abi == Abi::RustCall && !args.is_empty() {
+                            // Untuple
+                            let (&untuple_arg, args) = args.split_last().unwrap();
+                            trace!("eval_fn_call: Will pass last argument by untupling");
+                            Cow::from(
+                                args.iter()
+                                    .map(|&a| Ok(a))
+                                    .chain(
+                                        (0..untuple_arg.layout.fields.count())
+                                            .map(|i| self.operand_field(untuple_arg, i as u64)),
+                                    )
+                                    .collect::<InterpResult<'_, Vec<OpTy<'tcx, M::PointerTag>>>>(
+                                    )?,
+                            )
+                        } else {
+                            // Plain arg passing
+                            Cow::from(args)
                         };
-                        // We have two iterators: Where the arguments come from,
-                        // and where they go to.
-
-                        // For where they come from: If the ABI is RustCall, we untuple the
-                        // last incoming argument.  These two iterators do not have the same type,
-                        // so to keep the code paths uniform we accept an allocation
-                        // (for RustCall ABI only).
-                        let caller_args: Cow<'_, [OpTy<'tcx, M::PointerTag>]> =
-                            if caller_abi == Abi::RustCall && !args.is_empty() {
-                                // Untuple
-                                let (&untuple_arg, args) = args.split_last().unwrap();
-                                trace!("eval_fn_call: Will pass last argument by untupling");
-                                Cow::from(args.iter().map(|&a| Ok(a))
-                                .chain((0..untuple_arg.layout.fields.count())
-                                    .map(|i| self.operand_field(untuple_arg, i as u64))
-                                )
-                                .collect::<InterpResult<'_, Vec<OpTy<'tcx, M::PointerTag>>>>()?)
-                            } else {
-                                // Plain arg passing
-                                Cow::from(args)
-                            };
-                        // Skip ZSTs
-                        let mut caller_iter = caller_args
-                            .iter()
-                            .filter(|op| !rust_abi || !op.layout.is_zst())
-                            .copied();
-
-                        // Now we have to spread them out across the callee's locals,
-                        // taking into account the `spread_arg`.  If we could write
-                        // this is a single iterator (that handles `spread_arg`), then
-                        // `pass_argument` would be the loop body. It takes care to
-                        // not advance `caller_iter` for ZSTs.
-                        let mut locals_iter = body.args_iter();
-                        while let Some(local) = locals_iter.next() {
-                            let dest = self.eval_place(&mir::Place::from(local))?;
-                            if Some(local) == body.spread_arg {
-                                // Must be a tuple
-                                for i in 0..dest.layout.fields.count() {
-                                    let dest = self.place_field(dest, i as u64)?;
-                                    self.pass_argument(rust_abi, &mut caller_iter, dest)?;
-                                }
-                            } else {
-                                // Normal argument
+                    // Skip ZSTs
+                    let mut caller_iter =
+                        caller_args.iter().filter(|op| !rust_abi || !op.layout.is_zst()).copied();
+
+                    // Now we have to spread them out across the callee's locals,
+                    // taking into account the `spread_arg`.  If we could write
+                    // this is a single iterator (that handles `spread_arg`), then
+                    // `pass_argument` would be the loop body. It takes care to
+                    // not advance `caller_iter` for ZSTs.
+                    for local in body.args_iter() {
+                        let dest = self.eval_place(&mir::Place::from(local))?;
+                        if Some(local) == body.spread_arg {
+                            // Must be a tuple
+                            for i in 0..dest.layout.fields.count() {
+                                let dest = self.place_field(dest, i as u64)?;
                                 self.pass_argument(rust_abi, &mut caller_iter, dest)?;
                             }
+                        } else {
+                            // Normal argument
+                            self.pass_argument(rust_abi, &mut caller_iter, dest)?;
                         }
-                        // Now we should have no more caller args
-                        if caller_iter.next().is_some() {
-                            trace!("Caller has passed too many args");
-                            throw_unsup!(FunctionArgCountMismatch)
+                    }
+                    // Now we should have no more caller args
+                    if caller_iter.next().is_some() {
+                        throw_ub_format!("calling a function with more arguments than it expected")
+                    }
+                    // Don't forget to check the return type!
+                    if let Some((caller_ret, _)) = ret {
+                        let callee_ret = self.eval_place(&mir::Place::return_place())?;
+                        if !Self::check_argument_compat(
+                            rust_abi,
+                            caller_ret.layout,
+                            callee_ret.layout,
+                        ) {
+                            throw_ub_format!(
+                                "calling a function with return type {:?} passing \
+                                     return place of type {:?}",
+                                callee_ret.layout.ty,
+                                caller_ret.layout.ty
+                            )
                         }
-                        // Don't forget to check the return type!
-                        if let Some((caller_ret, _)) = ret {
-                            let callee_ret = self.eval_place(&mir::Place::return_place())?;
-                            if !Self::check_argument_compat(
-                                rust_abi,
-                                caller_ret.layout,
-                                callee_ret.layout,
-                            ) {
-                                throw_unsup!(FunctionRetMismatch(
-                                    caller_ret.layout.ty,
-                                    callee_ret.layout.ty
-                                ))
-                            }
-                        } else {
-                            let local = mir::RETURN_PLACE;
-                            let callee_layout = self.layout_of_local(self.frame(), local, None)?;
-                            if !callee_layout.abi.is_uninhabited() {
-                                throw_unsup!(FunctionRetMismatch(
-                                    self.tcx.types.never,
-                                    callee_layout.ty
-                                ))
-                            }
+                    } else {
+                        let local = mir::RETURN_PLACE;
+                        let callee_layout = self.layout_of_local(self.frame(), local, None)?;
+                        if !callee_layout.abi.is_uninhabited() {
+                            throw_ub_format!("calling a returning function without a return place")
                         }
-                        Ok(())
-                    })();
+                    }
+                };
                 match res {
                     Err(err) => {
                         self.stack.pop();
index aa2b3040a716f49a757207d8c33b88d1bd3386e5..d93b78a5bd5b618b5c47a644355ddab06e48f787 100644 (file)
@@ -29,7 +29,7 @@ macro_rules! throw_validation_failure {
             write_path(&mut msg, where_);
         }
         write!(&mut msg, ", but expected {}", $details).unwrap();
-        throw_unsup!(ValidationFailure(msg))
+        throw_ub!(ValidationFailure(msg))
     }};
     ($what:expr, $where:expr) => {{
         let mut msg = format!("encountered {}", $what);
@@ -38,7 +38,7 @@ macro_rules! throw_validation_failure {
             msg.push_str(" at ");
             write_path(&mut msg, where_);
         }
-        throw_unsup!(ValidationFailure(msg))
+        throw_ub!(ValidationFailure(msg))
     }};
 }
 
@@ -46,6 +46,8 @@ macro_rules! try_validation {
     ($e:expr, $what:expr, $where:expr, $details:expr) => {{
         match $e {
             Ok(x) => x,
+            // We re-throw the error, so we are okay with allocation:
+            // this can only slow down builds that fail anyway.
             Err(_) => throw_validation_failure!($what, $where, $details),
         }
     }};
@@ -53,6 +55,8 @@ macro_rules! try_validation {
     ($e:expr, $what:expr, $where:expr) => {{
         match $e {
             Ok(x) => x,
+            // We re-throw the error, so we are okay with allocation:
+            // this can only slow down builds that fail anyway.
             Err(_) => throw_validation_failure!($what, $where),
         }
     }};
@@ -67,11 +71,12 @@ pub enum PathElem {
     Field(Symbol),
     Variant(Symbol),
     GeneratorState(VariantIdx),
-    ClosureVar(Symbol),
+    CapturedVar(Symbol),
     ArrayElem(usize),
     TupleElem(usize),
     Deref,
-    Tag,
+    EnumTag,
+    GeneratorTag,
     DynDowncast,
 }
 
@@ -109,9 +114,11 @@ fn write_path(out: &mut String, path: &Vec<PathElem>) {
     for elem in path.iter() {
         match elem {
             Field(name) => write!(out, ".{}", name),
-            Variant(name) => write!(out, ".<downcast-variant({})>", name),
+            EnumTag => write!(out, ".<enum-tag>"),
+            Variant(name) => write!(out, ".<enum-variant({})>", name),
+            GeneratorTag => write!(out, ".<generator-tag>"),
             GeneratorState(idx) => write!(out, ".<generator-state({})>", idx.index()),
-            ClosureVar(name) => write!(out, ".<closure-var({})>", name),
+            CapturedVar(name) => write!(out, ".<captured-var({})>", name),
             TupleElem(idx) => write!(out, ".{}", idx),
             ArrayElem(idx) => write!(out, "[{}]", idx),
             // `.<deref>` does not match Rust syntax, but it is more readable for long paths -- and
@@ -119,7 +126,6 @@ fn write_path(out: &mut String, path: &Vec<PathElem>) {
             // even use the usual syntax because we are just showing the projections,
             // not the root.
             Deref => write!(out, ".<deref>"),
-            Tag => write!(out, ".<enum-tag>"),
             DynDowncast => write!(out, ".<dyn-downcast>"),
         }
         .unwrap()
@@ -142,16 +148,16 @@ fn wrapping_range_contains(r: &RangeInclusive<u128>, test: u128) -> bool {
 // "expected something <in the given range>" makes sense.
 fn wrapping_range_format(r: &RangeInclusive<u128>, max_hi: u128) -> String {
     let (lo, hi) = r.clone().into_inner();
-    debug_assert!(hi <= max_hi);
+    assert!(hi <= max_hi);
     if lo > hi {
         format!("less or equal to {}, or greater or equal to {}", hi, lo)
     } else if lo == hi {
         format!("equal to {}", lo)
     } else if lo == 0 {
-        debug_assert!(hi < max_hi, "should not be printing if the range covers everything");
+        assert!(hi < max_hi, "should not be printing if the range covers everything");
         format!("less or equal to {}", hi)
     } else if hi == max_hi {
-        debug_assert!(lo > 0, "should not be printing if the range covers everything");
+        assert!(lo > 0, "should not be printing if the range covers everything");
         format!("greater or equal to {}", lo)
     } else {
         format!("in the range {:?}", r)
@@ -165,11 +171,27 @@ struct ValidityVisitor<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> {
     path: Vec<PathElem>,
     ref_tracking_for_consts:
         Option<&'rt mut RefTracking<MPlaceTy<'tcx, M::PointerTag>, Vec<PathElem>>>,
+    may_ref_to_static: bool,
     ecx: &'rt InterpCx<'mir, 'tcx, M>,
 }
 
 impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M> {
     fn aggregate_field_path_elem(&mut self, layout: TyLayout<'tcx>, field: usize) -> PathElem {
+        // First, check if we are projecting to a variant.
+        match layout.variants {
+            layout::Variants::Multiple { discr_index, .. } => {
+                if discr_index == field {
+                    return match layout.ty.kind {
+                        ty::Adt(def, ..) if def.is_enum() => PathElem::EnumTag,
+                        ty::Generator(..) => PathElem::GeneratorTag,
+                        _ => bug!("non-variant type {:?}", layout.ty),
+                    };
+                }
+            }
+            layout::Variants::Single { .. } => {}
+        }
+
+        // Now we know we are projecting to a field, so figure out which one.
         match layout.ty.kind {
             // generators and closures.
             ty::Closure(def_id, _) | ty::Generator(def_id, _, _) => {
@@ -190,7 +212,7 @@ fn aggregate_field_path_elem(&mut self, layout: TyLayout<'tcx>, field: usize) ->
                     }
                 }
 
-                PathElem::ClosureVar(name.unwrap_or_else(|| {
+                PathElem::CapturedVar(name.unwrap_or_else(|| {
                     // Fall back to showing the field index.
                     sym::integer(field)
                 }))
@@ -201,13 +223,13 @@ fn aggregate_field_path_elem(&mut self, layout: TyLayout<'tcx>, field: usize) ->
 
             // enums
             ty::Adt(def, ..) if def.is_enum() => {
-                // we might be projecting *to* a variant, or to a field *in*a variant.
+                // we might be projecting *to* a variant, or to a field *in* a variant.
                 match layout.variants {
                     layout::Variants::Single { index } => {
                         // Inside a variant
                         PathElem::Field(def.variants[index].fields[field].ident.name)
                     }
-                    _ => bug!(),
+                    layout::Variants::Multiple { .. } => bug!("we handled variants above"),
                 }
             }
 
@@ -288,195 +310,192 @@ fn check_wide_ptr_meta(
 
         Ok(())
     }
-}
 
-impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
-    for ValidityVisitor<'rt, 'mir, 'tcx, M>
-{
-    type V = OpTy<'tcx, M::PointerTag>;
-
-    #[inline(always)]
-    fn ecx(&self) -> &InterpCx<'mir, 'tcx, M> {
-        &self.ecx
-    }
-
-    #[inline]
-    fn visit_field(
+    /// Check a reference or `Box`.
+    fn check_safe_pointer(
         &mut self,
-        old_op: OpTy<'tcx, M::PointerTag>,
-        field: usize,
-        new_op: OpTy<'tcx, M::PointerTag>,
+        value: OpTy<'tcx, M::PointerTag>,
+        kind: &str,
     ) -> InterpResult<'tcx> {
-        let elem = self.aggregate_field_path_elem(old_op.layout, field);
-        self.visit_elem(new_op, elem)
-    }
-
-    #[inline]
-    fn visit_variant(
-        &mut self,
-        old_op: OpTy<'tcx, M::PointerTag>,
-        variant_id: VariantIdx,
-        new_op: OpTy<'tcx, M::PointerTag>,
-    ) -> InterpResult<'tcx> {
-        let name = match old_op.layout.ty.kind {
-            ty::Adt(adt, _) => PathElem::Variant(adt.variants[variant_id].ident.name),
-            // Generators also have variants
-            ty::Generator(..) => PathElem::GeneratorState(variant_id),
-            _ => bug!("Unexpected type with variant: {:?}", old_op.layout.ty),
-        };
-        self.visit_elem(new_op, name)
-    }
-
-    #[inline]
-    fn visit_value(&mut self, op: OpTy<'tcx, M::PointerTag>) -> InterpResult<'tcx> {
-        trace!("visit_value: {:?}, {:?}", *op, op.layout);
-        // Translate some possible errors to something nicer.
-        match self.walk_value(op) {
-            Ok(()) => Ok(()),
+        let value = self.ecx.read_immediate(value)?;
+        // Handle wide pointers.
+        // Check metadata early, for better diagnostics
+        let place = try_validation!(self.ecx.ref_to_mplace(value), "undefined pointer", self.path);
+        if place.layout.is_unsized() {
+            self.check_wide_ptr_meta(place.meta, place.layout)?;
+        }
+        // Make sure this is dereferenceable and all.
+        let size_and_align = match self.ecx.size_and_align_of(place.meta, place.layout) {
+            Ok(res) => res,
             Err(err) => match err.kind {
-                err_ub!(InvalidDiscriminant(val)) => {
-                    throw_validation_failure!(val, self.path, "a valid enum discriminant")
+                err_ub!(InvalidMeta(msg)) => throw_validation_failure!(
+                    format_args!("invalid {} metadata: {}", kind, msg),
+                    self.path
+                ),
+                _ => bug!("Unexpected error during ptr size_and_align_of: {}", err),
+            },
+        };
+        let (size, align) = size_and_align
+            // for the purpose of validity, consider foreign types to have
+            // alignment and size determined by the layout (size will be 0,
+            // alignment should take attributes into account).
+            .unwrap_or_else(|| (place.layout.size, place.layout.align.abi));
+        let ptr: Option<_> = match self.ecx.memory.check_ptr_access_align(
+            place.ptr,
+            size,
+            Some(align),
+            CheckInAllocMsg::InboundsTest,
+        ) {
+            Ok(ptr) => ptr,
+            Err(err) => {
+                info!(
+                    "{:?} did not pass access check for size {:?}, align {:?}",
+                    place.ptr, size, align
+                );
+                match err.kind {
+                    err_ub!(InvalidIntPointerUsage(0)) => {
+                        throw_validation_failure!(format_args!("a NULL {}", kind), self.path)
+                    }
+                    err_ub!(InvalidIntPointerUsage(i)) => throw_validation_failure!(
+                        format_args!("a {} to unallocated address {}", kind, i),
+                        self.path
+                    ),
+                    err_ub!(AlignmentCheckFailed { required, has }) => throw_validation_failure!(
+                        format_args!(
+                            "an unaligned {} (required {} byte alignment but found {})",
+                            kind,
+                            required.bytes(),
+                            has.bytes()
+                        ),
+                        self.path
+                    ),
+                    err_unsup!(ReadBytesAsPointer) => throw_validation_failure!(
+                        format_args!("a dangling {} (created from integer)", kind),
+                        self.path
+                    ),
+                    err_ub!(PointerOutOfBounds { .. }) => throw_validation_failure!(
+                        format_args!(
+                            "a dangling {} (going beyond the bounds of its allocation)",
+                            kind
+                        ),
+                        self.path
+                    ),
+                    // This cannot happen during const-eval (because interning already detects
+                    // dangling pointers), but it can happen in Miri.
+                    err_ub!(PointerUseAfterFree(_)) => throw_validation_failure!(
+                        format_args!("a dangling {} (use-after-free)", kind),
+                        self.path
+                    ),
+                    _ => bug!("Unexpected error during ptr inbounds test: {}", err),
                 }
-                err_unsup!(ReadPointerAsBytes) => {
-                    throw_validation_failure!("a pointer", self.path, "plain (non-pointer) bytes")
+            }
+        };
+        // Recursive checking
+        if let Some(ref mut ref_tracking) = self.ref_tracking_for_consts {
+            if let Some(ptr) = ptr {
+                // not a ZST
+                // Skip validation entirely for some external statics
+                let alloc_kind = self.ecx.tcx.alloc_map.lock().get(ptr.alloc_id);
+                if let Some(GlobalAlloc::Static(did)) = alloc_kind {
+                    // `extern static` cannot be validated as they have no body.
+                    // FIXME: Statics from other crates are also skipped.
+                    // They might be checked at a different type, but for now we
+                    // want to avoid recursing too deeply.  This is not sound!
+                    if !did.is_local() || self.ecx.tcx.is_foreign_item(did) {
+                        return Ok(());
+                    }
+                    if !self.may_ref_to_static && self.ecx.tcx.is_static(did) {
+                        throw_validation_failure!(
+                            format_args!("a {} pointing to a static variable", kind),
+                            self.path
+                        );
+                    }
                 }
-                _ => Err(err),
-            },
+            }
+            // Proceed recursively even for ZST, no reason to skip them!
+            // `!` is a ZST and we want to validate it.
+            // Normalize before handing `place` to tracking because that will
+            // check for duplicates.
+            let place = if size.bytes() > 0 {
+                self.ecx.force_mplace_ptr(place).expect("we already bounds-checked")
+            } else {
+                place
+            };
+            let path = &self.path;
+            ref_tracking.track(place, || {
+                // We need to clone the path anyway, make sure it gets created
+                // with enough space for the additional `Deref`.
+                let mut new_path = Vec::with_capacity(path.len() + 1);
+                new_path.clone_from(path);
+                new_path.push(PathElem::Deref);
+                new_path
+            });
         }
+        Ok(())
     }
 
-    fn visit_primitive(&mut self, value: OpTy<'tcx, M::PointerTag>) -> InterpResult<'tcx> {
-        let value = self.ecx.read_immediate(value)?;
+    /// Check if this is a value of primitive type, and if yes check the validity of the value
+    /// at that type.  Return `true` if the type is indeed primitive.
+    fn try_visit_primitive(
+        &mut self,
+        value: OpTy<'tcx, M::PointerTag>,
+    ) -> InterpResult<'tcx, bool> {
         // Go over all the primitive types
         let ty = value.layout.ty;
         match ty.kind {
             ty::Bool => {
-                let value = value.to_scalar_or_undef();
+                let value = self.ecx.read_scalar(value)?;
                 try_validation!(value.to_bool(), value, self.path, "a boolean");
+                Ok(true)
             }
             ty::Char => {
-                let value = value.to_scalar_or_undef();
+                let value = self.ecx.read_scalar(value)?;
                 try_validation!(value.to_char(), value, self.path, "a valid unicode codepoint");
+                Ok(true)
             }
             ty::Float(_) | ty::Int(_) | ty::Uint(_) => {
+                let value = self.ecx.read_scalar(value)?;
                 // NOTE: Keep this in sync with the array optimization for int/float
                 // types below!
-                let size = value.layout.size;
-                let value = value.to_scalar_or_undef();
                 if self.ref_tracking_for_consts.is_some() {
                     // Integers/floats in CTFE: Must be scalar bits, pointers are dangerous
-                    try_validation!(
-                        value.to_bits(size),
-                        value,
-                        self.path,
-                        "initialized plain (non-pointer) bytes"
-                    );
+                    let is_bits = value.not_undef().map_or(false, |v| v.is_bits());
+                    if !is_bits {
+                        throw_validation_failure!(
+                            value,
+                            self.path,
+                            "initialized plain (non-pointer) bytes"
+                        )
+                    }
                 } else {
                     // At run-time, for now, we accept *anything* for these types, including
                     // undef. We should fix that, but let's start low.
                 }
+                Ok(true)
             }
             ty::RawPtr(..) => {
                 // We are conservative with undef for integers, but try to
                 // actually enforce our current rules for raw pointers.
-                let place =
-                    try_validation!(self.ecx.ref_to_mplace(value), "undefined pointer", self.path);
+                let place = try_validation!(
+                    self.ecx.ref_to_mplace(self.ecx.read_immediate(value)?),
+                    "undefined pointer",
+                    self.path
+                );
                 if place.layout.is_unsized() {
                     self.check_wide_ptr_meta(place.meta, place.layout)?;
                 }
+                Ok(true)
             }
-            _ if ty.is_box() || ty.is_region_ptr() => {
-                // Handle wide pointers.
-                // Check metadata early, for better diagnostics
-                let place =
-                    try_validation!(self.ecx.ref_to_mplace(value), "undefined pointer", self.path);
-                if place.layout.is_unsized() {
-                    self.check_wide_ptr_meta(place.meta, place.layout)?;
-                }
-                // Make sure this is dereferenceable and all.
-                let (size, align) = self
-                    .ecx
-                    .size_and_align_of(place.meta, place.layout)?
-                    // for the purpose of validity, consider foreign types to have
-                    // alignment and size determined by the layout (size will be 0,
-                    // alignment should take attributes into account).
-                    .unwrap_or_else(|| (place.layout.size, place.layout.align.abi));
-                let ptr: Option<_> = match self.ecx.memory.check_ptr_access_align(
-                    place.ptr,
-                    size,
-                    Some(align),
-                    CheckInAllocMsg::InboundsTest,
-                ) {
-                    Ok(ptr) => ptr,
-                    Err(err) => {
-                        info!(
-                            "{:?} did not pass access check for size {:?}, align {:?}",
-                            place.ptr, size, align
-                        );
-                        match err.kind {
-                            err_unsup!(InvalidNullPointerUsage) => {
-                                throw_validation_failure!("NULL reference", self.path)
-                            }
-                            err_unsup!(AlignmentCheckFailed { required, has }) => {
-                                throw_validation_failure!(
-                                    format_args!(
-                                        "unaligned reference \
-                                    (required {} byte alignment but found {})",
-                                        required.bytes(),
-                                        has.bytes()
-                                    ),
-                                    self.path
-                                )
-                            }
-                            err_unsup!(ReadBytesAsPointer) => throw_validation_failure!(
-                                "dangling reference (created from integer)",
-                                self.path
-                            ),
-                            _ => throw_validation_failure!(
-                                "dangling reference (not entirely in bounds)",
-                                self.path
-                            ),
-                        }
-                    }
-                };
-                // Recursive checking
-                if let Some(ref mut ref_tracking) = self.ref_tracking_for_consts {
-                    if let Some(ptr) = ptr {
-                        // not a ZST
-                        // Skip validation entirely for some external statics
-                        let alloc_kind = self.ecx.tcx.alloc_map.lock().get(ptr.alloc_id);
-                        if let Some(GlobalAlloc::Static(did)) = alloc_kind {
-                            // `extern static` cannot be validated as they have no body.
-                            // FIXME: Statics from other crates are also skipped.
-                            // They might be checked at a different type, but for now we
-                            // want to avoid recursing too deeply.  This is not sound!
-                            if !did.is_local() || self.ecx.tcx.is_foreign_item(did) {
-                                return Ok(());
-                            }
-                        }
-                    }
-                    // Proceed recursively even for ZST, no reason to skip them!
-                    // `!` is a ZST and we want to validate it.
-                    // Normalize before handing `place` to tracking because that will
-                    // check for duplicates.
-                    let place = if size.bytes() > 0 {
-                        self.ecx.force_mplace_ptr(place).expect("we already bounds-checked")
-                    } else {
-                        place
-                    };
-                    let path = &self.path;
-                    ref_tracking.track(place, || {
-                        // We need to clone the path anyway, make sure it gets created
-                        // with enough space for the additional `Deref`.
-                        let mut new_path = Vec::with_capacity(path.len() + 1);
-                        new_path.clone_from(path);
-                        new_path.push(PathElem::Deref);
-                        new_path
-                    });
-                }
+            ty::Ref(..) => {
+                self.check_safe_pointer(value, "reference")?;
+                Ok(true)
+            }
+            ty::Adt(def, ..) if def.is_box() => {
+                self.check_safe_pointer(value, "box")?;
+                Ok(true)
             }
             ty::FnPtr(_sig) => {
-                let value = value.to_scalar_or_undef();
+                let value = self.ecx.read_scalar(value)?;
                 let _fn = try_validation!(
                     value.not_undef().and_then(|ptr| self.ecx.memory.get_fn(ptr)),
                     value,
@@ -484,27 +503,49 @@ fn visit_primitive(&mut self, value: OpTy<'tcx, M::PointerTag>) -> InterpResult<
                     "a function pointer"
                 );
                 // FIXME: Check if the signature matches
+                Ok(true)
+            }
+            ty::Never => throw_validation_failure!("a value of the never type `!`", self.path),
+            ty::Foreign(..) | ty::FnDef(..) => {
+                // Nothing to check.
+                Ok(true)
             }
-            // This should be all the primitive types
-            _ => bug!("Unexpected primitive type {}", value.layout.ty),
+            // The above should be all the (inhabited) primitive types. The rest is compound, we
+            // check them by visiting their fields/variants.
+            // (`Str` UTF-8 check happens in `visit_aggregate`, too.)
+            ty::Adt(..)
+            | ty::Tuple(..)
+            | ty::Array(..)
+            | ty::Slice(..)
+            | ty::Str
+            | ty::Dynamic(..)
+            | ty::Closure(..)
+            | ty::Generator(..) => Ok(false),
+            // Some types only occur during typechecking, they have no layout.
+            // We should not see them here and we could not check them anyway.
+            ty::Error
+            | ty::Infer(..)
+            | ty::Placeholder(..)
+            | ty::Bound(..)
+            | ty::Param(..)
+            | ty::Opaque(..)
+            | ty::UnnormalizedProjection(..)
+            | ty::Projection(..)
+            | ty::GeneratorWitness(..) => bug!("Encountered invalid type {:?}", ty),
         }
-        Ok(())
-    }
-
-    fn visit_uninhabited(&mut self) -> InterpResult<'tcx> {
-        throw_validation_failure!("a value of an uninhabited type", self.path)
     }
 
     fn visit_scalar(
         &mut self,
         op: OpTy<'tcx, M::PointerTag>,
-        layout: &layout::Scalar,
+        scalar_layout: &layout::Scalar,
     ) -> InterpResult<'tcx> {
         let value = self.ecx.read_scalar(op)?;
+        let valid_range = &scalar_layout.valid_range;
+        let (lo, hi) = valid_range.clone().into_inner();
         // Determine the allowed range
-        let (lo, hi) = layout.valid_range.clone().into_inner();
         // `max_hi` is as big as the size fits
-        let max_hi = u128::max_value() >> (128 - op.layout.size.bits());
+        let max_hi = u128::MAX >> (128 - op.layout.size.bits());
         assert!(hi <= max_hi);
         // We could also write `(hi + 1) % (max_hi + 1) == lo` but `max_hi + 1` overflows for `u128`
         if (lo == 0 && hi == max_hi) || (hi + 1 == lo) {
@@ -516,7 +557,7 @@ fn visit_scalar(
             value.not_undef(),
             value,
             self.path,
-            format_args!("something {}", wrapping_range_format(&layout.valid_range, max_hi),)
+            format_args!("something {}", wrapping_range_format(valid_range, max_hi),)
         );
         let bits = match value.to_bits_or_ptr(op.layout.size, self.ecx) {
             Err(ptr) => {
@@ -528,7 +569,7 @@ fn visit_scalar(
                             self.path,
                             format_args!(
                                 "something that cannot possibly fail to be {}",
-                                wrapping_range_format(&layout.valid_range, max_hi)
+                                wrapping_range_format(valid_range, max_hi)
                             )
                         )
                     }
@@ -541,7 +582,7 @@ fn visit_scalar(
                         self.path,
                         format_args!(
                             "something that cannot possibly fail to be {}",
-                            wrapping_range_format(&layout.valid_range, max_hi)
+                            wrapping_range_format(valid_range, max_hi)
                         )
                     )
                 }
@@ -549,16 +590,122 @@ fn visit_scalar(
             Ok(data) => data,
         };
         // Now compare. This is slightly subtle because this is a special "wrap-around" range.
-        if wrapping_range_contains(&layout.valid_range, bits) {
+        if wrapping_range_contains(&valid_range, bits) {
             Ok(())
         } else {
             throw_validation_failure!(
                 bits,
                 self.path,
-                format_args!("something {}", wrapping_range_format(&layout.valid_range, max_hi))
+                format_args!("something {}", wrapping_range_format(valid_range, max_hi))
             )
         }
     }
+}
+
+impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
+    for ValidityVisitor<'rt, 'mir, 'tcx, M>
+{
+    type V = OpTy<'tcx, M::PointerTag>;
+
+    #[inline(always)]
+    fn ecx(&self) -> &InterpCx<'mir, 'tcx, M> {
+        &self.ecx
+    }
+
+    #[inline]
+    fn visit_field(
+        &mut self,
+        old_op: OpTy<'tcx, M::PointerTag>,
+        field: usize,
+        new_op: OpTy<'tcx, M::PointerTag>,
+    ) -> InterpResult<'tcx> {
+        let elem = self.aggregate_field_path_elem(old_op.layout, field);
+        self.visit_elem(new_op, elem)
+    }
+
+    #[inline]
+    fn visit_variant(
+        &mut self,
+        old_op: OpTy<'tcx, M::PointerTag>,
+        variant_id: VariantIdx,
+        new_op: OpTy<'tcx, M::PointerTag>,
+    ) -> InterpResult<'tcx> {
+        let name = match old_op.layout.ty.kind {
+            ty::Adt(adt, _) => PathElem::Variant(adt.variants[variant_id].ident.name),
+            // Generators also have variants
+            ty::Generator(..) => PathElem::GeneratorState(variant_id),
+            _ => bug!("Unexpected type with variant: {:?}", old_op.layout.ty),
+        };
+        self.visit_elem(new_op, name)
+    }
+
+    #[inline(always)]
+    fn visit_union(&mut self, op: OpTy<'tcx, M::PointerTag>, fields: usize) -> InterpResult<'tcx> {
+        // Empty unions are not accepted by rustc. But uninhabited enums
+        // claim to be unions, so allow them, too.
+        assert!(op.layout.abi.is_uninhabited() || fields > 0);
+        Ok(())
+    }
+
+    #[inline]
+    fn visit_value(&mut self, op: OpTy<'tcx, M::PointerTag>) -> InterpResult<'tcx> {
+        trace!("visit_value: {:?}, {:?}", *op, op.layout);
+
+        // Check primitive types -- the leafs of our recursive descend.
+        if self.try_visit_primitive(op)? {
+            return Ok(());
+        }
+        // Sanity check: `builtin_deref` does not know any pointers that are not primitive.
+        assert!(op.layout.ty.builtin_deref(true).is_none());
+
+        // Recursively walk the type. Translate some possible errors to something nicer.
+        match self.walk_value(op) {
+            Ok(()) => {}
+            Err(err) => match err.kind {
+                err_ub!(InvalidDiscriminant(val)) => {
+                    throw_validation_failure!(val, self.path, "a valid enum discriminant")
+                }
+                err_unsup!(ReadPointerAsBytes) => {
+                    throw_validation_failure!("a pointer", self.path, "plain (non-pointer) bytes")
+                }
+                // Propagate upwards (that will also check for unexpected errors).
+                _ => return Err(err),
+            },
+        }
+
+        // *After* all of this, check the ABI.  We need to check the ABI to handle
+        // types like `NonNull` where the `Scalar` info is more restrictive than what
+        // the fields say (`rustc_layout_scalar_valid_range_start`).
+        // But in most cases, this will just propagate what the fields say,
+        // and then we want the error to point at the field -- so, first recurse,
+        // then check ABI.
+        //
+        // FIXME: We could avoid some redundant checks here. For newtypes wrapping
+        // scalars, we do the same check on every "level" (e.g., first we check
+        // MyNewtype and then the scalar in there).
+        match op.layout.abi {
+            layout::Abi::Uninhabited => {
+                throw_validation_failure!(
+                    format_args!("a value of uninhabited type {:?}", op.layout.ty),
+                    self.path
+                );
+            }
+            layout::Abi::Scalar(ref scalar_layout) => {
+                self.visit_scalar(op, scalar_layout)?;
+            }
+            layout::Abi::ScalarPair { .. } | layout::Abi::Vector { .. } => {
+                // These have fields that we already visited above, so we already checked
+                // all their scalar-level restrictions.
+                // There is also no equivalent to `rustc_layout_scalar_valid_range_start`
+                // that would make skipping them here an issue.
+            }
+            layout::Abi::Aggregate { .. } => {
+                // Nothing to do.
+            }
+        }
+
+        Ok(())
+    }
 
     fn visit_aggregate(
         &mut self,
@@ -626,11 +773,11 @@ fn visit_aggregate(
                     Err(err) => {
                         // For some errors we might be able to provide extra information
                         match err.kind {
-                            err_unsup!(ReadUndefBytes(offset)) => {
+                            err_ub!(InvalidUndefBytes(Some(ptr))) => {
                                 // Some byte was undefined, determine which
                                 // element that byte belongs to so we can
                                 // provide an index.
-                                let i = (offset.bytes() / layout.size.bytes()) as usize;
+                                let i = (ptr.offset.bytes() / layout.size.bytes()) as usize;
                                 self.path.push(PathElem::ArrayElem(i));
 
                                 throw_validation_failure!("undefined bytes", self.path)
@@ -657,31 +804,59 @@ fn visit_aggregate(
 }
 
 impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
-    /// This function checks the data at `op`. `op` is assumed to cover valid memory if it
-    /// is an indirect operand.
-    /// It will error if the bits at the destination do not match the ones described by the layout.
-    ///
-    /// `ref_tracking_for_consts` can be `None` to avoid recursive checking below references.
-    /// This also toggles between "run-time" (no recursion) and "compile-time" (with recursion)
-    /// validation (e.g., pointer values are fine in integers at runtime) and various other const
-    /// specific validation checks.
-    pub fn validate_operand(
+    fn validate_operand_internal(
         &self,
         op: OpTy<'tcx, M::PointerTag>,
         path: Vec<PathElem>,
         ref_tracking_for_consts: Option<
             &mut RefTracking<MPlaceTy<'tcx, M::PointerTag>, Vec<PathElem>>,
         >,
+        may_ref_to_static: bool,
     ) -> InterpResult<'tcx> {
-        trace!("validate_operand: {:?}, {:?}", *op, op.layout.ty);
+        trace!("validate_operand_internal: {:?}, {:?}", *op, op.layout.ty);
 
         // Construct a visitor
-        let mut visitor = ValidityVisitor { path, ref_tracking_for_consts, ecx: self };
+        let mut visitor =
+            ValidityVisitor { path, ref_tracking_for_consts, may_ref_to_static, ecx: self };
 
         // Try to cast to ptr *once* instead of all the time.
         let op = self.force_op_ptr(op).unwrap_or(op);
 
-        // Run it
-        visitor.visit_value(op)
+        // Run it.
+        match visitor.visit_value(op) {
+            Ok(()) => Ok(()),
+            Err(err) if matches!(err.kind, err_ub!(ValidationFailure { .. })) => Err(err),
+            Err(err) if cfg!(debug_assertions) => {
+                bug!("Unexpected error during validation: {}", err)
+            }
+            Err(err) => Err(err),
+        }
+    }
+
+    /// This function checks the data at `op` to be const-valid.
+    /// `op` is assumed to cover valid memory if it is an indirect operand.
+    /// It will error if the bits at the destination do not match the ones described by the layout.
+    ///
+    /// `ref_tracking` is used to record references that we encounter so that they
+    /// can be checked recursively by an outside driving loop.
+    ///
+    /// `may_ref_to_static` controls whether references are allowed to point to statics.
+    #[inline(always)]
+    pub fn const_validate_operand(
+        &self,
+        op: OpTy<'tcx, M::PointerTag>,
+        path: Vec<PathElem>,
+        ref_tracking: &mut RefTracking<MPlaceTy<'tcx, M::PointerTag>, Vec<PathElem>>,
+        may_ref_to_static: bool,
+    ) -> InterpResult<'tcx> {
+        self.validate_operand_internal(op, path, Some(ref_tracking), may_ref_to_static)
+    }
+
+    /// This function checks the data at `op` to be runtime-valid.
+    /// `op` is assumed to cover valid memory if it is an indirect operand.
+    /// It will error if the bits at the destination do not match the ones described by the layout.
+    #[inline(always)]
+    pub fn validate_operand(&self, op: OpTy<'tcx, M::PointerTag>) -> InterpResult<'tcx> {
+        self.validate_operand_internal(op, vec![], None, false)
     }
 }
index d2594e8707104cf10e94f9c3cad066d7f3831fd7..8808fc70cf76b05f5a9b9c8f46843e36f5d341a4 100644 (file)
@@ -120,7 +120,7 @@ fn visit_value(&mut self, v: Self::V) -> InterpResult<'tcx>
             }
             /// Visits the given value as a union. No automatic recursion can happen here.
             #[inline(always)]
-            fn visit_union(&mut self, _v: Self::V) -> InterpResult<'tcx>
+            fn visit_union(&mut self, _v: Self::V, _fields: usize) -> InterpResult<'tcx>
             {
                 Ok(())
             }
@@ -150,8 +150,9 @@ fn visit_field(
             ) -> InterpResult<'tcx> {
                 self.visit_value(new_val)
             }
-
             /// Called when recursing into an enum variant.
+            /// This gives the visitor the chance to track the stack of nested fields that
+            /// we are descending through.
             #[inline(always)]
             fn visit_variant(
                 &mut self,
@@ -162,33 +163,6 @@ fn visit_variant(
                 self.visit_value(new_val)
             }
 
-            /// Called whenever we reach a value with uninhabited layout.
-            /// Recursing to fields will *always* continue after this!  This is not meant to control
-            /// whether and how we descend recursively/ into the scalar's fields if there are any,
-            /// it is meant to provide the chance for additional checks when a value of uninhabited
-            /// layout is detected.
-            #[inline(always)]
-            fn visit_uninhabited(&mut self) -> InterpResult<'tcx>
-            { Ok(()) }
-            /// Called whenever we reach a value with scalar layout.
-            /// We do NOT provide a `ScalarMaybeUndef` here to avoid accessing memory if the
-            /// visitor is not even interested in scalars.
-            /// Recursing to fields will *always* continue after this!  This is not meant to control
-            /// whether and how we descend recursively/ into the scalar's fields if there are any,
-            /// it is meant to provide the chance for additional checks when a value of scalar
-            /// layout is detected.
-            #[inline(always)]
-            fn visit_scalar(&mut self, _v: Self::V, _layout: &layout::Scalar) -> InterpResult<'tcx>
-            { Ok(()) }
-
-            /// Called whenever we reach a value of primitive type. There can be no recursion
-            /// below such a value. This is the leaf function.
-            /// We do *not* provide an `ImmTy` here because some implementations might want
-            /// to write to the place this primitive lives in.
-            #[inline(always)]
-            fn visit_primitive(&mut self, _v: Self::V) -> InterpResult<'tcx>
-            { Ok(()) }
-
             // Default recursors. Not meant to be overloaded.
             fn walk_aggregate(
                 &mut self,
@@ -204,23 +178,10 @@ fn walk_aggregate(
             fn walk_value(&mut self, v: Self::V) -> InterpResult<'tcx>
             {
                 trace!("walk_value: type: {}", v.layout().ty);
-                // If this is a multi-variant layout, we have to find the right one and proceed with
-                // that.
-                match v.layout().variants {
-                    layout::Variants::Multiple { .. } => {
-                        let op = v.to_op(self.ecx())?;
-                        let idx = self.ecx().read_discriminant(op)?.1;
-                        let inner = v.project_downcast(self.ecx(), idx)?;
-                        trace!("walk_value: variant layout: {:#?}", inner.layout());
-                        // recurse with the inner type
-                        return self.visit_variant(v, idx, inner);
-                    }
-                    layout::Variants::Single { .. } => {}
-                }
 
-                // Even for single variants, we might be able to get a more refined type:
-                // If it is a trait object, switch to the actual type that was used to create it.
+                // Special treatment for special types, where the (static) layout is not sufficient.
                 match v.layout().ty.kind {
+                    // If it is a trait object, switch to the real type that was used to create it.
                     ty::Dynamic(..) => {
                         // immediate trait objects are not a thing
                         let dest = v.to_op(self.ecx())?.assert_mem_place(self.ecx());
@@ -229,56 +190,16 @@ fn walk_value(&mut self, v: Self::V) -> InterpResult<'tcx>
                         // recurse with the inner type
                         return self.visit_field(v, 0, Value::from_mem_place(inner));
                     },
-                    ty::Generator(..) => {
-                        // FIXME: Generator layout is lying: it claims a whole bunch of fields exist
-                        // when really many of them can be uninitialized.
-                        // Just treat them as a union for now, until hopefully the layout
-                        // computation is fixed.
-                        return self.visit_union(v);
-                    }
+                    // Slices do not need special handling here: they have `Array` field
+                    // placement with length 0, so we enter the `Array` case below which
+                    // indirectly uses the metadata to determine the actual length.
                     _ => {},
                 };
 
-                // If this is a scalar, visit it as such.
-                // Things can be aggregates and have scalar layout at the same time, and that
-                // is very relevant for `NonNull` and similar structs: We need to visit them
-                // at their scalar layout *before* descending into their fields.
-                // FIXME: We could avoid some redundant checks here. For newtypes wrapping
-                // scalars, we do the same check on every "level" (e.g., first we check
-                // MyNewtype and then the scalar in there).
-                match v.layout().abi {
-                    layout::Abi::Uninhabited => {
-                        self.visit_uninhabited()?;
-                    }
-                    layout::Abi::Scalar(ref layout) => {
-                        self.visit_scalar(v, layout)?;
-                    }
-                    // FIXME: Should we do something for ScalarPair? Vector?
-                    _ => {}
-                }
-
-                // Check primitive types.  We do this after checking the scalar layout,
-                // just to have that done as well.  Primitives can have varying layout,
-                // so we check them separately and before aggregate handling.
-                // It is CRITICAL that we get this check right, or we might be
-                // validating the wrong thing!
-                let primitive = match v.layout().fields {
-                    // Primitives appear as Union with 0 fields - except for Boxes and fat pointers.
-                    layout::FieldPlacement::Union(0) => true,
-                    _ => v.layout().ty.builtin_deref(true).is_some(),
-                };
-                if primitive {
-                    return self.visit_primitive(v);
-                }
-
-                // Proceed into the fields.
+                // Visit the fields of this value.
                 match v.layout().fields {
                     layout::FieldPlacement::Union(fields) => {
-                        // Empty unions are not accepted by rustc. That's great, it means we can
-                        // use that as an unambiguous signal for detecting primitives.  Make sure
-                        // we did not miss any primitive.
-                        assert!(fields > 0);
-                        self.visit_union(v)
+                        self.visit_union(v, fields)?;
                     },
                     layout::FieldPlacement::Arbitrary { ref offsets, .. } => {
                         // FIXME: We collect in a vec because otherwise there are lifetime
@@ -288,18 +209,35 @@ fn walk_value(&mut self, v: Self::V) -> InterpResult<'tcx>
                                 v.project_field(self.ecx(), i as u64)
                             })
                             .collect();
-                        self.visit_aggregate(v, fields.into_iter())
+                        self.visit_aggregate(v, fields.into_iter())?;
                     },
                     layout::FieldPlacement::Array { .. } => {
                         // Let's get an mplace first.
                         let mplace = v.to_op(self.ecx())?.assert_mem_place(self.ecx());
                         // Now we can go over all the fields.
+                        // This uses the *run-time length*, i.e., if we are a slice,
+                        // the dynamic info from the metadata is used.
                         let iter = self.ecx().mplace_array_fields(mplace)?
                             .map(|f| f.and_then(|f| {
                                 Ok(Value::from_mem_place(f))
                             }));
-                        self.visit_aggregate(v, iter)
+                        self.visit_aggregate(v, iter)?;
+                    }
+                }
+
+                match v.layout().variants {
+                    // If this is a multi-variant layout, find the right variant and proceed
+                    // with *its* fields.
+                    layout::Variants::Multiple { .. } => {
+                        let op = v.to_op(self.ecx())?;
+                        let idx = self.ecx().read_discriminant(op)?.1;
+                        let inner = v.project_downcast(self.ecx(), idx)?;
+                        trace!("walk_value: variant layout: {:#?}", inner.layout());
+                        // recurse with the inner type
+                        self.visit_variant(v, idx, inner)
                     }
+                    // For single-variant layouts, we already did anything there is to do.
+                    layout::Variants::Single { .. } => Ok(())
                 }
             }
         }
index 284dd74ce99d48df5bce2b928c613c949d6ac350..7d3aba3ff034e03ca6272c343e8139a8622d2ce3 100644 (file)
@@ -9,6 +9,9 @@
 #![feature(bool_to_option)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
+#![feature(const_if_match)]
+#![feature(const_fn)]
+#![feature(const_panic)]
 #![feature(crate_visibility_modifier)]
 #![feature(drain_filter)]
 #![feature(exhaustive_patterns)]
index f6a93363dc109089dff3e27f5e8d9bef9563f56b..4dd037d93ce9b9c727013d84a35a25690c165668 100644 (file)
 use rustc::mir::mono::{InstantiationMode, MonoItem};
 use rustc::mir::visit::Visitor as MirVisitor;
 use rustc::mir::{self, Local, Location};
-use rustc::session::config::EntryFnType;
 use rustc::ty::adjustment::{CustomCoerceUnsized, PointerCast};
 use rustc::ty::print::obsolete::DefPathBasedNames;
-use rustc::ty::subst::{InternalSubsts, SubstsRef};
+use rustc::ty::subst::InternalSubsts;
 use rustc::ty::{self, GenericParamDefKind, Instance, Ty, TyCtxt, TypeFoldable};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::sync::{par_iter, MTLock, MTRef, ParallelIterator};
 use rustc_hir::def_id::{DefId, DefIdMap, LOCAL_CRATE};
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_index::bit_set::GrowableBitSet;
+use rustc_session::config::EntryFnType;
 use smallvec::SmallVec;
 use std::iter;
 
@@ -493,7 +493,21 @@ struct MirNeighborCollector<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
     body: &'a mir::Body<'tcx>,
     output: &'a mut Vec<MonoItem<'tcx>>,
-    param_substs: SubstsRef<'tcx>,
+    instance: Instance<'tcx>,
+}
+
+impl<'a, 'tcx> MirNeighborCollector<'a, 'tcx> {
+    pub fn monomorphize<T>(&self, value: T) -> T
+    where
+        T: TypeFoldable<'tcx>,
+    {
+        debug!("monomorphize: self.instance={:?}", self.instance);
+        if let Some(substs) = self.instance.substs_for_mir_body() {
+            self.tcx.subst_and_normalize_erasing_regions(substs, ty::ParamEnv::reveal_all(), &value)
+        } else {
+            self.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), value)
+        }
+    }
 }
 
 impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
@@ -509,17 +523,9 @@ fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'tcx>, location: Location) {
                 ref operand,
                 target_ty,
             ) => {
-                let target_ty = self.tcx.subst_and_normalize_erasing_regions(
-                    self.param_substs,
-                    ty::ParamEnv::reveal_all(),
-                    &target_ty,
-                );
+                let target_ty = self.monomorphize(target_ty);
                 let source_ty = operand.ty(self.body, self.tcx);
-                let source_ty = self.tcx.subst_and_normalize_erasing_regions(
-                    self.param_substs,
-                    ty::ParamEnv::reveal_all(),
-                    &source_ty,
-                );
+                let source_ty = self.monomorphize(source_ty);
                 let (source_ty, target_ty) =
                     find_vtable_types_for_unsizing(self.tcx, source_ty, target_ty);
                 // This could also be a different Unsize instruction, like
@@ -540,11 +546,7 @@ fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'tcx>, location: Location) {
                 _,
             ) => {
                 let fn_ty = operand.ty(self.body, self.tcx);
-                let fn_ty = self.tcx.subst_and_normalize_erasing_regions(
-                    self.param_substs,
-                    ty::ParamEnv::reveal_all(),
-                    &fn_ty,
-                );
+                let fn_ty = self.monomorphize(fn_ty);
                 visit_fn_use(self.tcx, fn_ty, false, &mut self.output);
             }
             mir::Rvalue::Cast(
@@ -553,11 +555,7 @@ fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'tcx>, location: Location) {
                 _,
             ) => {
                 let source_ty = operand.ty(self.body, self.tcx);
-                let source_ty = self.tcx.subst_and_normalize_erasing_regions(
-                    self.param_substs,
-                    ty::ParamEnv::reveal_all(),
-                    &source_ty,
-                );
+                let source_ty = self.monomorphize(source_ty);
                 match source_ty.kind {
                     ty::Closure(def_id, substs) => {
                         let instance = Instance::resolve_closure(
@@ -593,7 +591,23 @@ fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'tcx>, location: Location) {
     fn visit_const(&mut self, constant: &&'tcx ty::Const<'tcx>, location: Location) {
         debug!("visiting const {:?} @ {:?}", *constant, location);
 
-        collect_const(self.tcx, *constant, self.param_substs, self.output);
+        let substituted_constant = self.monomorphize(*constant);
+        let param_env = ty::ParamEnv::reveal_all();
+
+        match substituted_constant.val {
+            ty::ConstKind::Value(val) => collect_const_value(self.tcx, val, self.output),
+            ty::ConstKind::Unevaluated(def_id, substs, promoted) => {
+                match self.tcx.const_eval_resolve(param_env, def_id, substs, promoted, None) {
+                    Ok(val) => collect_const_value(self.tcx, val, self.output),
+                    Err(ErrorHandled::Reported) => {}
+                    Err(ErrorHandled::TooGeneric) => span_bug!(
+                        self.tcx.def_span(def_id),
+                        "collection encountered polymorphic constant",
+                    ),
+                }
+            }
+            _ => {}
+        }
 
         self.super_const(constant);
     }
@@ -605,21 +619,13 @@ fn visit_terminator_kind(&mut self, kind: &mir::TerminatorKind<'tcx>, location:
         match *kind {
             mir::TerminatorKind::Call { ref func, .. } => {
                 let callee_ty = func.ty(self.body, tcx);
-                let callee_ty = tcx.subst_and_normalize_erasing_regions(
-                    self.param_substs,
-                    ty::ParamEnv::reveal_all(),
-                    &callee_ty,
-                );
+                let callee_ty = self.monomorphize(callee_ty);
                 visit_fn_use(self.tcx, callee_ty, true, &mut self.output);
             }
             mir::TerminatorKind::Drop { ref location, .. }
             | mir::TerminatorKind::DropAndReplace { ref location, .. } => {
                 let ty = location.ty(self.body, self.tcx).ty;
-                let ty = tcx.subst_and_normalize_erasing_regions(
-                    self.param_substs,
-                    ty::ParamEnv::reveal_all(),
-                    &ty,
-                );
+                let ty = self.monomorphize(ty);
                 visit_drop_use(self.tcx, ty, true, self.output);
             }
             mir::TerminatorKind::Goto { .. }
@@ -824,11 +830,8 @@ fn find_vtable_types_for_unsizing<'tcx>(
         (&ty::Adt(source_adt_def, source_substs), &ty::Adt(target_adt_def, target_substs)) => {
             assert_eq!(source_adt_def, target_adt_def);
 
-            let kind = monomorphize::custom_coerce_unsize_info(tcx, source_ty, target_ty);
-
-            let coerce_index = match kind {
-                CustomCoerceUnsized::Struct(i) => i,
-            };
+            let CustomCoerceUnsized::Struct(coerce_index) =
+                monomorphize::custom_coerce_unsize_info(tcx, source_ty, target_ty);
 
             let source_fields = &source_adt_def.non_enum_variant().fields;
             let target_fields = &target_adt_def.non_enum_variant().fields;
@@ -986,7 +989,7 @@ fn visit_trait_item(&mut self, _: &'v hir::TraitItem<'v>) {
 
     fn visit_impl_item(&mut self, ii: &'v hir::ImplItem<'v>) {
         match ii.kind {
-            hir::ImplItemKind::Method(hir::FnSig { .. }, _) => {
+            hir::ImplItemKind::Fn(hir::FnSig { .. }, _) => {
                 let def_id = self.tcx.hir().local_def_id(ii.hir_id);
                 self.push_if_root(def_id);
             }
@@ -1091,9 +1094,9 @@ fn create_mono_items_for_default_impls<'tcx>(
                 let param_env = ty::ParamEnv::reveal_all();
                 let trait_ref = tcx.normalize_erasing_regions(param_env, trait_ref);
                 let overridden_methods: FxHashSet<_> =
-                    items.iter().map(|iiref| iiref.ident.modern()).collect();
+                    items.iter().map(|iiref| iiref.ident.normalize_to_macros_2_0()).collect();
                 for method in tcx.provided_trait_methods(trait_ref.def_id) {
-                    if overridden_methods.contains(&method.ident.modern()) {
+                    if overridden_methods.contains(&method.ident.normalize_to_macros_2_0()) {
                         continue;
                     }
 
@@ -1159,8 +1162,7 @@ fn collect_neighbours<'tcx>(
     debug!("collect_neighbours: {:?}", instance.def_id());
     let body = tcx.instance_mir(instance.def);
 
-    MirNeighborCollector { tcx, body: &body, output, param_substs: instance.substs }
-        .visit_body(body);
+    MirNeighborCollector { tcx, body: &body, output, instance }.visit_body(body);
 }
 
 fn def_id_to_string(tcx: TyCtxt<'_>, def_id: DefId) -> String {
@@ -1170,33 +1172,6 @@ fn def_id_to_string(tcx: TyCtxt<'_>, def_id: DefId) -> String {
     output
 }
 
-fn collect_const<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    constant: &'tcx ty::Const<'tcx>,
-    param_substs: SubstsRef<'tcx>,
-    output: &mut Vec<MonoItem<'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 {
-        ty::ConstKind::Value(val) => collect_const_value(tcx, val, output),
-        ty::ConstKind::Unevaluated(def_id, substs, promoted) => {
-            match tcx.const_eval_resolve(param_env, def_id, substs, promoted, None) {
-                Ok(val) => collect_const_value(tcx, val, output),
-                Err(ErrorHandled::Reported) => {}
-                Err(ErrorHandled::TooGeneric) => {
-                    span_bug!(tcx.def_span(def_id), "collection encountered polymorphic constant",)
-                }
-            }
-        }
-        _ => {}
-    }
-}
-
 fn collect_const_value<'tcx>(
     tcx: TyCtxt<'tcx>,
     value: ConstValue<'tcx>,
index 8bc63bfcfcbe34abb99ce413d02ad75f99fa44c6..7177bf726d4033b3caf36347b294dcb4be7ed85f 100644 (file)
@@ -13,12 +13,12 @@ pub fn custom_coerce_unsize_info<'tcx>(
     let def_id = tcx.lang_items().coerce_unsized_trait().unwrap();
 
     let trait_ref = ty::Binder::bind(ty::TraitRef {
-        def_id: def_id,
+        def_id,
         substs: tcx.mk_substs_trait(source_ty, &[target_ty.into()]),
     });
 
     match tcx.codegen_fulfill_obligation((ty::ParamEnv::reveal_all(), trait_ref)) {
-        traits::VtableImpl(traits::VtableImplData { impl_def_id, .. }) => {
+        Some(traits::VtableImpl(traits::VtableImplData { impl_def_id, .. })) => {
             tcx.coerce_unsized_info(impl_def_id).custom_kind.unwrap()
         }
         vtable => {
index 1f7db2861a2eb26b47b90c2b716050a1707eced6..c1d969a4b51633c37de4e4f6b40ad44490c555a8 100644 (file)
@@ -2,13 +2,13 @@
 use rustc::ty::layout::VariantIdx;
 use rustc::ty::query::Providers;
 use rustc::ty::subst::{InternalSubsts, Subst};
-use rustc::ty::{self, Ty, TyCtxt};
+use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 
 use rustc_index::vec::{Idx, IndexVec};
 
-use rustc_span::{sym, Span};
+use rustc_span::Span;
 use rustc_target::spec::abi::Abi;
 
 use std::fmt;
@@ -39,6 +39,11 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx
             None,
         ),
         ty::InstanceDef::FnPtrShim(def_id, ty) => {
+            // FIXME(eddyb) support generating shims for a "shallow type",
+            // e.g. `Foo<_>` or `[_]` instead of requiring a fully monomorphic
+            // `Foo<Bar>` or `[String]` etc.
+            assert!(!ty.needs_subst());
+
             let trait_ = tcx.trait_of_item(def_id).unwrap();
             let adjustment = match tcx.fn_trait_kind_from_lang_item(trait_) {
                 Some(ty::ClosureKind::FnOnce) => Adjustment::Identity,
@@ -81,17 +86,21 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx
                 None,
             )
         }
-        ty::InstanceDef::DropGlue(def_id, ty) => build_drop_shim(tcx, def_id, ty),
+        ty::InstanceDef::DropGlue(def_id, ty) => {
+            // FIXME(eddyb) support generating shims for a "shallow type",
+            // e.g. `Foo<_>` or `[_]` instead of requiring a fully monomorphic
+            // `Foo<Bar>` or `[String]` etc.
+            assert!(!ty.needs_subst());
+
+            build_drop_shim(tcx, def_id, ty)
+        }
         ty::InstanceDef::CloneShim(def_id, ty) => {
-            let name = tcx.item_name(def_id);
-            if name == sym::clone {
-                build_clone_shim(tcx, def_id, ty)
-            } else if name == sym::clone_from {
-                debug!("make_shim({:?}: using default trait implementation", instance);
-                return tcx.optimized_mir(def_id);
-            } else {
-                bug!("builtin clone shim {:?} not supported", instance)
-            }
+            // FIXME(eddyb) support generating shims for a "shallow type",
+            // e.g. `Foo<_>` or `[_]` instead of requiring a fully monomorphic
+            // `Foo<Bar>` or `[String]` etc.
+            assert!(!ty.needs_subst());
+
+            build_clone_shim(tcx, def_id, ty)
         }
         ty::InstanceDef::Virtual(..) => {
             bug!("InstanceDef::Virtual ({:?}) is for direct calls only", instance)
index a5b467c1e101f77bf8a6b4c4b00a0782ba9ccb60..aa9cad7ffc19fa67a886ef472633b4cb401fffcf 100644 (file)
 /// after the assignment, we can be sure to obtain the same place value.
 /// (Concurrent accesses by other threads are no problem as these are anyway non-atomic
 /// copies.  Data races are UB.)
-fn is_stable(place: PlaceRef<'_, '_>) -> bool {
+fn is_stable(place: PlaceRef<'_>) -> bool {
     place.projection.iter().all(|elem| {
         match elem {
             // Which place this evaluates to can change with any memory write,
             // so cannot assume this to be stable.
             ProjectionElem::Deref => false,
-            // Array indices are intersting, but MIR building generates a *fresh*
+            // Array indices are interesting, but MIR building generates a *fresh*
             // temporary for every array access, so the index cannot be changed as
             // a side-effect.
             ProjectionElem::Index { .. } |
@@ -34,7 +34,7 @@ fn is_stable(place: PlaceRef<'_, '_>) -> bool {
 }
 
 /// Determine whether this type may be a reference (or box), and thus needs retagging.
-fn may_be_reference<'tcx>(ty: Ty<'tcx>) -> bool {
+fn may_be_reference(ty: Ty<'tcx>) -> bool {
     match ty.kind {
         // Primitive types that are not references
         ty::Bool
@@ -75,8 +75,8 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut BodyAndC
         {
             let source_info = SourceInfo {
                 scope: OUTERMOST_SOURCE_SCOPE,
-                span: span, // FIXME: Consider using just the span covering the function
-                            // argument declaration.
+                span, // FIXME: Consider using just the span covering the function
+                      // argument declaration.
             };
             // Gather all arguments, skip return value.
             let places = local_decls
index 9ba44a4d18e5813b9c3ada4c5648b47f40b779e1..af7af7388bd28a62b8bb77236d8debb59d221449 100644 (file)
@@ -1,10 +1,9 @@
 //! Concrete error types for all operations which may be invalid in a certain const context.
 
-use rustc::session::config::nightly_options;
-use rustc::session::parse::feature_err;
-use rustc::ty::TyCtxt;
 use rustc_errors::struct_span_err;
 use rustc_hir::def_id::DefId;
+use rustc_session::config::nightly_options;
+use rustc_session::parse::feature_err;
 use rustc_span::symbol::sym;
 use rustc_span::{Span, Symbol};
 
@@ -15,9 +14,9 @@ pub trait NonConstOp: std::fmt::Debug {
     /// Whether this operation can be evaluated by miri.
     const IS_SUPPORTED_IN_MIRI: bool = true;
 
-    /// Returns a boolean indicating whether the feature gate that would allow this operation is
-    /// enabled, or `None` if such a feature gate does not exist.
-    fn feature_gate(_tcx: TyCtxt<'tcx>) -> Option<bool> {
+    /// Returns the `Symbol` corresponding to the feature gate that would enable this operation,
+    /// or `None` if such a feature gate does not exist.
+    fn feature_gate() -> Option<Symbol> {
         None
     }
 
@@ -25,8 +24,11 @@ fn feature_gate(_tcx: TyCtxt<'tcx>) -> Option<bool> {
     ///
     /// This check should assume that we are not in a non-const `fn`, where all operations are
     /// legal.
+    ///
+    /// By default, it returns `true` if and only if this operation has a corresponding feature
+    /// gate and that gate is enabled.
     fn is_allowed_in_item(&self, item: &Item<'_, '_>) -> bool {
-        Self::feature_gate(item.tcx).unwrap_or(false)
+        Self::feature_gate().map_or(false, |gate| item.tcx.features().enabled(gate))
     }
 
     fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
@@ -55,8 +57,8 @@ fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
 #[derive(Debug)]
 pub struct Downcast;
 impl NonConstOp for Downcast {
-    fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
-        Some(tcx.features().const_if_match)
+    fn feature_gate() -> Option<Symbol> {
+        Some(sym::const_if_match)
     }
 }
 
@@ -147,8 +149,8 @@ fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
 #[derive(Debug)]
 pub struct IfOrMatch;
 impl NonConstOp for IfOrMatch {
-    fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
-        Some(tcx.features().const_if_match)
+    fn feature_gate() -> Option<Symbol> {
+        Some(sym::const_if_match)
     }
 
     fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
@@ -175,8 +177,8 @@ fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
 #[derive(Debug)]
 pub struct Loop;
 impl NonConstOp for Loop {
-    fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
-        Some(tcx.features().const_loop)
+    fn feature_gate() -> Option<Symbol> {
+        Some(sym::const_loop)
     }
 
     fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
@@ -203,8 +205,8 @@ fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
 #[derive(Debug)]
 pub struct MutBorrow;
 impl NonConstOp for MutBorrow {
-    fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
-        Some(tcx.features().const_mut_refs)
+    fn feature_gate() -> Option<Symbol> {
+        Some(sym::const_mut_refs)
     }
 
     fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
@@ -238,8 +240,8 @@ fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
 #[derive(Debug)]
 pub struct MutAddressOf;
 impl NonConstOp for MutAddressOf {
-    fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
-        Some(tcx.features().const_mut_refs)
+    fn feature_gate() -> Option<Symbol> {
+        Some(sym::const_mut_refs)
     }
 
     fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
@@ -256,16 +258,16 @@ fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
 #[derive(Debug)]
 pub struct MutDeref;
 impl NonConstOp for MutDeref {
-    fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
-        Some(tcx.features().const_mut_refs)
+    fn feature_gate() -> Option<Symbol> {
+        Some(sym::const_mut_refs)
     }
 }
 
 #[derive(Debug)]
 pub struct Panic;
 impl NonConstOp for Panic {
-    fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
-        Some(tcx.features().const_panic)
+    fn feature_gate() -> Option<Symbol> {
+        Some(sym::const_panic)
     }
 
     fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
@@ -282,8 +284,8 @@ fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
 #[derive(Debug)]
 pub struct RawPtrComparison;
 impl NonConstOp for RawPtrComparison {
-    fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
-        Some(tcx.features().const_compare_raw_pointers)
+    fn feature_gate() -> Option<Symbol> {
+        Some(sym::const_compare_raw_pointers)
     }
 
     fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
@@ -300,8 +302,8 @@ fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
 #[derive(Debug)]
 pub struct RawPtrDeref;
 impl NonConstOp for RawPtrDeref {
-    fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
-        Some(tcx.features().const_raw_ptr_deref)
+    fn feature_gate() -> Option<Symbol> {
+        Some(sym::const_raw_ptr_deref)
     }
 
     fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
@@ -318,8 +320,8 @@ fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
 #[derive(Debug)]
 pub struct RawPtrToIntCast;
 impl NonConstOp for RawPtrToIntCast {
-    fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
-        Some(tcx.features().const_raw_ptr_to_usize_cast)
+    fn feature_gate() -> Option<Symbol> {
+        Some(sym::const_raw_ptr_to_usize_cast)
     }
 
     fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
@@ -386,11 +388,12 @@ fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
 impl NonConstOp for UnionAccess {
     fn is_allowed_in_item(&self, item: &Item<'_, '_>) -> bool {
         // Union accesses are stable in all contexts except `const fn`.
-        item.const_kind() != ConstKind::ConstFn || Self::feature_gate(item.tcx).unwrap()
+        item.const_kind() != ConstKind::ConstFn
+            || item.tcx.features().enabled(Self::feature_gate().unwrap())
     }
 
-    fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
-        Some(tcx.features().const_fn_union)
+    fn feature_gate() -> Option<Symbol> {
+        Some(sym::const_fn_union)
     }
 
     fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
index 215496e4d03cb7b108d4a3502a0d426072d642c7..9359ec16533a580f54e26220187a981aa45e154f 100644 (file)
@@ -1,7 +1,9 @@
-//! A copy of the `Qualif` trait in `qualify_consts.rs` that is suitable for the new validator.
+//! Structural const qualification.
+//!
+//! See the `Qualif` trait for more info.
 
 use rustc::mir::*;
-use rustc::ty::{self, Ty};
+use rustc::ty::{self, AdtDef, Ty};
 use rustc_span::DUMMY_SP;
 
 use super::Item as ConstCx;
@@ -14,11 +16,16 @@ pub fn in_any_value_of_ty(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> ConstQualifs
 }
 
 /// A "qualif"(-ication) is a way to look for something "bad" in the MIR that would disqualify some
-/// code for promotion or prevent it from evaluating at compile time. So `return true` means
-/// "I found something bad, no reason to go on searching". `false` is only returned if we
-/// definitely cannot find anything bad anywhere.
+/// code for promotion or prevent it from evaluating at compile time.
 ///
-/// The default implementations proceed structurally.
+/// Normally, we would determine what qualifications apply to each type and error when an illegal
+/// operation is performed on such a type. However, this was found to be too imprecise, especially
+/// in the presence of `enum`s. If only a single variant of an enum has a certain qualification, we
+/// needn't reject code unless it actually constructs and operates on the qualifed variant.
+///
+/// To accomplish this, const-checking and promotion use a value-based analysis (as opposed to a
+/// type-based one). Qualifications propagate structurally across variables: If a local (or a
+/// projection of a local) is assigned a qualifed value, that local itself becomes qualifed.
 pub trait Qualif {
     /// The name of the file used to debug the dataflow analysis that computes this qualif.
     const ANALYSIS_NAME: &'static str;
@@ -26,157 +33,27 @@ pub trait Qualif {
     /// Whether this `Qualif` is cleared when a local is moved from.
     const IS_CLEARED_ON_MOVE: bool = false;
 
+    /// Extracts the field of `ConstQualifs` that corresponds to this `Qualif`.
     fn in_qualifs(qualifs: &ConstQualifs) -> bool;
 
-    /// Return the qualification that is (conservatively) correct for any value
-    /// of the type.
-    fn in_any_value_of_ty(_cx: &ConstCx<'_, 'tcx>, _ty: Ty<'tcx>) -> bool;
-
-    fn in_projection_structurally(
-        cx: &ConstCx<'_, 'tcx>,
-        per_local: &mut impl FnMut(Local) -> bool,
-        place: PlaceRef<'_, 'tcx>,
-    ) -> bool {
-        if let [proj_base @ .., elem] = place.projection {
-            let base_qualif = Self::in_place(
-                cx,
-                per_local,
-                PlaceRef { local: place.local, projection: proj_base },
-            );
-            let qualif = base_qualif
-                && Self::in_any_value_of_ty(
-                    cx,
-                    Place::ty_from(place.local, proj_base, *cx.body, cx.tcx)
-                        .projection_ty(cx.tcx, elem)
-                        .ty,
-                );
-            match elem {
-                ProjectionElem::Deref
-                | ProjectionElem::Subslice { .. }
-                | ProjectionElem::Field(..)
-                | ProjectionElem::ConstantIndex { .. }
-                | ProjectionElem::Downcast(..) => qualif,
-
-                ProjectionElem::Index(local) => qualif || per_local(*local),
-            }
-        } else {
-            bug!("This should be called if projection is not empty");
-        }
-    }
-
-    fn in_projection(
-        cx: &ConstCx<'_, 'tcx>,
-        per_local: &mut impl FnMut(Local) -> bool,
-        place: PlaceRef<'_, 'tcx>,
-    ) -> bool {
-        Self::in_projection_structurally(cx, per_local, place)
-    }
-
-    fn in_place(
-        cx: &ConstCx<'_, 'tcx>,
-        per_local: &mut impl FnMut(Local) -> bool,
-        place: PlaceRef<'_, 'tcx>,
-    ) -> bool {
-        match place {
-            PlaceRef { local, projection: [] } => per_local(local),
-            PlaceRef { local: _, projection: [.., _] } => Self::in_projection(cx, per_local, place),
-        }
-    }
-
-    fn in_operand(
-        cx: &ConstCx<'_, 'tcx>,
-        per_local: &mut impl FnMut(Local) -> bool,
-        operand: &Operand<'tcx>,
-    ) -> bool {
-        match *operand {
-            Operand::Copy(ref place) | Operand::Move(ref place) => {
-                Self::in_place(cx, per_local, place.as_ref())
-            }
-
-            Operand::Constant(ref constant) => {
-                // Check the qualifs of the value of `const` items.
-                if let ty::ConstKind::Unevaluated(def_id, _, promoted) = constant.literal.val {
-                    assert!(promoted.is_none());
-                    // Don't peek inside trait associated constants.
-                    if cx.tcx.trait_of_item(def_id).is_none() {
-                        let qualifs = cx.tcx.at(constant.span).mir_const_qualif(def_id);
-                        if !Self::in_qualifs(&qualifs) {
-                            return false;
-                        }
-
-                        // Just in case the type is more specific than
-                        // the definition, e.g., impl associated const
-                        // with type parameters, take it into account.
-                    }
-                }
-                // Otherwise use the qualifs of the type.
-                Self::in_any_value_of_ty(cx, constant.literal.ty)
-            }
-        }
-    }
-
-    fn in_rvalue_structurally(
-        cx: &ConstCx<'_, 'tcx>,
-        per_local: &mut impl FnMut(Local) -> bool,
-        rvalue: &Rvalue<'tcx>,
-    ) -> bool {
-        match *rvalue {
-            Rvalue::NullaryOp(..) => false,
-
-            Rvalue::Discriminant(ref place) | Rvalue::Len(ref place) => {
-                Self::in_place(cx, per_local, place.as_ref())
-            }
-
-            Rvalue::Use(ref operand)
-            | Rvalue::Repeat(ref operand, _)
-            | Rvalue::UnaryOp(_, ref operand)
-            | Rvalue::Cast(_, ref operand, _) => Self::in_operand(cx, per_local, operand),
-
-            Rvalue::BinaryOp(_, ref lhs, ref rhs)
-            | Rvalue::CheckedBinaryOp(_, ref lhs, ref rhs) => {
-                Self::in_operand(cx, per_local, lhs) || Self::in_operand(cx, per_local, rhs)
-            }
-
-            Rvalue::Ref(_, _, ref place) | Rvalue::AddressOf(_, ref place) => {
-                // Special-case reborrows to be more like a copy of the reference.
-                if let [proj_base @ .., ProjectionElem::Deref] = place.projection.as_ref() {
-                    let base_ty = Place::ty_from(place.local, proj_base, *cx.body, cx.tcx).ty;
-                    if let ty::Ref(..) = base_ty.kind {
-                        return Self::in_place(
-                            cx,
-                            per_local,
-                            PlaceRef { local: place.local, projection: proj_base },
-                        );
-                    }
-                }
-
-                Self::in_place(cx, per_local, place.as_ref())
-            }
-
-            Rvalue::Aggregate(_, ref operands) => {
-                operands.iter().any(|o| Self::in_operand(cx, per_local, o))
-            }
-        }
-    }
-
-    fn in_rvalue(
-        cx: &ConstCx<'_, 'tcx>,
-        per_local: &mut impl FnMut(Local) -> bool,
-        rvalue: &Rvalue<'tcx>,
-    ) -> bool {
-        Self::in_rvalue_structurally(cx, per_local, rvalue)
-    }
-
-    fn in_call(
-        cx: &ConstCx<'_, 'tcx>,
-        _per_local: &mut impl FnMut(Local) -> bool,
-        _callee: &Operand<'tcx>,
-        _args: &[Operand<'tcx>],
-        return_ty: Ty<'tcx>,
-    ) -> bool {
-        // Be conservative about the returned value of a const fn.
-        Self::in_any_value_of_ty(cx, return_ty)
-    }
+    /// Returns `true` if *any* value of the given type could possibly have this `Qualif`.
+    ///
+    /// This function determines `Qualif`s when we cannot do a value-based analysis. Since qualif
+    /// propagation is context-insenstive, this includes function arguments and values returned
+    /// from a call to another function.
+    ///
+    /// It also determines the `Qualif`s for primitive types.
+    fn in_any_value_of_ty(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool;
+
+    /// Returns `true` if this `Qualif` is inherent to the given struct or enum.
+    ///
+    /// By default, `Qualif`s propagate into ADTs in a structural way: An ADT only becomes
+    /// qualified if part of it is assigned a value with that `Qualif`. However, some ADTs *always*
+    /// have a certain `Qualif`, regardless of whether their fields have it. For example, a type
+    /// with a custom `Drop` impl is inherently `NeedsDrop`.
+    ///
+    /// Returning `true` for `in_adt_inherently` but `false` for `in_any_value_of_ty` is unsound.
+    fn in_adt_inherently(cx: &ConstCx<'_, 'tcx>, adt: &AdtDef) -> bool;
 }
 
 /// Constant containing interior mutability (`UnsafeCell<T>`).
@@ -197,26 +74,10 @@ fn in_any_value_of_ty(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool {
         !ty.is_freeze(cx.tcx, cx.param_env, DUMMY_SP)
     }
 
-    fn in_rvalue(
-        cx: &ConstCx<'_, 'tcx>,
-        per_local: &mut impl FnMut(Local) -> bool,
-        rvalue: &Rvalue<'tcx>,
-    ) -> bool {
-        match *rvalue {
-            Rvalue::Aggregate(ref kind, _) => {
-                if let AggregateKind::Adt(def, ..) = **kind {
-                    if Some(def.did) == cx.tcx.lang_items().unsafe_cell_type() {
-                        let ty = rvalue.ty(*cx.body, cx.tcx);
-                        assert_eq!(Self::in_any_value_of_ty(cx, ty), true);
-                        return true;
-                    }
-                }
-            }
-
-            _ => {}
-        }
-
-        Self::in_rvalue_structurally(cx, per_local, rvalue)
+    fn in_adt_inherently(cx: &ConstCx<'_, 'tcx>, adt: &AdtDef) -> bool {
+        // Exactly one type, `UnsafeCell`, has the `HasMutInterior` qualif inherently.
+        // It arises structurally for all other types.
+        Some(adt.did) == cx.tcx.lang_items().unsafe_cell_type()
     }
 }
 
@@ -238,19 +99,127 @@ fn in_any_value_of_ty(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool {
         ty.needs_drop(cx.tcx, cx.param_env)
     }
 
-    fn in_rvalue(
-        cx: &ConstCx<'_, 'tcx>,
-        per_local: &mut impl FnMut(Local) -> bool,
-        rvalue: &Rvalue<'tcx>,
-    ) -> bool {
-        if let Rvalue::Aggregate(ref kind, _) = *rvalue {
+    fn in_adt_inherently(cx: &ConstCx<'_, 'tcx>, adt: &AdtDef) -> bool {
+        adt.has_dtor(cx.tcx)
+    }
+}
+
+// FIXME: Use `mir::visit::Visitor` for the `in_*` functions if/when it supports early return.
+
+/// Returns `true` if this `Rvalue` contains qualif `Q`.
+pub fn in_rvalue<Q, F>(cx: &ConstCx<'_, 'tcx>, in_local: &mut F, rvalue: &Rvalue<'tcx>) -> bool
+where
+    Q: Qualif,
+    F: FnMut(Local) -> bool,
+{
+    match rvalue {
+        Rvalue::NullaryOp(..) => Q::in_any_value_of_ty(cx, rvalue.ty(*cx.body, cx.tcx)),
+
+        Rvalue::Discriminant(place) | Rvalue::Len(place) => {
+            in_place::<Q, _>(cx, in_local, place.as_ref())
+        }
+
+        Rvalue::Use(operand)
+        | Rvalue::Repeat(operand, _)
+        | Rvalue::UnaryOp(_, operand)
+        | Rvalue::Cast(_, operand, _) => in_operand::<Q, _>(cx, in_local, operand),
+
+        Rvalue::BinaryOp(_, lhs, rhs) | Rvalue::CheckedBinaryOp(_, lhs, rhs) => {
+            in_operand::<Q, _>(cx, in_local, lhs) || in_operand::<Q, _>(cx, in_local, rhs)
+        }
+
+        Rvalue::Ref(_, _, place) | Rvalue::AddressOf(_, place) => {
+            // Special-case reborrows to be more like a copy of the reference.
+            if let &[ref proj_base @ .., ProjectionElem::Deref] = place.projection.as_ref() {
+                let base_ty = Place::ty_from(place.local, proj_base, *cx.body, cx.tcx).ty;
+                if let ty::Ref(..) = base_ty.kind {
+                    return in_place::<Q, _>(
+                        cx,
+                        in_local,
+                        PlaceRef { local: place.local, projection: proj_base },
+                    );
+                }
+            }
+
+            in_place::<Q, _>(cx, in_local, place.as_ref())
+        }
+
+        Rvalue::Aggregate(kind, operands) => {
+            // Return early if we know that the struct or enum being constructed is always
+            // qualified.
             if let AggregateKind::Adt(def, ..) = **kind {
-                if def.has_dtor(cx.tcx) {
+                if Q::in_adt_inherently(cx, def) {
                     return true;
                 }
             }
+
+            // Otherwise, proceed structurally...
+            operands.iter().any(|o| in_operand::<Q, _>(cx, in_local, o))
         }
+    }
+}
 
-        Self::in_rvalue_structurally(cx, per_local, rvalue)
+/// Returns `true` if this `Place` contains qualif `Q`.
+pub fn in_place<Q, F>(cx: &ConstCx<'_, 'tcx>, in_local: &mut F, place: PlaceRef<'tcx>) -> bool
+where
+    Q: Qualif,
+    F: FnMut(Local) -> bool,
+{
+    let mut projection = place.projection;
+    while let [ref proj_base @ .., proj_elem] = projection {
+        match *proj_elem {
+            ProjectionElem::Index(index) if in_local(index) => return true,
+
+            ProjectionElem::Deref
+            | ProjectionElem::Field(_, _)
+            | ProjectionElem::ConstantIndex { .. }
+            | ProjectionElem::Subslice { .. }
+            | ProjectionElem::Downcast(_, _)
+            | ProjectionElem::Index(_) => {}
+        }
+
+        let base_ty = Place::ty_from(place.local, proj_base, *cx.body, cx.tcx);
+        let proj_ty = base_ty.projection_ty(cx.tcx, proj_elem).ty;
+        if !Q::in_any_value_of_ty(cx, proj_ty) {
+            return false;
+        }
+
+        projection = proj_base;
+    }
+
+    assert!(projection.is_empty());
+    in_local(place.local)
+}
+
+/// Returns `true` if this `Operand` contains qualif `Q`.
+pub fn in_operand<Q, F>(cx: &ConstCx<'_, 'tcx>, in_local: &mut F, operand: &Operand<'tcx>) -> bool
+where
+    Q: Qualif,
+    F: FnMut(Local) -> bool,
+{
+    let constant = match operand {
+        Operand::Copy(place) | Operand::Move(place) => {
+            return in_place::<Q, _>(cx, in_local, place.as_ref());
+        }
+
+        Operand::Constant(c) => c,
+    };
+
+    // Check the qualifs of the value of `const` items.
+    if let ty::ConstKind::Unevaluated(def_id, _, promoted) = constant.literal.val {
+        assert!(promoted.is_none());
+        // Don't peek inside trait associated constants.
+        if cx.tcx.trait_of_item(def_id).is_none() {
+            let qualifs = cx.tcx.at(constant.span).mir_const_qualif(def_id);
+            if !Q::in_qualifs(&qualifs) {
+                return false;
+            }
+
+            // Just in case the type is more specific than
+            // the definition, e.g., impl associated const
+            // with type parameters, take it into account.
+        }
     }
+    // Otherwise use the qualifs of the type.
+    Q::in_any_value_of_ty(cx, constant.literal.ty)
 }
index 3e14cc6d32a671f579469fd7d6f7ce7a8e56b4c6..e42f64b5c7384adaeba81508f28224324cff8486 100644 (file)
@@ -8,7 +8,7 @@
 
 use std::marker::PhantomData;
 
-use super::{Item, Qualif};
+use super::{qualifs, Item, Qualif};
 use crate::dataflow::{self as old_dataflow, generic as dataflow};
 
 /// A `Visitor` that propagates qualifs between locals. This defines the transfer function of
@@ -66,18 +66,15 @@ fn assign_qualif_direct(&mut self, place: &mir::Place<'tcx>, value: bool) {
     fn apply_call_return_effect(
         &mut self,
         _block: BasicBlock,
-        func: &mir::Operand<'tcx>,
-        args: &[mir::Operand<'tcx>],
+        _func: &mir::Operand<'tcx>,
+        _args: &[mir::Operand<'tcx>],
         return_place: &mir::Place<'tcx>,
     ) {
+        // We cannot reason about another function's internals, so use conservative type-based
+        // qualification for the result of a function call.
         let return_ty = return_place.ty(*self.item.body, self.item.tcx).ty;
-        let qualif = Q::in_call(
-            self.item,
-            &mut |l| self.qualifs_per_local.contains(l),
-            func,
-            args,
-            return_ty,
-        );
+        let qualif = Q::in_any_value_of_ty(self.item, return_ty);
+
         if !return_place.is_indirect() {
             self.assign_qualif_direct(return_place, qualif);
         }
@@ -110,7 +107,11 @@ fn visit_assign(
         rvalue: &mir::Rvalue<'tcx>,
         location: Location,
     ) {
-        let qualif = Q::in_rvalue(self.item, &mut |l| self.qualifs_per_local.contains(l), rvalue);
+        let qualif = qualifs::in_rvalue::<Q, _>(
+            self.item,
+            &mut |l| self.qualifs_per_local.contains(l),
+            rvalue,
+        );
         if !place.is_indirect() {
             self.assign_qualif_direct(place, qualif);
         }
@@ -125,8 +126,12 @@ fn visit_terminator_kind(&mut self, kind: &mir::TerminatorKind<'tcx>, location:
         // here; that occurs in `apply_call_return_effect`.
 
         if let mir::TerminatorKind::DropAndReplace { value, location: dest, .. } = kind {
-            let qualif =
-                Q::in_operand(self.item, &mut |l| self.qualifs_per_local.contains(l), value);
+            let qualif = qualifs::in_operand::<Q, _>(
+                self.item,
+                &mut |l| self.qualifs_per_local.contains(l),
+                value,
+            );
+
             if !dest.is_indirect() {
                 self.assign_qualif_direct(dest, qualif);
             }
index 1553f826c7e4bb04c28127f997eede114bd05d60..be461c0e03d8635767f5d007db2f39f5458bf6fa 100644 (file)
@@ -9,9 +9,10 @@
 use rustc_hir::{def_id::DefId, HirId};
 use rustc_index::bit_set::BitSet;
 use rustc_infer::infer::TyCtxtInferExt;
-use rustc_infer::traits::{self, TraitEngine};
 use rustc_span::symbol::sym;
 use rustc_span::Span;
+use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
+use rustc_trait_selection::traits::{self, TraitEngine};
 
 use std::borrow::Cow;
 use std::ops::Deref;
@@ -212,7 +213,7 @@ pub fn check_op_spanned<O>(&mut self, op: O, span: Span)
 
         // If an operation is supported in miri (and is not already controlled by a feature gate) it
         // can be turned on with `-Zunleash-the-miri-inside-of-you`.
-        let is_unleashable = O::IS_SUPPORTED_IN_MIRI && O::feature_gate(self.tcx).is_none();
+        let is_unleashable = O::IS_SUPPORTED_IN_MIRI && O::feature_gate().is_none();
 
         if is_unleashable && self.tcx.sess.opts.debugging_opts.unleash_the_miri_inside_of_you {
             self.tcx.sess.span_warn(span, "skipping const checks");
@@ -276,7 +277,7 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
                         }
                     };
                     self.visit_place_base(&place.local, ctx, location);
-                    self.visit_projection(&place.local, reborrowed_proj, ctx, location);
+                    self.visit_projection(place.local, reborrowed_proj, ctx, location);
                     return;
                 }
             }
@@ -289,7 +290,7 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
                         Mutability::Mut => PlaceContext::MutatingUse(MutatingUseContext::AddressOf),
                     };
                     self.visit_place_base(&place.local, ctx, location);
-                    self.visit_projection(&place.local, reborrowed_proj, ctx, location);
+                    self.visit_projection(place.local, reborrowed_proj, ctx, location);
                     return;
                 }
             }
@@ -343,7 +344,7 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
             Rvalue::Ref(_, BorrowKind::Shared, ref place)
             | Rvalue::Ref(_, BorrowKind::Shallow, ref place)
             | Rvalue::AddressOf(Mutability::Not, ref place) => {
-                let borrowed_place_has_mut_interior = HasMutInterior::in_place(
+                let borrowed_place_has_mut_interior = qualifs::in_place::<HasMutInterior, _>(
                     &self.item,
                     &mut |local| self.qualifs.has_mut_interior(local, location),
                     place.as_ref(),
@@ -408,7 +409,7 @@ fn visit_operand(&mut self, op: &Operand<'tcx>, location: Location) {
     }
     fn visit_projection_elem(
         &mut self,
-        place_local: &Local,
+        place_local: Local,
         proj_base: &[PlaceElem<'tcx>],
         elem: &PlaceElem<'tcx>,
         context: PlaceContext,
@@ -428,11 +429,11 @@ fn visit_projection_elem(
 
         match elem {
             ProjectionElem::Deref => {
-                let base_ty = Place::ty_from(*place_local, proj_base, *self.body, self.tcx).ty;
+                let base_ty = Place::ty_from(place_local, proj_base, *self.body, self.tcx).ty;
                 if let ty::RawPtr(_) = base_ty.kind {
                     if proj_base.is_empty() {
                         if let (local, []) = (place_local, proj_base) {
-                            let decl = &self.body.local_decls[*local];
+                            let decl = &self.body.local_decls[local];
                             if let LocalInfo::StaticRef { def_id, .. } = decl.local_info {
                                 let span = decl.source_info.span;
                                 self.check_static(def_id, span);
@@ -452,7 +453,7 @@ fn visit_projection_elem(
             | ProjectionElem::Subslice { .. }
             | ProjectionElem::Field(..)
             | ProjectionElem::Index(_) => {
-                let base_ty = Place::ty_from(*place_local, proj_base, *self.body, self.tcx).ty;
+                let base_ty = Place::ty_from(place_local, proj_base, *self.body, self.tcx).ty;
                 match base_ty.ty_adt_def() {
                     Some(def) if def.is_union() => {
                         self.check_op(ops::UnionAccess);
index 4dcbcdcbae4a65585fd2059bf948d67bbf3ab65f..437a154a9b80faa68eaeefe15d2466c7660b2400 100644 (file)
@@ -1,5 +1,3 @@
-use rustc::hir::map::Map;
-use rustc::lint::builtin::{SAFE_PACKED_BORROWS, UNUSED_UNSAFE};
 use rustc::mir::visit::{MutatingUseContext, PlaceContext, Visitor};
 use rustc::mir::*;
 use rustc::ty::cast::CastTy;
@@ -11,6 +9,7 @@
 use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit;
 use rustc_hir::Node;
+use rustc_session::lint::builtin::{SAFE_PACKED_BORROWS, UNUSED_UNSAFE};
 use rustc_span::symbol::{sym, Symbol};
 
 use std::ops::Bound;
@@ -451,9 +450,9 @@ struct UnusedUnsafeVisitor<'a> {
 }
 
 impl<'a, 'tcx> intravisit::Visitor<'tcx> for UnusedUnsafeVisitor<'a> {
-    type Map = Map<'tcx>;
+    type Map = intravisit::ErasedMap<'tcx>;
 
-    fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, Self::Map> {
+    fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
         intravisit::NestedVisitorMap::None
     }
 
index 654130c6fab9bdef3e780b00220d11506beb2149..ca23c44f64668f19fb61788009b8384fc85d0b3d 100644 (file)
@@ -4,7 +4,6 @@
 use std::borrow::Cow;
 use std::cell::Cell;
 
-use rustc::lint;
 use rustc::mir::interpret::{InterpResult, Scalar};
 use rustc::mir::visit::{
     MutVisitor, MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor,
 use rustc_ast::ast::Mutability;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::def::DefKind;
-use rustc_hir::def_id::DefId;
 use rustc_hir::HirId;
 use rustc_index::vec::IndexVec;
-use rustc_infer::traits;
+use rustc_session::lint;
 use rustc_span::Span;
+use rustc_trait_selection::traits;
 
 use crate::const_eval::error_to_const_error;
 use crate::interpret::{
@@ -198,7 +197,6 @@ fn call_intrinsic(
 
     fn assert_panic(
         _ecx: &mut InterpCx<'mir, 'tcx, Self>,
-        _span: Span,
         _msg: &rustc::mir::AssertMessage<'tcx>,
         _unwind: Option<rustc::mir::BasicBlock>,
     ) -> InterpResult<'tcx> {
@@ -222,13 +220,6 @@ fn binary_ptr_op(
         ));
     }
 
-    fn find_foreign_static(
-        _tcx: TyCtxt<'tcx>,
-        _def_id: DefId,
-    ) -> InterpResult<'tcx, Cow<'tcx, Allocation<Self::PointerTag>>> {
-        throw_unsup!(ReadForeignStatic)
-    }
-
     #[inline(always)]
     fn init_allocation_extra<'b>(
         _memory_extra: &(),
@@ -279,10 +270,6 @@ fn before_access_static(
         Ok(())
     }
 
-    fn before_terminator(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
-        Ok(())
-    }
-
     #[inline(always)]
     fn stack_push(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
         Ok(())
@@ -416,32 +403,15 @@ fn use_ecx<F, T>(&mut self, f: F) -> Option<T>
         let r = match f(self) {
             Ok(val) => Some(val),
             Err(error) => {
-                use rustc::mir::interpret::{
-                    InterpError::*, UndefinedBehaviorInfo, UnsupportedOpInfo,
-                };
-                match error.kind {
-                    MachineStop(_) => bug!("ConstProp does not stop"),
-
-                    // Some error shouldn't come up because creating them causes
-                    // an allocation, which we should avoid. When that happens,
-                    // dedicated error variants should be introduced instead.
-                    // Only test this in debug builds though to avoid disruptions.
-                    Unsupported(UnsupportedOpInfo::Unsupported(_))
-                    | Unsupported(UnsupportedOpInfo::ValidationFailure(_))
-                    | UndefinedBehavior(UndefinedBehaviorInfo::Ub(_))
-                    | UndefinedBehavior(UndefinedBehaviorInfo::UbExperimental(_))
-                        if cfg!(debug_assertions) =>
-                    {
-                        bug!("const-prop encountered allocating error: {:?}", error.kind);
-                    }
-
-                    Unsupported(_)
-                    | UndefinedBehavior(_)
-                    | InvalidProgram(_)
-                    | ResourceExhaustion(_) => {
-                        // Ignore these errors.
-                    }
-                }
+                // Some errors shouldn't come up because creating them causes
+                // an allocation, which we should avoid. When that happens,
+                // dedicated error variants should be introduced instead.
+                // Only test this in debug builds though to avoid disruptions.
+                debug_assert!(
+                    !error.kind.allocates(),
+                    "const-prop encountered allocating error: {}",
+                    error
+                );
                 None
             }
         };
@@ -557,7 +527,9 @@ fn check_binary_op(
             let left_ty = left.ty(&self.local_decls, self.tcx);
             let left_size_bits = self.ecx.layout_of(left_ty).ok()?.size.bits();
             let right_size = r.layout.size;
-            let r_bits = r.to_scalar().and_then(|r| r.to_bits(right_size));
+            let r_bits = r.to_scalar().ok();
+            // This is basically `force_bits`.
+            let r_bits = r_bits.and_then(|r| r.to_bits_or_ptr(right_size, &self.tcx).ok());
             if r_bits.map_or(false, |b| b >= left_size_bits as u128) {
                 self.report_assert_as_lint(
                     lint::builtin::ARITHMETIC_OVERFLOW,
@@ -664,17 +636,18 @@ fn replace_with_const(
         source_info: SourceInfo,
     ) {
         trace!("attepting to replace {:?} with {:?}", rval, value);
-        if let Err(e) = self.ecx.validate_operand(
+        if let Err(e) = self.ecx.const_validate_operand(
             value,
             vec![],
             // FIXME: is ref tracking too expensive?
-            Some(&mut interpret::RefTracking::empty()),
+            &mut interpret::RefTracking::empty(),
+            /*may_ref_to_static*/ true,
         ) {
             trace!("validation error, attempt failed: {:?}", e);
             return;
         }
 
-        // FIXME> figure out what tho do when try_read_immediate fails
+        // FIXME> figure out what to do when try_read_immediate fails
         let imm = self.use_ecx(|this| this.ecx.try_read_immediate(value));
 
         if let Some(Ok(imm)) = imm {
index 5dec2c6df99dcf6991488c8eb4435f533cdbab26..795bcb57d0678cc4aff9a4d01c5ecf1ed56913e4 100644 (file)
@@ -8,8 +8,8 @@
 use crate::transform::{MirPass, MirSource};
 use crate::util as mir_util;
 use rustc::mir::{Body, BodyAndCache};
-use rustc::session::config::{OutputFilenames, OutputType};
 use rustc::ty::TyCtxt;
+use rustc_session::config::{OutputFilenames, OutputType};
 
 pub struct Marker(pub &'static str);
 
index 3107be1b62207348c57ce3a649986713ba437b28..b2906739ff1b1de3ffcc86b7ea62188712f31b8c 100644 (file)
@@ -107,15 +107,15 @@ fn tcx(&self) -> TyCtxt<'tcx> {
     }
 
     fn visit_local(&mut self, local: &mut Local, _: PlaceContext, _: Location) {
-        assert_ne!(*local, self_arg());
+        assert_ne!(*local, SELF_ARG);
     }
 
     fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, location: Location) {
-        if place.local == self_arg() {
+        if place.local == SELF_ARG {
             replace_base(
                 place,
                 Place {
-                    local: self_arg(),
+                    local: SELF_ARG,
                     projection: self.tcx().intern_place_elems(&[ProjectionElem::Deref]),
                 },
                 self.tcx,
@@ -125,7 +125,7 @@ fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, locati
 
             for elem in place.projection.iter() {
                 if let PlaceElem::Index(local) = elem {
-                    assert_ne!(*local, self_arg());
+                    assert_ne!(*local, SELF_ARG);
                 }
             }
         }
@@ -143,15 +143,15 @@ fn tcx(&self) -> TyCtxt<'tcx> {
     }
 
     fn visit_local(&mut self, local: &mut Local, _: PlaceContext, _: Location) {
-        assert_ne!(*local, self_arg());
+        assert_ne!(*local, SELF_ARG);
     }
 
     fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, location: Location) {
-        if place.local == self_arg() {
+        if place.local == SELF_ARG {
             replace_base(
                 place,
                 Place {
-                    local: self_arg(),
+                    local: SELF_ARG,
                     projection: self.tcx().intern_place_elems(&[ProjectionElem::Field(
                         Field::new(0),
                         self.ref_gen_ty,
@@ -164,7 +164,7 @@ fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, locati
 
             for elem in place.projection.iter() {
                 if let PlaceElem::Index(local) = elem {
-                    assert_ne!(*local, self_arg());
+                    assert_ne!(*local, SELF_ARG);
                 }
             }
         }
@@ -180,9 +180,7 @@ fn replace_base<'tcx>(place: &mut Place<'tcx>, new_base: Place<'tcx>, tcx: TyCtx
     place.projection = tcx.intern_place_elems(&new_projection);
 }
 
-fn self_arg() -> Local {
-    Local::new(1)
-}
+const SELF_ARG: Local = Local::from_u32(1);
 
 /// Generator has not been resumed yet.
 const UNRESUMED: usize = GeneratorSubsts::UNRESUMED;
@@ -237,7 +235,7 @@ fn make_state(&self, idx: VariantIdx, val: Operand<'tcx>) -> Rvalue<'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 self_place = Place::from(SELF_ARG);
         let base = self.tcx.mk_place_downcast_unnamed(self_place, variant_index);
         let mut projection = base.projection.to_vec();
         projection.push(ProjectionElem::Field(Field::new(idx), ty));
@@ -247,7 +245,7 @@ fn make_field(&self, variant_index: VariantIdx, idx: usize, ty: Ty<'tcx>) -> Pla
 
     // Create a statement which changes the discriminant
     fn set_discr(&self, state_disc: VariantIdx, source_info: SourceInfo) -> Statement<'tcx> {
-        let self_place = Place::from(self_arg());
+        let self_place = Place::from(SELF_ARG);
         Statement {
             source_info,
             kind: StatementKind::SetDiscriminant {
@@ -263,7 +261,7 @@ fn get_discr(&self, body: &mut Body<'tcx>) -> (Statement<'tcx>, Place<'tcx>) {
         let local_decls_len = body.local_decls.push(temp_decl);
         let temp = Place::from(local_decls_len);
 
-        let self_place = Place::from(self_arg());
+        let self_place = Place::from(SELF_ARG);
         let assign = Statement {
             source_info: source_info(body),
             kind: StatementKind::Assign(box (temp, Rvalue::Discriminant(self_place))),
@@ -506,7 +504,7 @@ fn locals_live_across_suspend_points(
 
     for (block, data) in body.basic_blocks().iter_enumerated() {
         if let TerminatorKind::Yield { .. } = data.terminator().kind {
-            let loc = Location { block: block, statement_index: data.statements.len() };
+            let loc = Location { block, statement_index: data.statements.len() };
 
             if !movable {
                 // The `liveness` variable contains the liveness of MIR locals ignoring borrows.
@@ -539,8 +537,8 @@ fn locals_live_across_suspend_points(
             let mut live_locals_here = storage_required;
             live_locals_here.intersect(&liveness.outs[block]);
 
-            // The generator argument is ignored
-            live_locals_here.remove(self_arg());
+            // The generator argument is ignored.
+            live_locals_here.remove(SELF_ARG);
 
             debug!("loc = {:?}, live_locals_here = {:?}", loc, live_locals_here);
 
@@ -837,7 +835,6 @@ fn elaborate_generator_drops<'tcx>(
     // generator's resume function.
 
     let param_env = tcx.param_env(def_id);
-    let gen = self_arg();
 
     let mut elaborator = DropShimElaborator { body, patch: MirPatch::new(body), tcx, param_env };
 
@@ -845,7 +842,7 @@ fn elaborate_generator_drops<'tcx>(
         let (target, unwind, source_info) = match block_data.terminator() {
             Terminator { source_info, kind: TerminatorKind::Drop { location, target, unwind } } => {
                 if let Some(local) = location.as_local() {
-                    if local == gen {
+                    if local == SELF_ARG {
                         (target, unwind, source_info)
                     } else {
                         continue;
@@ -864,7 +861,7 @@ fn elaborate_generator_drops<'tcx>(
         elaborate_drop(
             &mut elaborator,
             *source_info,
-            &Place::from(gen),
+            &Place::from(SELF_ARG),
             (),
             *target,
             unwind,
@@ -918,7 +915,7 @@ fn create_generator_drop_shim<'tcx>(
     make_generator_state_argument_indirect(tcx, def_id, &mut body);
 
     // Change the generator argument from &mut to *mut
-    body.local_decls[self_arg()] = LocalDecl {
+    body.local_decls[SELF_ARG] = LocalDecl {
         mutability: Mutability::Mut,
         ty: tcx.mk_ptr(ty::TypeAndMut { ty: gen_ty, mutbl: hir::Mutability::Mut }),
         user_ty: UserTypeProjections::none(),
@@ -933,7 +930,7 @@ fn create_generator_drop_shim<'tcx>(
             0,
             Statement {
                 source_info,
-                kind: StatementKind::Retag(RetagKind::Raw, box Place::from(self_arg())),
+                kind: StatementKind::Retag(RetagKind::Raw, box Place::from(SELF_ARG)),
             },
         )
     }
@@ -944,7 +941,7 @@ fn create_generator_drop_shim<'tcx>(
     // unrelated code from the resume part of the function
     simplify::remove_dead_blocks(&mut body);
 
-    dump_mir(tcx, None, "generator_drop", &0, source, &mut body, |_, _| Ok(()));
+    dump_mir(tcx, None, "generator_drop", &0, source, &body, |_, _| Ok(()));
 
     body
 }
@@ -991,18 +988,101 @@ fn insert_panic_block<'tcx>(
     assert_block
 }
 
+fn can_return<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool {
+    // Returning from a function with an uninhabited return type is undefined behavior.
+    if body.return_ty().conservative_is_privately_uninhabited(tcx) {
+        return false;
+    }
+
+    // If there's a return terminator the function may return.
+    for block in body.basic_blocks() {
+        if let TerminatorKind::Return = block.terminator().kind {
+            return true;
+        }
+    }
+
+    // Otherwise the function can't return.
+    false
+}
+
+fn can_unwind<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool {
+    // Nothing can unwind when landing pads are off.
+    if tcx.sess.no_landing_pads() {
+        return false;
+    }
+
+    // Unwinds can only start at certain terminators.
+    for block in body.basic_blocks() {
+        match block.terminator().kind {
+            // These never unwind.
+            TerminatorKind::Goto { .. }
+            | TerminatorKind::SwitchInt { .. }
+            | TerminatorKind::Abort
+            | TerminatorKind::Return
+            | TerminatorKind::Unreachable
+            | TerminatorKind::GeneratorDrop
+            | TerminatorKind::FalseEdges { .. }
+            | TerminatorKind::FalseUnwind { .. } => {}
+
+            // Resume will *continue* unwinding, but if there's no other unwinding terminator it
+            // will never be reached.
+            TerminatorKind::Resume => {}
+
+            TerminatorKind::Yield { .. } => {
+                unreachable!("`can_unwind` called before generator transform")
+            }
+
+            // These may unwind.
+            TerminatorKind::Drop { .. }
+            | TerminatorKind::DropAndReplace { .. }
+            | TerminatorKind::Call { .. }
+            | TerminatorKind::Assert { .. } => return true,
+        }
+    }
+
+    // If we didn't find an unwinding terminator, the function cannot unwind.
+    false
+}
+
 fn create_generator_resume_function<'tcx>(
     tcx: TyCtxt<'tcx>,
     transform: TransformVisitor<'tcx>,
     def_id: DefId,
     source: MirSource<'tcx>,
     body: &mut BodyAndCache<'tcx>,
+    can_return: bool,
 ) {
+    let can_unwind = can_unwind(tcx, body);
+
     // Poison the generator when it unwinds
-    for block in body.basic_blocks_mut() {
-        let source_info = block.terminator().source_info;
-        if let &TerminatorKind::Resume = &block.terminator().kind {
-            block.statements.push(transform.set_discr(VariantIdx::new(POISONED), source_info));
+    if can_unwind {
+        let poison_block = BasicBlock::new(body.basic_blocks().len());
+        let source_info = source_info(body);
+        body.basic_blocks_mut().push(BasicBlockData {
+            statements: vec![transform.set_discr(VariantIdx::new(POISONED), source_info)],
+            terminator: Some(Terminator { source_info, kind: TerminatorKind::Resume }),
+            is_cleanup: true,
+        });
+
+        for (idx, block) in body.basic_blocks_mut().iter_enumerated_mut() {
+            let source_info = block.terminator().source_info;
+
+            if let TerminatorKind::Resume = block.terminator().kind {
+                // An existing `Resume` terminator is redirected to jump to our dedicated
+                // "poisoning block" above.
+                if idx != poison_block {
+                    *block.terminator_mut() = Terminator {
+                        source_info,
+                        kind: TerminatorKind::Goto { target: poison_block },
+                    };
+                }
+            } else if !block.is_cleanup {
+                // Any terminators that *can* unwind but don't have an unwind target set are also
+                // pointed at our poisoning block (unless they're part of the cleanup path).
+                if let Some(unwind @ None) = block.terminator_mut().unwind_mut() {
+                    *unwind = Some(poison_block);
+                }
+            }
         }
     }
 
@@ -1015,8 +1095,20 @@ fn create_generator_resume_function<'tcx>(
 
     // Panic when resumed on the returned or poisoned state
     let generator_kind = body.generator_kind.unwrap();
-    cases.insert(1, (RETURNED, insert_panic_block(tcx, body, ResumedAfterReturn(generator_kind))));
-    cases.insert(2, (POISONED, insert_panic_block(tcx, body, ResumedAfterPanic(generator_kind))));
+
+    if can_unwind {
+        cases.insert(
+            1,
+            (POISONED, insert_panic_block(tcx, body, ResumedAfterPanic(generator_kind))),
+        );
+    }
+
+    if can_return {
+        cases.insert(
+            1,
+            (RETURNED, insert_panic_block(tcx, body, ResumedAfterReturn(generator_kind))),
+        );
+    }
 
     insert_switch(body, cases, &transform, TerminatorKind::Unreachable);
 
@@ -1042,7 +1134,7 @@ fn insert_clean_drop(body: &mut BodyAndCache<'_>) -> BasicBlock {
     // Create a block to destroy an unresumed generators. This can only destroy upvars.
     let drop_clean = BasicBlock::new(body.basic_blocks().len());
     let term = TerminatorKind::Drop {
-        location: Place::from(self_arg()),
+        location: Place::from(SELF_ARG),
         target: return_block,
         unwind: None,
     };
@@ -1200,6 +1292,8 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut BodyAn
         let (remap, layout, storage_liveness) =
             compute_layout(tcx, source, &upvars, interior, movable, body);
 
+        let can_return = can_return(tcx, body);
+
         // Run the transformation which converts Places from Local to generator struct
         // accesses for locals in `remap`.
         // It also rewrites `return x` and `yield y` as writing a new generator state and returning
@@ -1243,6 +1337,6 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut BodyAn
         body.generator_drop = Some(box drop_shim);
 
         // Create the Generator::resume function
-        create_generator_resume_function(tcx, transform, def_id, source, body);
+        create_generator_resume_function(tcx, transform, def_id, source, body, can_return);
     }
 }
index b6802505df73f0b255f27c3b5c45e630e8f06baa..769f3fdcc013fcb64ca46389d1ec93f57213ca57 100644 (file)
@@ -1,25 +1,22 @@
 //! Inlining pass for MIR functions
 
-use rustc_hir::def_id::DefId;
-
-use rustc_index::bit_set::BitSet;
-use rustc_index::vec::{Idx, IndexVec};
-
 use rustc::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc::mir::visit::*;
 use rustc::mir::*;
-use rustc::session::config::Sanitizer;
 use rustc::ty::subst::{InternalSubsts, Subst, SubstsRef};
 use rustc::ty::{self, Instance, InstanceDef, ParamEnv, Ty, TyCtxt, TypeFoldable};
+use rustc_attr as attr;
+use rustc_hir::def_id::DefId;
+use rustc_index::bit_set::BitSet;
+use rustc_index::vec::{Idx, IndexVec};
+use rustc_session::config::Sanitizer;
+use rustc_target::spec::abi::Abi;
 
 use super::simplify::{remove_dead_blocks, CfgSimplifier};
 use crate::transform::{MirPass, MirSource};
 use std::collections::VecDeque;
 use std::iter;
 
-use rustc_attr as attr;
-use rustc_target::spec::abi::Abi;
-
 const DEFAULT_THRESHOLD: usize = 50;
 const HINT_THRESHOLD: usize = 100;
 
index 57e002bf3f3d65158b51d09a1c6c0b37befde2dd..3eb9d23a32a259472cc4e2d17c118dfc194f3799 100644 (file)
@@ -1,5 +1,4 @@
 use crate::{shim, util};
-use rustc::hir::map::Map;
 use rustc::mir::{BodyAndCache, ConstQualifs, MirPhase, Promoted};
 use rustc::ty::query::Providers;
 use rustc::ty::steal::Steal;
@@ -86,8 +85,8 @@ fn visit_variant_data(
             }
             intravisit::walk_struct_def(self, v)
         }
-        type Map = Map<'tcx>;
-        fn nested_visit_map<'b>(&'b mut self) -> NestedVisitorMap<'b, Self::Map> {
+        type Map = intravisit::ErasedMap<'tcx>;
+        fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
             NestedVisitorMap::None
         }
     }
index 286740f99dde681139e11cf83b572c1e1265be97..1336206e18626734d8e72090e8cabd217ad5c033 100644 (file)
@@ -407,15 +407,17 @@ fn validate_candidate(&self, candidate: Candidate) -> Result<(), Unpromotable> {
 
     // FIXME(eddyb) maybe cache this?
     fn qualif_local<Q: qualifs::Qualif>(&self, local: Local) -> bool {
-        let per_local = &mut |l| self.qualif_local::<Q>(l);
-
         if let TempState::Defined { location: loc, .. } = self.temps[local] {
             let num_stmts = self.body[loc.block].statements.len();
 
             if loc.statement_index < num_stmts {
                 let statement = &self.body[loc.block].statements[loc.statement_index];
                 match &statement.kind {
-                    StatementKind::Assign(box (_, rhs)) => Q::in_rvalue(&self.item, per_local, rhs),
+                    StatementKind::Assign(box (_, rhs)) => qualifs::in_rvalue::<Q, _>(
+                        &self.item,
+                        &mut |l| self.qualif_local::<Q>(l),
+                        rhs,
+                    ),
                     _ => {
                         span_bug!(
                             statement.source_info.span,
@@ -427,9 +429,9 @@ fn qualif_local<Q: qualifs::Qualif>(&self, local: Local) -> bool {
             } else {
                 let terminator = self.body[loc.block].terminator();
                 match &terminator.kind {
-                    TerminatorKind::Call { func, args, .. } => {
+                    TerminatorKind::Call { .. } => {
                         let return_ty = self.body.local_decls[local].ty;
-                        Q::in_call(&self.item, per_local, func, args, return_ty)
+                        Q::in_any_value_of_ty(&self.item, return_ty)
                     }
                     kind => {
                         span_bug!(terminator.source_info.span, "{:?} not promotable", kind);
@@ -474,7 +476,7 @@ fn validate_local(&self, local: Local) -> Result<(), Unpromotable> {
         }
     }
 
-    fn validate_place(&self, place: PlaceRef<'_, 'tcx>) -> Result<(), Unpromotable> {
+    fn validate_place(&self, place: PlaceRef<'tcx>) -> Result<(), Unpromotable> {
         match place {
             PlaceRef { local, projection: [] } => self.validate_local(local),
             PlaceRef { local: _, projection: [proj_base @ .., elem] } => {
@@ -920,7 +922,7 @@ fn promote_candidate(
             let (blocks, local_decls) = self.source.basic_blocks_and_local_decls_mut();
             match candidate {
                 Candidate::Ref(loc) => {
-                    let ref mut statement = blocks[loc.block].statements[loc.statement_index];
+                    let statement = &mut blocks[loc.block].statements[loc.statement_index];
                     match statement.kind {
                         StatementKind::Assign(box (
                             _,
@@ -971,7 +973,7 @@ fn promote_candidate(
                     }
                 }
                 Candidate::Repeat(loc) => {
-                    let ref mut statement = blocks[loc.block].statements[loc.statement_index];
+                    let statement = &mut blocks[loc.block].statements[loc.statement_index];
                     match statement.kind {
                         StatementKind::Assign(box (_, Rvalue::Repeat(ref mut operand, _))) => {
                             let ty = operand.ty(local_decls, self.tcx);
index 2ae7bd4d727294cface8ba81b2684cbaef01b8bd..22ac3410a75ab7d3458ee81a3aa88257adf94e22 100644 (file)
@@ -34,7 +34,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut BodyAndCa
         let attributes = tcx.get_attrs(def_id);
         let param_env = tcx.param_env(def_id);
         let move_data = MoveData::gather_moves(body, tcx, param_env).unwrap();
-        let mdpe = MoveDataParamEnv { move_data: move_data, param_env: param_env };
+        let mdpe = MoveDataParamEnv { move_data, param_env };
 
         let flow_inits = MaybeInitializedPlaces::new(tcx, body, &mdpe)
             .into_engine(tcx, body, def_id)
index ddf8d73e5481f82d1ecbccc8f8cb8defc2d2adf1..4c54a46642f11e3cecd151357d03a050a3b26526 100644 (file)
@@ -95,6 +95,11 @@ pub fn simplify(mut self) {
 
         let mut start = START_BLOCK;
 
+        // Vec of the blocks that should be merged. We store the indices here, instead of the
+        // statements itself to avoid moving the (relatively) large statements twice.
+        // We do not push the statements directly into the target block (`bb`) as that is slower
+        // due to additional reallocations
+        let mut merged_blocks = Vec::new();
         loop {
             let mut changed = false;
 
@@ -114,18 +119,28 @@ pub fn simplify(mut self) {
                     self.collapse_goto_chain(successor, &mut changed);
                 }
 
-                let mut new_stmts = vec![];
                 let mut inner_changed = true;
+                merged_blocks.clear();
                 while inner_changed {
                     inner_changed = false;
                     inner_changed |= self.simplify_branch(&mut terminator);
-                    inner_changed |= self.merge_successor(&mut new_stmts, &mut terminator);
+                    inner_changed |= self.merge_successor(&mut merged_blocks, &mut terminator);
                     changed |= inner_changed;
                 }
 
-                let data = &mut self.basic_blocks[bb];
-                data.statements.extend(new_stmts);
-                data.terminator = Some(terminator);
+                let statements_to_merge =
+                    merged_blocks.iter().map(|&i| self.basic_blocks[i].statements.len()).sum();
+
+                if statements_to_merge > 0 {
+                    let mut statements = std::mem::take(&mut self.basic_blocks[bb].statements);
+                    statements.reserve(statements_to_merge);
+                    for &from in &merged_blocks {
+                        statements.append(&mut self.basic_blocks[from].statements);
+                    }
+                    self.basic_blocks[bb].statements = statements;
+                }
+
+                self.basic_blocks[bb].terminator = Some(terminator);
 
                 changed |= inner_changed;
             }
@@ -199,7 +214,7 @@ fn collapse_goto_chain(&mut self, start: &mut BasicBlock, changed: &mut bool) {
     // merge a block with 1 `goto` predecessor to its parent
     fn merge_successor(
         &mut self,
-        new_stmts: &mut Vec<Statement<'tcx>>,
+        merged_blocks: &mut Vec<BasicBlock>,
         terminator: &mut Terminator<'tcx>,
     ) -> bool {
         let target = match terminator.kind {
@@ -216,7 +231,8 @@ fn merge_successor(
                 return false;
             }
         };
-        new_stmts.extend(self.basic_blocks[target].statements.drain(..));
+
+        merged_blocks.push(target);
         self.pred_count[target] = 0;
 
         true
@@ -230,7 +246,7 @@ fn simplify_branch(&mut self, terminator: &mut Terminator<'tcx>) -> bool {
         };
 
         let first_succ = {
-            if let Some(&first_succ) = terminator.successors().nth(0) {
+            if let Some(&first_succ) = terminator.successors().next() {
                 if terminator.successors().all(|s| *s == first_succ) {
                     let count = terminator.successors().count();
                     self.pred_count[first_succ] -= (count - 1) as u32;
index f7239ae55faa2494bda8deb268afbe5849a30bbd..ecf0a8ea83ca3654dce21574c09c820f3e10617e 100644 (file)
@@ -549,7 +549,7 @@ fn destructor_call_block(&mut self, (succ, unwind): (BasicBlock, Unwind)) -> Bas
         debug!("destructor_call_block({:?}, {:?})", self, succ);
         let tcx = self.tcx();
         let drop_trait = tcx.lang_items().drop_trait().unwrap();
-        let drop_fn = tcx.associated_items(drop_trait).in_definition_order().nth(0).unwrap();
+        let drop_fn = tcx.associated_items(drop_trait).in_definition_order().next().unwrap();
         let ty = self.place_ty(self.place);
         let substs = tcx.mk_substs_trait(ty, &[]);
 
@@ -731,7 +731,7 @@ fn open_drop_for_array(&mut self, ety: Ty<'tcx>, opt_size: Option<u64>) -> Basic
         self.elaborator.patch().new_block(base_block)
     }
 
-    /// Ceates a pair of drop-loops of `place`, which drops its contents, even
+    /// Creates a pair of drop-loops of `place`, which drops its contents, even
     /// in the case of 1 panic. If `ptr_based`, creates a pointer loop,
     /// otherwise create an index loop.
     fn drop_loop_pair(
@@ -872,7 +872,7 @@ fn drop_flag_reset_block(
         debug!("drop_flag_reset_block({:?},{:?})", self, mode);
 
         let block = self.new_block(unwind, TerminatorKind::Goto { target: succ });
-        let block_start = Location { block: block, statement_index: 0 };
+        let block_start = Location { block, statement_index: 0 };
         self.elaborator.clear_drop_flag(block_start, self.path, mode);
         block
     }
@@ -921,7 +921,7 @@ fn unelaborated_free_block(
 
         let call = TerminatorKind::Call {
             func: Operand::function_handle(tcx, free_func, substs, self.source_info.span),
-            args: args,
+            args,
             destination: Some((unit_temp, target)),
             cleanup: None,
             from_hir_call: false,
index b12ad1e4c15cca55f8bee1d39e1690a8de49ebc9..f6c6f55549593c6b57bf0586b527767411ffee56 100644 (file)
@@ -293,7 +293,7 @@ fn dump_matched_mir_node<'tcx>(
         writeln!(file, "// MIR local liveness analysis for `{}`", node_path)?;
         writeln!(file, "// source = {:?}", source)?;
         writeln!(file, "// pass_name = {}", pass_name)?;
-        writeln!(file, "")?;
+        writeln!(file)?;
         write_mir_fn(tcx, source, body, &mut file, result)?;
         Ok(())
     });
@@ -316,7 +316,7 @@ pub fn write_mir_fn<'tcx>(
         write_basic_block(tcx, block, body, &mut |_, _| Ok(()), w)?;
         print(w, "   ", &result.outs)?;
         if block.index() + 1 != body.basic_blocks().len() {
-            writeln!(w, "")?;
+            writeln!(w)?;
         }
     }
 
index 6fd8f06fe8f25c4ba35ec39ea4cf8b892dc3ec49..f8dfddef2bbd5a087e4ba08b4445fb37580c30f1 100644 (file)
@@ -134,7 +134,7 @@ fn dump_matched_mir_node<'tcx, F>(
         if let Some(ref layout) = body.generator_layout {
             writeln!(file, "// generator_layout = {:?}", layout)?;
         }
-        writeln!(file, "")?;
+        writeln!(file)?;
         extra_data(PassWhere::BeforeCFG, &mut file)?;
         write_user_type_annotations(body, &mut file)?;
         write_mir_fn(tcx, source, body, &mut extra_data, &mut file)?;
@@ -242,13 +242,13 @@ pub fn write_mir_pretty<'tcx>(
             first = false;
         } else {
             // Put empty lines between all items
-            writeln!(w, "")?;
+            writeln!(w)?;
         }
 
         write_mir_fn(tcx, MirSource::item(def_id), body, &mut |_, _| Ok(()), w)?;
 
         for (i, body) in tcx.promoted_mir(def_id).iter_enumerated() {
-            writeln!(w, "")?;
+            writeln!(w)?;
             let src = MirSource { instance: ty::InstanceDef::Item(def_id), promoted: Some(i) };
             write_mir_fn(tcx, src, body, &mut |_, _| Ok(()), w)?;
         }
@@ -271,7 +271,7 @@ pub fn write_mir_fn<'tcx, F>(
         extra_data(PassWhere::BeforeBlock(block), w)?;
         write_basic_block(tcx, block, body, extra_data, w)?;
         if block.index() + 1 != body.basic_blocks().len() {
-            writeln!(w, "")?;
+            writeln!(w)?;
         }
     }
 
@@ -297,7 +297,7 @@ pub fn write_basic_block<'tcx, F>(
     writeln!(w, "{}{:?}{}: {{", INDENT, block, cleanup_text)?;
 
     // List of statements in the middle.
-    let mut current_location = Location { block: block, statement_index: 0 };
+    let mut current_location = Location { block, statement_index: 0 };
     for statement in &data.statements {
         extra_data(PassWhere::BeforeLocation(current_location), w)?;
         let indented_body = format!("{0}{0}{1:?};", INDENT, statement);
@@ -490,7 +490,7 @@ fn write_scope_tree(
     }
 
     let children = match scope_tree.get(&parent) {
-        Some(childs) => childs,
+        Some(children) => children,
         None => return Ok(()),
     };
 
@@ -529,7 +529,7 @@ pub fn write_mir_intro<'tcx>(
     write_scope_tree(tcx, body, &scope_tree, w, OUTERMOST_SOURCE_SCOPE, 1)?;
 
     // Add an empty line before the first block is printed.
-    writeln!(w, "")?;
+    writeln!(w)?;
 
     Ok(())
 }
@@ -545,7 +545,7 @@ fn write_mir_sig(
     trace!("write_mir_sig: {:?}", src.instance);
     let kind = tcx.def_kind(src.def_id());
     let is_function = match kind {
-        Some(DefKind::Fn) | Some(DefKind::Method) | Some(DefKind::Ctor(..)) => true,
+        Some(DefKind::Fn) | Some(DefKind::AssocFn) | Some(DefKind::Ctor(..)) => true,
         _ => tcx.is_closure(src.def_id()),
     };
     match (kind, src.promoted) {
index d53188a39e5e092a1ca996f788c8d25604a40a00..96716dbd604d50801ed11f0f945e7d5e34ed004e 100644 (file)
@@ -25,5 +25,6 @@ rustc_serialize = { path = "../libserialize", package = "serialize" }
 rustc_session = { path = "../librustc_session" }
 rustc_span = { path = "../librustc_span" }
 rustc_target = { path = "../librustc_target" }
+rustc_trait_selection = { path = "../librustc_trait_selection" }
 rustc_ast = { path = "../librustc_ast" }
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
index 56aa150dd37d2f46db86dc8337dc4aa8f0107673..aea4f5f1b3ac90d099332e0a9b4944cbf352d7db 100644 (file)
@@ -113,7 +113,7 @@ fn simplify_match_pair<'pat>(
                 // value being matched, taking the variance field into account.
                 candidate.ascriptions.push(Ascription {
                     span: user_ty_span,
-                    user_ty: user_ty,
+                    user_ty,
                     source: match_pair.place,
                     variance,
                 });
@@ -209,7 +209,12 @@ fn simplify_match_pair<'pat>(
                     i == variant_index || {
                         self.hir.tcx().features().exhaustive_patterns
                             && !v
-                                .uninhabited_from(self.hir.tcx(), substs, adt_def.adt_kind())
+                                .uninhabited_from(
+                                    self.hir.tcx(),
+                                    substs,
+                                    adt_def.adt_kind(),
+                                    self.hir.param_env,
+                                )
                                 .is_empty()
                     }
                 }) && (adt_def.did.is_local()
index 9f450f8fc7b773874e126c464650715b5fbf6336..d23a2708dc478d2a2bdaf7a101e810757734886b 100644 (file)
@@ -64,10 +64,7 @@ pub(super) fn test<'pat>(&mut self, match_pair: &MatchPair<'pat, 'tcx>) -> Test<
             PatKind::Slice { ref prefix, ref slice, ref suffix } => {
                 let len = prefix.len() + suffix.len();
                 let op = if slice.is_some() { BinOp::Ge } else { BinOp::Eq };
-                Test {
-                    span: match_pair.pattern.span,
-                    kind: TestKind::Len { len: len as u64, op: op },
-                }
+                Test { span: match_pair.pattern.span, kind: TestKind::Len { len: len as u64, op } }
             }
 
             PatKind::Or { .. } => bug!("or-patterns should have already been handled"),
index 830877f713e4bb91730d6e5dd3d9973f2f46875b..821c4d68c7e8aaa93fa7acfdd5dbf5fbb5970214 100644 (file)
@@ -39,12 +39,12 @@ fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> BodyAndCache<'_> {
             ..
         })
         | Node::ImplItem(hir::ImplItem {
-            kind: hir::ImplItemKind::Method(hir::FnSig { decl, .. }, body_id),
+            kind: hir::ImplItemKind::Fn(hir::FnSig { decl, .. }, body_id),
             ..
         })
         | Node::TraitItem(hir::TraitItem {
             kind:
-                hir::TraitItemKind::Method(hir::FnSig { decl, .. }, hir::TraitMethod::Provided(body_id)),
+                hir::TraitItemKind::Fn(hir::FnSig { decl, .. }, hir::TraitFn::Provided(body_id)),
             ..
         }) => (*body_id, decl.output.span()),
         Node::Item(hir::Item { kind: hir::ItemKind::Static(ty, _, body_id), .. })
@@ -418,7 +418,7 @@ struct GuardFrameLocal {
 
 impl GuardFrameLocal {
     fn new(id: hir::HirId, _binding_mode: BindingMode) -> Self {
-        GuardFrameLocal { id: id }
+        GuardFrameLocal { id }
     }
 }
 
index a883b84f8fe2f2d07da2779d15d815d02ed691b8..8d7225c8c7b51ef3a883014dcf5106b91b173bfa 100644 (file)
@@ -84,7 +84,7 @@ fn mirror_stmts<'a, 'tcx>(
 
                 result.push(StmtRef::Mirror(Box::new(Stmt {
                     kind: StmtKind::Let {
-                        remainder_scope: remainder_scope,
+                        remainder_scope,
                         init_scope: region::Scope {
                             id: hir_id.local_id,
                             data: region::ScopeData::Node,
index 46d49b6b4933f863464a1635ad1fe97754cf94b6..02b596863ab4090b9026b72b4a4967559bbb89b4 100644 (file)
@@ -10,7 +10,6 @@
 use rustc::ty::{self, AdtKind, Ty};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
-use rustc_hir::def_id::LocalDefId;
 use rustc_index::vec::Idx;
 use rustc_span::Span;
 
@@ -600,7 +599,7 @@ fn user_substs_applied_to_res<'tcx>(
         // a tuple-struct or tuple-variant. This has the type of a
         // `Fn` but with the user-given substitutions.
         Res::Def(DefKind::Fn, _)
-        | Res::Def(DefKind::Method, _)
+        | Res::Def(DefKind::AssocFn, _)
         | Res::Def(DefKind::Ctor(_, CtorKind::Fn), _)
         | Res::Def(DefKind::Const, _)
         | Res::Def(DefKind::AssocConst, _) => {
@@ -703,7 +702,7 @@ fn convert_path_expr<'a, 'tcx>(
     match res {
         // A regular function, constructor function or a constant.
         Res::Def(DefKind::Fn, _)
-        | Res::Def(DefKind::Method, _)
+        | Res::Def(DefKind::AssocFn, _)
         | Res::Def(DefKind::Ctor(_, CtorKind::Fn), _)
         | Res::SelfCtor(..) => {
             let user_ty = user_substs_applied_to_res(cx, expr.hir_id, res);
@@ -812,7 +811,7 @@ fn convert_var<'tcx>(
             let closure_def_id = cx.body_owner;
             let upvar_id = ty::UpvarId {
                 var_path: ty::UpvarPath { hir_id: var_hir_id },
-                closure_expr_id: LocalDefId::from_def_id(closure_def_id),
+                closure_expr_id: closure_def_id.expect_local(),
             };
             let var_ty = cx.tables().node_type(var_hir_id);
 
@@ -987,7 +986,7 @@ fn capture_upvar<'tcx>(
 ) -> ExprRef<'tcx> {
     let upvar_id = ty::UpvarId {
         var_path: ty::UpvarPath { hir_id: var_hir_id },
-        closure_expr_id: cx.tcx.hir().local_def_id(closure_expr.hir_id).to_local(),
+        closure_expr_id: cx.tcx.hir().local_def_id(closure_expr.hir_id).expect_local(),
     };
     let upvar_capture = cx.tables().upvar_capture(upvar_id);
     let temp_lifetime = cx.region_scope_tree.temporary_scope(closure_expr.hir_id.local_id);
index 449e2e7494697a9552864de884cf1645a7619fb3..99caa6a0f95b48b3d475ae145090ea3e73359b32 100644 (file)
@@ -19,6 +19,7 @@
 use rustc_index::vec::Idx;
 use rustc_infer::infer::InferCtxt;
 use rustc_span::symbol::{sym, Symbol};
+use rustc_trait_selection::infer::InferCtxtExt;
 
 #[derive(Clone)]
 crate struct Cx<'a, 'tcx> {
index 90e4f53647846c531656230704a4cf92c986b5f5..82810f356759d4fdc68cdcd799e057dfe4860946 100644 (file)
 use super::{compare_const_vals, PatternFoldable, PatternFolder};
 use super::{FieldPat, Pat, PatKind, PatRange};
 
-use rustc::ty::layout::{Integer, IntegerExt, Size, VariantIdx};
-use rustc::ty::{self, Const, Ty, TyCtxt, TypeFoldable, VariantDef};
-use rustc_hir::def_id::DefId;
-use rustc_hir::{HirId, RangeEnd};
-
-use rustc::lint;
 use rustc::mir::interpret::{truncate, AllocId, ConstValue, Pointer, Scalar};
 use rustc::mir::Field;
+use rustc::ty::layout::{Integer, IntegerExt, Size, VariantIdx};
+use rustc::ty::{self, Const, Ty, TyCtxt, TypeFoldable, VariantDef};
 use rustc::util::common::ErrorReported;
-
 use rustc_attr::{SignedInt, UnsignedInt};
+use rustc_hir::def_id::DefId;
+use rustc_hir::{HirId, RangeEnd};
+use rustc_session::lint;
 use rustc_span::{Span, DUMMY_SP};
 
 use arena::TypedArena;
@@ -480,7 +478,11 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> {
     /// Pushes a new row to the matrix. If the row starts with an or-pattern, this expands it.
     crate fn push(&mut self, row: PatStack<'p, 'tcx>) {
         if let Some(rows) = row.expand_or_pat() {
-            self.0.extend(rows);
+            for row in rows {
+                // We recursively expand the or-patterns of the new rows.
+                // This is necessary as we might have `0 | (1 | 2)` or e.g., `x @ 0 | x @ (1 | 2)`.
+                self.push(row)
+            }
         } else {
             self.0.push(row);
         }
@@ -594,7 +596,7 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
 
     fn is_uninhabited(&self, ty: Ty<'tcx>) -> bool {
         if self.tcx.features().exhaustive_patterns {
-            self.tcx.is_ty_uninhabited_from(self.module, ty)
+            self.tcx.is_ty_uninhabited_from(self.module, ty, self.param_env)
         } else {
             false
         }
@@ -837,7 +839,7 @@ fn subtract_ctors(&self, other_ctors: &Vec<Constructor<'tcx>>) -> Vec<Constructo
                             // eliminate it straight away.
                             remaining_ranges = vec![];
                         } else {
-                            // Otherwise explicitely compute the remaining ranges.
+                            // Otherwise explicitly compute the remaining ranges.
                             remaining_ranges = other_range.subtract_from(remaining_ranges);
                         }
 
@@ -1000,7 +1002,7 @@ fn apply<'a>(
                         PatKind::Leaf { subpatterns }
                     }
                 }
-                ty::Ref(..) => PatKind::Deref { subpattern: subpatterns.nth(0).unwrap() },
+                ty::Ref(..) => PatKind::Deref { subpattern: subpatterns.next().unwrap() },
                 ty::Slice(_) | ty::Array(..) => bug!("bad slice pattern {:?} {:?}", self, ty),
                 _ => PatKind::Wild,
             },
@@ -1263,7 +1265,7 @@ fn all_constructors<'a, 'tcx>(
                 def.variants
                     .iter()
                     .filter(|v| {
-                        !v.uninhabited_from(cx.tcx, substs, def.adt_kind())
+                        !v.uninhabited_from(cx.tcx, substs, def.adt_kind(), cx.param_env)
                             .contains(cx.tcx, cx.module)
                     })
                     .map(|v| Variant(v.def_id))
@@ -1396,21 +1398,19 @@ fn from_const(
     ) -> Option<IntRange<'tcx>> {
         if let Some((target_size, bias)) = Self::integral_size_and_signed_bias(tcx, value.ty) {
             let ty = value.ty;
-            let val = if let ty::ConstKind::Value(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 = (|| {
+                if let ty::ConstKind::Value(ConstValue::Scalar(scalar)) = 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 fall through, which
+                    // is more general but much slower.)
+                    if let Ok(bits) = scalar.to_bits_or_ptr(target_size, &tcx) {
+                        return Some(bits);
+                    }
+                }
+                // This is a more general form of the previous case.
+                value.try_eval_bits(tcx, param_env, ty)
+            })()?;
             let val = val ^ bias;
             Some(IntRange { range: val..=val, ty, span })
         } else {
@@ -2333,7 +2333,7 @@ fn specialize_one_pattern<'p, 'tcx>(
         PatKind::Binding { .. } | PatKind::Wild => Some(ctor_wild_subpatterns.iter().collect()),
 
         PatKind::Variant { adt_def, variant_index, ref subpatterns, .. } => {
-            let ref variant = adt_def.variants[variant_index];
+            let variant = &adt_def.variants[variant_index];
             let is_non_exhaustive = cx.is_foreign_non_exhaustive_variant(pat.ty, variant);
             Some(Variant(variant.def_id))
                 .filter(|variant_constructor| variant_constructor == constructor)
index d0eefb2e4d14f0e4ecbab35bd3760cf93475dd64..9c86669cf9d929da307390d08eee390e0a6c03aa 100644 (file)
@@ -4,7 +4,6 @@
 
 use super::{PatCtxt, PatKind, PatternError};
 
-use rustc::hir::map::Map;
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc_ast::ast::Mutability;
 use rustc_errors::{error_code, struct_span_err, Applicability, DiagnosticBuilder};
@@ -43,9 +42,9 @@ struct MatchVisitor<'a, 'tcx> {
 }
 
 impl<'tcx> Visitor<'tcx> for MatchVisitor<'_, 'tcx> {
-    type Map = Map<'tcx>;
+    type Map = intravisit::ErasedMap<'tcx>;
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
         NestedVisitorMap::None
     }
 
@@ -87,6 +86,9 @@ fn report_inlining_errors(&self, pat_span: Span) {
                 PatternError::AssocConstInPattern(span) => {
                     self.span_e0158(span, "associated consts cannot be referenced in patterns")
                 }
+                PatternError::ConstParamInPattern(span) => {
+                    self.span_e0158(span, "const parameters cannot be referenced in patterns")
+                }
                 PatternError::FloatBug => {
                     // FIXME(#31407) this is only necessary because float parsing is buggy
                     ::rustc::mir::interpret::struct_error(
@@ -143,7 +145,7 @@ fn lower_pattern<'p>(
 
     fn check_in_cx(&self, hir_id: HirId, f: impl FnOnce(MatchCheckCtxt<'_, 'tcx>)) {
         let module = self.tcx.parent_module(hir_id);
-        MatchCheckCtxt::create_and_enter(self.tcx, self.param_env, module, |cx| f(cx));
+        MatchCheckCtxt::create_and_enter(self.tcx, self.param_env, module.to_def_id(), |cx| f(cx));
     }
 
     fn check_match(
@@ -750,9 +752,9 @@ struct AtBindingPatternVisitor<'a, 'b, 'tcx> {
     }
 
     impl<'v> Visitor<'v> for AtBindingPatternVisitor<'_, '_, '_> {
-        type Map = Map<'v>;
+        type Map = intravisit::ErasedMap<'v>;
 
-        fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
+        fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
             NestedVisitorMap::None
         }
 
index 27d1bce76edc5f3003a1413c6c6c61f70c296ab2..ae951e810e32e6cc09e1c8b0dd0455d59e01981a 100644 (file)
@@ -1,14 +1,13 @@
-use rustc::lint;
 use rustc::mir::Field;
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc_hir as hir;
-use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
-use rustc_infer::traits::predicate_for_trait_def;
-use rustc_infer::traits::{self, ObligationCause, PredicateObligation};
-
 use rustc_index::vec::Idx;
-
+use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
+use rustc_session::lint;
 use rustc_span::Span;
+use rustc_trait_selection::traits::predicate_for_trait_def;
+use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
+use rustc_trait_selection::traits::{self, ObligationCause, PredicateObligation};
 
 use std::cell::Cell;
 
@@ -181,7 +180,7 @@ fn recur(&self, cv: &'tcx ty::Const<'tcx>) -> Pat<'tcx> {
         let kind = match cv.ty.kind {
             ty::Float(_) => {
                 tcx.struct_span_lint_hir(
-                    ::rustc::lint::builtin::ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
+                    lint::builtin::ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
                     id,
                     span,
                     |lint| lint.build("floating-point types cannot be used in patterns").emit(),
index f58216fbb4e76bfdf4c722500d3e0197ded7ab6b..6786c3562930840d5411ce940d0e90393ec96439 100644 (file)
@@ -31,6 +31,7 @@
 #[derive(Clone, Debug)]
 crate enum PatternError {
     AssocConstInPattern(Span),
+    ConstParamInPattern(Span),
     StaticInPattern(Span),
     FloatBug,
     NonConstPath(Span),
@@ -727,7 +728,11 @@ fn lower_variant_or_leaf(
             | Res::SelfCtor(..) => PatKind::Leaf { subpatterns },
 
             _ => {
-                self.errors.push(PatternError::NonConstPath(span));
+                let pattern_error = match res {
+                    Res::Def(DefKind::ConstParam, _) => PatternError::ConstParamInPattern(span),
+                    _ => PatternError::NonConstPath(span),
+                };
+                self.errors.push(pattern_error);
                 PatKind::Wild
             }
         };
index 3c35827d15d3e66ac34ea0eb6c753979cf527109..5a8b5a329634d0f28242cbeeaac505be4ec49b0a 100644 (file)
@@ -4,6 +4,9 @@
 
 #![feature(box_patterns)]
 #![feature(box_syntax)]
+#![feature(const_if_match)]
+#![feature(const_fn)]
+#![feature(const_panic)]
 #![feature(crate_visibility_modifier)]
 #![feature(bool_to_option)]
 #![recursion_limit = "256"]
index 0017f800de7021ec0b5a2ea52274595c9de08426..8b1ddf7461a766a01b65bb65fa326cf9fed36c39 100644 (file)
@@ -1,11 +1,11 @@
 use rustc::hir::map::blocks::FnLikeNode;
-use rustc::lint::builtin::UNCONDITIONAL_RECURSION;
 use rustc::mir::{self, Body, TerminatorKind};
 use rustc::ty::subst::InternalSubsts;
 use rustc::ty::{self, AssocItem, AssocItemContainer, Instance, TyCtxt};
 use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::FnKind;
 use rustc_index::bit_set::BitSet;
+use rustc_session::lint::builtin::UNCONDITIONAL_RECURSION;
 
 crate fn check<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, def_id: DefId) {
     let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
diff --git a/src/librustc_parse/config.rs b/src/librustc_parse/config.rs
deleted file mode 100644 (file)
index 17b9e78..0000000
+++ /dev/null
@@ -1,549 +0,0 @@
-//! Process the potential `cfg` attributes on a module.
-//! Also determine if the module should be included in this configuration.
-//!
-//! This module properly belongs in rustc_expand, but for now it's tied into
-//! parsing, so we leave it here to avoid complicated out-of-line dependencies.
-//!
-//! A principled solution to this wrong location would be to implement [#64197].
-//!
-//! [#64197]: https://github.com/rust-lang/rust/issues/64197
-
-use crate::{parse_in, validate_attr};
-use rustc_ast::ast::{self, AttrItem, Attribute, MetaItem};
-use rustc_ast::attr::HasAttrs;
-use rustc_ast::mut_visit::*;
-use rustc_ast::ptr::P;
-use rustc_ast::util::map_in_place::MapInPlace;
-use rustc_attr as attr;
-use rustc_data_structures::fx::FxHashMap;
-use rustc_errors::{error_code, struct_span_err, Applicability, Handler};
-use rustc_feature::{Feature, Features, State as FeatureState};
-use rustc_feature::{
-    ACCEPTED_FEATURES, ACTIVE_FEATURES, REMOVED_FEATURES, STABLE_REMOVED_FEATURES,
-};
-use rustc_session::parse::{feature_err, ParseSess};
-use rustc_span::edition::{Edition, ALL_EDITIONS};
-use rustc_span::symbol::{sym, Symbol};
-use rustc_span::{Span, DUMMY_SP};
-
-use smallvec::SmallVec;
-
-/// A folder that strips out items that do not belong in the current configuration.
-pub struct StripUnconfigured<'a> {
-    pub sess: &'a ParseSess,
-    pub features: Option<&'a Features>,
-}
-
-fn get_features(
-    span_handler: &Handler,
-    krate_attrs: &[ast::Attribute],
-    crate_edition: Edition,
-    allow_features: &Option<Vec<String>>,
-) -> Features {
-    fn feature_removed(span_handler: &Handler, span: Span, reason: Option<&str>) {
-        let mut err = struct_span_err!(span_handler, span, E0557, "feature has been removed");
-        err.span_label(span, "feature has been removed");
-        if let Some(reason) = reason {
-            err.note(reason);
-        }
-        err.emit();
-    }
-
-    fn active_features_up_to(edition: Edition) -> impl Iterator<Item = &'static Feature> {
-        ACTIVE_FEATURES.iter().filter(move |feature| {
-            if let Some(feature_edition) = feature.edition {
-                feature_edition <= edition
-            } else {
-                false
-            }
-        })
-    }
-
-    let mut features = Features::default();
-    let mut edition_enabled_features = FxHashMap::default();
-
-    for &edition in ALL_EDITIONS {
-        if edition <= crate_edition {
-            // The `crate_edition` implies its respective umbrella feature-gate
-            // (i.e., `#![feature(rust_20XX_preview)]` isn't needed on edition 20XX).
-            edition_enabled_features.insert(edition.feature_name(), edition);
-        }
-    }
-
-    for feature in active_features_up_to(crate_edition) {
-        feature.set(&mut features, DUMMY_SP);
-        edition_enabled_features.insert(feature.name, crate_edition);
-    }
-
-    // Process the edition umbrella feature-gates first, to ensure
-    // `edition_enabled_features` is completed before it's queried.
-    for attr in krate_attrs {
-        if !attr.check_name(sym::feature) {
-            continue;
-        }
-
-        let list = match attr.meta_item_list() {
-            Some(list) => list,
-            None => continue,
-        };
-
-        for mi in list {
-            if !mi.is_word() {
-                continue;
-            }
-
-            let name = mi.name_or_empty();
-
-            let edition = ALL_EDITIONS.iter().find(|e| name == e.feature_name()).copied();
-            if let Some(edition) = edition {
-                if edition <= crate_edition {
-                    continue;
-                }
-
-                for feature in active_features_up_to(edition) {
-                    // FIXME(Manishearth) there is currently no way to set
-                    // lib features by edition
-                    feature.set(&mut features, DUMMY_SP);
-                    edition_enabled_features.insert(feature.name, edition);
-                }
-            }
-        }
-    }
-
-    for attr in krate_attrs {
-        if !attr.check_name(sym::feature) {
-            continue;
-        }
-
-        let list = match attr.meta_item_list() {
-            Some(list) => list,
-            None => continue,
-        };
-
-        let bad_input = |span| {
-            struct_span_err!(span_handler, span, E0556, "malformed `feature` attribute input")
-        };
-
-        for mi in list {
-            let name = match mi.ident() {
-                Some(ident) if mi.is_word() => ident.name,
-                Some(ident) => {
-                    bad_input(mi.span())
-                        .span_suggestion(
-                            mi.span(),
-                            "expected just one word",
-                            format!("{}", ident.name),
-                            Applicability::MaybeIncorrect,
-                        )
-                        .emit();
-                    continue;
-                }
-                None => {
-                    bad_input(mi.span()).span_label(mi.span(), "expected just one word").emit();
-                    continue;
-                }
-            };
-
-            if let Some(edition) = edition_enabled_features.get(&name) {
-                let msg =
-                    &format!("the feature `{}` is included in the Rust {} edition", name, edition);
-                span_handler.struct_span_warn_with_code(mi.span(), msg, error_code!(E0705)).emit();
-                continue;
-            }
-
-            if ALL_EDITIONS.iter().any(|e| name == e.feature_name()) {
-                // Handled in the separate loop above.
-                continue;
-            }
-
-            let removed = REMOVED_FEATURES.iter().find(|f| name == f.name);
-            let stable_removed = STABLE_REMOVED_FEATURES.iter().find(|f| name == f.name);
-            if let Some(Feature { state, .. }) = removed.or(stable_removed) {
-                if let FeatureState::Removed { reason } | FeatureState::Stabilized { reason } =
-                    state
-                {
-                    feature_removed(span_handler, mi.span(), *reason);
-                    continue;
-                }
-            }
-
-            if let Some(Feature { since, .. }) = ACCEPTED_FEATURES.iter().find(|f| name == f.name) {
-                let since = Some(Symbol::intern(since));
-                features.declared_lang_features.push((name, mi.span(), since));
-                continue;
-            }
-
-            if let Some(allowed) = allow_features.as_ref() {
-                if allowed.iter().find(|&f| name.as_str() == *f).is_none() {
-                    struct_span_err!(
-                        span_handler,
-                        mi.span(),
-                        E0725,
-                        "the feature `{}` is not in the list of allowed features",
-                        name
-                    )
-                    .emit();
-                    continue;
-                }
-            }
-
-            if let Some(f) = ACTIVE_FEATURES.iter().find(|f| name == f.name) {
-                f.set(&mut features, mi.span());
-                features.declared_lang_features.push((name, mi.span(), None));
-                continue;
-            }
-
-            features.declared_lib_features.push((name, mi.span()));
-        }
-    }
-
-    features
-}
-
-// `cfg_attr`-process the crate's attributes and compute the crate's features.
-pub fn features(
-    mut krate: ast::Crate,
-    sess: &ParseSess,
-    edition: Edition,
-    allow_features: &Option<Vec<String>>,
-) -> (ast::Crate, Features) {
-    let mut strip_unconfigured = StripUnconfigured { sess, features: None };
-
-    let unconfigured_attrs = krate.attrs.clone();
-    let diag = &sess.span_diagnostic;
-    let err_count = diag.err_count();
-    let features = match strip_unconfigured.configure(krate.attrs) {
-        None => {
-            // The entire crate is unconfigured.
-            krate.attrs = Vec::new();
-            krate.module.items = Vec::new();
-            Features::default()
-        }
-        Some(attrs) => {
-            krate.attrs = attrs;
-            let features = get_features(diag, &krate.attrs, edition, allow_features);
-            if err_count == diag.err_count() {
-                // Avoid reconfiguring malformed `cfg_attr`s.
-                strip_unconfigured.features = Some(&features);
-                strip_unconfigured.configure(unconfigured_attrs);
-            }
-            features
-        }
-    };
-    (krate, features)
-}
-
-#[macro_export]
-macro_rules! configure {
-    ($this:ident, $node:ident) => {
-        match $this.configure($node) {
-            Some(node) => node,
-            None => return Default::default(),
-        }
-    };
-}
-
-const CFG_ATTR_GRAMMAR_HELP: &str = "#[cfg_attr(condition, attribute, other_attribute, ...)]";
-const CFG_ATTR_NOTE_REF: &str = "for more information, visit \
-    <https://doc.rust-lang.org/reference/conditional-compilation.html\
-    #the-cfg_attr-attribute>";
-
-impl<'a> StripUnconfigured<'a> {
-    pub fn configure<T: HasAttrs>(&mut self, mut node: T) -> Option<T> {
-        self.process_cfg_attrs(&mut node);
-        self.in_cfg(node.attrs()).then_some(node)
-    }
-
-    /// Parse and expand all `cfg_attr` attributes into a list of attributes
-    /// that are within each `cfg_attr` that has a true configuration predicate.
-    ///
-    /// Gives compiler warnigns if any `cfg_attr` does not contain any
-    /// attributes and is in the original source code. Gives compiler errors if
-    /// the syntax of any `cfg_attr` is incorrect.
-    pub fn process_cfg_attrs<T: HasAttrs>(&mut self, node: &mut T) {
-        node.visit_attrs(|attrs| {
-            attrs.flat_map_in_place(|attr| self.process_cfg_attr(attr));
-        });
-    }
-
-    /// Parse and expand a single `cfg_attr` attribute into a list of attributes
-    /// when the configuration predicate is true, or otherwise expand into an
-    /// empty list of attributes.
-    ///
-    /// Gives a compiler warning when the `cfg_attr` contains no attributes and
-    /// is in the original source file. Gives a compiler error if the syntax of
-    /// the attribute is incorrect.
-    fn process_cfg_attr(&mut self, attr: Attribute) -> Vec<Attribute> {
-        if !attr.has_name(sym::cfg_attr) {
-            return vec![attr];
-        }
-
-        let (cfg_predicate, expanded_attrs) = match self.parse_cfg_attr(&attr) {
-            None => return vec![],
-            Some(r) => r,
-        };
-
-        // Lint on zero attributes in source.
-        if expanded_attrs.is_empty() {
-            return vec![attr];
-        }
-
-        // At this point we know the attribute is considered used.
-        attr::mark_used(&attr);
-
-        if !attr::cfg_matches(&cfg_predicate, self.sess, self.features) {
-            return vec![];
-        }
-
-        // We call `process_cfg_attr` recursively in case there's 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)| {
-                let attr = attr::mk_attr_from_item(attr.style, item, span);
-                self.process_cfg_attr(attr)
-            })
-            .collect()
-    }
-
-    fn parse_cfg_attr(&self, attr: &Attribute) -> Option<(MetaItem, Vec<(AttrItem, Span)>)> {
-        match attr.get_normal_item().args {
-            ast::MacArgs::Delimited(dspan, delim, ref tts) if !tts.is_empty() => {
-                let msg = "wrong `cfg_attr` delimiters";
-                validate_attr::check_meta_bad_delim(self.sess, dspan, delim, msg);
-                match parse_in(self.sess, tts.clone(), "`cfg_attr` input", |p| p.parse_cfg_attr()) {
-                    Ok(r) => return Some(r),
-                    Err(mut e) => {
-                        e.help(&format!("the valid syntax is `{}`", CFG_ATTR_GRAMMAR_HELP))
-                            .note(CFG_ATTR_NOTE_REF)
-                            .emit();
-                    }
-                }
-            }
-            _ => self.error_malformed_cfg_attr_missing(attr.span),
-        }
-        None
-    }
-
-    fn error_malformed_cfg_attr_missing(&self, span: Span) {
-        self.sess
-            .span_diagnostic
-            .struct_span_err(span, "malformed `cfg_attr` attribute input")
-            .span_suggestion(
-                span,
-                "missing condition and attribute",
-                CFG_ATTR_GRAMMAR_HELP.to_string(),
-                Applicability::HasPlaceholders,
-            )
-            .note(CFG_ATTR_NOTE_REF)
-            .emit();
-    }
-
-    /// Determines if a node with the given attributes should be included in this configuration.
-    pub fn in_cfg(&self, attrs: &[Attribute]) -> bool {
-        attrs.iter().all(|attr| {
-            if !is_cfg(attr) {
-                return true;
-            }
-            let meta_item = match validate_attr::parse_meta(self.sess, attr) {
-                Ok(meta_item) => meta_item,
-                Err(mut err) => {
-                    err.emit();
-                    return true;
-                }
-            };
-            let error = |span, msg, suggestion: &str| {
-                let mut err = self.sess.span_diagnostic.struct_span_err(span, msg);
-                if !suggestion.is_empty() {
-                    err.span_suggestion(
-                        span,
-                        "expected syntax is",
-                        suggestion.into(),
-                        Applicability::MaybeIncorrect,
-                    );
-                }
-                err.emit();
-                true
-            };
-            let span = meta_item.span;
-            match meta_item.meta_item_list() {
-                None => error(span, "`cfg` is not followed by parentheses", "cfg(/* predicate */)"),
-                Some([]) => error(span, "`cfg` predicate is not specified", ""),
-                Some([_, .., l]) => error(l.span(), "multiple `cfg` predicates are specified", ""),
-                Some([single]) => match single.meta_item() {
-                    Some(meta_item) => attr::cfg_matches(meta_item, self.sess, self.features),
-                    None => error(single.span(), "`cfg` predicate key cannot be a literal", ""),
-                },
-            }
-        })
-    }
-
-    /// Visit attributes on expression and statements (but not attributes on items in blocks).
-    fn visit_expr_attrs(&mut self, attrs: &[Attribute]) {
-        // flag the offending attributes
-        for attr in attrs.iter() {
-            self.maybe_emit_expr_attr_err(attr);
-        }
-    }
-
-    /// If attributes are not allowed on expressions, emit an error for `attr`
-    pub fn maybe_emit_expr_attr_err(&self, attr: &Attribute) {
-        if !self.features.map(|features| features.stmt_expr_attributes).unwrap_or(true) {
-            let mut err = feature_err(
-                self.sess,
-                sym::stmt_expr_attributes,
-                attr.span,
-                "attributes on expressions are experimental",
-            );
-
-            if attr.is_doc_comment() {
-                err.help("`///` is for documentation comments. For a plain comment, use `//`.");
-            }
-
-            err.emit();
-        }
-    }
-
-    pub fn configure_foreign_mod(&mut self, foreign_mod: &mut ast::ForeignMod) {
-        let ast::ForeignMod { abi: _, items } = foreign_mod;
-        items.flat_map_in_place(|item| self.configure(item));
-    }
-
-    pub fn configure_generic_params(&mut self, params: &mut Vec<ast::GenericParam>) {
-        params.flat_map_in_place(|param| self.configure(param));
-    }
-
-    fn configure_variant_data(&mut self, vdata: &mut ast::VariantData) {
-        match vdata {
-            ast::VariantData::Struct(fields, ..) | ast::VariantData::Tuple(fields, _) => {
-                fields.flat_map_in_place(|field| self.configure(field))
-            }
-            ast::VariantData::Unit(_) => {}
-        }
-    }
-
-    pub fn configure_item_kind(&mut self, item: &mut ast::ItemKind) {
-        match item {
-            ast::ItemKind::Struct(def, _generics) | ast::ItemKind::Union(def, _generics) => {
-                self.configure_variant_data(def)
-            }
-            ast::ItemKind::Enum(ast::EnumDef { variants }, _generics) => {
-                variants.flat_map_in_place(|variant| self.configure(variant));
-                for variant in variants {
-                    self.configure_variant_data(&mut variant.data);
-                }
-            }
-            _ => {}
-        }
-    }
-
-    pub fn configure_expr_kind(&mut self, expr_kind: &mut ast::ExprKind) {
-        match expr_kind {
-            ast::ExprKind::Match(_m, arms) => {
-                arms.flat_map_in_place(|arm| self.configure(arm));
-            }
-            ast::ExprKind::Struct(_path, fields, _base) => {
-                fields.flat_map_in_place(|field| self.configure(field));
-            }
-            _ => {}
-        }
-    }
-
-    pub fn configure_expr(&mut self, expr: &mut P<ast::Expr>) {
-        self.visit_expr_attrs(expr.attrs());
-
-        // If an expr is valid to cfg away it will have been removed by the
-        // outer stmt or expression folder before descending in here.
-        // Anything else is always required, and thus has to error out
-        // in case of a cfg attr.
-        //
-        // N.B., this is intentionally not part of the visit_expr() function
-        //     in order for filter_map_expr() to be able to avoid this check
-        if let Some(attr) = expr.attrs().iter().find(|a| is_cfg(a)) {
-            let msg = "removing an expression is not supported in this position";
-            self.sess.span_diagnostic.span_err(attr.span, msg);
-        }
-
-        self.process_cfg_attrs(expr)
-    }
-
-    pub fn configure_pat(&mut self, pat: &mut P<ast::Pat>) {
-        if let ast::PatKind::Struct(_path, fields, _etc) = &mut pat.kind {
-            fields.flat_map_in_place(|field| self.configure(field));
-        }
-    }
-
-    pub fn configure_fn_decl(&mut self, fn_decl: &mut ast::FnDecl) {
-        fn_decl.inputs.flat_map_in_place(|arg| self.configure(arg));
-    }
-}
-
-impl<'a> MutVisitor for StripUnconfigured<'a> {
-    fn visit_foreign_mod(&mut self, foreign_mod: &mut ast::ForeignMod) {
-        self.configure_foreign_mod(foreign_mod);
-        noop_visit_foreign_mod(foreign_mod, self);
-    }
-
-    fn visit_item_kind(&mut self, item: &mut ast::ItemKind) {
-        self.configure_item_kind(item);
-        noop_visit_item_kind(item, self);
-    }
-
-    fn visit_expr(&mut self, expr: &mut P<ast::Expr>) {
-        self.configure_expr(expr);
-        self.configure_expr_kind(&mut expr.kind);
-        noop_visit_expr(expr, self);
-    }
-
-    fn filter_map_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
-        let mut expr = configure!(self, expr);
-        self.configure_expr_kind(&mut expr.kind);
-        noop_visit_expr(&mut expr, self);
-        Some(expr)
-    }
-
-    fn flat_map_stmt(&mut self, stmt: ast::Stmt) -> SmallVec<[ast::Stmt; 1]> {
-        noop_flat_map_stmt(configure!(self, stmt), self)
-    }
-
-    fn flat_map_item(&mut self, item: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
-        noop_flat_map_item(configure!(self, item), self)
-    }
-
-    fn flat_map_impl_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
-        noop_flat_map_assoc_item(configure!(self, item), self)
-    }
-
-    fn flat_map_trait_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
-        noop_flat_map_assoc_item(configure!(self, item), self)
-    }
-
-    fn visit_mac(&mut self, _mac: &mut ast::Mac) {
-        // Don't configure interpolated AST (cf. issue #34171).
-        // Interpolated AST will get configured once the surrounding tokens are parsed.
-    }
-
-    fn visit_pat(&mut self, pat: &mut P<ast::Pat>) {
-        self.configure_pat(pat);
-        noop_visit_pat(pat, self)
-    }
-
-    fn visit_fn_decl(&mut self, mut fn_decl: &mut P<ast::FnDecl>) {
-        self.configure_fn_decl(&mut fn_decl);
-        noop_visit_fn_decl(fn_decl, self);
-    }
-}
-
-fn is_cfg(attr: &Attribute) -> bool {
-    attr.check_name(sym::cfg)
-}
-
-/// Process the potential `cfg` attributes on a module.
-/// Also determine if the module should be included in this configuration.
-pub fn process_configure_mod(sess: &ParseSess, cfg_mods: bool, attrs: &mut Vec<Attribute>) -> bool {
-    // Don't perform gated feature checking.
-    let mut strip_unconfigured = StripUnconfigured { sess, features: None };
-    strip_unconfigured.process_cfg_attrs(attrs);
-    !cfg_mods || strip_unconfigured.in_cfg(&attrs)
-}
index 6c0acd0302fb1a7a1d2e7764383b0af988df4590..b65b894172844ccbdccb8f1ad221079138365472 100644 (file)
@@ -40,6 +40,7 @@ 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<Span>,
+    /// Collect empty block spans that might have been auto-inserted by editors.
     last_delim_empty_block_spans: FxHashMap<token::DelimToken, Span>,
 }
 
@@ -138,7 +139,11 @@ fn parse_token_tree(&mut self) -> PResult<'a, TreeAndJoint> {
 
                         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 !sm.is_multiline(empty_block_span) {
+                                // Only track if the block is in the form of `{}`, otherwise it is
+                                // likely that it was written on purpose.
+                                self.last_delim_empty_block_spans.insert(delim, empty_block_span);
+                            }
                         }
 
                         if self.open_braces.is_empty() {
index 25f9f8fd3ad4f076359896e5870be8b05f80e705..c31cc1b4c9f00b4d0263a091a0c5fb21dce439cf 100644 (file)
@@ -2,9 +2,11 @@
 
 #![feature(bool_to_option)]
 #![feature(crate_visibility_modifier)]
+#![feature(bindings_after_at)]
+#![feature(try_blocks)]
 
 use rustc_ast::ast;
-use rustc_ast::token::{self, Nonterminal, Token};
+use rustc_ast::token::{self, Nonterminal};
 use rustc_ast::tokenstream::{self, TokenStream, TokenTree};
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::sync::Lrc;
@@ -12,7 +14,7 @@
 use rustc_session::parse::ParseSess;
 use rustc_span::{FileName, SourceFile, Span};
 
-use std::path::{Path, PathBuf};
+use std::path::Path;
 use std::str;
 
 use log::info;
 use parser::{emit_unclosed_delims, make_unclosed_delims_error, Parser};
 pub mod lexer;
 pub mod validate_attr;
-#[macro_use]
-pub mod config;
-
-#[derive(Clone)]
-pub struct Directory {
-    pub path: PathBuf,
-    pub ownership: DirectoryOwnership,
-}
-
-#[derive(Copy, Clone)]
-pub enum DirectoryOwnership {
-    Owned {
-        // None if `mod.rs`, `Some("foo")` if we're in `foo.rs`.
-        relative: Option<ast::Ident>,
-    },
-    UnownedViaBlock,
-    UnownedViaMod,
-}
 
 // A bunch of utility functions of the form `parse_<thing>_from_<source>`
 // where <thing> includes crate, expr, item, stmt, tts, and one that
@@ -118,10 +102,7 @@ pub fn maybe_new_parser_from_source_str(
     name: FileName,
     source: String,
 ) -> Result<Parser<'_>, Vec<Diagnostic>> {
-    let mut parser =
-        maybe_source_file_to_parser(sess, sess.source_map().new_source_file(name, source))?;
-    parser.recurse_into_file_modules = false;
-    Ok(parser)
+    maybe_source_file_to_parser(sess, sess.source_map().new_source_file(name, source))
 }
 
 /// Creates a new parser, handling errors as appropriate if the file doesn't exist.
@@ -145,12 +126,10 @@ pub fn maybe_new_parser_from_file<'a>(
 pub fn new_sub_parser_from_file<'a>(
     sess: &'a ParseSess,
     path: &Path,
-    directory_ownership: DirectoryOwnership,
     module_name: Option<String>,
     sp: Span,
 ) -> Parser<'a> {
     let mut p = source_file_to_parser(sess, file_to_source_file(sess, path, Some(sp)));
-    p.directory.ownership = directory_ownership;
     p.root_module_name = module_name;
     p
 }
@@ -171,8 +150,7 @@ fn maybe_source_file_to_parser(
     let mut parser = stream_to_parser(sess, stream, None);
     parser.unclosed_delims = unclosed_delims;
     if parser.token == token::Eof {
-        let span = Span::new(end_pos, end_pos, parser.token.span.ctxt());
-        parser.set_token(Token::new(token::Eof, span));
+        parser.token.span = Span::new(end_pos, end_pos, parser.token.span.ctxt());
     }
 
     Ok(parser)
@@ -257,26 +235,7 @@ pub fn stream_to_parser<'a>(
     stream: TokenStream,
     subparser_name: Option<&'static str>,
 ) -> Parser<'a> {
-    Parser::new(sess, stream, None, true, false, subparser_name)
-}
-
-/// Given a stream, the `ParseSess` and the base directory, produces a parser.
-///
-/// Use this function when you are creating a parser from the token stream
-/// and also care about the current working directory of the parser (e.g.,
-/// you are trying to resolve modules defined inside a macro invocation).
-///
-/// # Note
-///
-/// The main usage of this function is outside of rustc, for those who uses
-/// librustc_ast as a library. Please do not remove this function while refactoring
-/// just because it is not used in rustc codebase!
-pub fn stream_to_parser_with_base_dir<'a>(
-    sess: &'a ParseSess,
-    stream: TokenStream,
-    base_dir: Directory,
-) -> Parser<'a> {
-    Parser::new(sess, stream, Some(base_dir), true, false, None)
+    Parser::new(sess, stream, false, subparser_name)
 }
 
 /// Runs the given subparser `f` on the tokens of the given `attr`'s item.
@@ -286,7 +245,7 @@ pub fn parse_in<'a, T>(
     name: &'static str,
     mut f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
 ) -> PResult<'a, T> {
-    let mut parser = Parser::new(sess, tts, None, false, false, Some(name));
+    let mut parser = Parser::new(sess, tts, false, Some(name));
     let result = f(&mut parser)?;
     if parser.token != token::Eof {
         parser.unexpected()?;
index c5f8b2dd862a51403c953d85b966f0815e246789..b56dd30739dae76ee75262c76e26663779ab7362 100644 (file)
@@ -1,4 +1,4 @@
-use super::{Parser, PathStyle, TokenType};
+use super::{Parser, PathStyle};
 use rustc_ast::ast;
 use rustc_ast::attr;
 use rustc_ast::token::{self, Nonterminal};
 use log::debug;
 
 #[derive(Debug)]
-enum InnerAttributeParsePolicy<'a> {
+pub(super) enum InnerAttrPolicy<'a> {
     Permitted,
-    NotPermitted { reason: &'a str, saw_doc_comment: bool, prev_attr_sp: Option<Span> },
+    Forbidden { reason: &'a str, saw_doc_comment: bool, prev_attr_sp: Option<Span> },
 }
 
 const DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG: &str = "an inner attribute is not \
                                                      permitted in this context";
 
+pub(super) const DEFAULT_INNER_ATTR_FORBIDDEN: InnerAttrPolicy<'_> = InnerAttrPolicy::Forbidden {
+    reason: DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG,
+    saw_doc_comment: false,
+    prev_attr_sp: None,
+};
+
 impl<'a> Parser<'a> {
     /// Parses attributes that appear before an item.
     pub(super) fn parse_outer_attributes(&mut self) -> PResult<'a, Vec<ast::Attribute>> {
@@ -25,48 +31,44 @@ pub(super) fn parse_outer_attributes(&mut self) -> PResult<'a, Vec<ast::Attribut
         let mut just_parsed_doc_comment = false;
         loop {
             debug!("parse_outer_attributes: self.token={:?}", self.token);
-            match self.token.kind {
-                token::Pound => {
-                    let inner_error_reason = if just_parsed_doc_comment {
-                        "an inner attribute is not permitted following an outer doc comment"
-                    } else if !attrs.is_empty() {
-                        "an inner attribute is not permitted following an outer attribute"
-                    } else {
-                        DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG
-                    };
-                    let inner_parse_policy = InnerAttributeParsePolicy::NotPermitted {
-                        reason: inner_error_reason,
-                        saw_doc_comment: just_parsed_doc_comment,
-                        prev_attr_sp: attrs.last().and_then(|a| Some(a.span)),
-                    };
-                    let attr = self.parse_attribute_with_inner_parse_policy(inner_parse_policy)?;
-                    attrs.push(attr);
-                    just_parsed_doc_comment = false;
-                }
-                token::DocComment(s) => {
-                    let attr = self.mk_doc_comment(s);
-                    if attr.style != ast::AttrStyle::Outer {
-                        let span = self.token.span;
-                        let mut err = self.struct_span_err(span, "expected outer doc comment");
-                        err.note(
+            if self.check(&token::Pound) {
+                let inner_error_reason = if just_parsed_doc_comment {
+                    "an inner attribute is not permitted following an outer doc comment"
+                } else if !attrs.is_empty() {
+                    "an inner attribute is not permitted following an outer attribute"
+                } else {
+                    DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG
+                };
+                let inner_parse_policy = InnerAttrPolicy::Forbidden {
+                    reason: inner_error_reason,
+                    saw_doc_comment: just_parsed_doc_comment,
+                    prev_attr_sp: attrs.last().map(|a| a.span),
+                };
+                let attr = self.parse_attribute_with_inner_parse_policy(inner_parse_policy)?;
+                attrs.push(attr);
+                just_parsed_doc_comment = false;
+            } else if let token::DocComment(s) = self.token.kind {
+                let attr = self.mk_doc_comment(s);
+                if attr.style != ast::AttrStyle::Outer {
+                    self.struct_span_err(self.token.span, "expected outer doc comment")
+                        .note(
                             "inner doc comments like this (starting with \
-                                  `//!` or `/*!`) can only appear before items",
-                        );
-                        return Err(err);
-                    }
-                    attrs.push(attr);
-                    self.bump();
-                    just_parsed_doc_comment = true;
+                              `//!` or `/*!`) can only appear before items",
+                        )
+                        .emit();
                 }
-                _ => break,
+                attrs.push(attr);
+                self.bump();
+                just_parsed_doc_comment = true;
+            } else {
+                break;
             }
         }
         Ok(attrs)
     }
 
     fn mk_doc_comment(&self, s: Symbol) -> ast::Attribute {
-        let style = comments::doc_comment_style(&s.as_str());
-        attr::mk_doc_comment(style, s, self.token.span)
+        attr::mk_doc_comment(comments::doc_comment_style(&s.as_str()), s, self.token.span)
     }
 
     /// Matches `attribute = # ! [ meta_item ]`.
@@ -75,96 +77,67 @@ fn mk_doc_comment(&self, s: Symbol) -> ast::Attribute {
     /// attribute.
     pub fn parse_attribute(&mut self, permit_inner: bool) -> PResult<'a, ast::Attribute> {
         debug!("parse_attribute: permit_inner={:?} self.token={:?}", permit_inner, self.token);
-        let inner_parse_policy = if permit_inner {
-            InnerAttributeParsePolicy::Permitted
-        } else {
-            InnerAttributeParsePolicy::NotPermitted {
-                reason: DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG,
-                saw_doc_comment: false,
-                prev_attr_sp: None,
-            }
-        };
+        let inner_parse_policy =
+            if permit_inner { InnerAttrPolicy::Permitted } else { DEFAULT_INNER_ATTR_FORBIDDEN };
         self.parse_attribute_with_inner_parse_policy(inner_parse_policy)
     }
 
-    /// The same as `parse_attribute`, except it takes in an `InnerAttributeParsePolicy`
+    /// The same as `parse_attribute`, except it takes in an `InnerAttrPolicy`
     /// that prescribes how to handle inner attributes.
     fn parse_attribute_with_inner_parse_policy(
         &mut self,
-        inner_parse_policy: InnerAttributeParsePolicy<'_>,
+        inner_parse_policy: InnerAttrPolicy<'_>,
     ) -> 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 {
-            token::Pound => {
-                let lo = self.token.span;
-                self.bump();
-
-                if let InnerAttributeParsePolicy::Permitted = inner_parse_policy {
-                    self.expected_tokens.push(TokenType::Token(token::Not));
-                }
-
-                let style = if self.token == token::Not {
-                    self.bump();
-                    ast::AttrStyle::Inner
-                } else {
-                    ast::AttrStyle::Outer
-                };
+        let lo = self.token.span;
+        let (span, item, style) = if self.eat(&token::Pound) {
+            let style =
+                if self.eat(&token::Not) { ast::AttrStyle::Inner } else { ast::AttrStyle::Outer };
 
-                self.expect(&token::OpenDelim(token::Bracket))?;
-                let item = self.parse_attr_item()?;
-                self.expect(&token::CloseDelim(token::Bracket))?;
-                let hi = self.prev_token.span;
-
-                let attr_sp = lo.to(hi);
-
-                // Emit error if inner attribute is encountered and not permitted
-                if style == ast::AttrStyle::Inner {
-                    if let InnerAttributeParsePolicy::NotPermitted {
-                        reason,
-                        saw_doc_comment,
-                        prev_attr_sp,
-                    } = inner_parse_policy
-                    {
-                        let prev_attr_note = if saw_doc_comment {
-                            "previous doc comment"
-                        } else {
-                            "previous outer attribute"
-                        };
-
-                        let mut diagnostic = self.struct_span_err(attr_sp, reason);
-
-                        if let Some(prev_attr_sp) = prev_attr_sp {
-                            diagnostic
-                                .span_label(attr_sp, "not permitted following an outer attibute")
-                                .span_label(prev_attr_sp, prev_attr_note);
-                        }
-
-                        diagnostic
-                            .note(
-                                "inner attributes, like `#![no_std]`, annotate the item \
-                                   enclosing them, and are usually found at the beginning of \
-                                   source files. Outer attributes, like `#[test]`, annotate the \
-                                   item following them.",
-                            )
-                            .emit();
-                    }
-                }
+            self.expect(&token::OpenDelim(token::Bracket))?;
+            let item = self.parse_attr_item()?;
+            self.expect(&token::CloseDelim(token::Bracket))?;
+            let attr_sp = lo.to(self.prev_token.span);
 
-                (attr_sp, item, style)
-            }
-            _ => {
-                let token_str = pprust::token_to_string(&self.token);
-                let msg = &format!("expected `#`, found `{}`", token_str);
-                return Err(self.struct_span_err(self.token.span, msg));
+            // Emit error if inner attribute is encountered and forbidden.
+            if style == ast::AttrStyle::Inner {
+                self.error_on_forbidden_inner_attr(attr_sp, inner_parse_policy);
             }
+
+            (attr_sp, item, style)
+        } else {
+            let token_str = pprust::token_to_string(&self.token);
+            let msg = &format!("expected `#`, found `{}`", token_str);
+            return Err(self.struct_span_err(self.token.span, msg));
         };
 
         Ok(attr::mk_attr_from_item(style, item, span))
     }
 
+    pub(super) fn error_on_forbidden_inner_attr(&self, attr_sp: Span, policy: InnerAttrPolicy<'_>) {
+        if let InnerAttrPolicy::Forbidden { reason, saw_doc_comment, prev_attr_sp } = policy {
+            let prev_attr_note =
+                if saw_doc_comment { "previous doc comment" } else { "previous outer attribute" };
+
+            let mut diag = self.struct_span_err(attr_sp, reason);
+
+            if let Some(prev_attr_sp) = prev_attr_sp {
+                diag.span_label(attr_sp, "not permitted following an outer attribute")
+                    .span_label(prev_attr_sp, prev_attr_note);
+            }
+
+            diag.note(
+                "inner attributes, like `#![no_std]`, annotate the item enclosing them, \
+                and are usually found at the beginning of source files. \
+                Outer attributes, like `#[test]`, annotate the item following them.",
+            )
+            .emit();
+        }
+    }
+
     /// Parses an inner part of an attribute (the path and following tokens).
     /// The tokens must be either a delimited token stream, or empty token stream,
     /// or the "legacy" key-value form.
@@ -200,28 +173,22 @@ pub fn parse_attr_item(&mut self) -> PResult<'a, ast::AttrItem> {
     crate fn parse_inner_attributes(&mut self) -> PResult<'a, Vec<ast::Attribute>> {
         let mut attrs: Vec<ast::Attribute> = vec![];
         loop {
-            match self.token.kind {
-                token::Pound => {
-                    // Don't even try to parse if it's not an inner attribute.
-                    if !self.look_ahead(1, |t| t == &token::Not) {
-                        break;
-                    }
-
-                    let attr = self.parse_attribute(true)?;
-                    assert_eq!(attr.style, ast::AttrStyle::Inner);
+            // Only try to parse if it is an inner attribute (has `!`).
+            if self.check(&token::Pound) && self.look_ahead(1, |t| t == &token::Not) {
+                let attr = self.parse_attribute(true)?;
+                assert_eq!(attr.style, ast::AttrStyle::Inner);
+                attrs.push(attr);
+            } else if let token::DocComment(s) = self.token.kind {
+                // We need to get the position of this token before we bump.
+                let attr = self.mk_doc_comment(s);
+                if attr.style == ast::AttrStyle::Inner {
                     attrs.push(attr);
+                    self.bump();
+                } else {
+                    break;
                 }
-                token::DocComment(s) => {
-                    // We need to get the position of this token before we bump.
-                    let attr = self.mk_doc_comment(s);
-                    if attr.style == ast::AttrStyle::Inner {
-                        attrs.push(attr);
-                        self.bump();
-                    } else {
-                        break;
-                    }
-                }
-                _ => break,
+            } else {
+                break;
             }
         }
         Ok(attrs)
@@ -232,12 +199,10 @@ pub fn parse_attr_item(&mut self) -> PResult<'a, ast::AttrItem> {
         debug!("checking if {:?} is unusuffixed", lit);
 
         if !lit.kind.is_unsuffixed() {
-            let msg = "suffixed literals are not allowed in attributes";
-            self.struct_span_err(lit.span, msg)
+            self.struct_span_err(lit.span, "suffixed literals are not allowed in attributes")
                 .help(
-                    "instead of using a suffixed literal \
-                                    (`1u8`, `1.0f32`, etc.), use an unsuffixed version \
-                                    (`1`, `1.0`, etc.)",
+                    "instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), \
+                    use an unsuffixed version (`1`, `1.0`, etc.)",
                 )
                 .emit();
         }
index 0759c43d45206281ae7eaf94034dcc48514a63cd..87255386b9e6602b101f6dbbf069cf43dd2b5c22 100644 (file)
@@ -19,7 +19,7 @@
 use log::{debug, trace};
 use std::mem;
 
-const TURBOFISH: &'static str = "use `::<...>` instead of `<...>` to specify type arguments";
+const TURBOFISH: &str = "use `::<...>` instead of `<...>` to specify type arguments";
 
 /// Creates a placeholder argument.
 pub(super) fn dummy_arg(ident: Ident) -> Param {
@@ -40,55 +40,12 @@ pub(super) fn dummy_arg(ident: Ident) -> Param {
 }
 
 pub enum Error {
-    FileNotFoundForModule {
-        mod_name: String,
-        default_path: String,
-        secondary_path: String,
-        dir_path: String,
-    },
-    DuplicatePaths {
-        mod_name: String,
-        default_path: String,
-        secondary_path: String,
-    },
     UselessDocComment,
 }
 
 impl Error {
     fn span_err(self, sp: impl Into<MultiSpan>, handler: &Handler) -> DiagnosticBuilder<'_> {
         match self {
-            Error::FileNotFoundForModule {
-                ref mod_name,
-                ref default_path,
-                ref secondary_path,
-                ref dir_path,
-            } => {
-                let mut err = struct_span_err!(
-                    handler,
-                    sp,
-                    E0583,
-                    "file not found for module `{}`",
-                    mod_name,
-                );
-                err.help(&format!(
-                    "name the file either {} or {} inside the directory \"{}\"",
-                    default_path, secondary_path, dir_path,
-                ));
-                err
-            }
-            Error::DuplicatePaths { ref mod_name, ref default_path, ref secondary_path } => {
-                let mut err = struct_span_err!(
-                    handler,
-                    sp,
-                    E0584,
-                    "file for module `{}` found at both {} and {}",
-                    mod_name,
-                    default_path,
-                    secondary_path,
-                );
-                err.help("delete or rename one of them to remove the ambiguity");
-                err
-            }
             Error::UselessDocComment => {
                 let mut err = struct_span_err!(
                     handler,
@@ -192,17 +149,19 @@ pub(super) fn expected_ident_found(&self) -> DiagnosticBuilder<'a> {
             TokenKind::CloseDelim(token::DelimToken::Brace),
             TokenKind::CloseDelim(token::DelimToken::Paren),
         ];
-        if let token::Ident(name, false) = self.normalized_token.kind {
-            if Ident::new(name, self.normalized_token.span).is_raw_guess()
-                && self.look_ahead(1, |t| valid_follow.contains(&t.kind))
+        match self.token.ident() {
+            Some((ident, false))
+                if ident.is_raw_guess()
+                    && self.look_ahead(1, |t| valid_follow.contains(&t.kind)) =>
             {
                 err.span_suggestion(
-                    self.normalized_token.span,
+                    ident.span,
                     "you can escape reserved keywords to use them as identifiers",
-                    format!("r#{}", name),
+                    format!("r#{}", ident.name),
                     Applicability::MaybeIncorrect,
                 );
             }
+            _ => {}
         }
         if let Some(token_descr) = super::token_descr_opt(&self.token) {
             err.span_label(self.token.span, format!("expected identifier, found {}", token_descr));
@@ -895,7 +854,7 @@ pub(super) fn expect_semi(&mut self) -> PResult<'a, ()> {
         let msg = format!("expected `;`, found `{}`", super::token_descr(&self.token));
         let appl = Applicability::MachineApplicable;
         if self.token.span == DUMMY_SP || self.prev_token.span == DUMMY_SP {
-            // Likely inside a macro, can't provide meaninful suggestions.
+            // Likely inside a macro, can't provide meaningful suggestions.
             return self.expect(&token::Semi).map(drop);
         } else if !sm.is_multiline(self.prev_token.span.until(self.token.span)) {
             // The current token is in the same line as the prior token, not recoverable.
index 18ddd23588e48c60ab08cf02497445dd21b4654c..c65e99842c5ddf3c63353bed158521c57f6ef081 100644 (file)
@@ -4,8 +4,8 @@
 use super::{SemiColonMode, SeqSep, TokenExpectType};
 use crate::maybe_recover_from_interpolated_ty_qpath;
 
-use rustc_ast::ast::{self, AttrStyle, AttrVec, CaptureBy, Field, Ident, Lit, DUMMY_NODE_ID};
-use rustc_ast::ast::{AnonConst, BinOp, BinOpKind, FnDecl, FnRetTy, Mac, Param, Ty, TyKind, UnOp};
+use rustc_ast::ast::{self, AttrStyle, AttrVec, CaptureBy, Field, Ident, Lit, UnOp, DUMMY_NODE_ID};
+use rustc_ast::ast::{AnonConst, BinOp, BinOpKind, FnDecl, FnRetTy, MacCall, Param, Ty, TyKind};
 use rustc_ast::ast::{Arm, Async, BlockCheckMode, Expr, ExprKind, Label, Movability, RangeLimits};
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Token, TokenKind};
@@ -50,7 +50,6 @@ macro_rules! maybe_whole_expr {
                         AttrVec::new(),
                     ));
                 }
-                // N.B., `NtIdent(ident)` is normalized to `Ident` in `fn bump`.
                 _ => {}
             };
         }
@@ -97,9 +96,9 @@ pub(super) fn parse_anon_const_expr(&mut self) -> PResult<'a, AnonConst> {
     fn parse_expr_catch_underscore(&mut self) -> PResult<'a, P<Expr>> {
         match self.parse_expr() {
             Ok(expr) => Ok(expr),
-            Err(mut err) => match self.normalized_token.kind {
-                token::Ident(name, false)
-                    if name == kw::Underscore && self.look_ahead(1, |t| t == &token::Comma) =>
+            Err(mut err) => match self.token.ident() {
+                Some((Ident { name: kw::Underscore, .. }, false))
+                    if self.look_ahead(1, |t| t == &token::Comma) =>
                 {
                     // Special-case handling of `foo(_, _, _)`
                     err.emit();
@@ -331,21 +330,19 @@ fn error_found_expr_would_be_stmt(&self, lhs: &Expr) {
     ///
     /// Also performs recovery for `and` / `or` which are mistaken for `&&` and `||` respectively.
     fn check_assoc_op(&self) -> Option<Spanned<AssocOp>> {
-        Some(Spanned {
-            node: match (AssocOp::from_token(&self.token), &self.normalized_token.kind) {
-                (Some(op), _) => op,
-                (None, token::Ident(sym::and, false)) => {
-                    self.error_bad_logical_op("and", "&&", "conjunction");
-                    AssocOp::LAnd
-                }
-                (None, token::Ident(sym::or, false)) => {
-                    self.error_bad_logical_op("or", "||", "disjunction");
-                    AssocOp::LOr
-                }
-                _ => return None,
-            },
-            span: self.normalized_token.span,
-        })
+        let (op, span) = match (AssocOp::from_token(&self.token), self.token.ident()) {
+            (Some(op), _) => (op, self.token.span),
+            (None, Some((Ident { name: sym::and, span }, false))) => {
+                self.error_bad_logical_op("and", "&&", "conjunction");
+                (AssocOp::LAnd, span)
+            }
+            (None, Some((Ident { name: sym::or, span }, false))) => {
+                self.error_bad_logical_op("or", "||", "disjunction");
+                (AssocOp::LOr, span)
+            }
+            _ => return None,
+        };
+        Some(source_map::respan(span, op))
     }
 
     /// Error on `and` and `or` suggesting `&&` and `||` respectively.
@@ -436,7 +433,7 @@ fn parse_prefix_expr(&mut self, attrs: Option<AttrVec>) -> PResult<'a, P<Expr>>
         let attrs = self.parse_or_use_outer_attributes(attrs)?;
         let lo = self.token.span;
         // Note: when adding new unary operators, don't forget to adjust TokenKind::can_begin_expr()
-        let (hi, ex) = match self.normalized_token.kind {
+        let (hi, ex) = match self.token.uninterpolate().kind {
             token::Not => self.parse_unary_expr(lo, UnOp::Not), // `!expr`
             token::Tilde => self.recover_tilde_expr(lo),        // `~expr`
             token::BinOp(token::Minus) => self.parse_unary_expr(lo, UnOp::Neg), // `-expr`
@@ -483,7 +480,7 @@ fn parse_box_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
     }
 
     fn is_mistaken_not_ident_negation(&self) -> bool {
-        let token_cannot_continue_expr = |t: &Token| match t.kind {
+        let token_cannot_continue_expr = |t: &Token| match t.uninterpolate().kind {
             // These tokens can start an expression after `!`, but
             // can't continue an expression after an ident
             token::Ident(name, is_raw) => token::ident_can_begin_expr(name, t.span, is_raw),
@@ -544,8 +541,8 @@ fn parse_assoc_op_cast(
         // Save the state of the parser before parsing type normally, in case there is a
         // LessThan comparison after this cast.
         let parser_snapshot_before_type = self.clone();
-        match self.parse_ty_no_plus() {
-            Ok(rhs) => Ok(mk_expr(self, rhs)),
+        let cast_expr = match self.parse_ty_no_plus() {
+            Ok(rhs) => mk_expr(self, rhs),
             Err(mut type_err) => {
                 // Rewind to before attempting to parse the type with generics, to recover
                 // from situations like `x as usize < y` in which we first tried to parse
@@ -599,17 +596,70 @@ fn parse_assoc_op_cast(
                             )
                             .emit();
 
-                        Ok(expr)
+                        expr
                     }
                     Err(mut path_err) => {
                         // Couldn't parse as a path, return original error and parser state.
                         path_err.cancel();
                         mem::replace(self, parser_snapshot_after_type);
-                        Err(type_err)
+                        return Err(type_err);
                     }
                 }
             }
-        }
+        };
+
+        self.parse_and_disallow_postfix_after_cast(cast_expr)
+    }
+
+    /// Parses a postfix operators such as `.`, `?`, or index (`[]`) after a cast,
+    /// then emits an error and returns the newly parsed tree.
+    /// The resulting parse tree for `&x as T[0]` has a precedence of `((&x) as T)[0]`.
+    fn parse_and_disallow_postfix_after_cast(
+        &mut self,
+        cast_expr: P<Expr>,
+    ) -> PResult<'a, P<Expr>> {
+        // Save the memory location of expr before parsing any following postfix operators.
+        // This will be compared with the memory location of the output expression.
+        // If they different we can assume we parsed another expression because the existing expression is not reallocated.
+        let addr_before = &*cast_expr as *const _ as usize;
+        let span = cast_expr.span;
+        let with_postfix = self.parse_dot_or_call_expr_with_(cast_expr, span)?;
+        let changed = addr_before != &*with_postfix as *const _ as usize;
+
+        // Check if an illegal postfix operator has been added after the cast.
+        // If the resulting expression is not a cast, or has a different memory location, it is an illegal postfix operator.
+        if !matches!(with_postfix.kind, ExprKind::Cast(_, _) | ExprKind::Type(_, _)) || changed {
+            let msg = format!(
+                "casts cannot be followed by {}",
+                match with_postfix.kind {
+                    ExprKind::Index(_, _) => "indexing",
+                    ExprKind::Try(_) => "?",
+                    ExprKind::Field(_, _) => "a field access",
+                    ExprKind::MethodCall(_, _) => "a method call",
+                    ExprKind::Call(_, _) => "a function call",
+                    ExprKind::Await(_) => "`.await`",
+                    _ => unreachable!("parse_dot_or_call_expr_with_ shouldn't produce this"),
+                }
+            );
+            let mut err = self.struct_span_err(span, &msg);
+            // If type ascription is "likely an error", the user will already be getting a useful
+            // help message, and doesn't need a second.
+            if self.last_type_ascription.map_or(false, |last_ascription| last_ascription.1) {
+                self.maybe_annotate_with_ascription(&mut err, false);
+            } else {
+                let suggestions = vec![
+                    (span.shrink_to_lo(), "(".to_string()),
+                    (span.shrink_to_hi(), ")".to_string()),
+                ];
+                err.multipart_suggestion(
+                    "try surrounding the expression in parentheses",
+                    suggestions,
+                    Applicability::MachineApplicable,
+                );
+            }
+            err.emit();
+        };
+        Ok(with_postfix)
     }
 
     fn parse_assoc_op_ascribe(&mut self, lhs: P<Expr>, lhs_span: Span) -> PResult<'a, P<Expr>> {
@@ -623,10 +673,28 @@ fn parse_assoc_op_ascribe(&mut self, lhs: P<Expr>, lhs_span: Span) -> PResult<'a
     /// Parse `& mut? <expr>` or `& raw [ const | mut ] <expr>`.
     fn parse_borrow_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
         self.expect_and()?;
+        let has_lifetime = self.token.is_lifetime() && self.look_ahead(1, |t| t != &token::Colon);
+        let lifetime = has_lifetime.then(|| self.expect_lifetime()); // For recovery, see below.
         let (borrow_kind, mutbl) = self.parse_borrow_modifiers(lo);
         let expr = self.parse_prefix_expr(None);
-        let (span, expr) = self.interpolated_or_expr_span(expr)?;
-        Ok((lo.to(span), ExprKind::AddrOf(borrow_kind, mutbl, expr)))
+        let (hi, expr) = self.interpolated_or_expr_span(expr)?;
+        let span = lo.to(hi);
+        if let Some(lt) = lifetime {
+            self.error_remove_borrow_lifetime(span, lt.ident.span);
+        }
+        Ok((span, ExprKind::AddrOf(borrow_kind, mutbl, expr)))
+    }
+
+    fn error_remove_borrow_lifetime(&self, span: Span, lt_span: Span) {
+        self.struct_span_err(span, "borrow expressions cannot be annotated with lifetimes")
+            .span_label(lt_span, "annotated with lifetime here")
+            .span_suggestion(
+                lt_span,
+                "remove the lifetime annotation",
+                String::new(),
+                Applicability::MachineApplicable,
+            )
+            .emit();
     }
 
     /// Parse `mut?` or `raw [ const | mut ]`.
@@ -665,20 +733,11 @@ pub(super) fn parse_dot_or_call_expr_with(
             expr.map(|mut expr| {
                 attrs.extend::<Vec<_>>(expr.attrs.into());
                 expr.attrs = attrs;
-                self.error_attr_on_if_expr(&expr);
                 expr
             })
         })
     }
 
-    fn error_attr_on_if_expr(&self, expr: &Expr) {
-        if let (ExprKind::If(..), [a0, ..]) = (&expr.kind, &*expr.attrs) {
-            // Just point to the first attribute in there...
-            self.struct_span_err(a0.span, "attributes are not yet allowed on `if` expressions")
-                .emit();
-        }
-    }
-
     fn parse_dot_or_call_expr_with_(&mut self, mut e: P<Expr>, lo: Span) -> PResult<'a, P<Expr>> {
         loop {
             if self.eat(&token::Question) {
@@ -703,7 +762,7 @@ fn parse_dot_or_call_expr_with_(&mut self, mut e: P<Expr>, lo: Span) -> PResult<
     }
 
     fn parse_dot_suffix_expr(&mut self, lo: Span, base: P<Expr>) -> PResult<'a, P<Expr>> {
-        match self.normalized_token.kind {
+        match self.token.uninterpolate().kind {
             token::Ident(..) => self.parse_dot_suffix(base, lo),
             token::Literal(token::Lit { kind: token::Integer, symbol, suffix }) => {
                 Ok(self.parse_tuple_field_access_expr(lo, base, symbol, suffix))
@@ -797,7 +856,7 @@ fn parse_index_expr(&mut self, lo: Span, base: P<Expr>) -> PResult<'a, P<Expr>>
 
     /// Assuming we have just parsed `.`, continue parsing into an expression.
     fn parse_dot_suffix(&mut self, self_arg: P<Expr>, lo: Span) -> PResult<'a, P<Expr>> {
-        if self.normalized_token.span.rust_2018() && self.eat_keyword(kw::Await) {
+        if self.token.uninterpolated_span().rust_2018() && self.eat_keyword(kw::Await) {
             return self.mk_await_expr(self_arg, lo);
         }
 
@@ -860,7 +919,7 @@ fn parse_bottom_expr(&mut self) -> PResult<'a, P<Expr>> {
         } else if self.eat_lt() {
             let (qself, path) = self.parse_qpath(PathStyle::Expr)?;
             Ok(self.mk_expr(lo.to(path.span), ExprKind::Path(Some(qself), path), attrs))
-        } else if self.token.is_path_start() {
+        } else if self.check_path() {
             self.parse_path_start_expr(attrs)
         } else if self.check_keyword(kw::Move) || self.check_keyword(kw::Static) {
             self.parse_closure_expr(attrs)
@@ -911,7 +970,7 @@ fn parse_bottom_expr(&mut self) -> PResult<'a, P<Expr>> {
             //       |             ^ expected expression
             self.bump();
             Ok(self.mk_expr_err(self.token.span))
-        } else if self.normalized_token.span.rust_2018() {
+        } else if self.token.uninterpolated_span().rust_2018() {
             // `Span::rust_2018()` is somewhat expensive; don't get it repeatedly.
             if self.check_keyword(kw::Async) {
                 if self.is_async_block() {
@@ -955,7 +1014,7 @@ fn parse_tuple_parens_expr(&mut self, mut attrs: AttrVec) -> PResult<'a, P<Expr>
         };
         let kind = if es.len() == 1 && !trailing_comma {
             // `(e)` is parenthesized `e`.
-            ExprKind::Paren(es.into_iter().nth(0).unwrap())
+            ExprKind::Paren(es.into_iter().next().unwrap())
         } else {
             // `(e,)` is a tuple with only one field, `e`.
             ExprKind::Tup(es)
@@ -1006,12 +1065,12 @@ fn parse_path_start_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> {
         // `!`, as an operator, is prefix, so we know this isn't that.
         let (hi, kind) = if self.eat(&token::Not) {
             // MACRO INVOCATION expression
-            let mac = Mac {
+            let mac = MacCall {
                 path,
                 args: self.parse_mac_args()?,
                 prior_type_ascription: self.last_type_ascription,
             };
-            (self.prev_token.span, ExprKind::Mac(mac))
+            (self.prev_token.span, ExprKind::MacCall(mac))
         } else if self.check(&token::OpenDelim(token::Brace)) {
             if let Some(expr) = self.maybe_parse_struct_expr(lo, &path, &attrs) {
                 return expr;
@@ -1026,26 +1085,44 @@ fn parse_path_start_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> {
         self.maybe_recover_from_bad_qpath(expr, true)
     }
 
+    /// Parse `'label: $expr`. The label is already parsed.
     fn parse_labeled_expr(&mut self, label: Label, attrs: AttrVec) -> PResult<'a, P<Expr>> {
         let lo = label.ident.span;
-        self.expect(&token::Colon)?;
-        if self.eat_keyword(kw::While) {
-            return self.parse_while_expr(Some(label), lo, attrs);
-        }
-        if self.eat_keyword(kw::For) {
-            return self.parse_for_expr(Some(label), lo, attrs);
-        }
-        if self.eat_keyword(kw::Loop) {
-            return self.parse_loop_expr(Some(label), lo, attrs);
-        }
-        if self.token == token::OpenDelim(token::Brace) {
-            return self.parse_block_expr(Some(label), lo, BlockCheckMode::Default, attrs);
+        let label = Some(label);
+        let ate_colon = self.eat(&token::Colon);
+        let expr = if self.eat_keyword(kw::While) {
+            self.parse_while_expr(label, lo, attrs)
+        } else if self.eat_keyword(kw::For) {
+            self.parse_for_expr(label, lo, attrs)
+        } else if self.eat_keyword(kw::Loop) {
+            self.parse_loop_expr(label, lo, attrs)
+        } else if self.check(&token::OpenDelim(token::Brace)) || self.token.is_whole_block() {
+            self.parse_block_expr(label, lo, BlockCheckMode::Default, attrs)
+        } else {
+            let msg = "expected `while`, `for`, `loop` or `{` after a label";
+            self.struct_span_err(self.token.span, msg).span_label(self.token.span, msg).emit();
+            // Continue as an expression in an effort to recover on `'label: non_block_expr`.
+            self.parse_expr()
+        }?;
+
+        if !ate_colon {
+            self.error_labeled_expr_must_be_followed_by_colon(lo, expr.span);
         }
 
-        let msg = "expected `while`, `for`, `loop` or `{` after a label";
-        self.struct_span_err(self.token.span, msg).span_label(self.token.span, msg).emit();
-        // Continue as an expression in an effort to recover on `'label: non_block_expr`.
-        self.parse_expr()
+        Ok(expr)
+    }
+
+    fn error_labeled_expr_must_be_followed_by_colon(&self, lo: Span, span: Span) {
+        self.struct_span_err(span, "labeled expression must be followed by `:`")
+            .span_label(lo, "the label")
+            .span_suggestion_short(
+                lo.shrink_to_hi(),
+                "add `:` after the label",
+                ": ".to_string(),
+                Applicability::MachineApplicable,
+            )
+            .note("labels are used before loops and blocks, allowing e.g., `break 'label` to them")
+            .emit();
     }
 
     /// Recover on the syntax `do catch { ... }` suggesting `try { ... }` instead.
@@ -1322,18 +1399,20 @@ pub(super) fn parse_block_expr(
         opt_label: Option<Label>,
         lo: Span,
         blk_mode: BlockCheckMode,
-        outer_attrs: AttrVec,
+        mut attrs: AttrVec,
     ) -> PResult<'a, P<Expr>> {
         if let Some(label) = opt_label {
             self.sess.gated_spans.gate(sym::label_break_value, label.ident.span);
         }
 
-        self.expect(&token::OpenDelim(token::Brace))?;
-
-        let mut attrs = outer_attrs;
-        attrs.extend(self.parse_inner_attributes()?);
+        if self.token.is_whole_block() {
+            self.struct_span_err(self.token.span, "cannot use a `block` macro fragment here")
+                .span_label(lo.to(self.token.span), "the `block` fragment is within this context")
+                .emit();
+        }
 
-        let blk = self.parse_block_tail(lo, blk_mode)?;
+        let (inner_attrs, blk) = self.parse_block_common(lo, blk_mode)?;
+        attrs.extend(inner_attrs);
         Ok(self.mk_expr(blk.span, ExprKind::Block(blk, opt_label), attrs))
     }
 
@@ -1344,11 +1423,14 @@ fn parse_closure_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> {
         let movability =
             if self.eat_keyword(kw::Static) { Movability::Static } else { Movability::Movable };
 
-        let asyncness =
-            if self.normalized_token.span.rust_2018() { self.parse_asyncness() } else { Async::No };
-        if asyncness.is_async() {
+        let asyncness = if self.token.uninterpolated_span().rust_2018() {
+            self.parse_asyncness()
+        } else {
+            Async::No
+        };
+        if let Async::Yes { span, .. } = asyncness {
             // Feature-gate `async ||` closures.
-            self.sess.gated_spans.gate(sym::async_closure, self.normalized_prev_token.span);
+            self.sess.gated_spans.gate(sym::async_closure, span);
         }
 
         let capture_clause = self.parse_capture_clause();
@@ -1373,7 +1455,7 @@ fn parse_closure_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> {
         ))
     }
 
-    /// Parses an optional `move` prefix to a closure lke construct.
+    /// Parses an optional `move` prefix to a closure-like construct.
     fn parse_capture_clause(&mut self) -> CaptureBy {
         if self.eat_keyword(kw::Move) { CaptureBy::Value } else { CaptureBy::Ref }
     }
@@ -1432,13 +1514,16 @@ fn parse_if_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> {
         let thn = if self.eat_keyword(kw::Else) || !cond.returns() {
             self.error_missing_if_cond(lo, cond.span)
         } else {
+            let attrs = self.parse_outer_attributes()?; // For recovery.
             let not_block = self.token != token::OpenDelim(token::Brace);
-            self.parse_block().map_err(|mut err| {
+            let block = self.parse_block().map_err(|mut err| {
                 if not_block {
                     err.span_label(lo, "this `if` expression has a condition, but no block");
                 }
                 err
-            })?
+            })?;
+            self.error_on_if_block_attrs(lo, false, block.span, &attrs);
+            block
         };
         let els = if self.eat_keyword(kw::Else) { Some(self.parse_else_expr()?) } else { None };
         Ok(self.mk_expr(lo.to(self.prev_token.span), ExprKind::If(cond, thn, els), attrs))
@@ -1480,12 +1565,40 @@ fn parse_let_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> {
 
     /// Parses an `else { ... }` expression (`else` token already eaten).
     fn parse_else_expr(&mut self) -> PResult<'a, P<Expr>> {
-        if self.eat_keyword(kw::If) {
-            self.parse_if_expr(AttrVec::new())
+        let ctx_span = self.prev_token.span; // `else`
+        let attrs = self.parse_outer_attributes()?; // For recovery.
+        let expr = if self.eat_keyword(kw::If) {
+            self.parse_if_expr(AttrVec::new())?
         } else {
             let blk = self.parse_block()?;
-            Ok(self.mk_expr(blk.span, ExprKind::Block(blk, None), AttrVec::new()))
-        }
+            self.mk_expr(blk.span, ExprKind::Block(blk, None), AttrVec::new())
+        };
+        self.error_on_if_block_attrs(ctx_span, true, expr.span, &attrs);
+        Ok(expr)
+    }
+
+    fn error_on_if_block_attrs(
+        &self,
+        ctx_span: Span,
+        is_ctx_else: bool,
+        branch_span: Span,
+        attrs: &[ast::Attribute],
+    ) {
+        let (span, last) = match attrs {
+            [] => return,
+            [x0 @ xn] | [x0, .., xn] => (x0.span.to(xn.span), xn.span),
+        };
+        let ctx = if is_ctx_else { "else" } else { "if" };
+        self.struct_span_err(last, "outer attributes are not allowed on `if` and `else` branches")
+            .span_label(branch_span, "the attributes are attached to this branch")
+            .span_label(ctx_span, format!("the branch belongs to this `{}`", ctx))
+            .span_suggestion(
+                span,
+                "remove the attributes",
+                String::new(),
+                Applicability::MachineApplicable,
+            )
+            .emit();
     }
 
     /// Parses `for <src_pat> in <src_expr> <src_loop_block>` (`for` token already eaten).
@@ -1704,7 +1817,7 @@ fn is_do_catch_block(&self) -> bool {
     fn is_try_block(&self) -> bool {
         self.token.is_keyword(kw::Try) &&
         self.look_ahead(1, |t| *t == token::OpenDelim(token::Brace)) &&
-        self.normalized_token.span.rust_2018() &&
+        self.token.uninterpolated_span().rust_2018() &&
         // Prevent `while try {} {}`, `if try {} {} else {}`, etc.
         !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL)
     }
@@ -1854,20 +1967,23 @@ pub(super) fn parse_struct_expr(
 
     /// Use in case of error after field-looking code: `S { foo: () with a }`.
     fn find_struct_error_after_field_looking_code(&self) -> Option<Field> {
-        if let token::Ident(name, _) = self.normalized_token.kind {
-            if !self.token.is_reserved_ident() && self.look_ahead(1, |t| *t == token::Colon) {
-                return Some(ast::Field {
-                    ident: Ident::new(name, self.normalized_token.span),
+        match self.token.ident() {
+            Some((ident, is_raw))
+                if (is_raw || !ident.is_reserved())
+                    && self.look_ahead(1, |t| *t == token::Colon) =>
+            {
+                Some(ast::Field {
+                    ident,
                     span: self.token.span,
                     expr: self.mk_expr_err(self.token.span),
                     is_shorthand: false,
                     attrs: AttrVec::new(),
                     id: DUMMY_NODE_ID,
                     is_placeholder: false,
-                });
+                })
             }
+            _ => None,
         }
-        None
     }
 
     fn recover_struct_comma_after_dotdot(&mut self, span: Span) {
index 9bca1d09901590654ce46fc13b70d2b817050a92..9d70f606f3ef4339e80e6c619cd1048282bbd8d6 100644 (file)
@@ -5,17 +5,14 @@
 use crate::maybe_whole;
 
 use rustc_ast::ast::{self, AttrStyle, AttrVec, Attribute, Ident, DUMMY_NODE_ID};
-use rustc_ast::ast::{AssocItem, AssocItemKind, ForeignItemKind, Item, ItemKind};
-use rustc_ast::ast::{
-    Async, Const, Defaultness, IsAuto, PathSegment, Unsafe, UseTree, UseTreeKind,
-};
-use rustc_ast::ast::{
-    BindingMode, Block, FnDecl, FnSig, Mac, MacArgs, MacDelimiter, Param, SelfKind,
-};
+use rustc_ast::ast::{AssocItem, AssocItemKind, ForeignItemKind, Item, ItemKind, Mod};
+use rustc_ast::ast::{Async, Const, Defaultness, IsAuto, Mutability, Unsafe, UseTree, UseTreeKind};
+use rustc_ast::ast::{BindingMode, Block, FnDecl, FnSig, Param, SelfKind};
 use rustc_ast::ast::{EnumDef, Generics, StructField, TraitRef, Ty, TyKind, Variant, VariantData};
-use rustc_ast::ast::{FnHeader, ForeignItem, Mutability, Visibility, VisibilityKind};
+use rustc_ast::ast::{FnHeader, ForeignItem, PathSegment, Visibility, VisibilityKind};
+use rustc_ast::ast::{MacArgs, MacCall, MacDelimiter};
 use rustc_ast::ptr::P;
-use rustc_ast::token;
+use rustc_ast::token::{self, TokenKind};
 use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree};
 use rustc_ast_pretty::pprust;
 use rustc_errors::{struct_span_err, Applicability, PResult, StashKey};
 use rustc_span::symbol::{kw, sym, Symbol};
 
 use log::debug;
+use std::convert::TryFrom;
 use std::mem;
 
+impl<'a> Parser<'a> {
+    /// Parses a source module as a crate. This is the main entry point for the parser.
+    pub fn parse_crate_mod(&mut self) -> PResult<'a, ast::Crate> {
+        let lo = self.token.span;
+        let (module, attrs) = self.parse_mod(&token::Eof)?;
+        let span = lo.to(self.token.span);
+        let proc_macros = Vec::new(); // Filled in by `proc_macro_harness::inject()`.
+        Ok(ast::Crate { attrs, module, span, proc_macros })
+    }
+
+    /// Parses a `mod <foo> { ... }` or `mod <foo>;` item.
+    fn parse_item_mod(&mut self, attrs: &mut Vec<Attribute>) -> PResult<'a, ItemInfo> {
+        let id = self.parse_ident()?;
+        let (module, mut inner_attrs) = if self.eat(&token::Semi) {
+            Default::default()
+        } else {
+            self.expect(&token::OpenDelim(token::Brace))?;
+            self.parse_mod(&token::CloseDelim(token::Brace))?
+        };
+        attrs.append(&mut inner_attrs);
+        Ok((id, ItemKind::Mod(module)))
+    }
+
+    /// Parses the contents of a module (inner attributes followed by module items).
+    pub fn parse_mod(&mut self, term: &TokenKind) -> PResult<'a, (Mod, Vec<Attribute>)> {
+        let lo = self.token.span;
+        let attrs = self.parse_inner_attributes()?;
+        let module = self.parse_mod_items(term, lo)?;
+        Ok((module, attrs))
+    }
+
+    /// Given a termination token, parses all of the items in a module.
+    fn parse_mod_items(&mut self, term: &TokenKind, inner_lo: Span) -> PResult<'a, Mod> {
+        let mut items = vec![];
+        while let Some(item) = self.parse_item()? {
+            items.push(item);
+            self.maybe_consume_incorrect_semicolon(&items);
+        }
+
+        if !self.eat(term) {
+            let token_str = super::token_descr(&self.token);
+            if !self.maybe_consume_incorrect_semicolon(&items) {
+                let msg = &format!("expected item, found {}", token_str);
+                let mut err = self.struct_span_err(self.token.span, msg);
+                err.span_label(self.token.span, "expected item");
+                return Err(err);
+            }
+        }
+
+        let hi = if self.token.span.is_dummy() { inner_lo } else { self.prev_token.span };
+
+        Ok(Mod { inner: inner_lo.to(hi), items, inline: true })
+    }
+}
+
 pub(super) type ItemInfo = (Ident, ItemKind);
 
 impl<'a> Parser<'a> {
@@ -217,9 +270,9 @@ fn parse_item_kind(
         } else if vis.node.is_pub() && self.isnt_macro_invocation() {
             self.recover_missing_kw_before_item()?;
             return Ok(None);
-        } else if macros_allowed && self.token.is_path_start() {
+        } else if macros_allowed && self.check_path() {
             // MACRO INVOCATION ITEM
-            (Ident::invalid(), ItemKind::Mac(self.parse_item_macro(vis)?))
+            (Ident::invalid(), ItemKind::MacCall(self.parse_item_macro(vis)?))
         } else {
             return Ok(None);
         };
@@ -338,21 +391,20 @@ fn recover_missing_kw_before_item(&mut self) -> PResult<'a, ()> {
     }
 
     /// Parses an item macro, e.g., `item!();`.
-    fn parse_item_macro(&mut self, vis: &Visibility) -> PResult<'a, Mac> {
+    fn parse_item_macro(&mut self, vis: &Visibility) -> PResult<'a, MacCall> {
         let path = self.parse_path(PathStyle::Mod)?; // `foo::bar`
         self.expect(&token::Not)?; // `!`
         let args = self.parse_mac_args()?; // `( .. )` or `[ .. ]` (followed by `;`), or `{ .. }`.
         self.eat_semi_for_macro_if_needed(&args);
         self.complain_if_pub_macro(vis, false);
-        Ok(Mac { path, args, prior_type_ascription: self.last_type_ascription })
+        Ok(MacCall { path, args, prior_type_ascription: self.last_type_ascription })
     }
 
     /// Recover if we parsed attributes and expected an item but there was none.
     fn recover_attrs_no_item(&mut self, attrs: &[Attribute]) -> PResult<'a, ()> {
         let (start, end) = match attrs {
             [] => return Ok(()),
-            [x0] => (x0, x0),
-            [x0, .., xn] => (x0, xn),
+            [x0 @ xn] | [x0, .., xn] => (x0, xn),
         };
         let msg = if end.is_doc_comment() {
             "expected item after doc comment"
@@ -373,6 +425,16 @@ fn is_async_fn(&self) -> bool {
         self.token.is_keyword(kw::Async) && self.is_keyword_ahead(1, &[kw::Fn])
     }
 
+    fn parse_polarity(&mut self) -> ast::ImplPolarity {
+        // Disambiguate `impl !Trait for Type { ... }` and `impl ! { ... }` for the never type.
+        if self.check(&token::Not) && self.look_ahead(1, |t| t.can_begin_type()) {
+            self.bump(); // `!`
+            ast::ImplPolarity::Negative(self.prev_token.span)
+        } else {
+            ast::ImplPolarity::Positive
+        }
+    }
+
     /// Parses an implementation item.
     ///
     /// ```
@@ -411,13 +473,7 @@ fn parse_item_impl(
             self.sess.gated_spans.gate(sym::const_trait_impl, span);
         }
 
-        // Disambiguate `impl !Trait for Type { ... }` and `impl ! { ... }` for the never type.
-        let polarity = if self.check(&token::Not) && self.look_ahead(1, |t| t.can_begin_type()) {
-            self.bump(); // `!`
-            ast::ImplPolarity::Negative
-        } else {
-            ast::ImplPolarity::Positive
-        };
+        let polarity = self.parse_polarity();
 
         // Parse both types and traits as a type, then reinterpret if necessary.
         let err_path = |span| ast::Path::from_ident(Ident::new(kw::Invalid, span));
@@ -573,7 +629,7 @@ fn parse_defaultness(&mut self) -> Defaultness {
             && self.look_ahead(1, |t| t.is_non_raw_ident_where(|i| i.name != kw::As))
         {
             self.bump(); // `default`
-            Defaultness::Default(self.normalized_prev_token.span)
+            Defaultness::Default(self.prev_token.uninterpolated_span())
         } else {
             Defaultness::Final
         }
@@ -650,16 +706,16 @@ pub fn parse_trait_item(&mut self) -> PResult<'a, Option<Option<P<AssocItem>>>>
     /// Parses associated items.
     fn parse_assoc_item(&mut self, req_name: ReqName) -> PResult<'a, Option<Option<P<AssocItem>>>> {
         Ok(self.parse_item_(req_name)?.map(|Item { attrs, id, span, vis, ident, kind, tokens }| {
-            let kind = match kind {
-                ItemKind::Mac(a) => AssocItemKind::Macro(a),
-                ItemKind::Fn(a, b, c, d) => AssocItemKind::Fn(a, b, c, d),
-                ItemKind::TyAlias(a, b, c, d) => AssocItemKind::TyAlias(a, b, c, d),
-                ItemKind::Const(a, b, c) => AssocItemKind::Const(a, b, c),
-                ItemKind::Static(a, _, b) => {
-                    self.struct_span_err(span, "associated `static` items are not allowed").emit();
-                    AssocItemKind::Const(Defaultness::Final, a, b)
-                }
-                _ => return self.error_bad_item_kind(span, &kind, "`trait`s or `impl`s"),
+            let kind = match AssocItemKind::try_from(kind) {
+                Ok(kind) => kind,
+                Err(kind) => match kind {
+                    ItemKind::Static(a, _, b) => {
+                        self.struct_span_err(span, "associated `static` items are not allowed")
+                            .emit();
+                        AssocItemKind::Const(Defaultness::Final, a, b)
+                    }
+                    _ => return self.error_bad_item_kind(span, &kind, "`trait`s or `impl`s"),
+                },
             };
             Some(P(Item { attrs, id, span, vis, ident, kind, tokens }))
         }))
@@ -749,10 +805,10 @@ fn parse_rename(&mut self) -> PResult<'a, Option<Ident>> {
     }
 
     fn parse_ident_or_underscore(&mut self) -> PResult<'a, ast::Ident> {
-        match self.normalized_token.kind {
-            token::Ident(name @ kw::Underscore, false) => {
+        match self.token.ident() {
+            Some((ident @ Ident { name: kw::Underscore, .. }, false)) => {
                 self.bump();
-                Ok(Ident::new(name, self.normalized_prev_token.span))
+                Ok(ident)
             }
             _ => self.parse_ident(),
         }
@@ -836,16 +892,15 @@ fn parse_item_foreign_mod(&mut self, attrs: &mut Vec<Attribute>) -> PResult<'a,
     /// Parses a foreign item (one in an `extern { ... }` block).
     pub fn parse_foreign_item(&mut self) -> PResult<'a, Option<Option<P<ForeignItem>>>> {
         Ok(self.parse_item_(|_| true)?.map(|Item { attrs, id, span, vis, ident, kind, tokens }| {
-            let kind = match kind {
-                ItemKind::Mac(a) => ForeignItemKind::Macro(a),
-                ItemKind::Fn(a, b, c, d) => ForeignItemKind::Fn(a, b, c, d),
-                ItemKind::TyAlias(a, b, c, d) => ForeignItemKind::TyAlias(a, b, c, d),
-                ItemKind::Static(a, b, c) => ForeignItemKind::Static(a, b, c),
-                ItemKind::Const(_, a, b) => {
-                    self.error_on_foreign_const(span, ident);
-                    ForeignItemKind::Static(a, Mutability::Not, b)
-                }
-                _ => return self.error_bad_item_kind(span, &kind, "`extern` blocks"),
+            let kind = match ForeignItemKind::try_from(kind) {
+                Ok(kind) => kind,
+                Err(kind) => match kind {
+                    ItemKind::Const(_, a, b) => {
+                        self.error_on_foreign_const(span, ident);
+                        ForeignItemKind::Static(a, Mutability::Not, b)
+                    }
+                    _ => return self.error_bad_item_kind(span, &kind, "`extern` blocks"),
+                },
             };
             Some(P(Item { attrs, id, span, vis, ident, kind, tokens }))
         }))
@@ -1261,7 +1316,7 @@ fn parse_item_decl_macro(&mut self, lo: Span) -> PResult<'a, ItemInfo> {
         };
 
         self.sess.gated_spans.gate(sym::decl_macro, lo.to(self.prev_token.span));
-        Ok((ident, ItemKind::MacroDef(ast::MacroDef { body, legacy: false })))
+        Ok((ident, ItemKind::MacroDef(ast::MacroDef { body, macro_rules: false })))
     }
 
     /// Is this unambiguously the start of a `macro_rules! foo` item defnition?
@@ -1271,7 +1326,7 @@ fn is_macro_rules_item(&mut self) -> bool {
             && self.look_ahead(2, |t| t.is_ident())
     }
 
-    /// Parses a legacy `macro_rules! foo { ... }` declarative macro.
+    /// Parses a `macro_rules! foo { ... }` declarative macro.
     fn parse_item_macro_rules(&mut self, vis: &Visibility) -> PResult<'a, ItemInfo> {
         self.expect_keyword(kw::MacroRules)?; // `macro_rules`
         self.expect(&token::Not)?; // `!`
@@ -1281,7 +1336,7 @@ fn parse_item_macro_rules(&mut self, vis: &Visibility) -> PResult<'a, ItemInfo>
         self.eat_semi_for_macro_if_needed(&body);
         self.complain_if_pub_macro(vis, true);
 
-        Ok((ident, ItemKind::MacroDef(ast::MacroDef { body, legacy: true })))
+        Ok((ident, ItemKind::MacroDef(ast::MacroDef { body, macro_rules: true })))
     }
 
     /// Item macro invocations or `macro_rules!` definitions need inherited visibility.
@@ -1411,23 +1466,28 @@ fn parse_fn(
     /// This can either be `;` when there's no body,
     /// or e.g. a block when the function is a provided one.
     fn parse_fn_body(&mut self, attrs: &mut Vec<Attribute>) -> PResult<'a, Option<P<Block>>> {
-        let (inner_attrs, body) = match self.token.kind {
-            token::Semi => {
-                self.bump();
-                (Vec::new(), None)
-            }
-            token::OpenDelim(token::Brace) => {
-                let (attrs, body) = self.parse_inner_attrs_and_block()?;
-                (attrs, Some(body))
-            }
-            token::Interpolated(ref nt) => match **nt {
-                token::NtBlock(..) => {
-                    let (attrs, body) = self.parse_inner_attrs_and_block()?;
-                    (attrs, Some(body))
-                }
-                _ => return self.expected_semi_or_open_brace(),
-            },
-            _ => return self.expected_semi_or_open_brace(),
+        let (inner_attrs, body) = if self.check(&token::Semi) {
+            self.bump(); // `;`
+            (Vec::new(), None)
+        } else if self.check(&token::OpenDelim(token::Brace)) || self.token.is_whole_block() {
+            self.parse_inner_attrs_and_block().map(|(attrs, body)| (attrs, Some(body)))?
+        } else if self.token.kind == token::Eq {
+            // Recover `fn foo() = $expr;`.
+            self.bump(); // `=`
+            let eq_sp = self.prev_token.span;
+            let _ = self.parse_expr()?;
+            self.expect_semi()?; // `;`
+            let span = eq_sp.to(self.prev_token.span);
+            self.struct_span_err(span, "function body cannot be `= expression;`")
+                .multipart_suggestion(
+                    "surround the expression with `{` and `}` instead of `=` and `;`",
+                    vec![(eq_sp, "{".to_string()), (self.prev_token.span, " }".to_string())],
+                    Applicability::MachineApplicable,
+                )
+                .emit();
+            (Vec::new(), Some(self.mk_block_err(span)))
+        } else {
+            return self.expected_semi_or_open_brace();
         };
         attrs.extend(inner_attrs);
         Ok(body)
@@ -1544,7 +1604,7 @@ fn parse_param_general(&mut self, req_name: ReqName, first_param: bool) -> PResu
 
         let is_name_required = match self.token.kind {
             token::DotDotDot => false,
-            _ => req_name(self.normalized_token.span.edition()),
+            _ => req_name(self.token.span.edition()),
         };
         let (pat, ty) = if is_name_required || self.is_named_param() {
             debug!("parse_param_general parse_pat (is_name_required:{})", is_name_required);
@@ -1609,15 +1669,12 @@ fn parse_param_general(&mut self, req_name: ReqName, first_param: bool) -> PResu
     /// Returns the parsed optional self parameter and whether a self shortcut was used.
     fn parse_self_param(&mut self) -> PResult<'a, Option<Param>> {
         // Extract an identifier *after* having confirmed that the token is one.
-        let expect_self_ident = |this: &mut Self| {
-            match this.normalized_token.kind {
-                // Preserve hygienic context.
-                token::Ident(name, _) => {
-                    this.bump();
-                    Ident::new(name, this.normalized_prev_token.span)
-                }
-                _ => unreachable!(),
+        let expect_self_ident = |this: &mut Self| match this.token.ident() {
+            Some((ident, false)) => {
+                this.bump();
+                ident
             }
+            _ => unreachable!(),
         };
         // Is `self` `n` tokens ahead?
         let is_isolated_self = |this: &Self, n| {
@@ -1651,7 +1708,7 @@ fn parse_self_param(&mut self) -> PResult<'a, Option<Param>> {
         // 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.normalized_token.kind {
+        let (eself, eself_ident, eself_hi) = match self.token.uninterpolate().kind {
             token::BinOp(token::And) => {
                 let eself = if is_isolated_self(self, 1) {
                     // `&self`
index 74101fef8e39b606eed2e708db6661e4ccfd5340..bb6793d08aa270dc24200d69cf5cc16e7fd0f4ea 100644 (file)
@@ -1,8 +1,6 @@
 pub mod attr;
 mod expr;
 mod item;
-mod module;
-pub use module::{ModulePath, ModulePathSuccess};
 mod pat;
 mod path;
 mod ty;
@@ -13,7 +11,6 @@
 use diagnostics::Error;
 
 use crate::lexer::UnmatchedBrace;
-use crate::{Directory, DirectoryOwnership};
 
 use log::debug;
 use rustc_ast::ast::DUMMY_NODE_ID;
 use rustc_ast_pretty::pprust;
 use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, FatalError, PResult};
 use rustc_session::parse::ParseSess;
-use rustc_span::source_map::respan;
+use rustc_span::source_map::{respan, Span, DUMMY_SP};
 use rustc_span::symbol::{kw, sym, Symbol};
-use rustc_span::{FileName, Span, DUMMY_SP};
 
-use std::path::PathBuf;
 use std::{cmp, mem, slice};
 
 bitflags::bitflags! {
@@ -88,27 +83,11 @@ macro_rules! maybe_recover_from_interpolated_ty_qpath {
 #[derive(Clone)]
 pub struct Parser<'a> {
     pub sess: &'a ParseSess,
-    /// The current non-normalized token.
+    /// The current token.
     pub token: Token,
-    /// The current normalized token.
-    /// "Normalized" means that some interpolated tokens
-    /// (`$i: ident` and `$l: lifetime` meta-variables) are replaced
-    /// with non-interpolated identifier and lifetime tokens they refer to.
-    /// Use this if you need to check for `token::Ident` or `token::Lifetime` specifically,
-    /// this also includes edition checks for edition-specific keyword identifiers.
-    pub normalized_token: Token,
-    /// The previous non-normalized token.
+    /// The previous token.
     pub prev_token: Token,
-    /// The previous normalized token.
-    /// Use this if you need to check for `token::Ident` or `token::Lifetime` specifically,
-    /// this also includes edition checks for edition-specific keyword identifiers.
-    pub normalized_prev_token: Token,
     restrictions: Restrictions,
-    /// Used to determine the path to externally loaded source files.
-    pub(super) directory: Directory,
-    /// `true` to parse sub-modules in other files.
-    // Public for rustfmt usage.
-    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.
@@ -116,9 +95,6 @@ pub struct Parser<'a> {
     expected_tokens: Vec<TokenType>,
     token_cursor: TokenCursor,
     desugar_doc_comments: bool,
-    /// `true` we should configure out of line modules as we parse.
-    // Public for rustfmt usage.
-    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.
@@ -366,23 +342,14 @@ impl<'a> Parser<'a> {
     pub fn new(
         sess: &'a ParseSess,
         tokens: TokenStream,
-        directory: Option<Directory>,
-        recurse_into_file_modules: bool,
         desugar_doc_comments: bool,
         subparser_name: Option<&'static str>,
     ) -> Self {
         let mut parser = Parser {
             sess,
             token: Token::dummy(),
-            normalized_token: Token::dummy(),
             prev_token: Token::dummy(),
-            normalized_prev_token: Token::dummy(),
             restrictions: Restrictions::empty(),
-            recurse_into_file_modules,
-            directory: Directory {
-                path: PathBuf::new(),
-                ownership: DirectoryOwnership::Owned { relative: None },
-            },
             root_module_name: None,
             expected_tokens: Vec::new(),
             token_cursor: TokenCursor {
@@ -390,7 +357,6 @@ pub fn new(
                 stack: Vec::new(),
             },
             desugar_doc_comments,
-            cfg_mods: true,
             unmatched_angle_bracket_count: 0,
             max_angle_bracket_count: 0,
             unclosed_delims: Vec::new(),
@@ -402,18 +368,6 @@ pub fn new(
         // Make parser point to the first token.
         parser.bump();
 
-        if let Some(directory) = directory {
-            parser.directory = directory;
-        } else if !parser.token.span.is_dummy() {
-            if let Some(FileName::Real(path)) =
-                &sess.source_map().lookup_char_pos(parser.token.span.lo()).file.unmapped_path
-            {
-                if let Some(directory_path) = path.parent() {
-                    parser.directory.path = directory_path.to_path_buf();
-                }
-            }
-        }
-
         parser
     }
 
@@ -480,9 +434,9 @@ pub fn parse_ident(&mut self) -> PResult<'a, ast::Ident> {
     }
 
     fn parse_ident_common(&mut self, recover: bool) -> PResult<'a, ast::Ident> {
-        match self.normalized_token.kind {
-            token::Ident(name, _) => {
-                if self.token.is_reserved_ident() {
+        match self.token.ident() {
+            Some((ident, is_raw)) => {
+                if !is_raw && ident.is_reserved() {
                     let mut err = self.expected_ident_found();
                     if recover {
                         err.emit();
@@ -491,7 +445,7 @@ fn parse_ident_common(&mut self, recover: bool) -> PResult<'a, ast::Ident> {
                     }
                 }
                 self.bump();
-                Ok(Ident::new(name, self.normalized_prev_token.span))
+                Ok(ident)
             }
             _ => Err(match self.prev_token.kind {
                 TokenKind::DocComment(..) => {
@@ -609,7 +563,7 @@ fn break_and_eat(&mut self, expected: TokenKind) -> bool {
             Some((first, second)) if first == expected => {
                 let first_span = self.sess.source_map().start_point(self.token.span);
                 let second_span = self.token.span.with_lo(first_span.hi());
-                self.set_token(Token::new(first, first_span));
+                self.token = Token::new(first, first_span);
                 self.bump_with(Token::new(second, second_span));
                 true
             }
@@ -817,23 +771,6 @@ fn parse_paren_comma_seq<T>(
         self.parse_delim_comma_seq(token::Paren, f)
     }
 
-    // Interpolated identifier (`$i: ident`) and lifetime (`$l: lifetime`)
-    // tokens are replaced with usual identifier and lifetime tokens,
-    // so the former are never encountered during normal parsing.
-    crate fn set_token(&mut self, token: Token) {
-        self.token = token;
-        self.normalized_token = match &self.token.kind {
-            token::Interpolated(nt) => match **nt {
-                token::NtIdent(ident, is_raw) => {
-                    Token::new(token::Ident(ident.name, is_raw), ident.span)
-                }
-                token::NtLifetime(ident) => Token::new(token::Lifetime(ident.name), ident.span),
-                _ => self.token.clone(),
-            },
-            _ => self.token.clone(),
-        }
-    }
-
     /// Advance the parser by one token using provided token as the next one.
     fn bump_with(&mut self, next_token: Token) {
         // Bumping after EOF is a bad sign, usually an infinite loop.
@@ -843,9 +780,7 @@ fn bump_with(&mut self, next_token: Token) {
         }
 
         // Update the current and previous tokens.
-        self.prev_token = self.token.take();
-        self.normalized_prev_token = self.normalized_token.take();
-        self.set_token(next_token);
+        self.prev_token = mem::replace(&mut self.token, next_token);
 
         // Diagnostics.
         self.expected_tokens.clear();
@@ -884,7 +819,7 @@ fn is_keyword_ahead(&self, dist: usize, kws: &[Symbol]) -> bool {
     /// Parses asyncness: `async` or nothing.
     fn parse_asyncness(&mut self) -> Async {
         if self.eat_keyword(kw::Async) {
-            let span = self.normalized_prev_token.span;
+            let span = self.prev_token.uninterpolated_span();
             Async::Yes { span, closure_id: DUMMY_NODE_ID, return_impl_trait_id: DUMMY_NODE_ID }
         } else {
             Async::No
@@ -894,7 +829,7 @@ fn parse_asyncness(&mut self) -> Async {
     /// Parses unsafety: `unsafe` or nothing.
     fn parse_unsafety(&mut self) -> Unsafe {
         if self.eat_keyword(kw::Unsafe) {
-            Unsafe::Yes(self.normalized_prev_token.span)
+            Unsafe::Yes(self.prev_token.uninterpolated_span())
         } else {
             Unsafe::No
         }
@@ -903,7 +838,7 @@ fn parse_unsafety(&mut self) -> Unsafe {
     /// Parses constness: `const` or nothing.
     fn parse_constness(&mut self) -> Const {
         if self.eat_keyword(kw::Const) {
-            Const::Yes(self.normalized_prev_token.span)
+            Const::Yes(self.prev_token.uninterpolated_span())
         } else {
             Const::No
         }
@@ -1005,7 +940,7 @@ pub fn parse_token_tree(&mut self) -> TokenTree {
                     &mut self.token_cursor.frame,
                     self.token_cursor.stack.pop().unwrap(),
                 );
-                self.set_token(Token::new(TokenKind::CloseDelim(frame.delim), frame.span.close));
+                self.token = Token::new(TokenKind::CloseDelim(frame.delim), frame.span.close);
                 self.bump();
                 TokenTree::Delimited(frame.span, frame.delim, frame.tree_cursor.stream)
             }
diff --git a/src/librustc_parse/parser/module.rs b/src/librustc_parse/parser/module.rs
deleted file mode 100644 (file)
index b436f19..0000000
+++ /dev/null
@@ -1,306 +0,0 @@
-use super::diagnostics::Error;
-use super::item::ItemInfo;
-use super::Parser;
-
-use crate::{new_sub_parser_from_file, DirectoryOwnership};
-
-use rustc_ast::ast::{self, Attribute, Crate, Ident, ItemKind, Mod};
-use rustc_ast::attr;
-use rustc_ast::token::{self, TokenKind};
-use rustc_errors::PResult;
-use rustc_span::source_map::{FileName, SourceMap, Span, DUMMY_SP};
-use rustc_span::symbol::sym;
-
-use std::path::{self, Path, PathBuf};
-
-/// Information about the path to a module.
-// Public for rustfmt usage.
-pub struct ModulePath {
-    name: String,
-    path_exists: bool,
-    pub result: Result<ModulePathSuccess, Error>,
-}
-
-// Public for rustfmt usage.
-pub struct ModulePathSuccess {
-    pub path: PathBuf,
-    pub directory_ownership: DirectoryOwnership,
-}
-
-impl<'a> Parser<'a> {
-    /// Parses a source module as a crate. This is the main entry point for the parser.
-    pub fn parse_crate_mod(&mut self) -> PResult<'a, Crate> {
-        let lo = self.token.span;
-        let krate = Ok(ast::Crate {
-            attrs: self.parse_inner_attributes()?,
-            module: self.parse_mod_items(&token::Eof, lo)?,
-            span: lo.to(self.token.span),
-            // Filled in by proc_macro_harness::inject()
-            proc_macros: Vec::new(),
-        });
-        krate
-    }
-
-    /// Parses a `mod <foo> { ... }` or `mod <foo>;` item.
-    pub(super) fn parse_item_mod(&mut self, attrs: &mut Vec<Attribute>) -> PResult<'a, ItemInfo> {
-        let in_cfg = crate::config::process_configure_mod(self.sess, self.cfg_mods, attrs);
-
-        let id_span = self.token.span;
-        let id = self.parse_ident()?;
-        let (module, mut inner_attrs) = if self.eat(&token::Semi) {
-            if in_cfg && self.recurse_into_file_modules {
-                // This mod is in an external file. Let's go get it!
-                let ModulePathSuccess { path, directory_ownership } =
-                    self.submod_path(id, &attrs, id_span)?;
-                self.eval_src_mod(path, directory_ownership, id.to_string(), id_span)?
-            } else {
-                (ast::Mod { inner: DUMMY_SP, items: Vec::new(), inline: false }, Vec::new())
-            }
-        } else {
-            let old_directory = self.directory.clone();
-            self.push_directory(id, &attrs);
-
-            self.expect(&token::OpenDelim(token::Brace))?;
-            let mod_inner_lo = self.token.span;
-            let inner_attrs = self.parse_inner_attributes()?;
-            let module = self.parse_mod_items(&token::CloseDelim(token::Brace), mod_inner_lo)?;
-
-            self.directory = old_directory;
-            (module, inner_attrs)
-        };
-        attrs.append(&mut inner_attrs);
-        Ok((id, ItemKind::Mod(module)))
-    }
-
-    /// Given a termination token, parses all of the items in a module.
-    fn parse_mod_items(&mut self, term: &TokenKind, inner_lo: Span) -> PResult<'a, Mod> {
-        let mut items = vec![];
-        while let Some(item) = self.parse_item()? {
-            items.push(item);
-            self.maybe_consume_incorrect_semicolon(&items);
-        }
-
-        if !self.eat(term) {
-            let token_str = super::token_descr(&self.token);
-            if !self.maybe_consume_incorrect_semicolon(&items) {
-                let msg = &format!("expected item, found {}", token_str);
-                let mut err = self.struct_span_err(self.token.span, msg);
-                err.span_label(self.token.span, "expected item");
-                return Err(err);
-            }
-        }
-
-        let hi = if self.token.span.is_dummy() { inner_lo } else { self.prev_token.span };
-
-        Ok(Mod { inner: inner_lo.to(hi), items, inline: true })
-    }
-
-    fn submod_path(
-        &mut self,
-        id: ast::Ident,
-        outer_attrs: &[Attribute],
-        id_sp: Span,
-    ) -> PResult<'a, ModulePathSuccess> {
-        if let Some(path) = Parser::submod_path_from_attr(outer_attrs, &self.directory.path) {
-            return Ok(ModulePathSuccess {
-                directory_ownership: match path.file_name().and_then(|s| s.to_str()) {
-                    // All `#[path]` files are treated as though they are a `mod.rs` file.
-                    // This means that `mod foo;` declarations inside `#[path]`-included
-                    // files are siblings,
-                    //
-                    // Note that this will produce weirdness when a file named `foo.rs` is
-                    // `#[path]` included and contains a `mod foo;` declaration.
-                    // If you encounter this, it's your own darn fault :P
-                    Some(_) => DirectoryOwnership::Owned { relative: None },
-                    _ => DirectoryOwnership::UnownedViaMod,
-                },
-                path,
-            });
-        }
-
-        let relative = match self.directory.ownership {
-            DirectoryOwnership::Owned { relative } => relative,
-            DirectoryOwnership::UnownedViaBlock | DirectoryOwnership::UnownedViaMod => None,
-        };
-        let paths =
-            Parser::default_submod_path(id, relative, &self.directory.path, self.sess.source_map());
-
-        match self.directory.ownership {
-            DirectoryOwnership::Owned { .. } => {
-                paths.result.map_err(|err| self.span_fatal_err(id_sp, err))
-            }
-            DirectoryOwnership::UnownedViaBlock => {
-                let msg = "Cannot declare a non-inline module inside a block \
-                    unless it has a path attribute";
-                let mut err = self.struct_span_err(id_sp, msg);
-                if paths.path_exists {
-                    let msg = format!(
-                        "Maybe `use` the module `{}` instead of redeclaring it",
-                        paths.name
-                    );
-                    err.span_note(id_sp, &msg);
-                }
-                Err(err)
-            }
-            DirectoryOwnership::UnownedViaMod => {
-                let mut err =
-                    self.struct_span_err(id_sp, "cannot declare a new module at this location");
-                if !id_sp.is_dummy() {
-                    let src_path = self.sess.source_map().span_to_filename(id_sp);
-                    if let FileName::Real(src_path) = src_path {
-                        if let Some(stem) = src_path.file_stem() {
-                            let mut dest_path = src_path.clone();
-                            dest_path.set_file_name(stem);
-                            dest_path.push("mod.rs");
-                            err.span_note(
-                                id_sp,
-                                &format!(
-                                    "maybe move this module `{}` to its own \
-                                                directory via `{}`",
-                                    src_path.display(),
-                                    dest_path.display()
-                                ),
-                            );
-                        }
-                    }
-                }
-                if paths.path_exists {
-                    err.span_note(
-                        id_sp,
-                        &format!(
-                            "... or maybe `use` the module `{}` instead \
-                                            of possibly redeclaring it",
-                            paths.name
-                        ),
-                    );
-                }
-                Err(err)
-            }
-        }
-    }
-
-    // Public for rustfmt usage.
-    pub fn submod_path_from_attr(attrs: &[Attribute], dir_path: &Path) -> Option<PathBuf> {
-        if let Some(s) = attr::first_attr_value_str_by_name(attrs, sym::path) {
-            let s = s.as_str();
-
-            // On windows, the base path might have the form
-            // `\\?\foo\bar` in which case it does not tolerate
-            // mixed `/` and `\` separators, so canonicalize
-            // `/` to `\`.
-            #[cfg(windows)]
-            let s = s.replace("/", "\\");
-            Some(dir_path.join(&*s))
-        } else {
-            None
-        }
-    }
-
-    /// Returns a path to a module.
-    // Public for rustfmt usage.
-    pub fn default_submod_path(
-        id: ast::Ident,
-        relative: Option<ast::Ident>,
-        dir_path: &Path,
-        source_map: &SourceMap,
-    ) -> ModulePath {
-        // If we're in a foo.rs file instead of a mod.rs file,
-        // we need to look for submodules in
-        // `./foo/<id>.rs` and `./foo/<id>/mod.rs` rather than
-        // `./<id>.rs` and `./<id>/mod.rs`.
-        let relative_prefix_string;
-        let relative_prefix = if let Some(ident) = relative {
-            relative_prefix_string = format!("{}{}", ident.name, path::MAIN_SEPARATOR);
-            &relative_prefix_string
-        } else {
-            ""
-        };
-
-        let mod_name = id.name.to_string();
-        let default_path_str = format!("{}{}.rs", relative_prefix, mod_name);
-        let secondary_path_str =
-            format!("{}{}{}mod.rs", relative_prefix, mod_name, path::MAIN_SEPARATOR);
-        let default_path = dir_path.join(&default_path_str);
-        let secondary_path = dir_path.join(&secondary_path_str);
-        let default_exists = source_map.file_exists(&default_path);
-        let secondary_exists = source_map.file_exists(&secondary_path);
-
-        let result = match (default_exists, secondary_exists) {
-            (true, false) => Ok(ModulePathSuccess {
-                path: default_path,
-                directory_ownership: DirectoryOwnership::Owned { relative: Some(id) },
-            }),
-            (false, true) => Ok(ModulePathSuccess {
-                path: secondary_path,
-                directory_ownership: DirectoryOwnership::Owned { relative: None },
-            }),
-            (false, false) => Err(Error::FileNotFoundForModule {
-                mod_name: mod_name.clone(),
-                default_path: default_path_str,
-                secondary_path: secondary_path_str,
-                dir_path: dir_path.display().to_string(),
-            }),
-            (true, true) => Err(Error::DuplicatePaths {
-                mod_name: mod_name.clone(),
-                default_path: default_path_str,
-                secondary_path: secondary_path_str,
-            }),
-        };
-
-        ModulePath { name: mod_name, path_exists: default_exists || secondary_exists, result }
-    }
-
-    /// Reads a module from a source file.
-    fn eval_src_mod(
-        &mut self,
-        path: PathBuf,
-        directory_ownership: DirectoryOwnership,
-        name: String,
-        id_sp: Span,
-    ) -> PResult<'a, (Mod, Vec<Attribute>)> {
-        let mut included_mod_stack = self.sess.included_mod_stack.borrow_mut();
-        if let Some(i) = included_mod_stack.iter().position(|p| *p == path) {
-            let mut err = String::from("circular modules: ");
-            let len = included_mod_stack.len();
-            for p in &included_mod_stack[i..len] {
-                err.push_str(&p.to_string_lossy());
-                err.push_str(" -> ");
-            }
-            err.push_str(&path.to_string_lossy());
-            return Err(self.struct_span_err(id_sp, &err[..]));
-        }
-        included_mod_stack.push(path.clone());
-        drop(included_mod_stack);
-
-        let mut p0 =
-            new_sub_parser_from_file(self.sess, &path, directory_ownership, Some(name), id_sp);
-        p0.cfg_mods = self.cfg_mods;
-        let mod_inner_lo = p0.token.span;
-        let mod_attrs = p0.parse_inner_attributes()?;
-        let mut m0 = p0.parse_mod_items(&token::Eof, mod_inner_lo)?;
-        m0.inline = false;
-        self.sess.included_mod_stack.borrow_mut().pop();
-        Ok((m0, mod_attrs))
-    }
-
-    fn push_directory(&mut self, id: Ident, attrs: &[Attribute]) {
-        if let Some(path) = attr::first_attr_value_str_by_name(attrs, sym::path) {
-            self.directory.path.push(&*path.as_str());
-            self.directory.ownership = DirectoryOwnership::Owned { relative: None };
-        } else {
-            // We have to push on the current module name in the case of relative
-            // paths in order to ensure that any additional module paths from inline
-            // `mod x { ... }` come after the relative extension.
-            //
-            // For example, a `mod z { ... }` inside `x/y.rs` should set the current
-            // directory path to `/x/y/z`, not `/x/z` with a relative offset of `y`.
-            if let DirectoryOwnership::Owned { relative } = &mut self.directory.ownership {
-                if let Some(ident) = relative.take() {
-                    // remove the relative offset
-                    self.directory.path.push(&*ident.as_str());
-                }
-            }
-            self.directory.path.push(&*id.as_str());
-        }
-    }
-}
index 45d1aacdd3cc6cf226abbb2164c52cad273f2606..4585941943b74a001a64c10a85ae14c2370e55d4 100644 (file)
@@ -1,9 +1,7 @@
 use super::{Parser, PathStyle};
 use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
-use rustc_ast::ast::{
-    self, AttrVec, Attribute, FieldPat, Mac, Pat, PatKind, RangeEnd, RangeSyntax,
-};
-use rustc_ast::ast::{BindingMode, Expr, ExprKind, Ident, Mutability, Path, QSelf};
+use rustc_ast::ast::{self, AttrVec, Attribute, FieldPat, MacCall, Pat, PatKind, RangeEnd};
+use rustc_ast::ast::{BindingMode, Expr, ExprKind, Ident, Mutability, Path, QSelf, RangeSyntax};
 use rustc_ast::mut_visit::{noop_visit_mac, noop_visit_pat, MutVisitor};
 use rustc_ast::ptr::P;
 use rustc_ast::token;
@@ -151,7 +149,7 @@ fn eat_or_separator(&mut self, lo: Option<Span>) -> bool {
     /// Note that there are more tokens such as `@` for which we know that the `|`
     /// is an illegal parse. However, the user's intent is less clear in that case.
     fn recover_trailing_vert(&mut self, lo: Option<Span>) -> bool {
-        let is_end_ahead = self.look_ahead(1, |token| match &token.kind {
+        let is_end_ahead = self.look_ahead(1, |token| match &token.uninterpolate().kind {
             token::FatArrow // e.g. `a | => 0,`.
             | token::Ident(kw::If, false) // e.g. `a | if expr`.
             | token::Eq // e.g. `let a | = 0`.
@@ -479,7 +477,7 @@ fn parse_pat_tuple_or_parens(&mut self) -> PResult<'a, PatKind> {
         // Here, `(pat,)` is a tuple pattern.
         // For backward compatibility, `(..)` is a tuple pattern as well.
         Ok(if fields.len() == 1 && !(trailing_comma || fields[0].is_rest()) {
-            PatKind::Paren(fields.into_iter().nth(0).unwrap())
+            PatKind::Paren(fields.into_iter().next().unwrap())
         } else {
             PatKind::Tuple(fields)
         })
@@ -540,7 +538,7 @@ fn recover_mut_ref_ident(&mut self, lo: Span) -> PResult<'a, PatKind> {
     fn make_all_value_bindings_mutable(pat: &mut P<Pat>) -> bool {
         struct AddMut(bool);
         impl MutVisitor for AddMut {
-            fn visit_mac(&mut self, mac: &mut Mac) {
+            fn visit_mac(&mut self, mac: &mut MacCall) {
                 noop_visit_mac(mac, self);
             }
 
@@ -597,8 +595,8 @@ fn recover_additional_muts(&mut self) {
     fn parse_pat_mac_invoc(&mut self, path: Path) -> PResult<'a, PatKind> {
         self.bump();
         let args = self.parse_mac_args()?;
-        let mac = Mac { path, args, prior_type_ascription: self.last_type_ascription };
-        Ok(PatKind::Mac(mac))
+        let mac = MacCall { path, args, prior_type_ascription: self.last_type_ascription };
+        Ok(PatKind::MacCall(mac))
     }
 
     fn fatal_unexpected_non_pat(
@@ -704,7 +702,7 @@ fn is_pat_range_end_start(&self, dist: usize) -> bool {
     }
 
     fn parse_pat_range_end(&mut self) -> PResult<'a, P<Expr>> {
-        if self.token.is_path_start() {
+        if self.check_path() {
             let lo = self.token.span;
             let (qself, path) = if self.eat_lt() {
                 // Parse a qualified path
index 355b6429a7494fdc8122120e81b88c766ffeb357..f88b4fe6ff0a8dfedec357ab9a8802e6797599ce 100644 (file)
@@ -240,10 +240,10 @@ pub(super) fn parse_path_segment(&mut self, style: PathStyle) -> PResult<'a, Pat
     }
 
     pub(super) fn parse_path_segment_ident(&mut self) -> PResult<'a, Ident> {
-        match self.normalized_token.kind {
-            token::Ident(name, _) if name.is_path_segment_keyword() => {
+        match self.token.ident() {
+            Some((ident, false)) if ident.is_path_segment_keyword() => {
                 self.bump();
-                Ok(Ident::new(name, self.normalized_prev_token.span))
+                Ok(ident)
             }
             _ => self.parse_ident(),
         }
index e38a7f2f1c2a251b59087a72c0bbe957c840dfd4..d40597d8fcb0c543127dc61e155dd87e54b84bd7 100644 (file)
@@ -1,13 +1,13 @@
+use super::attr::DEFAULT_INNER_ATTR_FORBIDDEN;
 use super::diagnostics::Error;
 use super::expr::LhsExpr;
 use super::pat::GateOr;
 use super::path::PathStyle;
 use super::{BlockMode, Parser, Restrictions, SemiColonMode};
 use crate::maybe_whole;
-use crate::DirectoryOwnership;
 
 use rustc_ast::ast;
-use rustc_ast::ast::{AttrStyle, AttrVec, Attribute, Mac, MacStmtStyle};
+use rustc_ast::ast::{AttrStyle, AttrVec, Attribute, MacCall, MacStmtStyle};
 use rustc_ast::ast::{Block, BlockCheckMode, Expr, ExprKind, Local, Stmt, StmtKind, DUMMY_NODE_ID};
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, TokenKind};
@@ -47,35 +47,19 @@ fn parse_stmt_without_recovery(&mut self) -> PResult<'a, Option<Stmt>> {
             self.bump(); // `var`
             let msg = "write `let` instead of `var` to introduce a new variable";
             self.recover_stmt_local(lo, attrs.into(), msg, "let")?
-        } else if self.token.is_path_start()
-            && !self.token.is_qpath_start()
-            && !self.is_path_start_item()
-        {
+        } else if self.check_path() && !self.token.is_qpath_start() && !self.is_path_start_item() {
             // We have avoided contextual keywords like `union`, items with `crate` visibility,
             // or `auto trait` items. We aim to parse an arbitrary path `a::b` but not something
             // that starts like a path (1 token), but it fact not a path.
             // Also, we avoid stealing syntax from `parse_item_`.
             self.parse_stmt_path_start(lo, attrs)?
-        } else if let Some(item) = self.parse_stmt_item(attrs.clone())? {
+        } else if let Some(item) = self.parse_item_common(attrs.clone(), false, true, |_| true)? {
             // FIXME: Bad copy of attrs
             self.mk_stmt(lo.to(item.span), StmtKind::Item(P(item)))
-        } else if self.token == token::Semi {
+        } else if self.eat(&token::Semi) {
             // Do not attempt to parse an expression if we're done here.
             self.error_outer_attrs(&attrs);
-            self.bump();
-            let mut last_semi = lo;
-            while self.token == token::Semi {
-                last_semi = self.token.span;
-                self.bump();
-            }
-            // We are encoding a string of semicolons as an an empty tuple that spans
-            // the excess semicolons to preserve this info until the lint stage.
-            let kind = StmtKind::Semi(self.mk_expr(
-                lo.to(last_semi),
-                ExprKind::Tup(Vec::new()),
-                AttrVec::new(),
-            ));
-            self.mk_stmt(lo.to(last_semi), kind)
+            self.mk_stmt(lo, StmtKind::Empty)
         } else if self.token != token::CloseDelim(token::Brace) {
             // Remainder are line-expr stmts.
             let e = self.parse_expr_res(Restrictions::STMT_EXPR, Some(attrs.into()))?;
@@ -87,13 +71,6 @@ fn parse_stmt_without_recovery(&mut self) -> PResult<'a, Option<Stmt>> {
         Ok(Some(stmt))
     }
 
-    fn parse_stmt_item(&mut self, attrs: Vec<Attribute>) -> PResult<'a, Option<ast::Item>> {
-        let old = mem::replace(&mut self.directory.ownership, DirectoryOwnership::UnownedViaBlock);
-        let item = self.parse_item_common(attrs, false, true, |_| true)?;
-        self.directory.ownership = old;
-        Ok(item)
-    }
-
     fn parse_stmt_path_start(&mut self, lo: Span, attrs: Vec<Attribute>) -> PResult<'a, Stmt> {
         let path = self.parse_path(PathStyle::Expr)?;
 
@@ -125,14 +102,14 @@ fn parse_stmt_mac(&mut self, lo: Span, attrs: AttrVec, path: ast::Path) -> PResu
         let style =
             if delim == token::Brace { MacStmtStyle::Braces } else { MacStmtStyle::NoBraces };
 
-        let mac = Mac { path, args, prior_type_ascription: self.last_type_ascription };
+        let mac = MacCall { path, args, prior_type_ascription: self.last_type_ascription };
 
         let kind = if delim == token::Brace || self.token == token::Semi || self.token == token::Eof
         {
-            StmtKind::Mac(P((mac, style, attrs)))
+            StmtKind::MacCall(P((mac, style, attrs)))
         } else {
             // Since none of the above applied, this is an expression statement macro.
-            let e = self.mk_expr(lo.to(hi), ExprKind::Mac(mac), AttrVec::new());
+            let e = self.mk_expr(lo.to(hi), ExprKind::MacCall(mac), AttrVec::new());
             let e = self.maybe_recover_from_bad_qpath(e, true)?;
             let e = self.parse_dot_or_call_expr_with(e, lo, attrs)?;
             let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e))?;
@@ -144,12 +121,11 @@ fn parse_stmt_mac(&mut self, lo: Span, attrs: AttrVec, path: ast::Path) -> PResu
     /// Error on outer attributes in this context.
     /// Also error if the previous token was a doc comment.
     fn error_outer_attrs(&self, attrs: &[Attribute]) {
-        if !attrs.is_empty() {
-            if matches!(self.prev_token.kind, TokenKind::DocComment(..)) {
-                self.span_fatal_err(self.prev_token.span, Error::UselessDocComment).emit();
+        if let [.., last] = attrs {
+            if last.is_doc_comment() {
+                self.span_fatal_err(last.span, Error::UselessDocComment).emit();
             } else if attrs.iter().any(|a| a.style == AttrStyle::Outer) {
-                self.struct_span_err(self.token.span, "expected statement after outer attribute")
-                    .emit();
+                self.struct_span_err(last.span, "expected statement after outer attribute").emit();
             }
         }
     }
@@ -252,15 +228,11 @@ fn parse_initializer(&mut self, skip_eq: bool) -> PResult<'a, Option<P<Expr>>> {
 
     /// Parses a block. No inner attributes are allowed.
     pub fn parse_block(&mut self) -> PResult<'a, P<Block>> {
-        maybe_whole!(self, NtBlock, |x| x);
-
-        let lo = self.token.span;
-
-        if !self.eat(&token::OpenDelim(token::Brace)) {
-            return self.error_block_no_opening_brace();
+        let (attrs, block) = self.parse_inner_attrs_and_block()?;
+        if let [.., last] = &*attrs {
+            self.error_on_forbidden_inner_attr(last.span, DEFAULT_INNER_ATTR_FORBIDDEN);
         }
-
-        self.parse_block_tail(lo, BlockCheckMode::Default)
+        Ok(block)
     }
 
     fn error_block_no_opening_brace<T>(&mut self) -> PResult<'a, T> {
@@ -276,16 +248,14 @@ fn error_block_no_opening_brace<T>(&mut self) -> PResult<'a, T> {
         //
         // which is valid in other languages, but not Rust.
         match self.parse_stmt_without_recovery() {
-            Ok(Some(stmt)) => {
+            // If the next token is an open brace (e.g., `if a b {`), the place-
+            // inside-a-block suggestion would be more likely wrong than right.
+            Ok(Some(_))
                 if self.look_ahead(1, |t| t == &token::OpenDelim(token::Brace))
-                    || do_not_suggest_help
-                {
-                    // If the next token is an open brace (e.g., `if a b {`), the place-
-                    // inside-a-block suggestion would be more likely wrong than right.
-                    e.span_label(sp, "expected `{`");
-                    return Err(e);
-                }
-                let stmt_span = if self.eat(&token::Semi) {
+                    || do_not_suggest_help => {}
+            Ok(Some(stmt)) => {
+                let stmt_own_line = self.sess.source_map().is_line_before_span_empty(sp);
+                let stmt_span = if stmt_own_line && self.eat(&token::Semi) {
                     // Expand the span to include the semicolon.
                     stmt.span.with_hi(self.prev_token.span.hi())
                 } else {
@@ -314,21 +284,28 @@ fn error_block_no_opening_brace<T>(&mut self) -> PResult<'a, T> {
     /// Parses a block. Inner attributes are allowed.
     pub(super) fn parse_inner_attrs_and_block(
         &mut self,
+    ) -> PResult<'a, (Vec<Attribute>, P<Block>)> {
+        self.parse_block_common(self.token.span, BlockCheckMode::Default)
+    }
+
+    /// Parses a block. Inner attributes are allowed.
+    pub(super) fn parse_block_common(
+        &mut self,
+        lo: Span,
+        blk_mode: BlockCheckMode,
     ) -> PResult<'a, (Vec<Attribute>, P<Block>)> {
         maybe_whole!(self, NtBlock, |x| (Vec::new(), x));
 
-        let lo = self.token.span;
-        self.expect(&token::OpenDelim(token::Brace))?;
-        Ok((self.parse_inner_attributes()?, self.parse_block_tail(lo, BlockCheckMode::Default)?))
+        if !self.eat(&token::OpenDelim(token::Brace)) {
+            return self.error_block_no_opening_brace();
+        }
+
+        Ok((self.parse_inner_attributes()?, self.parse_block_tail(lo, blk_mode)?))
     }
 
     /// Parses the rest of a block expression or function body.
     /// Precondition: already parsed the '{'.
-    pub(super) fn parse_block_tail(
-        &mut self,
-        lo: Span,
-        s: BlockCheckMode,
-    ) -> PResult<'a, P<Block>> {
+    fn parse_block_tail(&mut self, lo: Span, s: BlockCheckMode) -> PResult<'a, P<Block>> {
         let mut stmts = vec![];
         while !self.eat(&token::CloseDelim(token::Brace)) {
             if self.token == token::Eof {
@@ -401,6 +378,7 @@ pub fn parse_full_stmt(&mut self) -> PResult<'a, Option<Stmt>> {
                 self.expect_semi()?;
                 eat_semi = false;
             }
+            StmtKind::Empty => eat_semi = false,
             _ => {}
         }
 
index 3d2b0c014ac4977ed29a3bdb8921cb5190e99c99..c21ac8d04f194043465bfa27b53fcf7db7718bf1 100644 (file)
@@ -3,10 +3,8 @@
 use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
 
 use rustc_ast::ast::{self, BareFnTy, FnRetTy, GenericParam, Lifetime, MutTy, Ty, TyKind};
-use rustc_ast::ast::{
-    GenericBound, GenericBounds, PolyTraitRef, TraitBoundModifier, TraitObjectSyntax,
-};
-use rustc_ast::ast::{Mac, Mutability};
+use rustc_ast::ast::{GenericBound, GenericBounds, MacCall, Mutability};
+use rustc_ast::ast::{PolyTraitRef, TraitBoundModifier, TraitObjectSyntax};
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Token, TokenKind};
 use rustc_errors::{pluralize, struct_span_err, Applicability, PResult};
@@ -142,24 +140,20 @@ fn parse_ty_common(
             } else {
                 let path = self.parse_path(PathStyle::Type)?;
                 let parse_plus = allow_plus == AllowPlus::Yes && self.check_plus();
-                self.parse_remaining_bounds(lifetime_defs, path, lo, parse_plus)?
+                self.parse_remaining_bounds_path(lifetime_defs, path, lo, parse_plus)?
             }
         } else if self.eat_keyword(kw::Impl) {
             self.parse_impl_ty(&mut impl_dyn_multi)?
         } else if self.is_explicit_dyn_type() {
             self.parse_dyn_ty(&mut impl_dyn_multi)?
-        } else if self.check(&token::Question)
-            || self.check_lifetime() && self.look_ahead(1, |t| t.is_like_plus())
-        {
-            // Bound list (trait object type)
-            let bounds = self.parse_generic_bounds_common(allow_plus, None)?;
-            TyKind::TraitObject(bounds, TraitObjectSyntax::None)
         } else if self.eat_lt() {
             // Qualified path
             let (qself, path) = self.parse_qpath(PathStyle::Type)?;
             TyKind::Path(Some(qself), path)
-        } else if self.token.is_path_start() {
+        } else if self.check_path() {
             self.parse_path_start_ty(lo, allow_plus)?
+        } else if self.can_begin_bound() {
+            self.parse_bare_trait_object(lo, allow_plus)?
         } else if self.eat(&token::DotDotDot) {
             if allow_c_variadic == AllowCVariadic::Yes {
                 TyKind::CVarArgs
@@ -198,26 +192,17 @@ fn parse_ty_tuple_or_parens(&mut self, lo: Span, allow_plus: AllowPlus) -> PResu
         })?;
 
         if ts.len() == 1 && !trailing {
-            let ty = ts.into_iter().nth(0).unwrap().into_inner();
+            let ty = ts.into_iter().next().unwrap().into_inner();
             let maybe_bounds = allow_plus == AllowPlus::Yes && self.token.is_like_plus();
             match ty.kind {
                 // `(TY_BOUND_NOPAREN) + BOUND + ...`.
                 TyKind::Path(None, path) if maybe_bounds => {
-                    self.parse_remaining_bounds(Vec::new(), path, lo, true)
+                    self.parse_remaining_bounds_path(Vec::new(), path, lo, true)
                 }
-                TyKind::TraitObject(mut bounds, TraitObjectSyntax::None)
+                TyKind::TraitObject(bounds, TraitObjectSyntax::None)
                     if maybe_bounds && bounds.len() == 1 && !trailing_plus =>
                 {
-                    let path = match bounds.remove(0) {
-                        GenericBound::Trait(pt, ..) => pt.trait_ref.path,
-                        GenericBound::Outlives(..) => {
-                            return Err(self.struct_span_err(
-                                ty.span,
-                                "expected trait bound, not lifetime bound",
-                            ));
-                        }
-                    };
-                    self.parse_remaining_bounds(Vec::new(), path, lo, true)
+                    self.parse_remaining_bounds(bounds, true)
                 }
                 // `(TYPE)`
                 _ => Ok(TyKind::Paren(P(ty))),
@@ -227,18 +212,35 @@ fn parse_ty_tuple_or_parens(&mut self, lo: Span, allow_plus: AllowPlus) -> PResu
         }
     }
 
-    fn parse_remaining_bounds(
+    fn parse_bare_trait_object(&mut self, lo: Span, allow_plus: AllowPlus) -> PResult<'a, TyKind> {
+        let lt_no_plus = self.check_lifetime() && !self.look_ahead(1, |t| t.is_like_plus());
+        let bounds = self.parse_generic_bounds_common(allow_plus, None)?;
+        if lt_no_plus {
+            self.struct_span_err(lo, "lifetime in trait object type must be followed by `+`").emit()
+        }
+        Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::None))
+    }
+
+    fn parse_remaining_bounds_path(
         &mut self,
         generic_params: Vec<GenericParam>,
         path: ast::Path,
         lo: Span,
         parse_plus: bool,
     ) -> PResult<'a, TyKind> {
-        assert_ne!(self.token, token::Question);
-
         let poly_trait_ref = PolyTraitRef::new(generic_params, path, lo.to(self.prev_token.span));
-        let mut bounds = vec![GenericBound::Trait(poly_trait_ref, TraitBoundModifier::None)];
-        if parse_plus {
+        let bounds = vec![GenericBound::Trait(poly_trait_ref, TraitBoundModifier::None)];
+        self.parse_remaining_bounds(bounds, parse_plus)
+    }
+
+    /// Parse the remainder of a bare trait object type given an already parsed list.
+    fn parse_remaining_bounds(
+        &mut self,
+        mut bounds: GenericBounds,
+        plus: bool,
+    ) -> PResult<'a, TyKind> {
+        assert_ne!(self.token, token::Question);
+        if plus {
             self.eat_plus(); // `+`, or `+=` gets split and `+` is discarded
             bounds.append(&mut self.parse_generic_bounds(Some(self.prev_token.span))?);
         }
@@ -323,7 +325,7 @@ fn parse_impl_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind> {
     /// Is a `dyn B0 + ... + Bn` type allowed here?
     fn is_explicit_dyn_type(&mut self) -> bool {
         self.check_keyword(kw::Dyn)
-            && (self.normalized_token.span.rust_2018()
+            && (self.token.uninterpolated_span().rust_2018()
                 || self.look_ahead(1, |t| {
                     t.can_begin_bound() && !can_continue_type_after_non_fn_ident(t)
                 }))
@@ -351,14 +353,14 @@ fn parse_path_start_ty(&mut self, lo: Span, allow_plus: AllowPlus) -> PResult<'a
         let path = self.parse_path(PathStyle::Type)?;
         if self.eat(&token::Not) {
             // Macro invocation in type position
-            Ok(TyKind::Mac(Mac {
+            Ok(TyKind::MacCall(MacCall {
                 path,
                 args: self.parse_mac_args()?,
                 prior_type_ascription: self.last_type_ascription,
             }))
         } else if allow_plus == AllowPlus::Yes && self.check_plus() {
             // `Trait1 + Trait2 + 'a`
-            self.parse_remaining_bounds(Vec::new(), path, lo, true)
+            self.parse_remaining_bounds_path(Vec::new(), path, lo, true)
         } else {
             // Just a type path.
             Ok(TyKind::Path(None, path))
index 029aa5ed2baea81fc4b2f87acf8653becb364c5b..2512878ec65be06d77eedc820e0a9fa9edbed196 100644 (file)
@@ -57,7 +57,7 @@ pub fn parse_meta<'a>(sess: &'a ParseSess, attr: &Attribute) -> PResult<'a, Meta
     })
 }
 
-crate fn check_meta_bad_delim(sess: &ParseSess, span: DelimSpan, delim: MacDelimiter, msg: &str) {
+pub fn check_meta_bad_delim(sess: &ParseSess, span: DelimSpan, delim: MacDelimiter, msg: &str) {
     if let ast::MacDelimiter::Parenthesis = delim {
         return;
     }
index af8e7a5b71e46a86b4417fbbb41cc7bfa4609c28..8acb88f58d379cad6b3dfe99190e0b67e5afecc4 100644 (file)
@@ -22,3 +22,4 @@ rustc_session = { path = "../librustc_session" }
 rustc_target = { path = "../librustc_target" }
 rustc_ast = { path = "../librustc_ast" }
 rustc_span = { path = "../librustc_span" }
+rustc_trait_selection = { path = "../librustc_trait_selection" }
index f1ed074d6ab7708e8a618417597ee7a8722b09f1..373b7c56d3802e119d650083e52ad9bda576d1b0 100644 (file)
@@ -25,7 +25,7 @@
 fn target_from_impl_item<'tcx>(tcx: TyCtxt<'tcx>, impl_item: &hir::ImplItem<'_>) -> Target {
     match impl_item.kind {
         hir::ImplItemKind::Const(..) => Target::AssocConst,
-        hir::ImplItemKind::Method(..) => {
+        hir::ImplItemKind::Fn(..) => {
             let parent_hir_id = tcx.hir().get_parent_item(impl_item.hir_id);
             let containing_item = tcx.hir().expect_item(parent_hir_id);
             let containing_impl_is_for_trait = match &containing_item.kind {
@@ -418,8 +418,8 @@ fn check_used(&self, attrs: &'hir [Attribute], target: Target) {
 impl Visitor<'tcx> for CheckAttrVisitor<'tcx> {
     type Map = Map<'tcx>;
 
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, Self::Map> {
-        NestedVisitorMap::OnlyBodies(&self.tcx.hir())
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::OnlyBodies(self.tcx.hir())
     }
 
     fn visit_item(&mut self, item: &'tcx Item<'tcx>) {
index 53e8213ae4807795254b0888082df6e07ce89a80..30737360b9c20098f3c81f3d40712cd82b4e45aa 100644 (file)
@@ -8,9 +8,6 @@
 //! through, but errors for structured control flow in a `const` should be emitted here.
 
 use rustc::hir::map::Map;
-use rustc::hir::Hir;
-use rustc::session::config::nightly_options;
-use rustc::session::parse::feature_err;
 use rustc::ty::query::Providers;
 use rustc::ty::TyCtxt;
 use rustc_ast::ast::Mutability;
@@ -18,6 +15,8 @@
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
+use rustc_session::config::nightly_options;
+use rustc_session::parse::feature_err;
 use rustc_span::{sym, Span, Symbol};
 
 use std::fmt;
@@ -75,7 +74,7 @@ enum ConstKind {
 }
 
 impl ConstKind {
-    fn for_body(body: &hir::Body<'_>, hir_map: Hir<'_>) -> Option<Self> {
+    fn for_body(body: &hir::Body<'_>, hir_map: Map<'_>) -> Option<Self> {
         let is_const_fn = |id| hir_map.fn_sig_by_hir_id(id).unwrap().header.is_const();
 
         let owner = hir_map.body_owner(body.id());
@@ -202,8 +201,8 @@ fn recurse_into(&mut self, kind: Option<ConstKind>, f: impl FnOnce(&mut Self)) {
 impl<'tcx> Visitor<'tcx> for CheckConstVisitor<'tcx> {
     type Map = Map<'tcx>;
 
-    fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> {
-        NestedVisitorMap::OnlyBodies(&self.tcx.hir())
+    fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::OnlyBodies(self.tcx.hir())
     }
 
     fn visit_anon_const(&mut self, anon: &'tcx hir::AnonConst) {
index bcf9fd5a5353fdf16cc12aa213d2a0dce1a06033..4466dea89b0c1806185fd5f872f890fb4aa1de70 100644 (file)
@@ -210,9 +210,9 @@ fn mark_as_used_if_union(&mut self, adt: &ty::AdtDef, fields: &[hir::Field<'_>])
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> {
-    type Map = Map<'tcx>;
+    type Map = intravisit::ErasedMap<'tcx>;
 
-    fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> {
+    fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
         NestedVisitorMap::None
     }
 
@@ -391,7 +391,7 @@ fn visit_item(&mut self, item: &hir::Item<'_>) {
                     let trait_item = self.krate.trait_item(trait_item_ref.id);
                     match trait_item.kind {
                         hir::TraitItemKind::Const(_, Some(_))
-                        | hir::TraitItemKind::Method(_, hir::TraitMethod::Provided(_)) => {
+                        | hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)) => {
                             if has_allow_dead_code_or_lang_attr(
                                 self.tcx,
                                 trait_item.hir_id,
@@ -568,8 +568,8 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> {
     /// on inner functions when the outer function is already getting
     /// an error. We could do this also by checking the parents, but
     /// this is how the code is setup and it seems harmless enough.
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
-        NestedVisitorMap::All(&self.tcx.hir())
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::All(self.tcx.hir())
     }
 
     fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
@@ -661,7 +661,7 @@ fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
                 }
                 self.visit_nested_body(body_id)
             }
-            hir::ImplItemKind::Method(_, body_id) => {
+            hir::ImplItemKind::Fn(_, body_id) => {
                 if !self.symbol_is_live(impl_item.hir_id) {
                     let span = self.tcx.sess.source_map().def_span(impl_item.span);
                     self.warn_dead_code(
@@ -682,11 +682,11 @@ fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
     fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
         match trait_item.kind {
             hir::TraitItemKind::Const(_, Some(body_id))
-            | hir::TraitItemKind::Method(_, hir::TraitMethod::Provided(body_id)) => {
+            | hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(body_id)) => {
                 self.visit_nested_body(body_id)
             }
             hir::TraitItemKind::Const(_, None)
-            | hir::TraitItemKind::Method(_, hir::TraitMethod::Required(_))
+            | hir::TraitItemKind::Fn(_, hir::TraitFn::Required(_))
             | hir::TraitItemKind::Type(..) => {}
         }
     }
index f2239ad16eeb329c1e5938dabd96456ff1c5d7f4..7e0d0bfe9aba45c662b411e33a08bce412ddd9b8 100644 (file)
@@ -1,6 +1,4 @@
-use rustc::hir::Hir;
-use rustc::session::config::EntryFnType;
-use rustc::session::{config, Session};
+use rustc::hir::map::Map;
 use rustc::ty::query::Providers;
 use rustc::ty::TyCtxt;
 use rustc_ast::attr;
@@ -9,13 +7,15 @@
 use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_hir::{HirId, ImplItem, Item, ItemKind, TraitItem};
+use rustc_session::config::EntryFnType;
+use rustc_session::{config, Session};
 use rustc_span::symbol::sym;
 use rustc_span::{Span, DUMMY_SP};
 
 struct EntryContext<'a, 'tcx> {
     session: &'a Session,
 
-    map: Hir<'tcx>,
+    map: Map<'tcx>,
 
     /// The top-level function called `main`.
     main_fn: Option<(HirId, Span)>,
@@ -34,7 +34,7 @@ struct EntryContext<'a, 'tcx> {
 impl<'a, 'tcx> ItemLikeVisitor<'tcx> for EntryContext<'a, 'tcx> {
     fn visit_item(&mut self, item: &'tcx Item<'tcx>) {
         let def_id = self.map.local_def_id(item.hir_id);
-        let def_key = self.map.def_key(def_id);
+        let def_key = self.map.def_key(def_id.expect_local());
         let at_root = def_key.parent == Some(CRATE_DEF_INDEX);
         find_item(item, self, at_root);
     }
@@ -59,7 +59,7 @@ fn entry_fn(tcx: TyCtxt<'_>, cnum: CrateNum) -> Option<(DefId, EntryFnType)> {
     }
 
     // If the user wants no main function at all, then stop here.
-    if attr::contains_name(&tcx.hir().krate().attrs, sym::no_main) {
+    if attr::contains_name(&tcx.hir().krate().item.attrs, sym::no_main) {
         return None;
     }
 
@@ -157,7 +157,7 @@ fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) -> Option<(De
 }
 
 fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) {
-    let sp = tcx.hir().krate().span;
+    let sp = tcx.hir().krate().item.span;
     if *tcx.sess.parse_sess.reached_eof.borrow() {
         // There's an unclosed brace that made the parser reach `Eof`, we shouldn't complain about
         // the missing `fn main()` then as it might have been hidden inside an unclosed block.
@@ -196,7 +196,7 @@ fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) {
     // The file may be empty, which leads to the diagnostic machinery not emitting this
     // note. This is a relatively simple way to detect that case and emit a span-less
     // note instead.
-    if let Ok(_) = tcx.sess.source_map().lookup_line(sp.lo()) {
+    if tcx.sess.source_map().lookup_line(sp.lo()).is_ok() {
         err.set_span(sp);
         err.span_label(sp, &note);
     } else {
index c819809041f280d46bdba14fd18a8d0e299fb259..8bfe58da78f6e4077a7e18cae0c2d2e6578a755c 100644 (file)
@@ -95,7 +95,7 @@ fn visit_param(&mut self, param: &'v hir::Param<'v>) {
 
     type Map = Map<'v>;
 
-    fn nested_visit_map(&mut self) -> hir_visit::NestedVisitorMap<'_, Self::Map> {
+    fn nested_visit_map(&mut self) -> hir_visit::NestedVisitorMap<Self::Map> {
         panic!("visit_nested_xxx must be manually implemented in this visitor")
     }
 
@@ -336,8 +336,8 @@ fn visit_lifetime(&mut self, lifetime: &'v ast::Lifetime) {
         ast_visit::walk_lifetime(self, lifetime)
     }
 
-    fn visit_mac(&mut self, mac: &'v ast::Mac) {
-        self.record("Mac", Id::None, mac);
+    fn visit_mac(&mut self, mac: &'v ast::MacCall) {
+        self.record("MacCall", Id::None, mac);
     }
 
     fn visit_path_segment(&mut self, path_span: Span, path_segment: &'v ast::PathSegment) {
index 782199003c72a744bc1f9320cb72906735241c67..1b46aaeefcb18f28e98169353468a78315d78090 100644 (file)
@@ -1,4 +1,3 @@
-use rustc::hir::map::Map;
 use rustc::ty::layout::{LayoutError, Pointer, SizeSkeleton, VariantIdx};
 use rustc::ty::query::Providers;
 use rustc::ty::{self, Ty, TyCtxt};
@@ -122,9 +121,9 @@ fn check_transmute(&self, span: Span, from: Ty<'tcx>, to: Ty<'tcx>) {
 }
 
 impl Visitor<'tcx> for ItemVisitor<'tcx> {
-    type Map = Map<'tcx>;
+    type Map = intravisit::ErasedMap<'tcx>;
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
         NestedVisitorMap::None
     }
 
@@ -139,9 +138,9 @@ fn visit_nested_body(&mut self, body_id: hir::BodyId) {
 }
 
 impl Visitor<'tcx> for ExprVisitor<'tcx> {
-    type Map = Map<'tcx>;
+    type Map = intravisit::ErasedMap<'tcx>;
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
         NestedVisitorMap::None
     }
 
index 5f5acc7fdf8150eddc480f25811f23ca502b8ce5..88e92bbdba1aa00021319ae1ff8914c8e52f8b17 100644 (file)
@@ -143,7 +143,7 @@ fn collect_item(&mut self, item_index: usize, item_def_id: DefId) {
 }
 
 /// Traverses and collects all the lang items in all crates.
-fn collect<'tcx>(tcx: TyCtxt<'tcx>) -> LanguageItems {
+fn collect(tcx: TyCtxt<'_>) -> LanguageItems {
     // Initialize the collector.
     let mut collector = LanguageItemCollector::new(tcx);
 
index 172d7e7628e2157c4649aa97c72460c1a112a4e2..133e30f6ff01a2cf61f3a73830e7a6796c801329 100644 (file)
@@ -114,8 +114,8 @@ fn span_feature_error(&self, span: Span, msg: &str) {
 impl Visitor<'tcx> for LibFeatureCollector<'tcx> {
     type Map = Map<'tcx>;
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
-        NestedVisitorMap::All(&self.tcx.hir())
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::All(self.tcx.hir())
     }
 
     fn visit_attribute(&mut self, attr: &'tcx Attribute) {
index 5b6d0fc74e80f2966221980b663f38057893f294..70b106f5d2332eb0c11736d87cd7d463e984c9ff 100644 (file)
@@ -97,7 +97,6 @@
 use self::VarKind::*;
 
 use rustc::hir::map::Map;
-use rustc::lint;
 use rustc::ty::query::Providers;
 use rustc::ty::{self, TyCtxt};
 use rustc_ast::ast;
 use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::{self, FnKind, NestedVisitorMap, Visitor};
 use rustc_hir::{Expr, HirId, HirIdMap, HirIdSet, Node};
+use rustc_session::lint;
 use rustc_span::symbol::sym;
 use rustc_span::Span;
 
@@ -156,8 +156,8 @@ fn live_node_kind_to_string(lnk: LiveNodeKind, tcx: TyCtxt<'_>) -> String {
 impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> {
     type Map = Map<'tcx>;
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
-        NestedVisitorMap::OnlyBodies(&self.tcx.hir())
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::OnlyBodies(self.tcx.hir())
     }
 
     fn visit_fn(
@@ -398,7 +398,7 @@ fn visit_fn<'tcx>(
     intravisit::walk_fn(&mut fn_maps, fk, decl, body_id, sp, id);
 
     // compute liveness
-    let mut lsets = Liveness::new(&mut fn_maps, body_id);
+    let mut lsets = Liveness::new(&mut fn_maps, def_id);
     let entry_ln = lsets.compute(&body.value);
 
     // check for various error conditions
@@ -658,6 +658,7 @@ struct Specials {
 struct Liveness<'a, 'tcx> {
     ir: &'a mut IrMaps<'tcx>,
     tables: &'a ty::TypeckTables<'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
     s: Specials,
     successors: Vec<LiveNode>,
     rwu_table: RWUTable,
@@ -670,7 +671,7 @@ struct Liveness<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> Liveness<'a, 'tcx> {
-    fn new(ir: &'a mut IrMaps<'tcx>, body: hir::BodyId) -> Liveness<'a, 'tcx> {
+    fn new(ir: &'a mut IrMaps<'tcx>, def_id: DefId) -> Liveness<'a, 'tcx> {
         // Special nodes and variables:
         // - exit_ln represents the end of the fn, either by return or panic
         // - implicit_ret_var is a pseudo-variable that represents
@@ -681,7 +682,8 @@ fn new(ir: &'a mut IrMaps<'tcx>, body: hir::BodyId) -> Liveness<'a, 'tcx> {
             clean_exit_var: ir.add_variable(CleanExit),
         };
 
-        let tables = ir.tcx.body_tables(body);
+        let tables = ir.tcx.typeck_tables_of(def_id);
+        let param_env = ir.tcx.param_env(def_id);
 
         let num_live_nodes = ir.num_live_nodes;
         let num_vars = ir.num_vars;
@@ -689,6 +691,7 @@ fn new(ir: &'a mut IrMaps<'tcx>, body: hir::BodyId) -> Liveness<'a, 'tcx> {
         Liveness {
             ir,
             tables,
+            param_env,
             s: specials,
             successors: vec![invalid_node(); num_live_nodes],
             rwu_table: RWUTable::new(num_live_nodes * num_vars),
@@ -1125,8 +1128,12 @@ fn propagate_through_expr(&mut self, expr: &Expr<'_>, succ: LiveNode) -> LiveNod
             }
 
             hir::ExprKind::Call(ref f, ref args) => {
-                let m = self.ir.tcx.parent_module(expr.hir_id);
-                let succ = if self.ir.tcx.is_ty_uninhabited_from(m, self.tables.expr_ty(expr)) {
+                let m = self.ir.tcx.parent_module(expr.hir_id).to_def_id();
+                let succ = if self.ir.tcx.is_ty_uninhabited_from(
+                    m,
+                    self.tables.expr_ty(expr),
+                    self.param_env,
+                ) {
                     self.s.exit_ln
                 } else {
                     succ
@@ -1136,8 +1143,12 @@ fn propagate_through_expr(&mut self, expr: &Expr<'_>, succ: LiveNode) -> LiveNod
             }
 
             hir::ExprKind::MethodCall(.., ref args) => {
-                let m = self.ir.tcx.parent_module(expr.hir_id);
-                let succ = if self.ir.tcx.is_ty_uninhabited_from(m, self.tables.expr_ty(expr)) {
+                let m = self.ir.tcx.parent_module(expr.hir_id).to_def_id();
+                let succ = if self.ir.tcx.is_ty_uninhabited_from(
+                    m,
+                    self.tables.expr_ty(expr),
+                    self.param_env,
+                ) {
                     self.s.exit_ln
                 } else {
                     succ
@@ -1359,9 +1370,9 @@ fn propagate_through_loop(
 // Checking for error conditions
 
 impl<'a, 'tcx> Visitor<'tcx> for Liveness<'a, 'tcx> {
-    type Map = Map<'tcx>;
+    type Map = intravisit::ErasedMap<'tcx>;
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
         NestedVisitorMap::None
     }
 
index 2719057fb5351a7ade75e2f90ab381ecb5a2986d..1daef45a1f591776f159c17bd4d76c328af114cc 100644 (file)
@@ -24,15 +24,14 @@ enum Context {
 #[derive(Copy, Clone)]
 struct CheckLoopVisitor<'a, 'hir> {
     sess: &'a Session,
-    hir_map: &'a Map<'hir>,
+    hir_map: Map<'hir>,
     cx: Context,
 }
 
 fn check_mod_loops(tcx: TyCtxt<'_>, module_def_id: DefId) {
     tcx.hir().visit_item_likes_in_module(
         module_def_id,
-        &mut CheckLoopVisitor { sess: &tcx.sess, hir_map: &tcx.hir(), cx: Normal }
-            .as_deep_visitor(),
+        &mut CheckLoopVisitor { sess: &tcx.sess, hir_map: tcx.hir(), cx: Normal }.as_deep_visitor(),
     );
 }
 
@@ -43,8 +42,8 @@ pub(crate) fn provide(providers: &mut Providers<'_>) {
 impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> {
     type Map = Map<'hir>;
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
-        NestedVisitorMap::OnlyBodies(&self.hir_map)
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::OnlyBodies(self.hir_map)
     }
 
     fn visit_anon_const(&mut self, c: &'hir hir::AnonConst) {
index 888f4370dd5e80d127ed2e512784847f7a05e994..835e7cfb628169a3c182a62b3dd3dcd7181efe81 100644 (file)
@@ -5,10 +5,8 @@
 // makes all other generics or inline functions that it references
 // reachable as well.
 
-use rustc::hir::map::Map;
 use rustc::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
 use rustc::middle::privacy;
-use rustc::session::config;
 use rustc::ty::query::Providers;
 use rustc::ty::{self, TyCtxt};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_hir::def_id::{CrateNum, DefId};
-use rustc_hir::intravisit;
-use rustc_hir::intravisit::{NestedVisitorMap, Visitor};
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_hir::{HirIdSet, Node};
+use rustc_session::config;
 use rustc_target::spec::abi::Abi;
 
 // Returns true if the given item must be inlined because it may be
@@ -48,12 +46,12 @@ fn method_might_be_inlined(
     impl_item: &hir::ImplItem<'_>,
     impl_src: DefId,
 ) -> bool {
-    let codegen_fn_attrs = tcx.codegen_fn_attrs(impl_item.hir_id.owner_def_id());
+    let codegen_fn_attrs = tcx.codegen_fn_attrs(impl_item.hir_id.owner.to_def_id());
     let generics = tcx.generics_of(tcx.hir().local_def_id(impl_item.hir_id));
     if codegen_fn_attrs.requests_inline() || generics.requires_monomorphization(tcx) {
         return true;
     }
-    if let hir::ImplItemKind::Method(method_sig, _) = &impl_item.kind {
+    if let hir::ImplItemKind::Fn(method_sig, _) = &impl_item.kind {
         if method_sig.header.is_const() {
             return true;
         }
@@ -83,9 +81,9 @@ struct ReachableContext<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for ReachableContext<'a, 'tcx> {
-    type Map = Map<'tcx>;
+    type Map = intravisit::ErasedMap<'tcx>;
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
         NestedVisitorMap::None
     }
 
@@ -162,14 +160,14 @@ fn def_id_represents_local_inlined_item(&self, def_id: DefId) -> bool {
             },
             Some(Node::TraitItem(trait_method)) => match trait_method.kind {
                 hir::TraitItemKind::Const(_, ref default) => default.is_some(),
-                hir::TraitItemKind::Method(_, hir::TraitMethod::Provided(_)) => true,
-                hir::TraitItemKind::Method(_, hir::TraitMethod::Required(_))
+                hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)) => true,
+                hir::TraitItemKind::Fn(_, hir::TraitFn::Required(_))
                 | hir::TraitItemKind::Type(..) => false,
             },
             Some(Node::ImplItem(impl_item)) => {
                 match impl_item.kind {
                     hir::ImplItemKind::Const(..) => true,
-                    hir::ImplItemKind::Method(..) => {
+                    hir::ImplItemKind::Fn(..) => {
                         let attrs = self.tcx.codegen_fn_attrs(def_id);
                         let generics = self.tcx.generics_of(def_id);
                         if generics.requires_monomorphization(self.tcx) || attrs.requests_inline() {
@@ -278,11 +276,11 @@ fn propagate_node(&mut self, node: &Node<'tcx>, search_item: hir::HirId) {
             Node::TraitItem(trait_method) => {
                 match trait_method.kind {
                     hir::TraitItemKind::Const(_, None)
-                    | hir::TraitItemKind::Method(_, hir::TraitMethod::Required(_)) => {
+                    | hir::TraitItemKind::Fn(_, hir::TraitFn::Required(_)) => {
                         // Keep going, nothing to get exported
                     }
                     hir::TraitItemKind::Const(_, Some(body_id))
-                    | hir::TraitItemKind::Method(_, hir::TraitMethod::Provided(body_id)) => {
+                    | hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(body_id)) => {
                         self.visit_nested_body(body_id);
                     }
                     hir::TraitItemKind::Type(..) => {}
@@ -292,7 +290,7 @@ fn propagate_node(&mut self, node: &Node<'tcx>, search_item: hir::HirId) {
                 hir::ImplItemKind::Const(_, body) => {
                     self.visit_nested_body(body);
                 }
-                hir::ImplItemKind::Method(_, body) => {
+                hir::ImplItemKind::Fn(_, body) => {
                     let did = self.tcx.hir().get_parent_did(search_item);
                     if method_might_be_inlined(self.tcx, impl_item, did) {
                         self.visit_nested_body(body)
index e636144794ab6e6ec8d2cd5c5abc1c5de706234e..e771696a5b6bf9678935529ad070d3178caef8c0 100644 (file)
@@ -2,11 +2,10 @@
 //! the parent links in the region hierarchy.
 //!
 //! For more information about how MIR-based region-checking works,
-//! see the [rustc guide].
+//! see the [rustc dev guide].
 //!
-//! [rustc guide]: https://rust-lang.github.io/rustc-guide/borrow_check.html
+//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/borrow_check.html
 
-use rustc::hir::map::Map;
 use rustc::middle::region::*;
 use rustc::ty::query::Providers;
 use rustc::ty::TyCtxt;
@@ -285,7 +284,7 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h
 
     // Ordinarily, we can rely on the visit order of HIR intravisit
     // to correspond to the actual execution order of statements.
-    // However, there's a weird corner case with compund assignment
+    // However, there's a weird corner case with compound assignment
     // operators (e.g. `a += b`). The evaluation order depends on whether
     // or not the operator is overloaded (e.g. whether or not a trait
     // like AddAssign is implemented).
@@ -696,9 +695,9 @@ fn enter_node_scope_with_dtor(&mut self, id: hir::ItemLocalId) {
 }
 
 impl<'tcx> Visitor<'tcx> for RegionResolutionVisitor<'tcx> {
-    type Map = Map<'tcx>;
+    type Map = intravisit::ErasedMap<'tcx>;
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
         NestedVisitorMap::None
     }
 
index 5eae935f050e177e91fe5fd0e6e5a4ee67c85f8f..11311a3e8aa682d4aaa94f67213178f95ff830bf 100644 (file)
@@ -2,11 +2,8 @@
 //! propagating default levels lexically from parent to children ast nodes.
 
 use rustc::hir::map::Map;
-use rustc::lint;
 use rustc::middle::privacy::AccessLevels;
 use rustc::middle::stability::{DeprecationEntry, Index};
-use rustc::session::parse::feature_err;
-use rustc::session::Session;
 use rustc::ty::query::Providers;
 use rustc::ty::TyCtxt;
 use rustc_ast::ast::Attribute;
 use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::{Generics, HirId, Item, StructField, Variant};
-use rustc_infer::traits::misc::can_type_implement_copy;
+use rustc_session::lint;
+use rustc_session::parse::feature_err;
+use rustc_session::Session;
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
+use rustc_trait_selection::traits::misc::can_type_implement_copy;
 
 use std::cmp::Ordering;
 use std::mem::replace;
@@ -259,8 +259,8 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
     /// deep-walking.
     type Map = Map<'tcx>;
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
-        NestedVisitorMap::All(&self.tcx.hir())
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::All(self.tcx.hir())
     }
 
     fn visit_item(&mut self, i: &'tcx Item<'tcx>) {
@@ -350,8 +350,8 @@ fn check_missing_stability(&self, hir_id: HirId, span: Span, name: &str) {
 impl<'a, 'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'a, 'tcx> {
     type Map = Map<'tcx>;
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
-        NestedVisitorMap::OnlyBodies(&self.tcx.hir())
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::OnlyBodies(self.tcx.hir())
     }
 
     fn visit_item(&mut self, i: &'tcx Item<'tcx>) {
@@ -459,8 +459,8 @@ fn new_index(tcx: TyCtxt<'tcx>) -> Index<'tcx> {
 
         annotator.annotate(
             hir::CRATE_HIR_ID,
-            &krate.attrs,
-            krate.span,
+            &krate.item.attrs,
+            krate.item.span,
             AnnotationKind::Required,
             |v| intravisit::walk_crate(v, krate),
         );
@@ -492,8 +492,8 @@ impl Visitor<'tcx> for Checker<'tcx> {
     /// Because stability levels are scoped lexically, we want to walk
     /// nested items in the context of the outer item, so enable
     /// deep-walking.
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
-        NestedVisitorMap::OnlyBodies(&self.tcx.hir())
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::OnlyBodies(self.tcx.hir())
     }
 
     fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
@@ -551,7 +551,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
                     .emit();
                 } else {
                     let param_env = self.tcx.param_env(def_id);
-                    if !can_type_implement_copy(self.tcx, param_env, ty).is_ok() {
+                    if can_type_implement_copy(self.tcx, param_env, ty).is_err() {
                         feature_err(
                             &self.tcx.sess.parse_sess,
                             sym::untagged_unions,
@@ -585,7 +585,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
     if tcx.stability().staged_api[&LOCAL_CRATE] {
         let krate = tcx.hir().krate();
         let mut missing = MissingStabilityAnnotations { tcx, access_levels };
-        missing.check_missing_stability(hir::CRATE_HIR_ID, krate.span, "crate");
+        missing.check_missing_stability(hir::CRATE_HIR_ID, krate.item.span, "crate");
         intravisit::walk_crate(&mut missing, krate);
         krate.visit_all_item_likes(&mut missing.as_deep_visitor());
     }
@@ -655,7 +655,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
     }
 
     // FIXME(#44232): the `used_features` table no longer exists, so we
-    // don't lint about unused features. We should reenable this one day!
+    // don't lint about unused features. We should re-enable this one day!
 }
 
 fn unnecessary_stable_feature_lint(tcx: TyCtxt<'_>, span: Span, feature: Symbol, since: Symbol) {
index a2397f273385a531e9c109880a65716da7c09dbb..43f39e6c610c8ba5d96f3ebb86e4d55ad0b2e236 100644 (file)
@@ -1,6 +1,5 @@
 //! Upvar (closure capture) collection from cross-body HIR uses of `Res::Local`s.
 
-use rustc::hir::map::Map;
 use rustc::ty::query::Providers;
 use rustc::ty::TyCtxt;
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
@@ -44,9 +43,9 @@ struct LocalCollector {
 }
 
 impl Visitor<'tcx> for LocalCollector {
-    type Map = Map<'tcx>;
+    type Map = intravisit::ErasedMap<'tcx>;
 
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, Self::Map> {
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
         NestedVisitorMap::None
     }
 
@@ -73,9 +72,9 @@ fn visit_local_use(&mut self, var_id: HirId, span: Span) {
 }
 
 impl Visitor<'tcx> for CaptureCollector<'a, 'tcx> {
-    type Map = Map<'tcx>;
+    type Map = intravisit::ErasedMap<'tcx>;
 
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, Self::Map> {
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
         NestedVisitorMap::None
     }
 
index 1511742446b6ea4ddb05958ffd99f698bd3ed3ab..cde489e8d2c1eca8d4a202036acb4f2eb09fb89b 100644 (file)
@@ -2,15 +2,13 @@
 
 use rustc::middle::lang_items;
 use rustc::middle::lang_items::whitelisted;
-use rustc::session::config;
-
-use rustc::hir::map::Map;
 use rustc::ty::TyCtxt;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::weak_lang_items::WEAK_ITEMS_REFS;
+use rustc_session::config;
 use rustc_span::symbol::Symbol;
 use rustc_span::Span;
 
@@ -28,9 +26,6 @@ pub fn check_crate<'tcx>(tcx: TyCtxt<'tcx>, items: &mut lang_items::LanguageItem
     if items.eh_personality().is_none() {
         items.missing.push(lang_items::EhPersonalityLangItem);
     }
-    if tcx.sess.target.target.options.custom_unwind_resume & items.eh_unwind_resume().is_none() {
-        items.missing.push(lang_items::EhUnwindResumeLangItem);
-    }
 
     {
         let mut cx = Context { tcx, items };
@@ -88,9 +83,9 @@ fn register(&mut self, name: Symbol, span: Span) {
 }
 
 impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> {
-    type Map = Map<'v>;
+    type Map = intravisit::ErasedMap<'v>;
 
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, Map<'v>> {
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
         NestedVisitorMap::None
     }
 
index 893130725902103e7b024cb06f2c411e37162b60..372d6a534c8d4fd462439607c6a76cc3cce39261 100644 (file)
@@ -17,4 +17,5 @@ rustc_hir = { path = "../librustc_hir" }
 rustc_lint = { path = "../librustc_lint" }
 rustc_metadata = { path = "../librustc_metadata" }
 rustc_ast = { path = "../librustc_ast" }
+rustc_session = { path = "../librustc_session" }
 rustc_span = { path = "../librustc_span" }
index 9bd9bcb25ba8825025bc4de8e5046c6bf037d7dd..0810cf56d178370add97a81aa9842399c8f7593c 100644 (file)
@@ -2,10 +2,10 @@
 
 use crate::Registry;
 use rustc::middle::cstore::MetadataLoader;
-use rustc::session::Session;
 use rustc_ast::ast::{Crate, Ident};
 use rustc_errors::struct_span_err;
 use rustc_metadata::locator;
+use rustc_session::Session;
 use rustc_span::symbol::sym;
 use rustc_span::Span;
 
index 6d1272c117b4d919f03c578f7dde3800366fdcbc..9854e0f6c53f3a6ed76838efe6cd81bbb95cc528 100644 (file)
@@ -14,6 +14,7 @@ rustc_attr = { path = "../librustc_attr" }
 rustc_errors = { path = "../librustc_errors" }
 rustc_hir = { path = "../librustc_hir" }
 rustc_typeck = { path = "../librustc_typeck" }
+rustc_session = { path = "../librustc_session" }
 rustc_ast = { path = "../librustc_ast" }
 rustc_span = { path = "../librustc_span" }
 rustc_data_structures = { path = "../librustc_data_structures" }
index 24696b203326f428df0519be4306c1c81dc7cf36..c8c8c2299305ba55faee029f57c4291da3eda61d 100644 (file)
@@ -5,7 +5,6 @@
 
 use rustc::bug;
 use rustc::hir::map::Map;
-use rustc::lint;
 use rustc::middle::privacy::{AccessLevel, AccessLevels};
 use rustc::ty::fold::TypeVisitor;
 use rustc::ty::query::Providers;
@@ -20,6 +19,7 @@
 use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_hir::intravisit::{self, DeepVisitor, NestedVisitorMap, Visitor};
 use rustc_hir::{AssocItemKind, HirIdSet, Node, PatKind};
+use rustc_session::lint;
 use rustc_span::hygiene::Transparency;
 use rustc_span::symbol::{kw, sym};
 use rustc_span::Span;
@@ -327,7 +327,7 @@ fn def_id_visibility<'tcx>(
                 }
                 Node::Expr(expr) => {
                     return (
-                        ty::Visibility::Restricted(tcx.parent_module(expr.hir_id)),
+                        ty::Visibility::Restricted(tcx.parent_module(expr.hir_id).to_def_id()),
                         expr.span,
                         "private",
                     );
@@ -373,8 +373,8 @@ struct PubRestrictedVisitor<'tcx> {
 impl Visitor<'tcx> for PubRestrictedVisitor<'tcx> {
     type Map = Map<'tcx>;
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
-        NestedVisitorMap::All(&self.tcx.hir())
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::All(self.tcx.hir())
     }
     fn visit_vis(&mut self, vis: &'tcx hir::Visibility<'tcx>) {
         self.has_pub_restricted = self.has_pub_restricted || vis.node.is_pub_restricted();
@@ -620,7 +620,7 @@ fn update_macro_reachable_def(
             | DefKind::ForeignTy
             | DefKind::Fn
             | DefKind::OpaqueTy
-            | DefKind::Method
+            | DefKind::AssocFn
             | DefKind::Trait
             | DefKind::TyParam
             | DefKind::Variant => (),
@@ -678,8 +678,8 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> {
 
     /// We want to visit items in the context of their containing
     /// module and so forth, so supply a crate for doing a deep walk.
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
-        NestedVisitorMap::All(&self.tcx.hir())
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::All(self.tcx.hir())
     }
 
     fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
@@ -920,7 +920,7 @@ fn visit_mod(&mut self, m: &'tcx hir::Mod<'tcx>, _sp: Span, id: hir::HirId) {
     }
 
     fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef<'tcx>) {
-        if attr::find_transparency(&md.attrs, md.legacy).0 != Transparency::Opaque {
+        if attr::find_transparency(&md.attrs, md.ast.macro_rules).0 != Transparency::Opaque {
             self.update(md.hir_id, Some(AccessLevel::Public));
             return;
         }
@@ -1049,8 +1049,8 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> {
 
     /// We want to visit items in the context of their containing
     /// module and so forth, so supply a crate for doing a deep walk.
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
-        NestedVisitorMap::All(&self.tcx.hir())
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::All(self.tcx.hir())
     }
 
     fn visit_mod(&mut self, _m: &'tcx hir::Mod<'tcx>, _s: Span, _n: hir::HirId) {
@@ -1191,8 +1191,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
 
     /// We want to visit items in the context of their containing
     /// module and so forth, so supply a crate for doing a deep walk.
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
-        NestedVisitorMap::All(&self.tcx.hir())
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::All(self.tcx.hir())
     }
 
     fn visit_mod(&mut self, _m: &'tcx hir::Mod<'tcx>, _s: Span, _n: hir::HirId) {
@@ -1298,7 +1298,7 @@ fn visit_qpath(&mut self, qpath: &'tcx hir::QPath<'tcx>, id: hir::HirId, span: S
             _ => None,
         };
         let def = def.filter(|(kind, _)| match kind {
-            DefKind::Method
+            DefKind::AssocFn
             | DefKind::AssocConst
             | DefKind::AssocTy
             | DefKind::AssocOpaqueTy
@@ -1447,9 +1447,9 @@ fn item_is_public(&self, id: &hir::HirId, vis: &hir::Visibility<'_>) -> bool {
 }
 
 impl<'a, 'b, 'tcx, 'v> Visitor<'v> for ObsoleteCheckTypeForPrivatenessVisitor<'a, 'b, 'tcx> {
-    type Map = Map<'v>;
+    type Map = intravisit::ErasedMap<'v>;
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
         NestedVisitorMap::None
     }
 
@@ -1479,8 +1479,8 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
 
     /// We want to visit items in the context of their containing
     /// module and so forth, so supply a crate for doing a deep walk.
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
-        NestedVisitorMap::All(&self.tcx.hir())
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::All(self.tcx.hir())
     }
 
     fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
@@ -1556,7 +1556,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
                     || items.iter().any(|impl_item_ref| {
                         let impl_item = self.tcx.hir().impl_item(impl_item_ref.id);
                         match impl_item.kind {
-                            hir::ImplItemKind::Const(..) | hir::ImplItemKind::Method(..) => {
+                            hir::ImplItemKind::Const(..) | hir::ImplItemKind::Fn(..) => {
                                 self.access_levels.is_reachable(impl_item_ref.id.hir_id)
                             }
                             hir::ImplItemKind::OpaqueTy(..) | hir::ImplItemKind::TyAlias(_) => {
@@ -1578,8 +1578,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
                                 // types in private items.
                                 let impl_item = self.tcx.hir().impl_item(impl_item_ref.id);
                                 match impl_item.kind {
-                                    hir::ImplItemKind::Const(..)
-                                    | hir::ImplItemKind::Method(..)
+                                    hir::ImplItemKind::Const(..) | hir::ImplItemKind::Fn(..)
                                         if self
                                             .item_is_public(&impl_item.hir_id, &impl_item.vis) =>
                                     {
@@ -1925,8 +1924,8 @@ fn check_assoc_item(
 impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> {
     type Map = Map<'tcx>;
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
-        NestedVisitorMap::OnlyBodies(&self.tcx.hir())
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::OnlyBodies(self.tcx.hir())
     }
 
     fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
index 11a3cedcc74e9a656f28c4d3b91e3b7036d7fcb8..49f079ad2707071acaeb0e359c91ac5853456b7a 100644 (file)
@@ -24,7 +24,6 @@ rustc_errors = { path = "../librustc_errors" }
 rustc_expand = { path = "../librustc_expand" }
 rustc_feature = { path = "../librustc_feature" }
 rustc_hir = { path = "../librustc_hir" }
-rustc_infer = { path = "../librustc_infer" }
 rustc_metadata = { path = "../librustc_metadata" }
 rustc_session = { path = "../librustc_session" }
 rustc_span = { path = "../librustc_span" }
index 86816fd9f3a2a6981b223d514efe102bd4c660bb..ce3b1233a74737d94df369fd6caa8ab9c5bad79a 100644 (file)
@@ -6,9 +6,8 @@
 //! Imports are also considered items and placed into modules here, but not resolved yet.
 
 use crate::def_collector::collect_definitions;
-use crate::imports::ImportDirective;
-use crate::imports::ImportDirectiveSubclass::{self, GlobImport, SingleImport};
-use crate::macros::{LegacyBinding, LegacyScope};
+use crate::imports::{Import, ImportKind};
+use crate::macros::{MacroRulesBinding, MacroRulesScope};
 use crate::Namespace::{self, MacroNS, TypeNS, ValueNS};
 use crate::{CrateLint, Determinacy, PathResult, ResolutionError, VisResolutionError};
 use crate::{
@@ -166,11 +165,11 @@ impl<'a> Resolver<'a> {
         &mut self,
         fragment: &AstFragment,
         parent_scope: ParentScope<'a>,
-    ) -> LegacyScope<'a> {
+    ) -> MacroRulesScope<'a> {
         collect_definitions(&mut self.definitions, fragment, parent_scope.expansion);
         let mut visitor = BuildReducedGraphVisitor { r: self, parent_scope };
         fragment.visit_with(&mut visitor);
-        visitor.parent_scope.legacy
+        visitor.parent_scope.macro_rules
     }
 
     crate fn build_reduced_graph_external(&mut self, module: Module<'a>) {
@@ -303,16 +302,16 @@ fn insert_field_names(&mut self, def_id: DefId, field_names: Vec<Spanned<Name>>)
     fn block_needs_anonymous_module(&mut self, block: &Block) -> bool {
         // If any statements are items, we need to create an anonymous module
         block.stmts.iter().any(|statement| match statement.kind {
-            StmtKind::Item(_) | StmtKind::Mac(_) => true,
+            StmtKind::Item(_) | StmtKind::MacCall(_) => true,
             _ => false,
         })
     }
 
-    // Add an import directive to the current module.
-    fn add_import_directive(
+    // Add an import to the current module.
+    fn add_import(
         &mut self,
         module_path: Vec<Segment>,
-        subclass: ImportDirectiveSubclass<'a>,
+        kind: ImportKind<'a>,
         span: Span,
         id: NodeId,
         item: &ast::Item,
@@ -321,11 +320,11 @@ fn add_import_directive(
         vis: ty::Visibility,
     ) {
         let current_module = self.parent_scope.module;
-        let directive = self.r.arenas.alloc_import_directive(ImportDirective {
+        let import = self.r.arenas.alloc_import(Import {
+            kind,
             parent_scope: self.parent_scope,
             module_path,
             imported_module: Cell::new(None),
-            subclass,
             span,
             id,
             use_span: item.span,
@@ -337,25 +336,25 @@ fn add_import_directive(
             used: Cell::new(false),
         });
 
-        debug!("add_import_directive({:?})", directive);
+        debug!("add_import({:?})", import);
 
-        self.r.indeterminate_imports.push(directive);
-        match directive.subclass {
+        self.r.indeterminate_imports.push(import);
+        match import.kind {
             // Don't add unresolved underscore imports to modules
-            SingleImport { target: Ident { name: kw::Underscore, .. }, .. } => {}
-            SingleImport { target, type_ns_only, .. } => {
+            ImportKind::Single { target: Ident { name: kw::Underscore, .. }, .. } => {}
+            ImportKind::Single { 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();
-                        resolution.add_single_import(directive);
+                        resolution.add_single_import(import);
                     }
                 });
             }
             // We don't add prelude imports to the globs since they only affect lexical scopes,
             // which are not relevant to import resolution.
-            GlobImport { is_prelude: true, .. } => {}
-            GlobImport { .. } => current_module.globs.borrow_mut().push(directive),
+            ImportKind::Glob { is_prelude: true, .. } => {}
+            ImportKind::Glob { .. } => current_module.globs.borrow_mut().push(import),
             _ => unreachable!(),
         }
     }
@@ -480,7 +479,7 @@ fn build_reduced_graph_for_use_tree(
                     );
                 }
 
-                let subclass = SingleImport {
+                let kind = ImportKind::Single {
                     source: source.ident,
                     target: ident,
                     source_bindings: PerNS {
@@ -496,9 +495,9 @@ fn build_reduced_graph_for_use_tree(
                     type_ns_only,
                     nested,
                 };
-                self.add_import_directive(
+                self.add_import(
                     module_path,
-                    subclass,
+                    kind,
                     use_tree.span,
                     id,
                     item,
@@ -508,20 +507,11 @@ fn build_reduced_graph_for_use_tree(
                 );
             }
             ast::UseTreeKind::Glob => {
-                let subclass = GlobImport {
+                let kind = ImportKind::Glob {
                     is_prelude: attr::contains_name(&item.attrs, sym::prelude_import),
                     max_vis: Cell::new(ty::Visibility::Invisible),
                 };
-                self.add_import_directive(
-                    prefix,
-                    subclass,
-                    use_tree.span,
-                    id,
-                    item,
-                    root_span,
-                    item.id,
-                    vis,
-                );
+                self.add_import(prefix, kind, use_tree.span, id, item, root_span, item.id, vis);
             }
             ast::UseTreeKind::Nested(ref items) => {
                 // Ensure there is at most one `self` in the list
@@ -634,18 +624,15 @@ fn build_reduced_graph_for_item(&mut self, item: &'b Item) {
                     self.r.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX })
                 };
 
-                let used = self.process_legacy_macro_imports(item, module);
+                let used = self.process_macro_use_imports(item, module);
                 let binding =
                     (module, ty::Visibility::Public, sp, expansion).to_name_binding(self.r.arenas);
-                let directive = self.r.arenas.alloc_import_directive(ImportDirective {
+                let import = self.r.arenas.alloc_import(Import {
+                    kind: ImportKind::ExternCrate { source: orig_name, target: ident },
                     root_id: item.id,
                     id: item.id,
                     parent_scope: self.parent_scope,
                     imported_module: Cell::new(Some(ModuleOrUniformRoot::Module(module))),
-                    subclass: ImportDirectiveSubclass::ExternCrate {
-                        source: orig_name,
-                        target: ident,
-                    },
                     has_attributes: !item.attrs.is_empty(),
                     use_span_with_attributes: item.span_with_attributes(),
                     use_span: item.span,
@@ -655,10 +642,11 @@ fn build_reduced_graph_for_item(&mut self, item: &'b Item) {
                     vis: Cell::new(vis),
                     used: Cell::new(used),
                 });
-                self.r.potentially_unused_imports.push(directive);
-                let imported_binding = self.r.import(binding, directive);
+                self.r.potentially_unused_imports.push(import);
+                let imported_binding = self.r.import(binding, import);
                 if ptr::eq(parent, self.r.graph_root) {
-                    if let Some(entry) = self.r.extern_prelude.get(&ident.modern()) {
+                    if let Some(entry) = self.r.extern_prelude.get(&ident.normalize_to_macros_2_0())
+                    {
                         if expansion != ExpnId::root()
                             && orig_name.is_some()
                             && entry.extern_crate_item.is_none()
@@ -669,10 +657,12 @@ fn build_reduced_graph_for_item(&mut self, item: &'b Item) {
                         }
                     }
                     let entry =
-                        self.r.extern_prelude.entry(ident.modern()).or_insert(ExternPreludeEntry {
-                            extern_crate_item: None,
-                            introduced_by_item: true,
-                        });
+                        self.r.extern_prelude.entry(ident.normalize_to_macros_2_0()).or_insert(
+                            ExternPreludeEntry {
+                                extern_crate_item: None,
+                                introduced_by_item: true,
+                            },
+                        );
                     entry.extern_crate_item = Some(imported_binding);
                     if orig_name.is_some() {
                         entry.introduced_by_item = true;
@@ -816,7 +806,7 @@ fn build_reduced_graph_for_item(&mut self, item: &'b Item) {
             // These items do not add names to modules.
             ItemKind::Impl { .. } | ItemKind::ForeignMod(..) | ItemKind::GlobalAsm(..) => {}
 
-            ItemKind::MacroDef(..) | ItemKind::Mac(_) => unreachable!(),
+            ItemKind::MacroDef(..) | ItemKind::MacCall(_) => unreachable!(),
         }
     }
 
@@ -826,13 +816,13 @@ fn build_reduced_graph_for_foreign_item(&mut self, item: &ForeignItem) {
             ForeignItemKind::Fn(..) => {
                 (Res::Def(DefKind::Fn, self.r.definitions.local_def_id(item.id)), ValueNS)
             }
-            ForeignItemKind::Static(..) | ForeignItemKind::Const(..) => {
+            ForeignItemKind::Static(..) => {
                 (Res::Def(DefKind::Static, self.r.definitions.local_def_id(item.id)), ValueNS)
             }
             ForeignItemKind::TyAlias(..) => {
                 (Res::Def(DefKind::ForeignTy, self.r.definitions.local_def_id(item.id)), TypeNS)
             }
-            ForeignItemKind::Macro(_) => unreachable!(),
+            ForeignItemKind::MacCall(_) => unreachable!(),
         };
         let parent = self.parent_scope.module;
         let expansion = self.parent_scope.expansion;
@@ -887,7 +877,7 @@ fn build_reduced_graph_for_external_crate_res(&mut self, child: Export<NodeId>)
             | Res::PrimTy(..)
             | Res::ToolMod => self.r.define(parent, ident, TypeNS, (res, vis, span, expansion)),
             Res::Def(DefKind::Fn, _)
-            | Res::Def(DefKind::Method, _)
+            | Res::Def(DefKind::AssocFn, _)
             | Res::Def(DefKind::Static, _)
             | Res::Def(DefKind::Const, _)
             | Res::Def(DefKind::AssocConst, _)
@@ -911,7 +901,7 @@ fn build_reduced_graph_for_external_crate_res(&mut self, child: Export<NodeId>)
                 let field_names = cstore.struct_field_names_untracked(def_id, self.r.session);
                 self.insert_field_names(def_id, field_names);
             }
-            Res::Def(DefKind::Method, def_id) => {
+            Res::Def(DefKind::AssocFn, def_id) => {
                 if cstore.associated_item_cloned_untracked(def_id).method_has_self_argument {
                     self.r.has_self.insert(def_id);
                 }
@@ -926,7 +916,7 @@ fn build_reduced_graph_for_external_crate_res(&mut self, child: Export<NodeId>)
         }
     }
 
-    fn legacy_import_macro(
+    fn add_macro_use_binding(
         &mut self,
         name: ast::Name,
         binding: &'a NameBinding<'a>,
@@ -942,7 +932,7 @@ fn legacy_import_macro(
     }
 
     /// Returns `true` if we should consider the underlying `extern crate` to be used.
-    fn process_legacy_macro_imports(&mut self, item: &Item, module: Module<'a>) -> bool {
+    fn process_macro_use_imports(&mut self, item: &Item, module: Module<'a>) -> bool {
         let mut import_all = None;
         let mut single_imports = Vec::new();
         for attr in &item.attrs {
@@ -992,13 +982,13 @@ fn process_legacy_macro_imports(&mut self, item: &Item, module: Module<'a>) -> b
             }
         }
 
-        let macro_use_directive = |this: &Self, span| {
-            this.r.arenas.alloc_import_directive(ImportDirective {
+        let macro_use_import = |this: &Self, span| {
+            this.r.arenas.alloc_import(Import {
+                kind: ImportKind::MacroUse,
                 root_id: item.id,
                 id: item.id,
                 parent_scope: this.parent_scope,
                 imported_module: Cell::new(Some(ModuleOrUniformRoot::Module(module))),
-                subclass: ImportDirectiveSubclass::MacroUse,
                 use_span_with_attributes: item.span_with_attributes(),
                 has_attributes: !item.attrs.is_empty(),
                 use_span: item.span,
@@ -1012,12 +1002,12 @@ fn process_legacy_macro_imports(&mut self, item: &Item, module: Module<'a>) -> b
 
         let allow_shadowing = self.parent_scope.expansion == ExpnId::root();
         if let Some(span) = import_all {
-            let directive = macro_use_directive(self, span);
-            self.r.potentially_unused_imports.push(directive);
+            let import = macro_use_import(self, span);
+            self.r.potentially_unused_imports.push(import);
             module.for_each_child(self, |this, ident, ns, binding| {
                 if ns == MacroNS {
-                    let imported_binding = this.r.import(binding, directive);
-                    this.legacy_import_macro(ident.name, imported_binding, span, allow_shadowing);
+                    let imported_binding = this.r.import(binding, import);
+                    this.add_macro_use_binding(ident.name, imported_binding, span, allow_shadowing);
                 }
             });
         } else {
@@ -1031,10 +1021,10 @@ fn process_legacy_macro_imports(&mut self, item: &Item, module: Module<'a>) -> b
                     ident.span,
                 );
                 if let Ok(binding) = result {
-                    let directive = macro_use_directive(self, ident.span);
-                    self.r.potentially_unused_imports.push(directive);
-                    let imported_binding = self.r.import(binding, directive);
-                    self.legacy_import_macro(
+                    let import = macro_use_import(self, ident.span);
+                    self.r.potentially_unused_imports.push(import);
+                    let imported_binding = self.r.import(binding, import);
+                    self.add_macro_use_binding(
                         ident.name,
                         imported_binding,
                         ident.span,
@@ -1073,7 +1063,7 @@ fn contains_macro_use(&mut self, attrs: &[ast::Attribute]) -> bool {
         false
     }
 
-    fn visit_invoc(&mut self, id: NodeId) -> LegacyScope<'a> {
+    fn visit_invoc(&mut self, id: NodeId) -> MacroRulesScope<'a> {
         let invoc_id = id.placeholder_to_expn_id();
 
         self.parent_scope.module.unexpanded_invocations.borrow_mut().insert(invoc_id);
@@ -1081,7 +1071,7 @@ fn visit_invoc(&mut self, id: NodeId) -> LegacyScope<'a> {
         let old_parent_scope = self.r.invocation_parent_scopes.insert(invoc_id, self.parent_scope);
         assert!(old_parent_scope.is_none(), "invocation data is reset for an invocation");
 
-        LegacyScope::Invocation(invoc_id)
+        MacroRulesScope::Invocation(invoc_id)
     }
 
     fn proc_macro_stub(item: &ast::Item) -> Option<(MacroKind, Ident, Span)> {
@@ -1108,20 +1098,20 @@ fn insert_unused_macro(&mut self, ident: Ident, node_id: NodeId, span: Span) {
         }
     }
 
-    fn define_macro(&mut self, item: &ast::Item) -> LegacyScope<'a> {
+    fn define_macro(&mut self, item: &ast::Item) -> MacroRulesScope<'a> {
         let parent_scope = self.parent_scope;
         let expansion = parent_scope.expansion;
-        let (ext, ident, span, is_legacy) = match &item.kind {
+        let (ext, ident, span, macro_rules) = match &item.kind {
             ItemKind::MacroDef(def) => {
                 let ext = Lrc::new(self.r.compile_macro(item, self.r.session.edition()));
-                (ext, item.ident, item.span, def.legacy)
+                (ext, item.ident, item.span, def.macro_rules)
             }
             ItemKind::Fn(..) => match Self::proc_macro_stub(item) {
                 Some((macro_kind, ident, span)) => {
                     self.r.proc_macro_stubs.insert(item.id);
                     (self.r.dummy_ext(macro_kind), ident, span, false)
                 }
-                None => return parent_scope.legacy,
+                None => return parent_scope.macro_rules,
             },
             _ => unreachable!(),
         };
@@ -1131,8 +1121,8 @@ fn define_macro(&mut self, item: &ast::Item) -> LegacyScope<'a> {
         self.r.macro_map.insert(def_id, ext);
         self.r.local_macro_def_scopes.insert(item.id, parent_scope.module);
 
-        if is_legacy {
-            let ident = ident.modern();
+        if macro_rules {
+            let ident = ident.normalize_to_macros_2_0();
             self.r.macro_names.insert(ident);
             let is_macro_export = attr::contains_name(&item.attrs, sym::macro_export);
             let vis = if is_macro_export {
@@ -1150,8 +1140,8 @@ fn define_macro(&mut self, item: &ast::Item) -> LegacyScope<'a> {
                 self.r.check_reserved_macro_name(ident, res);
                 self.insert_unused_macro(ident, item.id, span);
             }
-            LegacyScope::Binding(self.r.arenas.alloc_legacy_binding(LegacyBinding {
-                parent_legacy_scope: parent_scope.legacy,
+            MacroRulesScope::Binding(self.r.arenas.alloc_macro_rules_binding(MacroRulesBinding {
+                parent_macro_rules_scope: parent_scope.macro_rules,
                 binding,
                 ident,
             }))
@@ -1162,7 +1152,7 @@ fn define_macro(&mut self, item: &ast::Item) -> LegacyScope<'a> {
                 self.insert_unused_macro(ident, item.id, span);
             }
             self.r.define(module, ident, MacroNS, (res, vis, span, expansion));
-            self.parent_scope.legacy
+            self.parent_scope.macro_rules
         }
     }
 }
@@ -1180,43 +1170,43 @@ fn $visit(&mut self, node: &'b $ty) {
 }
 
 impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> {
-    method!(visit_expr: ast::Expr, ast::ExprKind::Mac, walk_expr);
-    method!(visit_pat: ast::Pat, ast::PatKind::Mac, walk_pat);
-    method!(visit_ty: ast::Ty, ast::TyKind::Mac, walk_ty);
+    method!(visit_expr: ast::Expr, ast::ExprKind::MacCall, walk_expr);
+    method!(visit_pat: ast::Pat, ast::PatKind::MacCall, walk_pat);
+    method!(visit_ty: ast::Ty, ast::TyKind::MacCall, walk_ty);
 
     fn visit_item(&mut self, item: &'b Item) {
         let macro_use = match item.kind {
             ItemKind::MacroDef(..) => {
-                self.parent_scope.legacy = self.define_macro(item);
+                self.parent_scope.macro_rules = self.define_macro(item);
                 return;
             }
-            ItemKind::Mac(..) => {
-                self.parent_scope.legacy = self.visit_invoc(item.id);
+            ItemKind::MacCall(..) => {
+                self.parent_scope.macro_rules = self.visit_invoc(item.id);
                 return;
             }
             ItemKind::Mod(..) => self.contains_macro_use(&item.attrs),
             _ => false,
         };
         let orig_current_module = self.parent_scope.module;
-        let orig_current_legacy_scope = self.parent_scope.legacy;
+        let orig_current_macro_rules_scope = self.parent_scope.macro_rules;
         self.build_reduced_graph_for_item(item);
         visit::walk_item(self, item);
         self.parent_scope.module = orig_current_module;
         if !macro_use {
-            self.parent_scope.legacy = orig_current_legacy_scope;
+            self.parent_scope.macro_rules = orig_current_macro_rules_scope;
         }
     }
 
     fn visit_stmt(&mut self, stmt: &'b ast::Stmt) {
-        if let ast::StmtKind::Mac(..) = stmt.kind {
-            self.parent_scope.legacy = self.visit_invoc(stmt.id);
+        if let ast::StmtKind::MacCall(..) = stmt.kind {
+            self.parent_scope.macro_rules = self.visit_invoc(stmt.id);
         } else {
             visit::walk_stmt(self, stmt);
         }
     }
 
     fn visit_foreign_item(&mut self, foreign_item: &'b ForeignItem) {
-        if let ForeignItemKind::Macro(_) = foreign_item.kind {
+        if let ForeignItemKind::MacCall(_) = foreign_item.kind {
             self.visit_invoc(foreign_item.id);
             return;
         }
@@ -1227,17 +1217,17 @@ fn visit_foreign_item(&mut self, foreign_item: &'b ForeignItem) {
 
     fn visit_block(&mut self, block: &'b Block) {
         let orig_current_module = self.parent_scope.module;
-        let orig_current_legacy_scope = self.parent_scope.legacy;
+        let orig_current_macro_rules_scope = self.parent_scope.macro_rules;
         self.build_reduced_graph_for_block(block);
         visit::walk_block(self, block);
         self.parent_scope.module = orig_current_module;
-        self.parent_scope.legacy = orig_current_legacy_scope;
+        self.parent_scope.macro_rules = orig_current_macro_rules_scope;
     }
 
     fn visit_assoc_item(&mut self, item: &'b AssocItem, ctxt: AssocCtxt) {
         let parent = self.parent_scope.module;
 
-        if let AssocItemKind::Macro(_) = item.kind {
+        if let AssocItemKind::MacCall(_) = item.kind {
             self.visit_invoc(item.id);
             return;
         }
@@ -1251,16 +1241,15 @@ fn visit_assoc_item(&mut self, item: &'b AssocItem, ctxt: AssocCtxt) {
         // Add the item to the trait info.
         let item_def_id = self.r.definitions.local_def_id(item.id);
         let (res, ns) = match item.kind {
-            AssocItemKind::Static(..) // Let's pretend it's a `const` for recovery.
-            | AssocItemKind::Const(..) => (Res::Def(DefKind::AssocConst, item_def_id), ValueNS),
+            AssocItemKind::Const(..) => (Res::Def(DefKind::AssocConst, item_def_id), ValueNS),
             AssocItemKind::Fn(_, ref sig, _, _) => {
                 if sig.decl.has_self() {
                     self.r.has_self.insert(item_def_id);
                 }
-                (Res::Def(DefKind::Method, item_def_id), ValueNS)
+                (Res::Def(DefKind::AssocFn, item_def_id), ValueNS)
             }
             AssocItemKind::TyAlias(..) => (Res::Def(DefKind::AssocTy, item_def_id), TypeNS),
-            AssocItemKind::Macro(_) => bug!(), // handled above
+            AssocItemKind::MacCall(_) => bug!(), // handled above
         };
 
         let vis = ty::Visibility::Public;
@@ -1273,7 +1262,7 @@ fn visit_assoc_item(&mut self, item: &'b AssocItem, ctxt: AssocCtxt) {
     fn visit_token(&mut self, t: Token) {
         if let token::Interpolated(nt) = t.kind {
             if let token::NtExpr(ref expr) = *nt {
-                if let ast::ExprKind::Mac(..) = expr.kind {
+                if let ast::ExprKind::MacCall(..) = expr.kind {
                     self.visit_invoc(expr.id);
                 }
             }
index 659a54b169b3974f91a1787ec53ba7b15bd85572..35876176e3e4b0381381a6404e3392abaa086533 100644 (file)
@@ -3,7 +3,7 @@
 //
 // Although this is mostly a lint pass, it lives in here because it depends on
 // resolve data structures and because it finalises the privacy information for
-// `use` directives.
+// `use` items.
 //
 // Unused trait imports can't be checked until the method resolution. We save
 // candidates here, and do the actual check in librustc_typeck/check_unused.rs.
 //  - `check_crate` finally emits the diagnostics based on the data generated
 //    in the last step
 
-use crate::imports::ImportDirectiveSubclass;
+use crate::imports::ImportKind;
 use crate::Resolver;
 
-use rustc::{lint, ty};
+use rustc::ty;
 use rustc_ast::ast;
 use rustc_ast::node_id::NodeMap;
 use rustc_ast::visit::{self, Visitor};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::pluralize;
+use rustc_session::lint::builtin::{MACRO_USE_EXTERN_CRATE, UNUSED_IMPORTS};
 use rustc_session::lint::BuiltinLintDiagnostics;
 use rustc_span::{MultiSpan, Span, DUMMY_SP};
 
@@ -58,7 +59,7 @@ struct UnusedImportCheckVisitor<'a, 'b> {
 }
 
 impl<'a, 'b> UnusedImportCheckVisitor<'a, 'b> {
-    // We have information about whether `use` (import) directives are actually
+    // We have information about whether `use` (import) items are actually
     // used now. If an import is not used at all, we signal a lint error.
     fn check_import(&mut self, id: ast::NodeId) {
         let mut used = false;
@@ -223,33 +224,32 @@ fn calc_unused_spans(
 
 impl Resolver<'_> {
     crate fn check_unused(&mut self, krate: &ast::Crate) {
-        for directive in self.potentially_unused_imports.iter() {
-            match directive.subclass {
-                _ if directive.used.get()
-                    || directive.vis.get() == ty::Visibility::Public
-                    || directive.span.is_dummy() =>
+        for import in self.potentially_unused_imports.iter() {
+            match import.kind {
+                _ if import.used.get()
+                    || import.vis.get() == ty::Visibility::Public
+                    || import.span.is_dummy() =>
                 {
-                    if let ImportDirectiveSubclass::MacroUse = directive.subclass {
-                        if !directive.span.is_dummy() {
+                    if let ImportKind::MacroUse = import.kind {
+                        if !import.span.is_dummy() {
                             self.lint_buffer.buffer_lint(
-                                lint::builtin::MACRO_USE_EXTERN_CRATE,
-                                directive.id,
-                                directive.span,
-                                "deprecated `#[macro_use]` directive used to \
+                                MACRO_USE_EXTERN_CRATE,
+                                import.id,
+                                import.span,
+                                "deprecated `#[macro_use]` attribute used to \
                                 import macros should be replaced at use sites \
-                                with a `use` statement to import the macro \
+                                with a `use` item to import the macro \
                                 instead",
                             );
                         }
                     }
                 }
-                ImportDirectiveSubclass::ExternCrate { .. } => {
-                    self.maybe_unused_extern_crates.push((directive.id, directive.span));
+                ImportKind::ExternCrate { .. } => {
+                    self.maybe_unused_extern_crates.push((import.id, import.span));
                 }
-                ImportDirectiveSubclass::MacroUse => {
-                    let lint = lint::builtin::UNUSED_IMPORTS;
+                ImportKind::MacroUse => {
                     let msg = "unused `#[macro_use]` import";
-                    self.lint_buffer.buffer_lint(lint, directive.id, directive.span, msg);
+                    self.lint_buffer.buffer_lint(UNUSED_IMPORTS, import.id, import.span, msg);
                 }
                 _ => {}
             }
@@ -314,7 +314,7 @@ impl Resolver<'_> {
             };
 
             visitor.r.lint_buffer.buffer_lint_with_diagnostic(
-                lint::builtin::UNUSED_IMPORTS,
+                UNUSED_IMPORTS,
                 unused.use_tree_id,
                 ms,
                 &msg,
index 2e687c88941fac1a95a3a8a42438ae0963959295..505cd331a25099f5debc4e96d1a632d52dbd9d2d 100644 (file)
@@ -2,9 +2,9 @@
 use rustc::hir::map::definitions::*;
 use rustc_ast::ast::*;
 use rustc_ast::token::{self, Token};
-use rustc_ast::visit;
+use rustc_ast::visit::{self, FnKind};
 use rustc_expand::expand::AstFragment;
-use rustc_hir::def_id::DefIndex;
+use rustc_hir::def_id::LocalDefId;
 use rustc_span::hygiene::ExpnId;
 use rustc_span::symbol::{kw, sym};
 use rustc_span::Span;
 /// Creates `DefId`s for nodes in the AST.
 struct DefCollector<'a> {
     definitions: &'a mut Definitions,
-    parent_def: DefIndex,
+    parent_def: LocalDefId,
     expansion: ExpnId,
 }
 
 impl<'a> DefCollector<'a> {
-    fn create_def(&mut self, node_id: NodeId, data: DefPathData, span: Span) -> DefIndex {
+    fn create_def(&mut self, node_id: NodeId, data: DefPathData, span: Span) -> LocalDefId {
         let parent_def = self.parent_def;
         debug!("create_def(node_id={:?}, data={:?}, parent_def={:?})", node_id, data, parent_def);
         self.definitions.create_def_with_parent(parent_def, node_id, data, self.expansion, span)
     }
 
-    fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_def: DefIndex, f: F) {
+    fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_def: LocalDefId, f: F) {
         let orig_parent_def = std::mem::replace(&mut self.parent_def, parent_def);
         f(self);
         self.parent_def = orig_parent_def;
     }
 
-    fn visit_async_fn(
-        &mut self,
-        id: NodeId,
-        name: Name,
-        span: Span,
-        header: &FnHeader,
-        generics: &'a Generics,
-        decl: &'a FnDecl,
-        body: Option<&'a Block>,
-    ) {
-        let (closure_id, return_impl_trait_id) = match header.asyncness {
-            Async::Yes { span: _, closure_id, return_impl_trait_id } => {
-                (closure_id, return_impl_trait_id)
-            }
-            _ => unreachable!(),
-        };
-
-        // 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 = 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);
-
-            visit::walk_generics(this, generics);
-            visit::walk_fn_decl(this, decl);
-
-            let closure_def = this.create_def(closure_id, DefPathData::ClosureExpr, span);
-            this.with_parent(closure_def, |this| {
-                if let Some(body) = body {
-                    visit::walk_block(this, body);
-                }
-            })
-        });
-    }
-
     fn collect_field(&mut self, field: &'a StructField, index: Option<usize>) {
         let index = |this: &Self| {
             index.unwrap_or_else(|| {
@@ -117,22 +81,11 @@ fn visit_item(&mut self, i: &'a Item) {
             | ItemKind::ExternCrate(..)
             | ItemKind::ForeignMod(..)
             | ItemKind::TyAlias(..) => DefPathData::TypeNs(i.ident.name),
-            ItemKind::Fn(_, sig, generics, body) if sig.header.asyncness.is_async() => {
-                return self.visit_async_fn(
-                    i.id,
-                    i.ident.name,
-                    i.span,
-                    &sig.header,
-                    generics,
-                    &sig.decl,
-                    body.as_deref(),
-                );
-            }
             ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) => {
                 DefPathData::ValueNs(i.ident.name)
             }
             ItemKind::MacroDef(..) => DefPathData::MacroNs(i.ident.name),
-            ItemKind::Mac(..) => return self.visit_macro_invoc(i.id),
+            ItemKind::MacCall(..) => return self.visit_macro_invoc(i.id),
             ItemKind::GlobalAsm(..) => DefPathData::Misc,
             ItemKind::Use(..) => {
                 return visit::walk_item(self, i);
@@ -154,13 +107,34 @@ fn visit_item(&mut self, i: &'a Item) {
         });
     }
 
+    fn visit_fn(&mut self, fn_kind: FnKind<'a>, span: Span, _: NodeId) {
+        if let FnKind::Fn(_, _, sig, _, body) = fn_kind {
+            if let Async::Yes { closure_id, return_impl_trait_id, .. } = sig.header.asyncness {
+                self.create_def(return_impl_trait_id, DefPathData::ImplTrait, span);
+
+                // For async functions, we need to create their inner defs inside of a
+                // closure to match their desugared representation. Besides that,
+                // we must mirror everything that `visit::walk_fn` below does.
+                self.visit_fn_header(&sig.header);
+                visit::walk_fn_decl(self, &sig.decl);
+                if let Some(body) = body {
+                    let closure_def = self.create_def(closure_id, DefPathData::ClosureExpr, span);
+                    self.with_parent(closure_def, |this| this.visit_block(body));
+                }
+                return;
+            }
+        }
+
+        visit::walk_fn(self, fn_kind, span);
+    }
+
     fn visit_use_tree(&mut self, use_tree: &'a UseTree, id: NodeId, _nested: bool) {
         self.create_def(id, DefPathData::Misc, use_tree.span);
         visit::walk_use_tree(self, use_tree, id);
     }
 
     fn visit_foreign_item(&mut self, foreign_item: &'a ForeignItem) {
-        if let ForeignItemKind::Macro(_) = foreign_item.kind {
+        if let ForeignItemKind::MacCall(_) = foreign_item.kind {
             return self.visit_macro_invoc(foreign_item.id);
         }
 
@@ -215,24 +189,9 @@ fn visit_generic_param(&mut self, param: &'a GenericParam) {
 
     fn visit_assoc_item(&mut self, i: &'a AssocItem, ctxt: visit::AssocCtxt) {
         let def_data = match &i.kind {
-            AssocItemKind::Fn(_, FnSig { header, decl }, generics, body)
-                if header.asyncness.is_async() =>
-            {
-                return self.visit_async_fn(
-                    i.id,
-                    i.ident.name,
-                    i.span,
-                    header,
-                    generics,
-                    decl,
-                    body.as_deref(),
-                );
-            }
-            AssocItemKind::Fn(..) | AssocItemKind::Const(..) | AssocItemKind::Static(..) => {
-                DefPathData::ValueNs(i.ident.name)
-            }
+            AssocItemKind::Fn(..) | AssocItemKind::Const(..) => DefPathData::ValueNs(i.ident.name),
             AssocItemKind::TyAlias(..) => DefPathData::TypeNs(i.ident.name),
-            AssocItemKind::Macro(..) => return self.visit_macro_invoc(i.id),
+            AssocItemKind::MacCall(..) => return self.visit_macro_invoc(i.id),
         };
 
         let def = self.create_def(i.id, def_data, i.span);
@@ -241,7 +200,7 @@ fn visit_assoc_item(&mut self, i: &'a AssocItem, ctxt: visit::AssocCtxt) {
 
     fn visit_pat(&mut self, pat: &'a Pat) {
         match pat.kind {
-            PatKind::Mac(..) => return self.visit_macro_invoc(pat.id),
+            PatKind::MacCall(..) => return self.visit_macro_invoc(pat.id),
             _ => visit::walk_pat(self, pat),
         }
     }
@@ -253,7 +212,7 @@ fn visit_anon_const(&mut self, constant: &'a AnonConst) {
 
     fn visit_expr(&mut self, expr: &'a Expr) {
         let parent_def = match expr.kind {
-            ExprKind::Mac(..) => return self.visit_macro_invoc(expr.id),
+            ExprKind::MacCall(..) => return self.visit_macro_invoc(expr.id),
             ExprKind::Closure(_, asyncness, ..) => {
                 // Async closures desugar to closures inside of closures, so
                 // we must create two defs.
@@ -276,7 +235,7 @@ fn visit_expr(&mut self, expr: &'a Expr) {
 
     fn visit_ty(&mut self, ty: &'a Ty) {
         match ty.kind {
-            TyKind::Mac(..) => return self.visit_macro_invoc(ty.id),
+            TyKind::MacCall(..) => return self.visit_macro_invoc(ty.id),
             TyKind::ImplTrait(node_id, _) => {
                 self.create_def(node_id, DefPathData::ImplTrait, ty.span);
             }
@@ -287,7 +246,7 @@ fn visit_ty(&mut self, ty: &'a Ty) {
 
     fn visit_stmt(&mut self, stmt: &'a Stmt) {
         match stmt.kind {
-            StmtKind::Mac(..) => self.visit_macro_invoc(stmt.id),
+            StmtKind::MacCall(..) => self.visit_macro_invoc(stmt.id),
             _ => visit::walk_stmt(self, stmt),
         }
     }
@@ -295,7 +254,7 @@ fn visit_stmt(&mut self, stmt: &'a Stmt) {
     fn visit_token(&mut self, t: Token) {
         if let token::Interpolated(nt) = t.kind {
             if let token::NtExpr(ref expr) = *nt {
-                if let ExprKind::Mac(..) = expr.kind {
+                if let ExprKind::MacCall(..) = expr.kind {
                     self.visit_macro_invoc(expr.id);
                 }
             }
index 18192a18cef3663e60f579f2f7a77b661c45d204..6f567ab65a70c01ea3990c8d78cabd1ca211bf4e 100644 (file)
@@ -1,8 +1,8 @@
 use std::cmp::Reverse;
+use std::ptr;
 
 use log::debug;
 use rustc::bug;
-use rustc::session::Session;
 use rustc::ty::{self, DefIdTree};
 use rustc_ast::ast::{self, Ident, Path};
 use rustc_ast::util::lev_distance::find_best_match_for_name;
 use rustc_hir::def::Namespace::{self, *};
 use rustc_hir::def::{self, CtorKind, CtorOf, DefKind, NonMacroAttrKind};
 use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_session::Session;
 use rustc_span::hygiene::MacroKind;
 use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::{kw, Symbol};
 use rustc_span::{BytePos, MultiSpan, Span};
 
-use crate::imports::{ImportDirective, ImportDirectiveSubclass, ImportResolver};
+use crate::imports::{Import, ImportKind, ImportResolver};
 use crate::path_names_to_string;
 use crate::{AmbiguityError, AmbiguityErrorMisc, AmbiguityKind};
-use crate::{BindingError, CrateLint, HasGenericParams, LegacyScope, Module, ModuleOrUniformRoot};
+use crate::{
+    BindingError, CrateLint, HasGenericParams, MacroRulesScope, Module, ModuleOrUniformRoot,
+};
 use crate::{NameBinding, NameBindingKind, PrivacyError, VisResolutionError};
 use crate::{ParentScope, PathResult, ResolutionError, Resolver, Scope, ScopeSet, Segment};
 
@@ -249,8 +252,7 @@ impl<'a> Resolver<'a> {
                     self.session,
                     span,
                     E0409,
-                    "variable `{}` is bound in inconsistent \
-                                ways within the same match arm",
+                    "variable `{}` is bound inconsistently across alternatives separated by `|`",
                     variable_name
                 );
                 err.span_label(span, "bound in different ways");
@@ -499,12 +501,12 @@ fn early_lookup_typo_candidate(
                         }
                     }
                 }
-                Scope::MacroRules(legacy_scope) => {
-                    if let LegacyScope::Binding(legacy_binding) = legacy_scope {
-                        let res = legacy_binding.binding.res();
+                Scope::MacroRules(macro_rules_scope) => {
+                    if let MacroRulesScope::Binding(macro_rules_binding) = macro_rules_scope {
+                        let res = macro_rules_binding.binding.res();
                         if filter_fn(res) {
                             suggestions
-                                .push(TypoSuggestion::from_res(legacy_binding.ident.name, res))
+                                .push(TypoSuggestion::from_res(macro_rules_binding.ident.name, res))
                         }
                     }
                 }
@@ -757,7 +759,7 @@ fn lookup_import_candidates_from_module<FilterFn>(
             let msg = format!("unsafe traits like `{}` should be implemented explicitly", ident);
             err.span_note(ident.span, &msg);
         }
-        if self.macro_names.contains(&ident.modern()) {
+        if self.macro_names.contains(&ident.normalize_to_macros_2_0()) {
             err.help("have you added the `#[macro_use]` on the module/import?");
         }
     }
@@ -917,50 +919,81 @@ fn binding_description(&self, b: &NameBinding<'_>, ident: Ident, from_prelude: b
         err.emit();
     }
 
-    crate fn report_privacy_error(&self, privacy_error: &PrivacyError<'_>) {
-        let PrivacyError { ident, binding, .. } = *privacy_error;
-        let session = &self.session;
-        let mk_struct_span_error = |is_constructor| {
-            let mut descr = binding.res().descr().to_string();
-            if is_constructor {
-                descr += " constructor";
-            }
-            if binding.is_import() {
-                descr += " import";
-            }
-
-            let mut err =
-                struct_span_err!(session, ident.span, E0603, "{} `{}` is private", descr, ident);
-
-            err.span_label(ident.span, &format!("this {} is private", descr));
-            err.span_note(
-                session.source_map().def_span(binding.span),
-                &format!("the {} `{}` is defined here", descr, ident),
-            );
-
-            err
-        };
-
-        let mut err = if let NameBindingKind::Res(
+    /// If the binding refers to a tuple struct constructor with fields,
+    /// returns the span of its fields.
+    fn ctor_fields_span(&self, binding: &NameBinding<'_>) -> Option<Span> {
+        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)
+                return Some(fields.iter().fold(first_field.span, |acc, field| acc.to(field.span)));
             }
-        } else {
-            mk_struct_span_error(false)
-        };
+        }
+        None
+    }
+
+    crate fn report_privacy_error(&self, privacy_error: &PrivacyError<'_>) {
+        let PrivacyError { ident, binding, .. } = *privacy_error;
+
+        let res = binding.res();
+        let ctor_fields_span = self.ctor_fields_span(binding);
+        let plain_descr = res.descr().to_string();
+        let nonimport_descr =
+            if ctor_fields_span.is_some() { plain_descr + " constructor" } else { plain_descr };
+        let import_descr = nonimport_descr.clone() + " import";
+        let get_descr =
+            |b: &NameBinding<'_>| if b.is_import() { &import_descr } else { &nonimport_descr };
+
+        // Print the primary message.
+        let descr = get_descr(binding);
+        let mut err =
+            struct_span_err!(self.session, ident.span, E0603, "{} `{}` is private", descr, ident);
+        err.span_label(ident.span, &format!("this {} is private", descr));
+        if let Some(span) = ctor_fields_span {
+            err.span_label(span, "a constructor is private if any of the fields is private");
+        }
+
+        // Print the whole import chain to make it easier to see what happens.
+        let first_binding = binding;
+        let mut next_binding = Some(binding);
+        let mut next_ident = ident;
+        while let Some(binding) = next_binding {
+            let name = next_ident;
+            next_binding = match binding.kind {
+                _ if res == Res::Err => None,
+                NameBindingKind::Import { binding, import, .. } => match import.kind {
+                    _ if binding.span.is_dummy() => None,
+                    ImportKind::Single { source, .. } => {
+                        next_ident = source;
+                        Some(binding)
+                    }
+                    ImportKind::Glob { .. } | ImportKind::MacroUse => Some(binding),
+                    ImportKind::ExternCrate { .. } => None,
+                },
+                _ => None,
+            };
+
+            let first = ptr::eq(binding, first_binding);
+            let descr = get_descr(binding);
+            let msg = format!(
+                "{and_refers_to}the {item} `{name}`{which} is defined here{dots}",
+                and_refers_to = if first { "" } else { "...and refers to " },
+                item = descr,
+                name = name,
+                which = if first { "" } else { " which" },
+                dots = if next_binding.is_some() { "..." } else { "" },
+            );
+            let def_span = self.session.source_map().def_span(binding.span);
+            let mut note_span = MultiSpan::from_span(def_span);
+            if !first && binding.vis == ty::Visibility::Public {
+                note_span.push_span_label(def_span, "consider importing it directly".into());
+            }
+            err.span_note(note_span, &msg);
+        }
 
         err.emit();
     }
@@ -1090,7 +1123,7 @@ fn make_external_crate_suggestion(
         }
 
         // Sort extern crate names in reverse order to get
-        // 1) some consistent ordering for emitted dignostics, and
+        // 1) some consistent ordering for emitted diagnostics, and
         // 2) `std` suggestions before `core` suggestions.
         let mut extern_crate_names =
             self.r.extern_prelude.iter().map(|(ident, _)| ident.name).collect::<Vec<_>>();
@@ -1126,7 +1159,7 @@ fn make_external_crate_suggestion(
     /// ```
     pub(crate) fn check_for_module_export_macro(
         &mut self,
-        directive: &'b ImportDirective<'b>,
+        import: &'b Import<'b>,
         module: ModuleOrUniformRoot<'b>,
         ident: Ident,
     ) -> Option<(Option<Suggestion>, Vec<String>)> {
@@ -1151,28 +1184,26 @@ pub(crate) fn check_for_module_export_macro(
         let binding = resolution.borrow().binding()?;
         if let Res::Def(DefKind::Macro(MacroKind::Bang), _) = binding.res() {
             let module_name = crate_module.kind.name().unwrap();
-            let import = match directive.subclass {
-                ImportDirectiveSubclass::SingleImport { source, target, .. }
-                    if source != target =>
-                {
+            let import_snippet = match import.kind {
+                ImportKind::Single { source, target, .. } if source != target => {
                     format!("{} as {}", source, target)
                 }
                 _ => format!("{}", ident),
             };
 
             let mut corrections: Vec<(Span, String)> = Vec::new();
-            if !directive.is_nested() {
+            if !import.is_nested() {
                 // Assume this is the easy case of `use issue_59764::foo::makro;` and just remove
                 // intermediate segments.
-                corrections.push((directive.span, format!("{}::{}", module_name, import)));
+                corrections.push((import.span, format!("{}::{}", module_name, import_snippet)));
             } else {
                 // Find the binding span (and any trailing commas and spaces).
                 //   ie. `use a::b::{c, d, e};`
                 //                      ^^^
                 let (found_closing_brace, binding_span) = find_span_of_binding_until_next_binding(
                     self.r.session,
-                    directive.span,
-                    directive.use_span,
+                    import.span,
+                    import.use_span,
                 );
                 debug!(
                     "check_for_module_export_macro: found_closing_brace={:?} binding_span={:?}",
@@ -1209,7 +1240,7 @@ pub(crate) fn check_for_module_export_macro(
                 let (has_nested, after_crate_name) = find_span_immediately_after_crate_name(
                     self.r.session,
                     module_name,
-                    directive.use_span,
+                    import.use_span,
                 );
                 debug!(
                     "check_for_module_export_macro: has_nested={:?} after_crate_name={:?}",
@@ -1225,11 +1256,11 @@ pub(crate) fn check_for_module_export_macro(
                         start_point,
                         if has_nested {
                             // In this case, `start_snippet` must equal '{'.
-                            format!("{}{}, ", start_snippet, import)
+                            format!("{}{}, ", start_snippet, import_snippet)
                         } else {
                             // In this case, add a `{`, then the moved import, then whatever
                             // was there before.
-                            format!("{{{}, {}", import, start_snippet)
+                            format!("{{{}, {}", import_snippet, start_snippet)
                         },
                     ));
                 }
index 9198c74d89a4c829c5342172282dfaf5e68cb5d5..663e61ad2add4c0b79d5b09882bc2c045df7af60 100644 (file)
@@ -1,7 +1,5 @@
 //! A bunch of methods and structures more or less related to resolving imports.
 
-use ImportDirectiveSubclass::*;
-
 use crate::diagnostics::Suggestion;
 use crate::Determinacy::{self, *};
 use crate::Namespace::{self, MacroNS, TypeNS};
@@ -12,7 +10,6 @@
 use crate::{NameBinding, NameBindingKind, PathResult, PrivacyError, ToNameBinding};
 
 use rustc::hir::exports::Export;
-use rustc::lint::builtin::{PUB_USE_OF_PRIVATE_EXTERN_CRATE, UNUSED_IMPORTS};
 use rustc::ty;
 use rustc::{bug, span_bug};
 use rustc_ast::ast::{Ident, Name, NodeId};
@@ -23,6 +20,7 @@
 use rustc_errors::{pluralize, struct_span_err, Applicability};
 use rustc_hir::def::{self, PartialRes};
 use rustc_hir::def_id::DefId;
+use rustc_session::lint::builtin::{PUB_USE_OF_PRIVATE_EXTERN_CRATE, UNUSED_IMPORTS};
 use rustc_session::lint::BuiltinLintDiagnostics;
 use rustc_session::DiagnosticMessageId;
 use rustc_span::hygiene::ExpnId;
 
 type Res = def::Res<NodeId>;
 
-/// Contains data for specific types of import directives.
+/// Contains data for specific kinds of imports.
 #[derive(Clone, Debug)]
-pub enum ImportDirectiveSubclass<'a> {
-    SingleImport {
+pub enum ImportKind<'a> {
+    Single {
         /// `source` in `use prefix::source as target`.
         source: Ident,
         /// `target` in `use prefix::source as target`.
@@ -53,7 +51,7 @@ pub enum ImportDirectiveSubclass<'a> {
         /// Did this import result from a nested import? ie. `use foo::{bar, baz};`
         nested: bool,
     },
-    GlobImport {
+    Glob {
         is_prelude: bool,
         max_vis: Cell<ty::Visibility>, // The visibility of the greatest re-export.
                                        // n.b. `max_vis` is only used in `finalize_import` to check for re-export errors.
@@ -65,19 +63,21 @@ pub enum ImportDirectiveSubclass<'a> {
     MacroUse,
 }
 
-/// One import directive.
+/// One import.
 #[derive(Debug, Clone)]
-crate struct ImportDirective<'a> {
-    /// The ID of the `extern crate`, `UseTree` etc that imported this `ImportDirective`.
+crate struct Import<'a> {
+    pub kind: ImportKind<'a>,
+
+    /// The ID of the `extern crate`, `UseTree` etc that imported this `Import`.
     ///
-    /// In the case where the `ImportDirective` was expanded from a "nested" use tree,
+    /// In the case where the `Import` was expanded from a "nested" use tree,
     /// this id is the ID of the leaf tree. For example:
     ///
     /// ```ignore (pacify the mercilous tidy)
     /// use foo::bar::{a, b}
     /// ```
     ///
-    /// If this is the import directive for `foo::bar::a`, we would have the ID of the `UseTree`
+    /// If this is the import for `foo::bar::a`, we would have the ID of the `UseTree`
     /// for `a` in this field.
     pub id: NodeId,
 
@@ -107,22 +107,21 @@ pub enum ImportDirectiveSubclass<'a> {
     pub module_path: Vec<Segment>,
     /// The resolution of `module_path`.
     pub imported_module: Cell<Option<ModuleOrUniformRoot<'a>>>,
-    pub subclass: ImportDirectiveSubclass<'a>,
     pub vis: Cell<ty::Visibility>,
     pub used: Cell<bool>,
 }
 
-impl<'a> ImportDirective<'a> {
+impl<'a> Import<'a> {
     pub fn is_glob(&self) -> bool {
-        match self.subclass {
-            ImportDirectiveSubclass::GlobImport { .. } => true,
+        match self.kind {
+            ImportKind::Glob { .. } => true,
             _ => false,
         }
     }
 
     pub fn is_nested(&self) -> bool {
-        match self.subclass {
-            ImportDirectiveSubclass::SingleImport { nested, .. } => nested,
+        match self.kind {
+            ImportKind::Single { nested, .. } => nested,
             _ => false,
         }
     }
@@ -136,8 +135,8 @@ pub fn is_nested(&self) -> bool {
 /// Records information about the resolution of a name in a namespace of a module.
 pub struct NameResolution<'a> {
     /// Single imports that may define the name in the namespace.
-    /// Import directives are arena-allocated, so it's ok to use pointers as keys.
-    single_imports: FxHashSet<PtrKey<'a, ImportDirective<'a>>>,
+    /// Imports are arena-allocated, so it's ok to use pointers as keys.
+    single_imports: FxHashSet<PtrKey<'a, Import<'a>>>,
     /// The least shadowable known binding for this name, or None if there are no known bindings.
     pub binding: Option<&'a NameBinding<'a>>,
     shadowed_glob: Option<&'a NameBinding<'a>>,
@@ -155,8 +154,8 @@ pub(crate) fn binding(&self) -> Option<&'a NameBinding<'a>> {
         })
     }
 
-    crate fn add_single_import(&mut self, directive: &'a ImportDirective<'a>) {
-        self.single_imports.insert(PtrKey(directive));
+    crate fn add_single_import(&mut self, import: &'a Import<'a>) {
+        self.single_imports.insert(PtrKey(import));
     }
 }
 
@@ -313,9 +312,9 @@ impl<'a> Resolver<'a> {
                             }
                         }
 
-                        if !self.is_accessible_from(binding.vis, parent_scope.module) &&
+                        if !(self.is_accessible_from(binding.vis, parent_scope.module) ||
                        // Remove this together with `PUB_USE_OF_PRIVATE_EXTERN_CRATE`
-                       !(self.last_import_segment && binding.is_extern_crate())
+                       (self.last_import_segment && binding.is_extern_crate()))
                         {
                             self.privacy_errors.push(PrivacyError {
                                 ident,
@@ -348,8 +347,8 @@ impl<'a> Resolver<'a> {
                 single_import.imported_module.get(),
                 return Err((Undetermined, Weak::No))
             );
-            let ident = match single_import.subclass {
-                SingleImport { source, .. } => source,
+            let ident = match single_import.kind {
+                ImportKind::Single { source, .. } => source,
                 _ => unreachable!(),
             };
             match self.resolve_ident_in_module(
@@ -417,7 +416,8 @@ impl<'a> Resolver<'a> {
                 None => return Err((Undetermined, Weak::Yes)),
             };
             let tmp_parent_scope;
-            let (mut adjusted_parent_scope, mut ident) = (parent_scope, ident.modern());
+            let (mut adjusted_parent_scope, mut ident) =
+                (parent_scope, ident.normalize_to_macros_2_0());
             match ident.span.glob_adjust(module.expansion, glob_import.span) {
                 Some(Some(def)) => {
                     tmp_parent_scope =
@@ -451,34 +451,34 @@ impl<'a> Resolver<'a> {
         Err((Determined, Weak::No))
     }
 
-    // Given a binding and an import directive that resolves to it,
-    // return the corresponding binding defined by the import directive.
+    // Given a binding and an import that resolves to it,
+    // return the corresponding binding defined by the import.
     crate fn import(
         &self,
         binding: &'a NameBinding<'a>,
-        directive: &'a ImportDirective<'a>,
+        import: &'a Import<'a>,
     ) -> &'a NameBinding<'a> {
-        let vis = if binding.pseudo_vis().is_at_least(directive.vis.get(), self) ||
+        let vis = if binding.pseudo_vis().is_at_least(import.vis.get(), self) ||
                      // cf. `PUB_USE_OF_PRIVATE_EXTERN_CRATE`
-                     !directive.is_glob() && binding.is_extern_crate()
+                     !import.is_glob() && binding.is_extern_crate()
         {
-            directive.vis.get()
+            import.vis.get()
         } else {
             binding.pseudo_vis()
         };
 
-        if let GlobImport { ref max_vis, .. } = directive.subclass {
-            if vis == directive.vis.get() || vis.is_at_least(max_vis.get(), self) {
+        if let ImportKind::Glob { ref max_vis, .. } = import.kind {
+            if vis == import.vis.get() || vis.is_at_least(max_vis.get(), self) {
                 max_vis.set(vis)
             }
         }
 
         self.arenas.alloc_name_binding(NameBinding {
-            kind: NameBindingKind::Import { binding, directive, used: Cell::new(false) },
+            kind: NameBindingKind::Import { binding, import, used: Cell::new(false) },
             ambiguity: None,
-            span: directive.span,
+            span: import.span,
             vis,
-            expansion: directive.parent_scope.expansion,
+            expansion: import.parent_scope.expansion,
         })
     }
 
@@ -577,17 +577,17 @@ fn update_resolution<T, F>(&mut self, module: Module<'a>, key: BindingKey, f: F)
         };
 
         // Define `binding` in `module`s glob importers.
-        for directive in module.glob_importers.borrow_mut().iter() {
+        for import in module.glob_importers.borrow_mut().iter() {
             let mut ident = key.ident;
-            let scope = match ident.span.reverse_glob_adjust(module.expansion, directive.span) {
+            let scope = match ident.span.reverse_glob_adjust(module.expansion, import.span) {
                 Some(Some(def)) => self.macro_def_scope(def),
-                Some(None) => directive.parent_scope.module,
+                Some(None) => import.parent_scope.module,
                 None => continue,
             };
             if self.is_accessible_from(binding.vis, scope) {
-                let imported_binding = self.import(binding, directive);
+                let imported_binding = self.import(binding, import);
                 let key = BindingKey { ident, ..key };
-                let _ = self.try_define(directive.parent_scope.module, key, imported_binding);
+                let _ = self.try_define(import.parent_scope.module, key, imported_binding);
             }
         }
 
@@ -596,13 +596,13 @@ fn update_resolution<T, F>(&mut self, module: Module<'a>, key: BindingKey, f: F)
 
     // Define a "dummy" resolution containing a Res::Err as a placeholder for a
     // failed resolution
-    fn import_dummy_binding(&mut self, directive: &'a ImportDirective<'a>) {
-        if let SingleImport { target, .. } = directive.subclass {
+    fn import_dummy_binding(&mut self, import: &'a Import<'a>) {
+        if let ImportKind::Single { target, .. } = import.kind {
             let dummy_binding = self.dummy_binding;
-            let dummy_binding = self.import(dummy_binding, directive);
+            let dummy_binding = self.import(dummy_binding, import);
             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(import.parent_scope.module, key, dummy_binding);
                 // Consider erroneous imports used to avoid duplicate diagnostics.
                 this.record_use(target, ns, dummy_binding, false);
             });
@@ -671,7 +671,7 @@ pub fn finalize_imports(&mut self) {
             .chain(indeterminate_imports.into_iter().map(|i| (true, i)))
         {
             if let Some(err) = self.finalize_import(import) {
-                if let SingleImport { source, ref source_bindings, .. } = import.subclass {
+                if let ImportKind::Single { source, ref source_bindings, .. } = import.kind {
                     if source.name == kw::SelfLower {
                         // Silence `unresolved import` error if E0429 is already emitted
                         if let Err(Determined) = source_bindings.value_ns.get() {
@@ -695,7 +695,7 @@ pub fn finalize_imports(&mut self) {
                 if seen_spans.insert(err.span) {
                     let path = import_path_to_string(
                         &import.module_path.iter().map(|seg| seg.ident).collect::<Vec<_>>(),
-                        &import.subclass,
+                        &import.kind,
                         err.span,
                     );
                     errors.push((path, err));
@@ -706,7 +706,7 @@ pub fn finalize_imports(&mut self) {
                 self.r.used_imports.insert((import.id, TypeNS));
                 let path = import_path_to_string(
                     &import.module_path.iter().map(|seg| seg.ident).collect::<Vec<_>>(),
-                    &import.subclass,
+                    &import.kind,
                     import.span,
                 );
                 let err = UnresolvedImportError {
@@ -767,28 +767,28 @@ fn throw_unresolved_import_error(
 
     /// Attempts to resolve the given import, returning true if its resolution is determined.
     /// If successful, the resolved bindings are written into the module.
-    fn resolve_import(&mut self, directive: &'b ImportDirective<'b>) -> bool {
+    fn resolve_import(&mut self, import: &'b Import<'b>) -> bool {
         debug!(
             "(resolving import for module) resolving import `{}::...` in `{}`",
-            Segment::names_to_string(&directive.module_path),
-            module_to_string(directive.parent_scope.module).unwrap_or_else(|| "???".to_string()),
+            Segment::names_to_string(&import.module_path),
+            module_to_string(import.parent_scope.module).unwrap_or_else(|| "???".to_string()),
         );
 
-        let module = if let Some(module) = directive.imported_module.get() {
+        let module = if let Some(module) = import.imported_module.get() {
             module
         } else {
             // For better failure detection, pretend that the import will
             // not define any names while resolving its module path.
-            let orig_vis = directive.vis.replace(ty::Visibility::Invisible);
+            let orig_vis = import.vis.replace(ty::Visibility::Invisible);
             let path_res = self.r.resolve_path(
-                &directive.module_path,
+                &import.module_path,
                 None,
-                &directive.parent_scope,
+                &import.parent_scope,
                 false,
-                directive.span,
-                directive.crate_lint(),
+                import.span,
+                import.crate_lint(),
             );
-            directive.vis.set(orig_vis);
+            import.vis.set(orig_vis);
 
             match path_res {
                 PathResult::Module(module) => module,
@@ -797,23 +797,22 @@ fn resolve_import(&mut self, directive: &'b ImportDirective<'b>) -> bool {
             }
         };
 
-        directive.imported_module.set(Some(module));
-        let (source, target, source_bindings, target_bindings, type_ns_only) =
-            match directive.subclass {
-                SingleImport {
-                    source,
-                    target,
-                    ref source_bindings,
-                    ref target_bindings,
-                    type_ns_only,
-                    ..
-                } => (source, target, source_bindings, target_bindings, type_ns_only),
-                GlobImport { .. } => {
-                    self.resolve_glob_import(directive);
-                    return true;
-                }
-                _ => unreachable!(),
-            };
+        import.imported_module.set(Some(module));
+        let (source, target, source_bindings, target_bindings, type_ns_only) = match import.kind {
+            ImportKind::Single {
+                source,
+                target,
+                ref source_bindings,
+                ref target_bindings,
+                type_ns_only,
+                ..
+            } => (source, target, source_bindings, target_bindings, type_ns_only),
+            ImportKind::Glob { .. } => {
+                self.resolve_glob_import(import);
+                return true;
+            }
+            _ => unreachable!(),
+        };
 
         let mut indeterminate = false;
         self.r.per_ns(|this, ns| {
@@ -821,23 +820,23 @@ fn resolve_import(&mut self, directive: &'b ImportDirective<'b>) -> bool {
                 if let Err(Undetermined) = source_bindings[ns].get() {
                     // For better failure detection, pretend that the import will
                     // not define any names while resolving its module path.
-                    let orig_vis = directive.vis.replace(ty::Visibility::Invisible);
+                    let orig_vis = import.vis.replace(ty::Visibility::Invisible);
                     let binding = this.resolve_ident_in_module(
                         module,
                         source,
                         ns,
-                        &directive.parent_scope,
+                        &import.parent_scope,
                         false,
-                        directive.span,
+                        import.span,
                     );
-                    directive.vis.set(orig_vis);
+                    import.vis.set(orig_vis);
 
                     source_bindings[ns].set(binding);
                 } else {
                     return;
                 };
 
-                let parent = directive.parent_scope.module;
+                let parent = import.parent_scope.module;
                 match source_bindings[ns].get() {
                     Err(Undetermined) => indeterminate = true,
                     // Don't update the resolution, because it was never added.
@@ -845,20 +844,20 @@ fn resolve_import(&mut self, directive: &'b ImportDirective<'b>) -> bool {
                     Err(Determined) => {
                         let key = this.new_key(target, ns);
                         this.update_resolution(parent, key, |_, resolution| {
-                            resolution.single_imports.remove(&PtrKey(directive));
+                            resolution.single_imports.remove(&PtrKey(import));
                         });
                     }
                     Ok(binding) if !binding.is_importable() => {
                         let msg = format!("`{}` is not directly importable", target);
-                        struct_span_err!(this.session, directive.span, E0253, "{}", &msg)
-                            .span_label(directive.span, "cannot be imported directly")
+                        struct_span_err!(this.session, import.span, E0253, "{}", &msg)
+                            .span_label(import.span, "cannot be imported directly")
                             .emit();
                         // Do not import this illegal binding. Import a dummy binding and pretend
                         // everything is fine
-                        this.import_dummy_binding(directive);
+                        this.import_dummy_binding(import);
                     }
                     Ok(binding) => {
-                        let imported_binding = this.import(binding, directive);
+                        let imported_binding = this.import(binding, import);
                         target_bindings[ns].set(Some(imported_binding));
                         this.define(parent, target, ns, imported_binding);
                     }
@@ -873,38 +872,35 @@ fn resolve_import(&mut self, directive: &'b ImportDirective<'b>) -> bool {
     ///
     /// Optionally returns an unresolved import error. This error is buffered and used to
     /// consolidate multiple unresolved import errors into a single diagnostic.
-    fn finalize_import(
-        &mut self,
-        directive: &'b ImportDirective<'b>,
-    ) -> Option<UnresolvedImportError> {
-        let orig_vis = directive.vis.replace(ty::Visibility::Invisible);
+    fn finalize_import(&mut self, import: &'b Import<'b>) -> Option<UnresolvedImportError> {
+        let orig_vis = import.vis.replace(ty::Visibility::Invisible);
         let prev_ambiguity_errors_len = self.r.ambiguity_errors.len();
         let path_res = self.r.resolve_path(
-            &directive.module_path,
+            &import.module_path,
             None,
-            &directive.parent_scope,
+            &import.parent_scope,
             true,
-            directive.span,
-            directive.crate_lint(),
+            import.span,
+            import.crate_lint(),
         );
         let no_ambiguity = self.r.ambiguity_errors.len() == prev_ambiguity_errors_len;
-        directive.vis.set(orig_vis);
+        import.vis.set(orig_vis);
         if let PathResult::Failed { .. } | PathResult::NonModule(..) = path_res {
             // Consider erroneous imports used to avoid duplicate diagnostics.
-            self.r.used_imports.insert((directive.id, TypeNS));
+            self.r.used_imports.insert((import.id, TypeNS));
         }
         let module = match path_res {
             PathResult::Module(module) => {
                 // Consistency checks, analogous to `finalize_macro_resolutions`.
-                if let Some(initial_module) = directive.imported_module.get() {
+                if let Some(initial_module) = import.imported_module.get() {
                     if !ModuleOrUniformRoot::same_def(module, initial_module) && no_ambiguity {
-                        span_bug!(directive.span, "inconsistent resolution for an import");
+                        span_bug!(import.span, "inconsistent resolution for an import");
                     }
                 } else {
                     if self.r.privacy_errors.is_empty() {
                         let msg = "cannot determine resolution for the import";
                         let msg_note = "import resolution is stuck, try simplifying other imports";
-                        self.r.session.struct_span_err(directive.span, msg).note(msg_note).emit();
+                        self.r.session.struct_span_err(import.span, msg).note(msg_note).emit();
                     }
                 }
 
@@ -912,7 +908,7 @@ fn finalize_import(
             }
             PathResult::Failed { is_error_from_last_segment: false, span, label, suggestion } => {
                 if no_ambiguity {
-                    assert!(directive.imported_module.get().is_none());
+                    assert!(import.imported_module.get().is_none());
                     self.r
                         .report_error(span, ResolutionError::FailedToResolve { label, suggestion });
                 }
@@ -920,11 +916,11 @@ fn finalize_import(
             }
             PathResult::Failed { is_error_from_last_segment: true, span, label, suggestion } => {
                 if no_ambiguity {
-                    assert!(directive.imported_module.get().is_none());
+                    assert!(import.imported_module.get().is_none());
                     let err = match self.make_path_suggestion(
                         span,
-                        directive.module_path.clone(),
-                        &directive.parent_scope,
+                        import.module_path.clone(),
+                        &import.parent_scope,
                     ) {
                         Some((suggestion, note)) => UnresolvedImportError {
                             span,
@@ -949,7 +945,7 @@ fn finalize_import(
             }
             PathResult::NonModule(path_res) if path_res.base_res() == Res::Err => {
                 if no_ambiguity {
-                    assert!(directive.imported_module.get().is_none());
+                    assert!(import.imported_module.get().is_none());
                 }
                 // The error was already reported earlier.
                 return None;
@@ -957,10 +953,8 @@ fn finalize_import(
             PathResult::Indeterminate | PathResult::NonModule(..) => unreachable!(),
         };
 
-        let (ident, target, source_bindings, target_bindings, type_ns_only) = match directive
-            .subclass
-        {
-            SingleImport {
+        let (ident, target, source_bindings, target_bindings, type_ns_only) = match import.kind {
+            ImportKind::Single {
                 source,
                 target,
                 ref source_bindings,
@@ -968,25 +962,25 @@ fn finalize_import(
                 type_ns_only,
                 ..
             } => (source, target, source_bindings, target_bindings, type_ns_only),
-            GlobImport { is_prelude, ref max_vis } => {
-                if directive.module_path.len() <= 1 {
+            ImportKind::Glob { is_prelude, ref max_vis } => {
+                if import.module_path.len() <= 1 {
                     // HACK(eddyb) `lint_if_path_starts_with_module` needs at least
                     // 2 segments, so the `resolve_path` above won't trigger it.
-                    let mut full_path = directive.module_path.clone();
+                    let mut full_path = import.module_path.clone();
                     full_path.push(Segment::from_ident(Ident::invalid()));
                     self.r.lint_if_path_starts_with_module(
-                        directive.crate_lint(),
+                        import.crate_lint(),
                         &full_path,
-                        directive.span,
+                        import.span,
                         None,
                     );
                 }
 
                 if let ModuleOrUniformRoot::Module(module) = module {
-                    if module.def_id() == directive.parent_scope.module.def_id() {
+                    if module.def_id() == import.parent_scope.module.def_id() {
                         // Importing a module into itself is not allowed.
                         return Some(UnresolvedImportError {
-                            span: directive.span,
+                            span: import.span,
                             label: Some(String::from("cannot glob-import a module into itself")),
                             note: Vec::new(),
                             suggestion: None,
@@ -995,15 +989,10 @@ fn finalize_import(
                 }
                 if !is_prelude &&
                    max_vis.get() != ty::Visibility::Invisible && // Allow empty globs.
-                   !max_vis.get().is_at_least(directive.vis.get(), &*self)
+                   !max_vis.get().is_at_least(import.vis.get(), &*self)
                 {
                     let msg = "glob import doesn't reexport anything because no candidate is public enough";
-                    self.r.lint_buffer.buffer_lint(
-                        UNUSED_IMPORTS,
-                        directive.id,
-                        directive.span,
-                        msg,
-                    );
+                    self.r.lint_buffer.buffer_lint(UNUSED_IMPORTS, import.id, import.span, msg);
                 }
                 return None;
             }
@@ -1013,7 +1002,7 @@ fn finalize_import(
         let mut all_ns_err = true;
         self.r.per_ns(|this, ns| {
             if !type_ns_only || ns == TypeNS {
-                let orig_vis = directive.vis.replace(ty::Visibility::Invisible);
+                let orig_vis = import.vis.replace(ty::Visibility::Invisible);
                 let orig_blacklisted_binding =
                     mem::replace(&mut this.blacklisted_binding, target_bindings[ns].get());
                 let orig_last_import_segment = mem::replace(&mut this.last_import_segment, true);
@@ -1021,13 +1010,13 @@ fn finalize_import(
                     module,
                     ident,
                     ns,
-                    &directive.parent_scope,
+                    &import.parent_scope,
                     true,
-                    directive.span,
+                    import.span,
                 );
                 this.last_import_segment = orig_last_import_segment;
                 this.blacklisted_binding = orig_blacklisted_binding;
-                directive.vis.set(orig_vis);
+                import.vis.set(orig_vis);
 
                 match binding {
                     Ok(binding) => {
@@ -1044,7 +1033,7 @@ fn finalize_import(
                                         ident,
                                         ns,
                                         target_binding,
-                                        directive.module_path.is_empty(),
+                                        import.module_path.is_empty(),
                                     );
                                 }
                             }
@@ -1053,7 +1042,7 @@ fn finalize_import(
                         let res = binding.res();
                         if let Ok(initial_res) = initial_res {
                             if res != initial_res && this.ambiguity_errors.is_empty() {
-                                span_bug!(directive.span, "inconsistent resolution for an import");
+                                span_bug!(import.span, "inconsistent resolution for an import");
                             }
                         } else {
                             if res != Res::Err
@@ -1064,7 +1053,7 @@ fn finalize_import(
                                 let msg_note =
                                     "import resolution is stuck, try simplifying other imports";
                                 this.session
-                                    .struct_span_err(directive.span, msg)
+                                    .struct_span_err(import.span, msg)
                                     .note(msg_note)
                                     .emit();
                             }
@@ -1075,7 +1064,7 @@ fn finalize_import(
                         // single import (see test `issue-55884-2.rs`). In theory single imports should
                         // always block globs, even if they are not yet resolved, so that this kind of
                         // self-inconsistent resolution never happens.
-                        // Reenable the assert when the issue is fixed.
+                        // Re-enable the assert when the issue is fixed.
                         // assert!(result[ns].get().is_err());
                     }
                 }
@@ -1090,9 +1079,9 @@ fn finalize_import(
                         module,
                         ident,
                         ns,
-                        &directive.parent_scope,
+                        &import.parent_scope,
                         true,
-                        directive.span,
+                        import.span,
                     );
                     if binding.is_ok() {
                         all_ns_failed = false;
@@ -1143,7 +1132,7 @@ fn finalize_import(
                     });
 
                 let (suggestion, note) =
-                    match self.check_for_module_export_macro(directive, module, ident) {
+                    match self.check_for_module_export_macro(import, module, ident) {
                         Some((suggestion, note)) => (suggestion.or(lev_suggestion), note),
                         _ => (lev_suggestion, Vec::new()),
                     };
@@ -1169,14 +1158,14 @@ fn finalize_import(
                 };
 
                 Some(UnresolvedImportError {
-                    span: directive.span,
+                    span: import.span,
                     label: Some(label),
                     note,
                     suggestion,
                 })
             } else {
                 // `resolve_ident_in_module` reported a privacy error.
-                self.r.import_dummy_binding(directive);
+                self.r.import_dummy_binding(import);
                 None
             };
         }
@@ -1185,7 +1174,7 @@ fn finalize_import(
         let mut any_successful_reexport = false;
         self.r.per_ns(|this, ns| {
             if let Ok(binding) = source_bindings[ns].get() {
-                let vis = directive.vis.get();
+                let vis = import.vis.get();
                 if !binding.pseudo_vis().is_at_least(vis, &*this) {
                     reexport_error = Some((ns, binding));
                 } else {
@@ -1206,42 +1195,42 @@ fn finalize_import(
                 );
                 self.r.lint_buffer.buffer_lint(
                     PUB_USE_OF_PRIVATE_EXTERN_CRATE,
-                    directive.id,
-                    directive.span,
+                    import.id,
+                    import.span,
                     &msg,
                 );
             } else if ns == TypeNS {
                 struct_span_err!(
                     self.r.session,
-                    directive.span,
+                    import.span,
                     E0365,
                     "`{}` is private, and cannot be re-exported",
                     ident
                 )
-                .span_label(directive.span, format!("re-export of private `{}`", ident))
+                .span_label(import.span, format!("re-export of private `{}`", ident))
                 .note(&format!("consider declaring type or module `{}` with `pub`", ident))
                 .emit();
             } else {
                 let msg = format!("`{}` is private, and cannot be re-exported", ident);
                 let note_msg =
                     format!("consider marking `{}` as `pub` in the imported module", ident,);
-                struct_span_err!(self.r.session, directive.span, E0364, "{}", &msg)
-                    .span_note(directive.span, &note_msg)
+                struct_span_err!(self.r.session, import.span, E0364, "{}", &msg)
+                    .span_note(import.span, &note_msg)
                     .emit();
             }
         }
 
-        if directive.module_path.len() <= 1 {
+        if import.module_path.len() <= 1 {
             // HACK(eddyb) `lint_if_path_starts_with_module` needs at least
             // 2 segments, so the `resolve_path` above won't trigger it.
-            let mut full_path = directive.module_path.clone();
+            let mut full_path = import.module_path.clone();
             full_path.push(Segment::from_ident(ident));
             self.r.per_ns(|this, ns| {
                 if let Ok(binding) = source_bindings[ns].get() {
                     this.lint_if_path_starts_with_module(
-                        directive.crate_lint(),
+                        import.crate_lint(),
                         &full_path,
-                        directive.span,
+                        import.span,
                         Some(binding),
                     );
                 }
@@ -1252,18 +1241,12 @@ fn finalize_import(
         // this may resolve to either a value or a type, but for documentation
         // purposes it's good enough to just favor one over the other.
         self.r.per_ns(|this, ns| {
-            if let Some(binding) = source_bindings[ns].get().ok() {
-                this.import_res_map.entry(directive.id).or_default()[ns] = Some(binding.res());
+            if let Ok(binding) = source_bindings[ns].get() {
+                this.import_res_map.entry(import.id).or_default()[ns] = Some(binding.res());
             }
         });
 
-        self.check_for_redundant_imports(
-            ident,
-            directive,
-            source_bindings,
-            target_bindings,
-            target,
-        );
+        self.check_for_redundant_imports(ident, import, source_bindings, target_bindings, target);
 
         debug!("(resolving single import) successfully resolved import");
         None
@@ -1272,19 +1255,19 @@ fn finalize_import(
     fn check_for_redundant_imports(
         &mut self,
         ident: Ident,
-        directive: &'b ImportDirective<'b>,
+        import: &'b Import<'b>,
         source_bindings: &PerNS<Cell<Result<&'b NameBinding<'b>, Determinacy>>>,
         target_bindings: &PerNS<Cell<Option<&'b NameBinding<'b>>>>,
         target: Ident,
     ) {
         // Skip if the import was produced by a macro.
-        if directive.parent_scope.expansion != ExpnId::root() {
+        if import.parent_scope.expansion != ExpnId::root() {
             return;
         }
 
         // Skip if we are inside a named module (in contrast to an anonymous
         // module defined by a block).
-        if let ModuleKind::Def(..) = directive.parent_scope.module.kind {
+        if let ModuleKind::Def(..) = import.parent_scope.module.kind {
             return;
         }
 
@@ -1293,7 +1276,7 @@ fn check_for_redundant_imports(
         let mut redundant_span = PerNS { value_ns: None, type_ns: None, macro_ns: None };
 
         self.r.per_ns(|this, ns| {
-            if let Some(binding) = source_bindings[ns].get().ok() {
+            if let Ok(binding) = source_bindings[ns].get() {
                 if binding.res() == Res::Err {
                     return;
                 }
@@ -1304,10 +1287,10 @@ fn check_for_redundant_imports(
                 match this.early_resolve_ident_in_lexical_scope(
                     target,
                     ScopeSet::All(ns, false),
-                    &directive.parent_scope,
+                    &import.parent_scope,
                     false,
                     false,
-                    directive.span,
+                    import.span,
                 ) {
                     Ok(other_binding) => {
                         is_redundant[ns] = Some(
@@ -1329,35 +1312,35 @@ fn check_for_redundant_imports(
             redundant_spans.dedup();
             self.r.lint_buffer.buffer_lint_with_diagnostic(
                 UNUSED_IMPORTS,
-                directive.id,
-                directive.span,
+                import.id,
+                import.span,
                 &format!("the item `{}` is imported redundantly", ident),
                 BuiltinLintDiagnostics::RedundantImport(redundant_spans, ident),
             );
         }
     }
 
-    fn resolve_glob_import(&mut self, directive: &'b ImportDirective<'b>) {
-        let module = match directive.imported_module.get().unwrap() {
+    fn resolve_glob_import(&mut self, import: &'b Import<'b>) {
+        let module = match import.imported_module.get().unwrap() {
             ModuleOrUniformRoot::Module(module) => module,
             _ => {
-                self.r.session.span_err(directive.span, "cannot glob-import all possible crates");
+                self.r.session.span_err(import.span, "cannot glob-import all possible crates");
                 return;
             }
         };
 
         if module.is_trait() {
-            self.r.session.span_err(directive.span, "items in traits are not importable.");
+            self.r.session.span_err(import.span, "items in traits are not importable.");
             return;
-        } else if module.def_id() == directive.parent_scope.module.def_id() {
+        } else if module.def_id() == import.parent_scope.module.def_id() {
             return;
-        } else if let GlobImport { is_prelude: true, .. } = directive.subclass {
+        } else if let ImportKind::Glob { is_prelude: true, .. } = import.kind {
             self.r.prelude = Some(module);
             return;
         }
 
         // Add to module's glob_importers
-        module.glob_importers.borrow_mut().push(directive);
+        module.glob_importers.borrow_mut().push(import);
 
         // Ensure that `resolutions` isn't borrowed during `try_define`,
         // since it might get updated via a glob cycle.
@@ -1371,19 +1354,19 @@ fn resolve_glob_import(&mut self, directive: &'b ImportDirective<'b>) {
             })
             .collect::<Vec<_>>();
         for (mut key, binding) in bindings {
-            let scope = match key.ident.span.reverse_glob_adjust(module.expansion, directive.span) {
+            let scope = match key.ident.span.reverse_glob_adjust(module.expansion, import.span) {
                 Some(Some(def)) => self.r.macro_def_scope(def),
-                Some(None) => directive.parent_scope.module,
+                Some(None) => import.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 imported_binding = self.r.import(binding, import);
+                let _ = self.r.try_define(import.parent_scope.module, key, imported_binding);
             }
         }
 
         // Record the destination of this import
-        self.r.record_partial_res(directive.id, PartialRes::new(module.res().unwrap()));
+        self.r.record_partial_res(import.id, PartialRes::new(module.res().unwrap()));
     }
 
     // Miscellaneous post-processing, including recording re-exports,
@@ -1403,25 +1386,20 @@ fn finalize_resolutions_in(&mut self, module: Module<'b>) {
             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);
-                        }
-                    }
                     reexports.push(Export { ident, res, span: binding.span, vis: binding.vis });
                 }
             }
 
-            if let NameBindingKind::Import { binding: orig_binding, directive, .. } = binding.kind {
+            if let NameBindingKind::Import { binding: orig_binding, import, .. } = binding.kind {
                 if ns == TypeNS
                     && orig_binding.is_variant()
                     && !orig_binding.vis.is_at_least(binding.vis, &*this)
                 {
-                    let msg = match directive.subclass {
-                        ImportDirectiveSubclass::SingleImport { .. } => {
+                    let msg = match import.kind {
+                        ImportKind::Single { .. } => {
                             format!("variant `{}` is private and cannot be re-exported", ident)
                         }
-                        ImportDirectiveSubclass::GlobImport { .. } => {
+                        ImportKind::Glob { .. } => {
                             let msg = "enum is private and its variants \
                                            cannot be re-exported"
                                 .to_owned();
@@ -1437,18 +1415,18 @@ fn finalize_resolutions_in(&mut self, module: Module<'b>) {
                             }
                             msg
                         }
-                        ref s @ _ => bug!("unexpected import subclass {:?}", s),
+                        ref s => bug!("unexpected import kind {:?}", s),
                     };
                     let mut err = this.session.struct_span_err(binding.span, &msg);
 
-                    let imported_module = match directive.imported_module.get() {
+                    let imported_module = match import.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 enum_path_segment_index = directive.module_path.len() - 1;
-                    let enum_ident = directive.module_path[enum_path_segment_index].ident;
+                    let enum_path_segment_index = import.module_path.len() - 1;
+                    let enum_ident = import.module_path[enum_path_segment_index].ident;
 
                     let key = this.new_key(enum_ident, TypeNS);
                     let enum_resolution = resolutions.get(&key).expect("resolution should exist");
@@ -1486,11 +1464,7 @@ fn finalize_resolutions_in(&mut self, module: Module<'b>) {
     }
 }
 
-fn import_path_to_string(
-    names: &[Ident],
-    subclass: &ImportDirectiveSubclass<'_>,
-    span: Span,
-) -> String {
+fn import_path_to_string(names: &[Ident], import_kind: &ImportKind<'_>, span: Span) -> String {
     let pos = names.iter().position(|p| span == p.span && p.name != kw::PathRoot);
     let global = !names.is_empty() && names[0].name == kw::PathRoot;
     if let Some(pos) = pos {
@@ -1499,22 +1473,22 @@ fn import_path_to_string(
     } else {
         let names = if global { &names[1..] } else { names };
         if names.is_empty() {
-            import_directive_subclass_to_string(subclass)
+            import_kind_to_string(import_kind)
         } else {
             format!(
                 "{}::{}",
                 names_to_string(&names.iter().map(|ident| ident.name).collect::<Vec<_>>()),
-                import_directive_subclass_to_string(subclass),
+                import_kind_to_string(import_kind),
             )
         }
     }
 }
 
-fn import_directive_subclass_to_string(subclass: &ImportDirectiveSubclass<'_>) -> String {
-    match *subclass {
-        SingleImport { source, .. } => source.to_string(),
-        GlobImport { .. } => "*".to_string(),
-        ExternCrate { .. } => "<extern crate>".to_string(),
-        MacroUse => "#[macro_use]".to_string(),
+fn import_kind_to_string(import_kind: &ImportKind<'_>) -> String {
+    match import_kind {
+        ImportKind::Single { source, .. } => source.to_string(),
+        ImportKind::Glob { .. } => "*".to_string(),
+        ImportKind::ExternCrate { .. } => "<extern crate>".to_string(),
+        ImportKind::MacroUse => "#[macro_use]".to_string(),
     }
 }
index e5aa9c7d8962a3a73114406a7bd6f71c660bb74c..4a3c9f338d90379ea99b7008e8aea431c7a62cf5 100644 (file)
@@ -11,7 +11,7 @@
 use crate::{Module, ModuleOrUniformRoot, NameBindingKind, ParentScope, PathResult};
 use crate::{ResolutionError, Resolver, Segment, UseError};
 
-use rustc::{bug, lint, span_bug};
+use rustc::{bug, span_bug};
 use rustc_ast::ast::*;
 use rustc_ast::ptr::P;
 use rustc_ast::util::lev_distance::find_best_match_for_name;
@@ -23,6 +23,7 @@
 use rustc_hir::def::{self, CtorKind, DefKind, PartialRes, PerNS};
 use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX};
 use rustc_hir::TraitCandidate;
+use rustc_session::lint;
 use rustc_span::symbol::{kw, sym};
 use rustc_span::Span;
 use smallvec::{smallvec, SmallVec};
@@ -266,7 +267,7 @@ fn descr_expected(self) -> &'static str {
                 | Res::Def(DefKind::Static, _)
                 | Res::Local(..)
                 | Res::Def(DefKind::Fn, _)
-                | Res::Def(DefKind::Method, _)
+                | Res::Def(DefKind::AssocFn, _)
                 | Res::Def(DefKind::AssocConst, _)
                 | Res::SelfCtor(..)
                 | Res::Def(DefKind::ConstParam, _) => true,
@@ -293,7 +294,7 @@ fn descr_expected(self) -> &'static str {
                 _ => false,
             },
             PathSource::TraitItem(ns) => match res {
-                Res::Def(DefKind::AssocConst, _) | Res::Def(DefKind::Method, _)
+                Res::Def(DefKind::AssocConst, _) | Res::Def(DefKind::AssocFn, _)
                     if ns == ValueNS =>
                 {
                     true
@@ -444,12 +445,12 @@ fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) {
                     visit::walk_foreign_item(this, foreign_item);
                 });
             }
-            ForeignItemKind::Const(..) | ForeignItemKind::Static(..) => {
+            ForeignItemKind::Static(..) => {
                 self.with_item_rib(HasGenericParams::No, |this| {
                     visit::walk_foreign_item(this, foreign_item);
                 });
             }
-            ForeignItemKind::Macro(..) => {
+            ForeignItemKind::MacCall(..) => {
                 visit::walk_foreign_item(self, foreign_item);
             }
         }
@@ -553,7 +554,7 @@ fn visit_generic_arg(&mut self, arg: &'ast GenericArg) {
         let prev = replace(&mut self.diagnostic_metadata.currently_processing_generics, true);
         match arg {
             GenericArg::Type(ref ty) => {
-                // We parse const arguments as path types as we cannot distiguish them during
+                // We parse const arguments as path types as we cannot distinguish them during
                 // parsing. We try to resolve that ambiguity by attempting resolution the type
                 // namespace first, and if that fails we try again in the value namespace. If
                 // resolution in the value namespace succeeds, we have an generic const argument on
@@ -838,8 +839,7 @@ fn resolve_item(&mut self, item: &'ast Item) {
                         for item in trait_items {
                             this.with_trait_items(trait_items, |this| {
                                 match &item.kind {
-                                    AssocItemKind::Static(ty, _, default)
-                                    | AssocItemKind::Const(_, ty, default) => {
+                                    AssocItemKind::Const(_, ty, default) => {
                                         this.visit_ty(ty);
                                         // Only impose the restrictions of `ConstRibKind` for an
                                         // actual constant expression in a provided default.
@@ -853,7 +853,7 @@ fn resolve_item(&mut self, item: &'ast Item) {
                                     AssocItemKind::TyAlias(_, generics, _, _) => {
                                         walk_assoc_item(this, generics, item);
                                     }
-                                    AssocItemKind::Macro(_) => {
+                                    AssocItemKind::MacCall(_) => {
                                         panic!("unexpanded macro in resolve!")
                                     }
                                 };
@@ -898,7 +898,7 @@ fn resolve_item(&mut self, item: &'ast Item) {
                 // do nothing, these are just around to be encoded
             }
 
-            ItemKind::Mac(_) => panic!("unexpanded macro in resolve!"),
+            ItemKind::MacCall(_) => panic!("unexpanded macro in resolve!"),
         }
     }
 
@@ -936,7 +936,7 @@ fn with_generic_param_rib<'c, F>(&'c mut self, generics: &'c Generics, kind: Rib
                 _ => unreachable!(),
             };
 
-            let ident = param.ident.modern();
+            let ident = param.ident.normalize_to_macros_2_0();
             debug!("with_generic_param_rib: {}", param.id);
 
             if seen_bindings.contains_key(&ident) {
@@ -1114,7 +1114,7 @@ fn resolve_implementation(
                                 for item in impl_items {
                                     use crate::ResolutionError::*;
                                     match &item.kind {
-                                        AssocItemKind::Static(..) | AssocItemKind::Const(..) => {
+                                        AssocItemKind::Const(..) => {
                                             debug!("resolve_implementation AssocItemKind::Const",);
                                             // If this is a trait impl, ensure the const
                                             // exists in trait
@@ -1175,7 +1175,7 @@ fn resolve_implementation(
                                                 },
                                             );
                                         }
-                                        AssocItemKind::Macro(_) => {
+                                        AssocItemKind::MacCall(_) => {
                                             panic!("unexpanded macro in resolve!")
                                         }
                                     }
@@ -1465,7 +1465,7 @@ fn fresh_binding(
         // Add the binding to the local ribs, if it doesn't already exist in the bindings map.
         // (We must not add it if it's in the bindings map because that breaks the assumptions
         // later passes make about or-patterns.)
-        let ident = ident.modern_and_legacy();
+        let ident = ident.normalize_to_macro_rules();
 
         let mut bound_iter = bindings.iter().filter(|(_, set)| set.contains(&ident));
         // Already bound in a product pattern? e.g. `(a, a)` which is not allowed.
@@ -1518,9 +1518,17 @@ fn try_resolve_as_non_binding(
         ident: Ident,
         has_sub: bool,
     ) -> Option<Res> {
-        let binding =
-            self.resolve_ident_in_lexical_scope(ident, ValueNS, None, pat.span)?.item()?;
-        let res = binding.res();
+        let ls_binding = self.resolve_ident_in_lexical_scope(ident, ValueNS, None, pat.span)?;
+        let (res, binding) = match ls_binding {
+            LexicalScopeBinding::Item(binding) if binding.is_ambiguity() => {
+                // For ambiguous bindings we don't know all their definitions and cannot check
+                // whether they can be shadowed by fresh bindings or not, so force an error.
+                self.r.record_use(ident, ValueNS, binding, false);
+                return None;
+            }
+            LexicalScopeBinding::Item(binding) => (binding.res(), Some(binding)),
+            LexicalScopeBinding::Res(res) => (res, None),
+        };
 
         // An immutable (no `mut`) by-value (no `ref`) binding pattern without
         // a sub pattern (no `@ $pat`) is syntactically ambiguous as it could
@@ -1528,11 +1536,15 @@ fn try_resolve_as_non_binding(
         let is_syntactic_ambiguity = !has_sub && bm == BindingMode::ByValue(Mutability::Not);
 
         match res {
-            Res::Def(DefKind::Ctor(_, CtorKind::Const), _) | Res::Def(DefKind::Const, _)
+            Res::Def(DefKind::Ctor(_, CtorKind::Const), _)
+            | Res::Def(DefKind::Const, _)
+            | Res::Def(DefKind::ConstParam, _)
                 if is_syntactic_ambiguity =>
             {
                 // Disambiguate in favor of a unit struct/variant or constant pattern.
-                self.r.record_use(ident, ValueNS, binding, false);
+                if let Some(binding) = binding {
+                    self.r.record_use(ident, ValueNS, binding, false);
+                }
                 Some(res)
             }
             Res::Def(DefKind::Ctor(..), _)
@@ -1548,23 +1560,20 @@ fn try_resolve_as_non_binding(
                     ResolutionError::BindingShadowsSomethingUnacceptable(
                         pat_src.descr(),
                         ident.name,
-                        binding,
+                        binding.expect("no binding for a ctor or static"),
                     ),
                 );
                 None
             }
-            Res::Def(DefKind::Fn, _) | Res::Err => {
+            Res::Def(DefKind::Fn, _) | Res::Local(..) | Res::Err => {
                 // These entities are explicitly allowed to be shadowed by fresh bindings.
                 None
             }
-            res => {
-                span_bug!(
-                    ident.span,
-                    "unexpected resolution for an \
-                                        identifier in pattern: {:?}",
-                    res
-                );
-            }
+            _ => span_bug!(
+                ident.span,
+                "unexpected resolution for an identifier in pattern: {:?}",
+                res
+            ),
         }
     }
 
@@ -1865,7 +1874,7 @@ fn with_resolved_label(&mut self, label: Option<Label>, id: NodeId, f: impl FnOn
                 self.diagnostic_metadata.unused_labels.insert(id, label.ident.span);
             }
             self.with_label_rib(NormalRibKind, |this| {
-                let ident = label.ident.modern_and_legacy();
+                let ident = label.ident.normalize_to_macro_rules();
                 this.label_ribs.last_mut().unwrap().bindings.insert(ident, id);
                 f(this);
             });
@@ -1941,7 +1950,7 @@ fn resolve_expr(&mut self, expr: &'ast Expr, parent: Option<&'ast Expr>) {
 
             ExprKind::Break(Some(label), _) | ExprKind::Continue(Some(label)) => {
                 let node_id = self.search_label(label.ident, |rib, ident| {
-                    rib.bindings.get(&ident.modern_and_legacy()).cloned()
+                    rib.bindings.get(&ident.normalize_to_macro_rules()).cloned()
                 });
                 match node_id {
                     None => {
@@ -2103,11 +2112,11 @@ fn get_traits_containing_item(
                 .is_ok()
             {
                 let def_id = module.def_id().unwrap();
-                found_traits.push(TraitCandidate { def_id: def_id, import_ids: smallvec![] });
+                found_traits.push(TraitCandidate { def_id, import_ids: smallvec![] });
             }
         }
 
-        ident.span = ident.span.modern();
+        ident.span = ident.span.normalize_to_macros_2_0();
         let mut search_module = self.parent_scope.module;
         loop {
             self.get_traits_in_module_containing_item(ident, ns, search_module, &mut found_traits);
@@ -2190,10 +2199,10 @@ fn find_transitive_imports(
         trait_name: Ident,
     ) -> SmallVec<[NodeId; 1]> {
         let mut import_ids = smallvec![];
-        while let NameBindingKind::Import { directive, binding, .. } = kind {
-            self.r.maybe_unused_trait_imports.insert(directive.id);
-            self.r.add_to_glob_map(&directive, trait_name);
-            import_ids.push(directive.id);
+        while let NameBindingKind::Import { import, binding, .. } = kind {
+            self.r.maybe_unused_trait_imports.insert(import.id);
+            self.r.add_to_glob_map(&import, trait_name);
+            import_ids.push(import.id);
             kind = &binding.kind;
         }
         import_ids
index 817a276ff3e73fab9ef2f37d3018492eebec3ac9..41380b2a4b78a2b787e15b6a370400e4449f9aeb 100644 (file)
@@ -5,7 +5,6 @@
 use crate::{CrateLint, Module, ModuleKind, ModuleOrUniformRoot};
 use crate::{PathResult, PathSource, Segment};
 
-use rustc::session::config::nightly_options;
 use rustc_ast::ast::{self, Expr, ExprKind, Ident, Item, ItemKind, NodeId, Path, Ty, TyKind};
 use rustc_ast::util::lev_distance::find_best_match_for_name;
 use rustc_data_structures::fx::FxHashSet;
@@ -15,6 +14,7 @@
 use rustc_hir::def::{self, CtorKind, DefKind};
 use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX};
 use rustc_hir::PrimTy;
+use rustc_session::config::nightly_options;
 use rustc_span::hygiene::MacroKind;
 use rustc_span::symbol::{kw, sym};
 use rustc_span::Span;
@@ -124,7 +124,7 @@ pub(crate) fn smart_resolve_report_errors(
                             .unwrap_or(false)
                     }
                     Res::Def(DefKind::Ctor(..), _)
-                    | Res::Def(DefKind::Method, _)
+                    | Res::Def(DefKind::AssocFn, _)
                     | Res::Def(DefKind::Const, _)
                     | Res::Def(DefKind::AssocConst, _)
                     | Res::SelfCtor(_)
@@ -1086,7 +1086,7 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
                     for param in params {
                         if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(param.span)
                         {
-                            if snippet.starts_with("&") && !snippet.starts_with("&'") {
+                            if snippet.starts_with('&') && !snippet.starts_with("&'") {
                                 introduce_suggestion
                                     .push((param.span, format!("&'a {}", &snippet[1..])));
                             } else if snippet.starts_with("&'_ ") {
@@ -1107,18 +1107,14 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
                 }
             };
 
-            match (
-                lifetime_names.len(),
-                lifetime_names.iter().next(),
-                snippet.as_ref().map(|s| s.as_str()),
-            ) {
+            match (lifetime_names.len(), lifetime_names.iter().next(), snippet.as_deref()) {
                 (1, Some(name), Some("&")) => {
                     suggest_existing(err, format!("&{} ", name));
                 }
                 (1, Some(name), Some("'_")) => {
                     suggest_existing(err, name.to_string());
                 }
-                (1, Some(name), Some(snippet)) if !snippet.ends_with(">") => {
+                (1, Some(name), Some(snippet)) if !snippet.ends_with('>') => {
                     suggest_existing(err, format!("{}<{}>", snippet, name));
                 }
                 (0, _, Some("&")) => {
@@ -1127,7 +1123,7 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
                 (0, _, Some("'_")) => {
                     suggest_new(err, "'a");
                 }
-                (0, _, Some(snippet)) if !snippet.ends_with(">") => {
+                (0, _, Some(snippet)) if !snippet.ends_with('>') => {
                     suggest_new(err, &format!("{}<'a>", snippet));
                 }
                 _ => {
index 463452e45ce99b00a9692f0f621b292311105152..51bf1f48439725da647c6741d2fa1b5256181c4f 100644 (file)
@@ -7,7 +7,6 @@
 
 use crate::late::diagnostics::{ForLifetimeSpanType, MissingLifetimeSpot};
 use rustc::hir::map::Map;
-use rustc::lint;
 use rustc::middle::resolve_lifetime::*;
 use rustc::ty::{self, DefIdTree, GenericParamDefKind, TyCtxt};
 use rustc::{bug, span_bug};
 use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LOCAL_CRATE};
+use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LOCAL_CRATE};
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::{GenericArg, GenericParam, LifetimeName, Node, ParamName, QPath};
 use rustc_hir::{GenericParamKind, HirIdMap, HirIdSet, LifetimeParamKind};
+use rustc_session::lint;
 use rustc_span::symbol::{kw, sym};
 use rustc_span::Span;
 use std::borrow::Cow;
@@ -62,7 +62,7 @@ fn early(hir_map: &Map<'_>, index: &mut u32, param: &GenericParam<'_>) -> (Param
         let def_id = hir_map.local_def_id(param.hir_id);
         let origin = LifetimeDefOrigin::from_param(param);
         debug!("Region::early: index={} def_id={:?}", i, def_id);
-        (param.name.modern(), Region::EarlyBound(i, def_id, origin))
+        (param.name.normalize_to_macros_2_0(), Region::EarlyBound(i, def_id, origin))
     }
 
     fn late(hir_map: &Map<'_>, param: &GenericParam<'_>) -> (ParamName, Region) {
@@ -73,7 +73,7 @@ fn late(hir_map: &Map<'_>, param: &GenericParam<'_>) -> (ParamName, Region) {
             "Region::late: param={:?} depth={:?} def_id={:?} origin={:?}",
             param, depth, def_id, origin,
         );
-        (param.name.modern(), Region::LateBound(depth, def_id, origin))
+        (param.name.normalize_to_macros_2_0(), Region::LateBound(depth, def_id, origin))
     }
 
     fn late_anon(index: &Cell<u32>) -> Region {
@@ -280,25 +280,14 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) {
     *providers = ty::query::Providers {
         resolve_lifetimes,
 
-        named_region_map: |tcx, id| {
-            let id = LocalDefId::from_def_id(DefId::local(id)); // (*)
-            tcx.resolve_lifetimes(LOCAL_CRATE).defs.get(&id)
-        },
-
-        is_late_bound_map: |tcx, id| {
-            let id = LocalDefId::from_def_id(DefId::local(id)); // (*)
-            tcx.resolve_lifetimes(LOCAL_CRATE).late_bound.get(&id)
-        },
-
+        named_region_map: |tcx, id| tcx.resolve_lifetimes(LOCAL_CRATE).defs.get(&id),
+        is_late_bound_map: |tcx, id| tcx.resolve_lifetimes(LOCAL_CRATE).late_bound.get(&id),
         object_lifetime_defaults_map: |tcx, id| {
-            let id = LocalDefId::from_def_id(DefId::local(id)); // (*)
             tcx.resolve_lifetimes(LOCAL_CRATE).object_lifetime_defaults.get(&id)
         },
 
         ..*providers
     };
-
-    // (*) FIXME the query should be defined to take a LocalDefId
 }
 
 /// Computes the `ResolveLifetimes` map that contains data for the
@@ -313,15 +302,15 @@ fn resolve_lifetimes(tcx: TyCtxt<'_>, for_krate: CrateNum) -> &ResolveLifetimes
     let mut rl = ResolveLifetimes::default();
 
     for (hir_id, v) in named_region_map.defs {
-        let map = rl.defs.entry(hir_id.owner_local_def_id()).or_default();
+        let map = rl.defs.entry(hir_id.owner).or_default();
         map.insert(hir_id.local_id, v);
     }
     for hir_id in named_region_map.late_bound {
-        let map = rl.late_bound.entry(hir_id.owner_local_def_id()).or_default();
+        let map = rl.late_bound.entry(hir_id.owner).or_default();
         map.insert(hir_id.local_id);
     }
     for (hir_id, v) in named_region_map.object_lifetime_defaults {
-        let map = rl.object_lifetime_defaults.entry(hir_id.owner_local_def_id()).or_default();
+        let map = rl.object_lifetime_defaults.entry(hir_id.owner).or_default();
         map.insert(hir_id.local_id, v);
     }
 
@@ -347,7 +336,7 @@ fn krate(tcx: TyCtxt<'_>) -> NamedRegionMap {
             lifetime_uses: &mut Default::default(),
             missing_named_lifetime_spots: vec![],
         };
-        for (_, item) in &krate.items {
+        for item in krate.items.values() {
             visitor.visit_item(item);
         }
     }
@@ -367,8 +356,8 @@ fn sub_items_have_self_param(node: &hir::ItemKind<'_>) -> bool {
 impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
     type Map = Map<'tcx>;
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
-        NestedVisitorMap::All(&self.tcx.hir())
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::All(self.tcx.hir())
     }
 
     // We want to nest trait/impl items in their parent, but nothing else.
@@ -540,7 +529,7 @@ fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
                     LifetimeName::Implicit => {
                         // For types like `dyn Foo`, we should
                         // generate a special form of elided.
-                        span_bug!(ty.span, "object-lifetime-default expected, not implict",);
+                        span_bug!(ty.span, "object-lifetime-default expected, not implicit",);
                     }
                     LifetimeName::ImplicitObjectLifetimeDefault => {
                         // If the user does not write *anything*, we
@@ -713,7 +702,7 @@ fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
         use self::hir::TraitItemKind::*;
         self.missing_named_lifetime_spots.push((&trait_item.generics).into());
         match trait_item.kind {
-            Method(ref sig, _) => {
+            Fn(ref sig, _) => {
                 let tcx = self.tcx;
                 self.visit_early_late(
                     Some(tcx.hir().get_parent_item(trait_item.hir_id)),
@@ -771,7 +760,7 @@ fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
         use self::hir::ImplItemKind::*;
         self.missing_named_lifetime_spots.push((&impl_item.generics).into());
         match impl_item.kind {
-            Method(ref sig, _) => {
+            Fn(ref sig, _) => {
                 let tcx = self.tcx;
                 self.visit_early_late(
                     Some(tcx.hir().get_parent_item(impl_item.hir_id)),
@@ -1032,13 +1021,13 @@ struct Shadower {
 }
 
 fn original_label(span: Span) -> Original {
-    Original { kind: ShadowKind::Label, span: span }
+    Original { kind: ShadowKind::Label, span }
 }
 fn shadower_label(span: Span) -> Shadower {
-    Shadower { kind: ShadowKind::Label, span: span }
+    Shadower { kind: ShadowKind::Label, span }
 }
 fn original_lifetime(span: Span) -> Original {
-    Original { kind: ShadowKind::Lifetime, span: span }
+    Original { kind: ShadowKind::Lifetime, span }
 }
 fn shadower_lifetime(param: &hir::GenericParam<'_>) -> Shadower {
     Shadower { kind: ShadowKind::Lifetime, span: param.span }
@@ -1123,9 +1112,9 @@ struct GatherLabels<'a, 'tcx> {
     gather.visit_body(body);
 
     impl<'v, 'a, 'tcx> Visitor<'v> for GatherLabels<'a, 'tcx> {
-        type Map = Map<'v>;
+        type Map = intravisit::ErasedMap<'v>;
 
-        fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
+        fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
             NestedVisitorMap::None
         }
 
@@ -1174,7 +1163,9 @@ fn check_if_label_shadows_lifetime(
 
                 Scope::Binder { ref lifetimes, s, .. } => {
                     // FIXME (#24278): non-hygienic comparison
-                    if let Some(def) = lifetimes.get(&hir::ParamName::Plain(label.modern())) {
+                    if let Some(def) =
+                        lifetimes.get(&hir::ParamName::Plain(label.normalize_to_macros_2_0()))
+                    {
                         let hir_id = tcx.hir().as_local_hir_id(def.id().unwrap()).unwrap();
 
                         signal_shadowing_problem(
@@ -1253,7 +1244,7 @@ fn object_lifetime_defaults_for_item(
     fn add_bounds(set: &mut Set1<hir::LifetimeName>, bounds: &[hir::GenericBound<'_>]) {
         for bound in bounds {
             if let hir::GenericBound::Outlives(ref lifetime) = *bound {
-                set.insert(lifetime.name.modern());
+                set.insert(lifetime.name.normalize_to_macros_2_0());
             }
         }
     }
@@ -1347,7 +1338,7 @@ fn with<F>(&mut self, wrap_scope: Scope<'_>, f: F)
         let missing_named_lifetime_spots = take(&mut self.missing_named_lifetime_spots);
         let mut this = LifetimeContext {
             tcx: *tcx,
-            map: map,
+            map,
             scope: &wrap_scope,
             trait_ref_hack: self.trait_ref_hack,
             is_in_fn_syntax: self.is_in_fn_syntax,
@@ -1466,7 +1457,7 @@ fn suggest_eliding_single_use_lifetime(
                         }
                     }
                     Node::ImplItem(impl_item) => {
-                        if let hir::ImplItemKind::Method(sig, _) = &impl_item.kind {
+                        if let hir::ImplItemKind::Fn(sig, _) = &impl_item.kind {
                             find_arg_use_span(sig.decl.inputs);
                         }
                     }
@@ -1791,7 +1782,8 @@ fn resolve_lifetime_ref(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
                 Scope::Binder { ref lifetimes, s, .. } => {
                     match lifetime_ref.name {
                         LifetimeName::Param(param_name) => {
-                            if let Some(&def) = lifetimes.get(&param_name.modern()) {
+                            if let Some(&def) = lifetimes.get(&param_name.normalize_to_macros_2_0())
+                            {
                                 break Some(def.shifted(late_depth));
                             }
                         }
@@ -1816,12 +1808,9 @@ fn resolve_lifetime_ref(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
                 match self.tcx.hir().get(fn_id) {
                     Node::Item(&hir::Item { kind: hir::ItemKind::Fn(..), .. })
                     | Node::TraitItem(&hir::TraitItem {
-                        kind: hir::TraitItemKind::Method(..),
-                        ..
+                        kind: hir::TraitItemKind::Fn(..), ..
                     })
-                    | Node::ImplItem(&hir::ImplItem {
-                        kind: hir::ImplItemKind::Method(..), ..
-                    }) => {
+                    | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }) => {
                         let scope = self.tcx.hir().local_def_id(fn_id);
                         def = Region::Free(scope, def.id().unwrap());
                     }
@@ -2093,9 +2082,7 @@ fn visit_fn_like_elision(
             // `fn` definitions and methods.
             Node::Item(&hir::Item { kind: hir::ItemKind::Fn(.., body), .. }) => Some(body),
 
-            Node::TraitItem(&hir::TraitItem {
-                kind: hir::TraitItemKind::Method(_, ref m), ..
-            }) => {
+            Node::TraitItem(&hir::TraitItem { kind: hir::TraitItemKind::Fn(_, ref m), .. }) => {
                 if let hir::ItemKind::Trait(.., ref trait_items) =
                     self.tcx.hir().expect_item(self.tcx.hir().get_parent_item(parent)).kind
                 {
@@ -2103,12 +2090,12 @@ fn visit_fn_like_elision(
                         trait_items.iter().find(|ti| ti.id.hir_id == parent).map(|ti| ti.kind);
                 }
                 match *m {
-                    hir::TraitMethod::Required(_) => None,
-                    hir::TraitMethod::Provided(body) => Some(body),
+                    hir::TraitFn::Required(_) => None,
+                    hir::TraitFn::Provided(body) => Some(body),
                 }
             }
 
-            Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Method(_, body), .. }) => {
+            Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(_, body), .. }) => {
                 if let hir::ItemKind::Impl { ref self_ty, ref items, .. } =
                     self.tcx.hir().expect_item(self.tcx.hir().get_parent_item(parent)).kind
                 {
@@ -2175,9 +2162,9 @@ fn is_self_ty(&self, res: Res) -> bool {
             }
 
             impl<'a> Visitor<'a> for SelfVisitor<'a> {
-                type Map = Map<'a>;
+                type Map = intravisit::ErasedMap<'a>;
 
-                fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
+                fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
                     NestedVisitorMap::None
                 }
 
@@ -2266,9 +2253,9 @@ struct GatherLifetimes<'a> {
         }
 
         impl<'v, 'a> Visitor<'v> for GatherLifetimes<'a> {
-            type Map = Map<'v>;
+            type Map = intravisit::ErasedMap<'v>;
 
-            fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
+            fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
                 NestedVisitorMap::None
             }
 
@@ -2547,7 +2534,9 @@ fn check_lifetime_params(
         let lifetimes: Vec<_> = params
             .iter()
             .filter_map(|param| match param.kind {
-                GenericParamKind::Lifetime { .. } => Some((param, param.name.modern())),
+                GenericParamKind::Lifetime { .. } => {
+                    Some((param, param.name.normalize_to_macros_2_0()))
+                }
                 _ => None,
             })
             .collect();
@@ -2664,7 +2653,7 @@ fn check_lifetime_param_for_shadowing(
                 }
 
                 Scope::Binder { ref lifetimes, s, .. } => {
-                    if let Some(&def) = lifetimes.get(&param.name.modern()) {
+                    if let Some(&def) = lifetimes.get(&param.name.normalize_to_macros_2_0()) {
                         let hir_id = self.tcx.hir().as_local_hir_id(def.id().unwrap()).unwrap();
 
                         signal_shadowing_problem(
@@ -2802,7 +2791,7 @@ fn insert_late_bound_lifetimes(
                 // `'a: 'b` means both `'a` and `'b` are referenced
                 appears_in_where_clause
                     .regions
-                    .insert(hir::LifetimeName::Param(param.name.modern()));
+                    .insert(hir::LifetimeName::Param(param.name.normalize_to_macros_2_0()));
             }
         }
     }
@@ -2824,7 +2813,7 @@ fn insert_late_bound_lifetimes(
             hir::GenericParamKind::Type { .. } | hir::GenericParamKind::Const { .. } => continue,
         }
 
-        let lt_name = hir::LifetimeName::Param(param.name.modern());
+        let lt_name = hir::LifetimeName::Param(param.name.normalize_to_macros_2_0());
         // appears in the where clauses? early-bound.
         if appears_in_where_clause.regions.contains(&lt_name) {
             continue;
@@ -2855,9 +2844,9 @@ struct ConstrainedCollector {
     }
 
     impl<'v> Visitor<'v> for ConstrainedCollector {
-        type Map = Map<'v>;
+        type Map = intravisit::ErasedMap<'v>;
 
-        fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
+        fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
             NestedVisitorMap::None
         }
 
@@ -2888,7 +2877,7 @@ fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) {
         }
 
         fn visit_lifetime(&mut self, lifetime_ref: &'v hir::Lifetime) {
-            self.regions.insert(lifetime_ref.name.modern());
+            self.regions.insert(lifetime_ref.name.normalize_to_macros_2_0());
         }
     }
 
@@ -2898,14 +2887,14 @@ struct AllCollector {
     }
 
     impl<'v> Visitor<'v> for AllCollector {
-        type Map = Map<'v>;
+        type Map = intravisit::ErasedMap<'v>;
 
-        fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
+        fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
             NestedVisitorMap::None
         }
 
         fn visit_lifetime(&mut self, lifetime_ref: &'v hir::Lifetime) {
-            self.regions.insert(lifetime_ref.name.modern());
+            self.regions.insert(lifetime_ref.name.normalize_to_macros_2_0());
         }
     }
 }
index 44eba0d533d3afda42a21981fde60437b48cfca1..4a2a2a296faea32bb1405be9d09a02ae19e0ecd8 100644 (file)
@@ -18,7 +18,6 @@
 
 use rustc::hir::exports::ExportMap;
 use rustc::hir::map::{DefKey, Definitions};
-use rustc::lint;
 use rustc::middle::cstore::{CrateStore, MetadataLoaderDyn};
 use rustc::span_bug;
 use rustc::ty::query::Providers;
 use rustc_expand::base::SyntaxExtension;
 use rustc_hir::def::Namespace::*;
 use rustc_hir::def::{self, CtorOf, DefKind, NonMacroAttrKind, PartialRes};
-use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX};
 use rustc_hir::PrimTy::{self, Bool, Char, Float, Int, Str, Uint};
 use rustc_hir::{GlobMap, TraitMap};
 use rustc_metadata::creader::{CStore, CrateLoader};
+use rustc_session::lint;
 use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer};
 use rustc_session::Session;
 use rustc_span::hygiene::{ExpnId, ExpnKind, MacroKind, SyntaxContext, Transparency};
@@ -56,9 +56,9 @@
 
 use diagnostics::{extend_span_to_previous_binding, find_span_of_binding_until_next_binding};
 use diagnostics::{ImportSuggestion, Suggestion};
-use imports::{ImportDirective, ImportDirectiveSubclass, ImportResolver, NameResolution};
+use imports::{Import, ImportKind, ImportResolver, NameResolution};
 use late::{HasGenericParams, PathSource, Rib, RibKind::*};
-use macros::{LegacyBinding, LegacyScope};
+use macros::{MacroRulesBinding, MacroRulesScope};
 
 type Res = def::Res<NodeId>;
 
@@ -94,7 +94,7 @@ fn determined(determined: bool) -> Determinacy {
 enum Scope<'a> {
     DeriveHelpers(ExpnId),
     DeriveHelpersCompat,
-    MacroRules(LegacyScope<'a>),
+    MacroRules(MacroRulesScope<'a>),
     CrateRoot,
     Module(Module<'a>),
     RegisteredAttrs,
@@ -127,7 +127,7 @@ enum ScopeSet {
 pub struct ParentScope<'a> {
     module: Module<'a>,
     expansion: ExpnId,
-    legacy: LegacyScope<'a>,
+    macro_rules: MacroRulesScope<'a>,
     derives: &'a [ast::Path],
 }
 
@@ -135,7 +135,12 @@ impl<'a> ParentScope<'a> {
     /// Creates a parent scope with the passed argument used as the module scope component,
     /// and other scope components set to default empty values.
     pub fn module(module: Module<'a>) -> ParentScope<'a> {
-        ParentScope { module, expansion: ExpnId::root(), legacy: LegacyScope::Empty, derives: &[] }
+        ParentScope {
+            module,
+            expansion: ExpnId::root(),
+            macro_rules: MacroRulesScope::Empty,
+            derives: &[],
+        }
     }
 }
 
@@ -323,13 +328,6 @@ enum LexicalScopeBinding<'a> {
 }
 
 impl<'a> LexicalScopeBinding<'a> {
-    fn item(self) -> Option<&'a NameBinding<'a>> {
-        match self {
-            LexicalScopeBinding::Item(binding) => Some(binding),
-            _ => None,
-        }
-    }
-
     fn res(self) -> Res {
         match self {
             LexicalScopeBinding::Item(binding) => binding.res(),
@@ -426,7 +424,7 @@ pub fn name(&self) -> Option<Name> {
 /// 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
+    /// The identifier for the binding, aways the `normalize_to_macros_2_0` version of the
     /// identifier.
     ident: Ident,
     ns: Namespace,
@@ -456,8 +454,8 @@ pub struct ModuleData<'a> {
 
     no_implicit_prelude: bool,
 
-    glob_importers: RefCell<Vec<&'a ImportDirective<'a>>>,
-    globs: RefCell<Vec<&'a ImportDirective<'a>>>,
+    glob_importers: RefCell<Vec<&'a Import<'a>>>,
+    globs: RefCell<Vec<&'a Import<'a>>>,
 
     // Used to memoize the traits in this module for faster searches through all traits in scope.
     traits: RefCell<Option<Box<[(Ident, &'a NameBinding<'a>)]>>>,
@@ -584,7 +582,7 @@ fn to_name_binding(self, _: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> {
 enum NameBindingKind<'a> {
     Res(Res, /* is_macro_export */ bool),
     Module(Module<'a>),
-    Import { binding: &'a NameBinding<'a>, directive: &'a ImportDirective<'a>, used: Cell<bool> },
+    Import { binding: &'a NameBinding<'a>, import: &'a Import<'a>, used: Cell<bool> },
 }
 
 impl<'a> NameBindingKind<'a> {
@@ -620,7 +618,7 @@ enum AmbiguityKind {
     Import,
     BuiltinAttr,
     DeriveHelper,
-    LegacyVsModern,
+    MacroRulesVsModularized,
     GlobVsOuter,
     GlobVsGlob,
     GlobVsExpanded,
@@ -633,7 +631,9 @@ fn descr(self) -> &'static str {
             AmbiguityKind::Import => "name vs any other name during import resolution",
             AmbiguityKind::BuiltinAttr => "built-in attribute vs any other name",
             AmbiguityKind::DeriveHelper => "derive helper attribute vs any other name",
-            AmbiguityKind::LegacyVsModern => "`macro_rules` vs non-`macro_rules` from other module",
+            AmbiguityKind::MacroRulesVsModularized => {
+                "`macro_rules` vs non-`macro_rules` from other module"
+            }
             AmbiguityKind::GlobVsOuter => {
                 "glob import vs any other name from outer scope during import/macro resolution"
             }
@@ -713,8 +713,7 @@ fn is_variant(&self) -> bool {
     fn is_extern_crate(&self) -> bool {
         match self.kind {
             NameBindingKind::Import {
-                directive:
-                    &ImportDirective { subclass: ImportDirectiveSubclass::ExternCrate { .. }, .. },
+                import: &Import { kind: ImportKind::ExternCrate { .. }, .. },
                 ..
             } => true,
             NameBindingKind::Module(&ModuleData {
@@ -734,7 +733,7 @@ fn is_import(&self) -> bool {
 
     fn is_glob_import(&self) -> bool {
         match self.kind {
-            NameBindingKind::Import { directive, .. } => directive.is_glob(),
+            NameBindingKind::Import { import, .. } => import.is_glob(),
             _ => false,
         }
     }
@@ -742,7 +741,7 @@ fn is_glob_import(&self) -> bool {
     fn is_importable(&self) -> bool {
         match self.res() {
             Res::Def(DefKind::AssocConst, _)
-            | Res::Def(DefKind::Method, _)
+            | Res::Def(DefKind::AssocFn, _)
             | Res::Def(DefKind::AssocTy, _) => false,
             _ => true,
         }
@@ -839,10 +838,10 @@ pub struct Resolver<'a> {
     field_names: FxHashMap<DefId, Vec<Spanned<Name>>>,
 
     /// All imports known to succeed or fail.
-    determined_imports: Vec<&'a ImportDirective<'a>>,
+    determined_imports: Vec<&'a Import<'a>>,
 
     /// All non-determined imports.
-    indeterminate_imports: Vec<&'a ImportDirective<'a>>,
+    indeterminate_imports: Vec<&'a Import<'a>>,
 
     /// FIXME: Refactor things so that these fields are passed through arguments and not resolver.
     /// We are resolving a last import segment during import validation.
@@ -938,16 +937,16 @@ pub struct Resolver<'a> {
     /// Parent scopes in which the macros were invoked.
     /// FIXME: `derives` are missing in these parent scopes and need to be taken from elsewhere.
     invocation_parent_scopes: FxHashMap<ExpnId, ParentScope<'a>>,
-    /// Legacy scopes *produced* by expanding the macro invocations,
+    /// `macro_rules` scopes *produced* by expanding the macro invocations,
     /// include all the `macro_rules` items and other invocations generated by them.
-    output_legacy_scopes: FxHashMap<ExpnId, LegacyScope<'a>>,
+    output_macro_rules_scopes: FxHashMap<ExpnId, MacroRulesScope<'a>>,
     /// Helper attributes that are in scope for the given expansion.
     helper_attrs: FxHashMap<ExpnId, Vec<Ident>>,
 
     /// Avoid duplicated errors for "name already defined".
     name_already_seen: FxHashMap<Name, Span>,
 
-    potentially_unused_imports: Vec<&'a ImportDirective<'a>>,
+    potentially_unused_imports: Vec<&'a Import<'a>>,
 
     /// Table for mapping struct IDs into struct constructor IDs,
     /// it's not used during normal resolution, only for better error reporting.
@@ -971,9 +970,9 @@ pub struct ResolverArenas<'a> {
     modules: arena::TypedArena<ModuleData<'a>>,
     local_modules: RefCell<Vec<Module<'a>>>,
     name_bindings: arena::TypedArena<NameBinding<'a>>,
-    import_directives: arena::TypedArena<ImportDirective<'a>>,
+    imports: arena::TypedArena<Import<'a>>,
     name_resolutions: arena::TypedArena<RefCell<NameResolution<'a>>>,
-    legacy_bindings: arena::TypedArena<LegacyBinding<'a>>,
+    macro_rules_bindings: arena::TypedArena<MacroRulesBinding<'a>>,
     ast_paths: arena::TypedArena<ast::Path>,
 }
 
@@ -991,17 +990,17 @@ fn local_modules(&'a self) -> std::cell::Ref<'a, Vec<Module<'a>>> {
     fn alloc_name_binding(&'a self, name_binding: NameBinding<'a>) -> &'a NameBinding<'a> {
         self.name_bindings.alloc(name_binding)
     }
-    fn alloc_import_directive(
-        &'a self,
-        import_directive: ImportDirective<'a>,
-    ) -> &'a ImportDirective<'_> {
-        self.import_directives.alloc(import_directive)
+    fn alloc_import(&'a self, import: Import<'a>) -> &'a Import<'_> {
+        self.imports.alloc(import)
     }
     fn alloc_name_resolution(&'a self) -> &'a RefCell<NameResolution<'a>> {
         self.name_resolutions.alloc(Default::default())
     }
-    fn alloc_legacy_binding(&'a self, binding: LegacyBinding<'a>) -> &'a LegacyBinding<'a> {
-        self.legacy_bindings.alloc(binding)
+    fn alloc_macro_rules_binding(
+        &'a self,
+        binding: MacroRulesBinding<'a>,
+    ) -> &'a MacroRulesBinding<'a> {
+        self.macro_rules_bindings.alloc(binding)
     }
     fn alloc_ast_paths(&'a self, paths: &[ast::Path]) -> &'a [ast::Path] {
         self.ast_paths.alloc_from_iter(paths.iter().cloned())
@@ -1016,9 +1015,9 @@ fn as_mut(&mut self) -> &mut Resolver<'a> {
 
 impl<'a, 'b> DefIdTree for &'a Resolver<'b> {
     fn parent(self, id: DefId) -> Option<DefId> {
-        match id.krate {
-            LOCAL_CRATE => self.definitions.def_key(id.index).parent,
-            _ => self.cstore().def_key(id).parent,
+        match id.as_local() {
+            Some(id) => self.definitions.def_key(id).parent,
+            None => self.cstore().def_key(id).parent,
         }
         .map(|index| DefId { index, ..id })
     }
@@ -1028,7 +1027,11 @@ fn parent(self, id: DefId) -> Option<DefId> {
 /// the resolver is no longer needed as all the relevant information is inline.
 impl rustc_ast_lowering::Resolver for Resolver<'_> {
     fn def_key(&mut self, id: DefId) -> DefKey {
-        if id.is_local() { self.definitions().def_key(id.index) } else { self.cstore().def_key(id) }
+        if let Some(id) = id.as_local() {
+            self.definitions().def_key(id)
+        } else {
+            self.cstore().def_key(id)
+        }
     }
 
     fn item_generics_num_lifetimes(&self, def_id: DefId, sess: &Session) -> usize {
@@ -1221,7 +1224,7 @@ pub fn new(
             dummy_ext_derive: Lrc::new(SyntaxExtension::dummy_derive(session.edition())),
             non_macro_attrs: [non_macro_attr(false), non_macro_attr(true)],
             invocation_parent_scopes,
-            output_legacy_scopes: Default::default(),
+            output_macro_rules_scopes: Default::default(),
             helper_attrs: Default::default(),
             macro_defs,
             local_macro_def_scopes: FxHashMap::default(),
@@ -1363,7 +1366,7 @@ fn new_module(
     }
 
     fn new_key(&mut self, ident: Ident, ns: Namespace) -> BindingKey {
-        let ident = ident.modern();
+        let ident = ident.normalize_to_macros_2_0();
         let disambiguator = if ident.name == kw::Underscore {
             self.underscore_disambiguator += 1;
             self.underscore_disambiguator
@@ -1410,11 +1413,11 @@ fn record_use(
                 misc2: AmbiguityErrorMisc::None,
             });
         }
-        if let NameBindingKind::Import { directive, binding, ref used } = used_binding.kind {
+        if let NameBindingKind::Import { import, binding, ref used } = used_binding.kind {
             // Avoid marking `extern crate` items that refer to a name from extern prelude,
             // but not introduce it, as used if they are accessed from lexical scope.
             if is_lexical_scope {
-                if let Some(entry) = self.extern_prelude.get(&ident.modern()) {
+                if let Some(entry) = self.extern_prelude.get(&ident.normalize_to_macros_2_0()) {
                     if let Some(crate_item) = entry.extern_crate_item {
                         if ptr::eq(used_binding, crate_item) && !entry.introduced_by_item {
                             return;
@@ -1423,17 +1426,17 @@ fn record_use(
                 }
             }
             used.set(true);
-            directive.used.set(true);
-            self.used_imports.insert((directive.id, ns));
-            self.add_to_glob_map(&directive, ident);
+            import.used.set(true);
+            self.used_imports.insert((import.id, ns));
+            self.add_to_glob_map(&import, ident);
             self.record_use(ident, ns, binding, false);
         }
     }
 
     #[inline]
-    fn add_to_glob_map(&mut self, directive: &ImportDirective<'_>, ident: Ident) {
-        if directive.is_glob() {
-            self.glob_map.entry(directive.id).or_default().insert(ident.name);
+    fn add_to_glob_map(&mut self, import: &Import<'_>, ident: Ident) {
+        if import.is_glob() {
+            self.glob_map.entry(import.id).or_default().insert(ident.name);
         }
     }
 
@@ -1476,7 +1479,7 @@ fn visit_scopes<T>(
         //    derives (you need to resolve the derive first to add helpers into scope), but they
         //    should be available before the derive is expanded for compatibility.
         //    It's mess in general, so we are being conservative for now.
-        // 1-3. `macro_rules` (open, not controlled), loop through legacy scopes. Have higher
+        // 1-3. `macro_rules` (open, not controlled), loop through `macro_rules` scopes. Have higher
         //    priority than prelude macros, but create ambiguities with macros in modules.
         // 1-3. Names in modules (both normal `mod`ules and blocks), loop through hygienic parents
         //    (open, not controlled). Have higher priority than prelude macros, but create
@@ -1501,7 +1504,7 @@ fn visit_scopes<T>(
             TypeNS | ValueNS => Scope::Module(module),
             MacroNS => Scope::DeriveHelpers(parent_scope.expansion),
         };
-        let mut ident = ident.modern();
+        let mut ident = ident.normalize_to_macros_2_0();
         let mut use_prelude = !module.no_implicit_prelude;
 
         loop {
@@ -1541,16 +1544,18 @@ fn visit_scopes<T>(
                     }
                 }
                 Scope::DeriveHelpers(..) => Scope::DeriveHelpersCompat,
-                Scope::DeriveHelpersCompat => Scope::MacroRules(parent_scope.legacy),
-                Scope::MacroRules(legacy_scope) => match legacy_scope {
-                    LegacyScope::Binding(binding) => Scope::MacroRules(binding.parent_legacy_scope),
-                    LegacyScope::Invocation(invoc_id) => Scope::MacroRules(
-                        self.output_legacy_scopes
+                Scope::DeriveHelpersCompat => Scope::MacroRules(parent_scope.macro_rules),
+                Scope::MacroRules(macro_rules_scope) => match macro_rules_scope {
+                    MacroRulesScope::Binding(binding) => {
+                        Scope::MacroRules(binding.parent_macro_rules_scope)
+                    }
+                    MacroRulesScope::Invocation(invoc_id) => Scope::MacroRules(
+                        self.output_macro_rules_scopes
                             .get(&invoc_id)
                             .cloned()
-                            .unwrap_or(self.invocation_parent_scopes[&invoc_id].legacy),
+                            .unwrap_or(self.invocation_parent_scopes[&invoc_id].macro_rules),
                     ),
-                    LegacyScope::Empty => Scope::Module(module),
+                    MacroRulesScope::Empty => Scope::Module(module),
                 },
                 Scope::CrateRoot => match ns {
                     TypeNS => {
@@ -1621,18 +1626,18 @@ fn resolve_ident_in_lexical_scope(
         if ident.name == kw::Invalid {
             return Some(LexicalScopeBinding::Res(Res::Err));
         }
-        let (general_span, modern_span) = if ident.name == kw::SelfUpper {
+        let (general_span, normalized_span) = if ident.name == kw::SelfUpper {
             // FIXME(jseyfried) improve `Self` hygiene
             let empty_span = ident.span.with_ctxt(SyntaxContext::root());
             (empty_span, empty_span)
         } else if ns == TypeNS {
-            let modern_span = ident.span.modern();
-            (modern_span, modern_span)
+            let normalized_span = ident.span.normalize_to_macros_2_0();
+            (normalized_span, normalized_span)
         } else {
-            (ident.span.modern_and_legacy(), ident.span.modern())
+            (ident.span.normalize_to_macro_rules(), ident.span.normalize_to_macros_2_0())
         };
         ident.span = general_span;
-        let modern_ident = Ident { span: modern_span, ..ident };
+        let normalized_ident = Ident { span: normalized_span, ..ident };
 
         // Walk backwards up the ribs in scope.
         let record_used = record_used_id.is_some();
@@ -1640,8 +1645,8 @@ fn resolve_ident_in_lexical_scope(
         for i in (0..ribs.len()).rev() {
             debug!("walk rib\n{:?}", ribs[i].bindings);
             // Use the rib kind to determine whether we are resolving parameters
-            // (modern hygiene) or local variables (legacy hygiene).
-            let rib_ident = if ribs[i].kind.contains_params() { modern_ident } else { ident };
+            // (macro 2.0 hygiene) or local variables (`macro_rules` hygiene).
+            let rib_ident = if ribs[i].kind.contains_params() { normalized_ident } else { ident };
             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(
@@ -1684,7 +1689,7 @@ fn resolve_ident_in_lexical_scope(
             }
         }
 
-        ident = modern_ident;
+        ident = normalized_ident;
         let mut poisoned = None;
         loop {
             let opt_module = if let Some(node_id) = record_used_id {
@@ -1853,14 +1858,14 @@ fn resolve_ident_in_module_ext(
         let mut adjusted_parent_scope = parent_scope;
         match module {
             ModuleOrUniformRoot::Module(m) => {
-                if let Some(def) = ident.span.modernize_and_adjust(m.expansion) {
+                if let Some(def) = ident.span.normalize_to_macros_2_0_and_adjust(m.expansion) {
                     tmp_parent_scope =
                         ParentScope { module: self.macro_def_scope(def), ..*parent_scope };
                     adjusted_parent_scope = &tmp_parent_scope;
                 }
             }
             ModuleOrUniformRoot::ExternPrelude => {
-                ident.span.modernize_and_adjust(ExpnId::root());
+                ident.span.normalize_to_macros_2_0_and_adjust(ExpnId::root());
             }
             ModuleOrUniformRoot::CrateRootAndExternPrelude | ModuleOrUniformRoot::CurrentScope => {
                 // No adjustments
@@ -1883,14 +1888,14 @@ fn resolve_crate_root(&mut self, ident: Ident) -> Module<'a> {
         let mark = if ident.name == kw::DollarCrate {
             // When resolving `$crate` from a `macro_rules!` invoked in a `macro`,
             // we don't want to pretend that the `macro_rules!` definition is in the `macro`
-            // as described in `SyntaxContext::apply_mark`, so we ignore prepended modern marks.
+            // as described in `SyntaxContext::apply_mark`, so we ignore prepended opaque marks.
             // FIXME: This is only a guess and it doesn't work correctly for `macro_rules!`
             // definitions actually produced by `macro` and `macro` definitions produced by
             // `macro_rules!`, but at least such configurations are not stable yet.
-            ctxt = ctxt.modern_and_legacy();
+            ctxt = ctxt.normalize_to_macro_rules();
             let mut iter = ctxt.marks().into_iter().rev().peekable();
             let mut result = None;
-            // Find the last modern mark from the end if it exists.
+            // Find the last opaque mark from the end if it exists.
             while let Some(&(mark, transparency)) = iter.peek() {
                 if transparency == Transparency::Opaque {
                     result = Some(mark);
@@ -1899,7 +1904,7 @@ fn resolve_crate_root(&mut self, ident: Ident) -> Module<'a> {
                     break;
                 }
             }
-            // Then find the last legacy mark from the end if it exists.
+            // Then find the last semi-transparent mark from the end if it exists.
             for (mark, transparency) in iter {
                 if transparency == Transparency::SemiTransparent {
                     result = Some(mark);
@@ -1909,7 +1914,7 @@ fn resolve_crate_root(&mut self, ident: Ident) -> Module<'a> {
             }
             result
         } else {
-            ctxt = ctxt.modern();
+            ctxt = ctxt.normalize_to_macros_2_0();
             ctxt.adjust(ExpnId::root())
         };
         let module = match mark {
@@ -1921,7 +1926,7 @@ fn resolve_crate_root(&mut self, ident: Ident) -> Module<'a> {
 
     fn resolve_self(&mut self, ctxt: &mut SyntaxContext, module: Module<'a>) -> Module<'a> {
         let mut module = self.get_module(module.normal_ancestor_id);
-        while module.span.ctxt().modern() != *ctxt {
+        while module.span.ctxt().normalize_to_macros_2_0() != *ctxt {
             let parent = module.parent.unwrap_or_else(|| self.macro_def_scope(ctxt.remove_mark()));
             module = self.get_module(parent.normal_ancestor_id);
         }
@@ -1989,7 +1994,7 @@ fn resolve_path_with_ribs(
 
             if ns == TypeNS {
                 if allow_super && name == kw::Super {
-                    let mut ctxt = ident.span.ctxt().modern();
+                    let mut ctxt = ident.span.ctxt().normalize_to_macros_2_0();
                     let self_module = match i {
                         0 => Some(self.resolve_self(&mut ctxt, parent_scope.module)),
                         _ => match module {
@@ -2015,7 +2020,7 @@ fn resolve_path_with_ribs(
                 }
                 if i == 0 {
                     if name == kw::SelfLower {
-                        let mut ctxt = ident.span.ctxt().modern();
+                        let mut ctxt = ident.span.ctxt().normalize_to_macros_2_0();
                         module = Some(ModuleOrUniformRoot::Module(
                             self.resolve_self(&mut ctxt, parent_scope.module),
                         ));
@@ -2187,11 +2192,8 @@ fn resolve_path_with_ribs(
                                     Applicability::MaybeIncorrect,
                                 )),
                             )
-                        } else if !ident.is_reserved() {
-                            (format!("maybe a missing crate `{}`?", ident), None)
                         } else {
-                            // the parser will already have complained about the keyword being used
-                            return PathResult::NonModule(PartialRes::new(Res::Err));
+                            (format!("maybe a missing crate `{}`?", ident), None)
                         }
                     } else if i == 0 {
                         (format!("use of undeclared type or module `{}`", ident), None)
@@ -2258,10 +2260,9 @@ fn lint_if_path_starts_with_module(
         // `ExternCrate` (also used for `crate::...`) then no need to issue a
         // warning, this looks all good!
         if let Some(binding) = second_binding {
-            if let NameBindingKind::Import { directive: d, .. } = binding.kind {
-                // Careful: we still want to rewrite paths from
-                // renamed extern crates.
-                if let ImportDirectiveSubclass::ExternCrate { source: None, .. } = d.subclass {
+            if let NameBindingKind::Import { import, .. } = binding.kind {
+                // Careful: we still want to rewrite paths from renamed extern crates.
+                if let ImportKind::ExternCrate { source: None, .. } = import.kind {
                     return;
                 }
             }
@@ -2425,21 +2426,21 @@ fn set_binding_parent_module(&mut self, binding: &'a NameBinding<'a>, module: Mo
         }
     }
 
-    fn disambiguate_legacy_vs_modern(
+    fn disambiguate_macro_rules_vs_modularized(
         &self,
-        legacy: &'a NameBinding<'a>,
-        modern: &'a NameBinding<'a>,
+        macro_rules: &'a NameBinding<'a>,
+        modularized: &'a NameBinding<'a>,
     ) -> bool {
-        // Some non-controversial subset of ambiguities "modern macro name" vs "macro_rules"
+        // Some non-controversial subset of ambiguities "modularized macro name" vs "macro_rules"
         // is disambiguated to mitigate regressions from macro modularization.
         // Scoping for `macro_rules` behaves like scoping for `let` at module level, in general.
         match (
-            self.binding_parent_modules.get(&PtrKey(legacy)),
-            self.binding_parent_modules.get(&PtrKey(modern)),
+            self.binding_parent_modules.get(&PtrKey(macro_rules)),
+            self.binding_parent_modules.get(&PtrKey(modularized)),
         ) {
-            (Some(legacy), Some(modern)) => {
-                legacy.normal_ancestor_id == modern.normal_ancestor_id
-                    && modern.is_ancestor_of(legacy)
+            (Some(macro_rules), Some(modularized)) => {
+                macro_rules.normal_ancestor_id == modularized.normal_ancestor_id
+                    && modularized.is_ancestor_of(macro_rules)
             }
             _ => false,
         }
@@ -2564,10 +2565,10 @@ fn report_conflict<'b>(
 
         // See https://github.com/rust-lang/rust/issues/32354
         use NameBindingKind::Import;
-        let directive = match (&new_binding.kind, &old_binding.kind) {
+        let import = match (&new_binding.kind, &old_binding.kind) {
             // If there are two imports where one or both have attributes then prefer removing the
             // import without attributes.
-            (Import { directive: new, .. }, Import { directive: old, .. })
+            (Import { import: new, .. }, Import { import: old, .. })
                 if {
                     !new_binding.span.is_dummy()
                         && !old_binding.span.is_dummy()
@@ -2581,11 +2582,11 @@ fn report_conflict<'b>(
                 }
             }
             // Otherwise prioritize the new binding.
-            (Import { directive, .. }, other) if !new_binding.span.is_dummy() => {
-                Some((directive, new_binding.span, other.is_import()))
+            (Import { import, .. }, other) if !new_binding.span.is_dummy() => {
+                Some((import, new_binding.span, other.is_import()))
             }
-            (other, Import { directive, .. }) if !old_binding.span.is_dummy() => {
-                Some((directive, old_binding.span, other.is_import()))
+            (other, Import { import, .. }) if !old_binding.span.is_dummy() => {
+                Some((import, old_binding.span, other.is_import()))
             }
             _ => None,
         };
@@ -2602,22 +2603,22 @@ fn report_conflict<'b>(
             && !has_dummy_span
             && ((new_binding.is_extern_crate() || old_binding.is_extern_crate()) || from_item);
 
-        match directive {
-            Some((directive, span, true)) if should_remove_import && directive.is_nested() => {
-                self.add_suggestion_for_duplicate_nested_use(&mut err, directive, span)
+        match import {
+            Some((import, span, true)) if should_remove_import && import.is_nested() => {
+                self.add_suggestion_for_duplicate_nested_use(&mut err, import, span)
             }
-            Some((directive, _, true)) if should_remove_import && !directive.is_glob() => {
+            Some((import, _, true)) if should_remove_import && !import.is_glob() => {
                 // Simple case - remove the entire import. Due to the above match arm, this can
                 // only be a single use so just remove it entirely.
                 err.tool_only_span_suggestion(
-                    directive.use_span_with_attributes,
+                    import.use_span_with_attributes,
                     "remove unnecessary import",
                     String::new(),
                     Applicability::MaybeIncorrect,
                 );
             }
-            Some((directive, span, _)) => {
-                self.add_suggestion_for_rename_of_use(&mut err, name, directive, span)
+            Some((import, span, _)) => {
+                self.add_suggestion_for_rename_of_use(&mut err, name, import, span)
             }
             _ => {}
         }
@@ -2639,7 +2640,7 @@ fn add_suggestion_for_rename_of_use(
         &self,
         err: &mut DiagnosticBuilder<'_>,
         name: Name,
-        directive: &ImportDirective<'_>,
+        import: &Import<'_>,
         binding_span: Span,
     ) {
         let suggested_name = if name.as_str().chars().next().unwrap().is_uppercase() {
@@ -2649,11 +2650,11 @@ fn add_suggestion_for_rename_of_use(
         };
 
         let mut suggestion = None;
-        match directive.subclass {
-            ImportDirectiveSubclass::SingleImport { type_ns_only: true, .. } => {
+        match import.kind {
+            ImportKind::Single { type_ns_only: true, .. } => {
                 suggestion = Some(format!("self as {}", suggested_name))
             }
-            ImportDirectiveSubclass::SingleImport { source, .. } => {
+            ImportKind::Single { source, .. } => {
                 if let Some(pos) =
                     source.span.hi().0.checked_sub(binding_span.lo().0).map(|pos| pos as usize)
                 {
@@ -2669,7 +2670,7 @@ fn add_suggestion_for_rename_of_use(
                     }
                 }
             }
-            ImportDirectiveSubclass::ExternCrate { source, target, .. } => {
+            ImportKind::ExternCrate { source, target, .. } => {
                 suggestion = Some(format!(
                     "extern crate {} as {};",
                     source.unwrap_or(target.name),
@@ -2711,27 +2712,27 @@ fn add_suggestion_for_rename_of_use(
     /// If the nested use contains only one import then the suggestion will remove the entire
     /// line.
     ///
-    /// It is expected that the directive provided is a nested import - this isn't checked by the
+    /// It is expected that the provided import is nested - this isn't checked by the
     /// function. If this invariant is not upheld, this function's behaviour will be unexpected
     /// as characters expected by span manipulations won't be present.
     fn add_suggestion_for_duplicate_nested_use(
         &self,
         err: &mut DiagnosticBuilder<'_>,
-        directive: &ImportDirective<'_>,
+        import: &Import<'_>,
         binding_span: Span,
     ) {
-        assert!(directive.is_nested());
+        assert!(import.is_nested());
         let message = "remove unnecessary import";
 
         // Two examples will be used to illustrate the span manipulations we're doing:
         //
         // - Given `use issue_52891::{d, a, e};` where `a` is a duplicate then `binding_span` is
-        //   `a` and `directive.use_span` is `issue_52891::{d, a, e};`.
+        //   `a` and `import.use_span` is `issue_52891::{d, a, e};`.
         // - Given `use issue_52891::{d, e, a};` where `a` is a duplicate then `binding_span` is
-        //   `a` and `directive.use_span` is `issue_52891::{d, e, a};`.
+        //   `a` and `import.use_span` is `issue_52891::{d, e, a};`.
 
         let (found_closing_brace, span) =
-            find_span_of_binding_until_next_binding(self.session, binding_span, directive.use_span);
+            find_span_of_binding_until_next_binding(self.session, binding_span, import.use_span);
 
         // If there was a closing brace then identify the span to remove any trailing commas from
         // previous imports.
@@ -2747,7 +2748,7 @@ fn add_suggestion_for_duplicate_nested_use(
                 // Remove the entire line if we cannot extend the span back, this indicates a
                 // `issue_52891::{self}` case.
                 err.span_suggestion(
-                    directive.use_span_with_attributes,
+                    import.use_span_with_attributes,
                     message,
                     String::new(),
                     Applicability::MaybeIncorrect,
@@ -2769,7 +2770,7 @@ fn extern_prelude_get(
             // Make sure `self`, `super` etc produce an error when passed to here.
             return None;
         }
-        self.extern_prelude.get(&ident.modern()).cloned().and_then(|entry| {
+        self.extern_prelude.get(&ident.normalize_to_macros_2_0()).cloned().and_then(|entry| {
             if let Some(binding) = entry.extern_crate_item {
                 if !speculative && entry.introduced_by_item {
                     self.record_use(ident, TypeNS, binding, false);
@@ -2778,12 +2779,8 @@ fn extern_prelude_get(
             } else {
                 let crate_id = if !speculative {
                     self.crate_loader.process_path_extern(ident.name, ident.span)
-                } else if let Some(crate_id) =
-                    self.crate_loader.maybe_process_path_extern(ident.name, ident.span)
-                {
-                    crate_id
                 } else {
-                    return None;
+                    self.crate_loader.maybe_process_path_extern(ident.name, ident.span)?
                 };
                 let crate_root = self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
                 Some(
index e11aec906693ecca29ffa137bbbbca48e0e88296..6f2e0bce3acaf63e9d2cf15dfa92099b79d295bd 100644 (file)
@@ -7,9 +7,7 @@
 use crate::{CrateLint, ParentScope, ResolutionError, Resolver, Scope, ScopeSet, Weak};
 use crate::{ModuleKind, ModuleOrUniformRoot, NameBinding, PathResult, Segment, ToNameBinding};
 use rustc::middle::stability;
-use rustc::session::parse::feature_err;
-use rustc::session::Session;
-use rustc::{lint, span_bug, ty};
+use rustc::{span_bug, ty};
 use rustc_ast::ast::{self, Ident, NodeId};
 use rustc_ast_pretty::pprust;
 use rustc_attr::{self as attr, StabilityLevel};
@@ -21,6 +19,9 @@
 use rustc_feature::is_builtin_attr_name;
 use rustc_hir::def::{self, DefKind, NonMacroAttrKind};
 use rustc_hir::def_id;
+use rustc_session::lint::builtin::UNUSED_MACROS;
+use rustc_session::parse::feature_err;
+use rustc_session::Session;
 use rustc_span::edition::Edition;
 use rustc_span::hygiene::{self, ExpnData, ExpnId, ExpnKind};
 use rustc_span::symbol::{kw, sym, Symbol};
 type Res = def::Res<NodeId>;
 
 /// Binding produced by a `macro_rules` item.
-/// Not modularized, can shadow previous legacy bindings, etc.
+/// Not modularized, can shadow previous `macro_rules` bindings, etc.
 #[derive(Debug)]
-pub struct LegacyBinding<'a> {
+pub struct MacroRulesBinding<'a> {
     crate binding: &'a NameBinding<'a>,
-    /// Legacy scope into which the `macro_rules` item was planted.
-    crate parent_legacy_scope: LegacyScope<'a>,
+    /// `macro_rules` scope into which the `macro_rules` item was planted.
+    crate parent_macro_rules_scope: MacroRulesScope<'a>,
     crate ident: Ident,
 }
 
 /// The scope introduced by a `macro_rules!` macro.
 /// This starts at the macro's definition and ends at the end of the macro's parent
 /// module (named or unnamed), or even further if it escapes with `#[macro_use]`.
-/// Some macro invocations need to introduce legacy scopes too because they
+/// Some macro invocations need to introduce `macro_rules` scopes too because they
 /// can potentially expand into macro definitions.
 #[derive(Copy, Clone, Debug)]
-pub enum LegacyScope<'a> {
+pub enum MacroRulesScope<'a> {
     /// Empty "root" scope at the crate start containing no names.
     Empty,
     /// The scope introduced by a `macro_rules!` macro definition.
-    Binding(&'a LegacyBinding<'a>),
+    Binding(&'a MacroRulesBinding<'a>),
     /// The scope introduced by a macro invocation that can potentially
     /// create a `macro_rules!` macro definition.
     Invocation(ExpnId),
@@ -159,8 +160,8 @@ fn visit_ast_fragment_with_placeholders(&mut self, expansion: ExpnId, fragment:
         // 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);
-        self.output_legacy_scopes.insert(expansion, output_legacy_scope);
+        let output_macro_rules_scope = self.build_reduced_graph(fragment, parent_scope);
+        self.output_macro_rules_scopes.insert(expansion, output_macro_rules_scope);
 
         parent_scope.module.unexpanded_invocations.borrow_mut().remove(&expansion);
     }
@@ -258,7 +259,13 @@ fn resolve_macro_invocation(
                             force,
                         ) {
                             Ok((Some(ext), _)) => {
-                                let span = path.segments.last().unwrap().ident.span.modern();
+                                let span = path
+                                    .segments
+                                    .last()
+                                    .unwrap()
+                                    .ident
+                                    .span
+                                    .normalize_to_macros_2_0();
                                 helper_attrs.extend(
                                     ext.helper_attrs.iter().map(|name| Ident::new(*name, span)),
                                 );
@@ -323,12 +330,7 @@ fn resolve_macro_invocation(
 
     fn check_unused_macros(&mut self) {
         for (&node_id, &span) in self.unused_macros.iter() {
-            self.lint_buffer.buffer_lint(
-                lint::builtin::UNUSED_MACROS,
-                node_id,
-                span,
-                "unused macro definition",
-            );
+            self.lint_buffer.buffer_lint(UNUSED_MACROS, node_id, span, "unused macro definition");
         }
     }
 
@@ -339,6 +341,42 @@ fn has_derive_copy(&self, expn_id: ExpnId) -> bool {
     fn add_derive_copy(&mut self, expn_id: ExpnId) {
         self.containers_deriving_copy.insert(expn_id);
     }
+
+    // The function that implements the resolution logic of `#[cfg_accessible(path)]`.
+    // Returns true if the path can certainly be resolved in one of three namespaces,
+    // returns false if the path certainly cannot be resolved in any of the three namespaces.
+    // Returns `Indeterminate` if we cannot give a certain answer yet.
+    fn cfg_accessible(&mut self, expn_id: ExpnId, path: &ast::Path) -> Result<bool, Indeterminate> {
+        let span = path.span;
+        let path = &Segment::from_path(path);
+        let parent_scope = self.invocation_parent_scopes[&expn_id];
+
+        let mut indeterminate = false;
+        for ns in [TypeNS, ValueNS, MacroNS].iter().copied() {
+            match self.resolve_path(path, Some(ns), &parent_scope, false, span, CrateLint::No) {
+                PathResult::Module(ModuleOrUniformRoot::Module(_)) => return Ok(true),
+                PathResult::NonModule(partial_res) if partial_res.unresolved_segments() == 0 => {
+                    return Ok(true);
+                }
+                PathResult::Indeterminate => indeterminate = true,
+                // FIXME: `resolve_path` is not ready to report partially resolved paths
+                // correctly, so we just report an error if the path was reported as unresolved.
+                // This needs to be fixed for `cfg_accessible` to be useful.
+                PathResult::NonModule(..) | PathResult::Failed { .. } => {}
+                PathResult::Module(_) => panic!("unexpected path resolution"),
+            }
+        }
+
+        if indeterminate {
+            return Err(Indeterminate);
+        }
+
+        self.session
+            .struct_span_err(span, "not sure whether the path is accessible or not")
+            .span_note(span, "`cfg_accessible` is not fully implemented")
+            .emit();
+        Ok(false)
+    }
 }
 
 impl<'a> Resolver<'a> {
@@ -608,12 +646,14 @@ struct Flags: u8 {
                         }
                         result
                     }
-                    Scope::MacroRules(legacy_scope) => match legacy_scope {
-                        LegacyScope::Binding(legacy_binding) if ident == legacy_binding.ident => {
-                            Ok((legacy_binding.binding, Flags::MACRO_RULES))
+                    Scope::MacroRules(macro_rules_scope) => match macro_rules_scope {
+                        MacroRulesScope::Binding(macro_rules_binding)
+                            if ident == macro_rules_binding.ident =>
+                        {
+                            Ok((macro_rules_binding.binding, Flags::MACRO_RULES))
                         }
-                        LegacyScope::Invocation(invoc_id)
-                            if !this.output_legacy_scopes.contains_key(&invoc_id) =>
+                        MacroRulesScope::Invocation(invoc_id)
+                            if !this.output_macro_rules_scopes.contains_key(&invoc_id) =>
                         {
                             Err(Determinacy::Undetermined)
                         }
@@ -759,16 +799,18 @@ struct Flags: u8 {
                                     Some(AmbiguityKind::DeriveHelper)
                                 } else if innermost_flags.contains(Flags::MACRO_RULES)
                                     && flags.contains(Flags::MODULE)
-                                    && !this
-                                        .disambiguate_legacy_vs_modern(innermost_binding, binding)
+                                    && !this.disambiguate_macro_rules_vs_modularized(
+                                        innermost_binding,
+                                        binding,
+                                    )
                                     || flags.contains(Flags::MACRO_RULES)
                                         && innermost_flags.contains(Flags::MODULE)
-                                        && !this.disambiguate_legacy_vs_modern(
+                                        && !this.disambiguate_macro_rules_vs_modularized(
                                             binding,
                                             innermost_binding,
                                         )
                                 {
-                                    Some(AmbiguityKind::LegacyVsModern)
+                                    Some(AmbiguityKind::MacroRulesVsModularized)
                                 } else if innermost_binding.is_glob_import() {
                                     Some(AmbiguityKind::GlobVsOuter)
                                 } else if innermost_binding
index 0f4cc4192b626fe2a1ead11ad548db0c9c9d4805..4717664b6ba8000d4bf00850734bb7ddcb450889 100644 (file)
@@ -18,6 +18,7 @@ rustc_hir = { path = "../librustc_hir" }
 rustc_parse = { path = "../librustc_parse" }
 serde_json = "1"
 rustc_ast = { path = "../librustc_ast" }
+rustc_session = { path = "../librustc_session" }
 rustc_span = { path = "../librustc_span" }
 rls-data = "0.19"
 rls-span = "0.5"
index e8cd5ea832db05581adf8e2e2e28e978d9b13030..8d1a39eab89d8a16080184555e7cd4a10da11083 100644 (file)
@@ -13,7 +13,6 @@
 //! DumpVisitor walks the AST and processes it, and Dumper is used for
 //! recording the output.
 
-use rustc::session::config::Input;
 use rustc::span_bug;
 use rustc::ty::{self, DefIdTree, TyCtxt};
 use rustc_ast::ast::{self, Attribute, NodeId, PatKind};
@@ -25,6 +24,7 @@
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::def::{DefKind as HirDefKind, Res};
 use rustc_hir::def_id::DefId;
+use rustc_session::config::Input;
 use rustc_span::source_map::{respan, DUMMY_SP};
 use rustc_span::*;
 
@@ -1004,8 +1004,7 @@ fn process_trait_item(&mut self, trait_item: &'l ast::AssocItem, trait_id: DefId
         self.process_macro_use(trait_item.span);
         let vis_span = trait_item.span.shrink_to_lo();
         match trait_item.kind {
-            ast::AssocItemKind::Static(ref ty, _, ref expr)
-            | ast::AssocItemKind::Const(_, ref ty, ref expr) => {
+            ast::AssocItemKind::Const(_, ref ty, ref expr) => {
                 self.process_assoc_const(
                     trait_item.id,
                     trait_item.ident,
@@ -1068,15 +1067,14 @@ fn process_trait_item(&mut self, trait_item: &'l ast::AssocItem, trait_id: DefId
                     self.visit_ty(default_ty)
                 }
             }
-            ast::AssocItemKind::Macro(_) => {}
+            ast::AssocItemKind::MacCall(_) => {}
         }
     }
 
     fn process_impl_item(&mut self, impl_item: &'l ast::AssocItem, impl_id: DefId) {
         self.process_macro_use(impl_item.span);
         match impl_item.kind {
-            ast::AssocItemKind::Static(ref ty, _, ref expr)
-            | ast::AssocItemKind::Const(_, ref ty, ref expr) => {
+            ast::AssocItemKind::Const(_, ref ty, ref expr) => {
                 self.process_assoc_const(
                     impl_item.id,
                     impl_item.ident,
@@ -1105,7 +1103,7 @@ fn process_impl_item(&mut self, impl_item: &'l ast::AssocItem, impl_id: DefId) {
                 // trait.
                 self.visit_ty(ty)
             }
-            ast::AssocItemKind::Macro(_) => {}
+            ast::AssocItemKind::MacCall(_) => {}
         }
     }
 
@@ -1347,7 +1345,7 @@ fn visit_item(&mut self, item: &'l ast::Item) {
                 walk_list!(self, visit_ty, ty);
                 self.process_generic_params(ty_params, &qualname, item.id);
             }
-            Mac(_) => (),
+            MacCall(_) => (),
             _ => visit::walk_item(self, item),
         }
     }
@@ -1537,8 +1535,7 @@ fn visit_foreign_item(&mut self, item: &'l ast::ForeignItem) {
                     self.visit_ty(&ret_ty);
                 }
             }
-            ast::ForeignItemKind::Const(_, ref ty, _)
-            | ast::ForeignItemKind::Static(ref ty, _, _) => {
+            ast::ForeignItemKind::Static(ref ty, _, _) => {
                 if let Some(var_data) = self.save_ctxt.get_extern_item_data(item) {
                     down_cast_data!(var_data, DefData, item.span);
                     self.dumper.dump_def(&access, var_data);
@@ -1552,7 +1549,7 @@ fn visit_foreign_item(&mut self, item: &'l ast::ForeignItem) {
                     self.dumper.dump_def(&access, var_data);
                 }
             }
-            ast::ForeignItemKind::Macro(..) => {}
+            ast::ForeignItemKind::MacCall(..) => {}
         }
     }
 }
index c68289adb10595474ff673e384b834ea153c7b06..98d81c6252242c3bec73c27aa30a5c2dfc5eb7f4 100644 (file)
@@ -10,7 +10,6 @@
 
 use rustc::middle::cstore::ExternCrate;
 use rustc::middle::privacy::AccessLevels;
-use rustc::session::config::{CrateType, Input, OutputType};
 use rustc::ty::{self, DefIdTree, TyCtxt};
 use rustc::{bug, span_bug};
 use rustc_ast::ast::{self, Attribute, NodeId, PatKind, DUMMY_NODE_ID};
@@ -22,6 +21,7 @@
 use rustc_hir::def::{CtorOf, DefKind as HirDefKind, Res};
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_hir::Node;
+use rustc_session::config::{CrateType, Input, OutputType};
 use rustc_span::source_map::Spanned;
 use rustc_span::*;
 
@@ -151,8 +151,7 @@ pub fn get_extern_item_data(&self, item: &ast::ForeignItem) -> Option<Data> {
                     attributes: lower_attributes(item.attrs.clone(), self),
                 }))
             }
-            ast::ForeignItemKind::Const(_, ref ty, _)
-            | ast::ForeignItemKind::Static(ref ty, _, _) => {
+            ast::ForeignItemKind::Static(ref ty, _, _) => {
                 filter!(self.span_utils, item.ident.span);
 
                 let id = id_from_node_id(item.id, self);
@@ -175,7 +174,7 @@ pub fn get_extern_item_data(&self, item: &ast::ForeignItem) -> Option<Data> {
             }
             // FIXME(plietar): needs a new DefKind in rls-data
             ast::ForeignItemKind::TyAlias(..) => None,
-            ast::ForeignItemKind::Macro(..) => None,
+            ast::ForeignItemKind::MacCall(..) => None,
         }
     }
 
@@ -335,7 +334,7 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
                                     Some(_) => ImplKind::Direct,
                                     None => ImplKind::Inherent,
                                 },
-                                span: span,
+                                span,
                                 value: String::new(),
                                 parent: None,
                                 children: items
@@ -533,13 +532,16 @@ pub fn get_expr_data(&self, expr: &ast::Expr) -> Option<Data> {
                 match self.tables.expr_ty_adjusted(&hir_node).kind {
                     ty::Adt(def, _) if !def.is_enum() => {
                         let variant = &def.non_enum_variant();
-                        let index = self.tcx.find_field_index(ident, variant).unwrap();
                         filter!(self.span_utils, ident.span);
                         let span = self.span_from_span(ident.span);
                         return Some(Data::RefData(Ref {
                             kind: RefKind::Variable,
                             span,
-                            ref_id: id_from_def_id(variant.fields[index].did),
+                            ref_id: self
+                                .tcx
+                                .find_field_index(ident, variant)
+                                .map(|index| id_from_def_id(variant.fields[index].did))
+                                .unwrap_or_else(|| null_id()),
                         }));
                     }
                     ty::Tuple(..) => None,
@@ -716,7 +718,7 @@ fn fn_type(seg: &ast::PathSegment) -> bool {
             | Res::Def(HirDefKind::Ctor(..), _) => {
                 Some(Ref { kind: RefKind::Variable, span, ref_id: id_from_def_id(res.def_id()) })
             }
-            Res::Def(HirDefKind::Method, decl_id) => {
+            Res::Def(HirDefKind::AssocFn, decl_id) => {
                 let def_id = if decl_id.is_local() {
                     let ti = self.tcx.associated_item(decl_id);
 
@@ -792,19 +794,6 @@ pub fn get_macro_use_data(&self, span: Span) -> Option<MacroRef> {
             ExpnKind::Root | ExpnKind::AstPass(_) | ExpnKind::Desugaring(_) => return None,
         };
 
-        // If the callee is an imported macro from an external crate, need to get
-        // the source span and name from the session, as their spans are localized
-        // when read in, and no longer correspond to the source.
-        if let Some(mac) = self.tcx.sess.imported_macro_spans.borrow().get(&callee.def_site) {
-            let &(ref mac_name, mac_span) = mac;
-            let mac_span = self.span_from_span(mac_span);
-            return Some(MacroRef {
-                span: callsite_span,
-                qualname: mac_name.clone(), // FIXME: generate the real qualname
-                callee_span: mac_span,
-            });
-        }
-
         let callee_span = self.span_from_span(callee.def_site);
         Some(MacroRef {
             span: callsite_span,
index 32da62adc3c0201e3e3b4c8f1a4c8edeb9e683db..51434e9333049bc248c5749beb80280f4216cfc7 100644 (file)
@@ -308,7 +308,7 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_,
             | ast::TyKind::Infer
             | ast::TyKind::Err
             | ast::TyKind::ImplicitSelf
-            | ast::TyKind::Mac(_) => Err("Ty"),
+            | ast::TyKind::MacCall(_) => Err("Ty"),
         }
     }
 }
@@ -519,7 +519,7 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_,
                 text.push(' ');
 
                 let trait_sig = if let Some(ref t) = *of_trait {
-                    if polarity == ast::ImplPolarity::Negative {
+                    if let ast::ImplPolarity::Negative(_) = polarity {
                         text.push('!');
                     }
                     let trait_sig = t.path.make(offset + text.len(), id, scx)?;
@@ -544,7 +544,7 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_,
             ast::ItemKind::ExternCrate(_) => Err("extern crate"),
             // FIXME should implement this (e.g., pub use).
             ast::ItemKind::Use(_) => Err("import"),
-            ast::ItemKind::Mac(..) | ast::ItemKind::MacroDef(_) => Err("Macro"),
+            ast::ItemKind::MacCall(..) | ast::ItemKind::MacroDef(_) => Err("Macro"),
         }
     }
 }
@@ -793,10 +793,9 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_,
                 text.push_str(&name);
                 text.push(';');
 
-                Ok(Signature { text: text, defs: defs, refs: vec![] })
+                Ok(Signature { text, defs, refs: vec![] })
             }
-            ast::ForeignItemKind::Const(..) => Err("foreign const"),
-            ast::ForeignItemKind::Macro(..) => Err("macro"),
+            ast::ForeignItemKind::MacCall(..) => Err("macro"),
         }
     }
 }
index 152435206fec43b872aed7f1bdf41c9a69a5ed48..6620941c440465bc2c12c54c1af038c6cab81342 100644 (file)
@@ -1,7 +1,7 @@
 use crate::generated_code;
-use rustc::session::Session;
 use rustc_ast::token::{self, TokenKind};
 use rustc_parse::lexer::{self, StringReader};
+use rustc_session::Session;
 use rustc_span::*;
 
 #[derive(Clone)]
index 9b89c7ae32abc68470f63ca7bec42d8e8f83aab5..c263da69c3521131cdb846bbf0a02c4dc650c129 100644 (file)
@@ -70,7 +70,7 @@ pub fn record_type_size<S: ToString>(
             type_description: type_desc.to_string(),
             align: align.bytes(),
             overall_size: overall_size.bytes(),
-            packed: packed,
+            packed,
             opt_discr_size: opt_discr_size.map(|s| s.bytes()),
             variants,
         };
index db4412a18a35b84c85cfa7fe56ae9255c011e091..c273e7fdbf916432e03439a4529cf98ccc6128a5 100644 (file)
@@ -391,6 +391,7 @@ pub fn files(&self) -> Option<impl Iterator<Item = &String>> {
 pub enum PrintRequest {
     FileNames,
     Sysroot,
+    TargetLibdir,
     CrateName,
     Cfg,
     TargetList,
@@ -912,7 +913,7 @@ pub fn rustc_short_optgroups() -> Vec<RustcOptGroup> {
             "",
             "print",
             "Compiler information to print on stdout",
-            "[crate-name|file-names|sysroot|cfg|target-list|\
+            "[crate-name|file-names|sysroot|target-libdir|cfg|target-list|\
              target-cpus|target-features|relocation-models|\
              code-models|tls-models|target-spec-json|native-static-libs]",
         ),
@@ -1344,6 +1345,7 @@ fn collect_print_requests(
         "crate-name" => PrintRequest::CrateName,
         "file-names" => PrintRequest::FileNames,
         "sysroot" => PrintRequest::Sysroot,
+        "target-libdir" => PrintRequest::TargetLibdir,
         "cfg" => PrintRequest::Cfg,
         "target-list" => PrintRequest::TargetList,
         "target-cpus" => PrintRequest::TargetCPUs,
index d3163fa356436ec87155d105ac27ac4467812591..a1ecf4e8528beff31ca17171251a398c3e366498 100644 (file)
@@ -922,8 +922,6 @@ fn parse_symbol_mangling_version(
         "tell the linker to strip debuginfo when building without debuginfo enabled."),
     share_generics: Option<bool> = (None, parse_opt_bool, [TRACKED],
         "make the current crate share its generic instantiations"),
-    chalk: bool = (false, parse_bool, [TRACKED],
-        "enable the experimental Chalk-based trait solving engine"),
     no_parallel_llvm: bool = (false, parse_bool, [UNTRACKED],
         "don't run LLVM in parallel (while keeping codegen-units and ThinLTO)"),
     no_leak_check: bool = (false, parse_bool, [UNTRACKED],
index 2fb7977dce9eeced5169eeb9f3800563ea82bf45..81281857dbc2e092469a5df463c0158efcbeddfa 100644 (file)
@@ -49,6 +49,18 @@ pub struct OptimizationFuel {
     out_of_fuel: bool,
 }
 
+/// The behavior of the CTFE engine when an error occurs with regards to backtraces.
+#[derive(Clone, Copy)]
+pub enum CtfeBacktrace {
+    /// Do nothing special, return the error as usual without a backtrace.
+    Disabled,
+    /// Capture a backtrace at the point the error is created and return it in the error
+    /// (to be printed later if/when the error ever actually gets shown to the user).
+    Capture,
+    /// Capture a backtrace at the point the error is created and immediately print it out.
+    Immediate,
+}
+
 /// Represents the data associated with a compilation
 /// session for a single crate.
 pub struct Session {
@@ -88,10 +100,8 @@ pub struct Session {
     /// The maximum length of types during monomorphization.
     pub type_length_limit: Once<usize>,
 
-    /// Map from imported macro spans (which consist of
-    /// the localized span for the macro body) to the
-    /// macro name and definition span in the source crate.
-    pub imported_macro_spans: OneThread<RefCell<FxHashMap<Span, (String, Span)>>>,
+    /// The maximum blocks a const expression can evaluate.
+    pub const_eval_limit: Once<usize>,
 
     incr_comp_session: OneThread<RefCell<IncrCompSession>>,
     /// Used for incremental compilation tests. Will only be populated if
@@ -136,6 +146,11 @@ pub struct Session {
     /// Path for libraries that will take preference over libraries shipped by Rust.
     /// Used by windows-gnu targets to priortize system mingw-w64 libraries.
     pub system_library_path: OneThread<RefCell<Option<Option<PathBuf>>>>,
+
+    /// Tracks the current behavior of the CTFE engine when an error occurs.
+    /// Options range from returning the error without a backtrace to returning an error
+    /// and immediately printing the backtrace to stderr.
+    pub ctfe_backtrace: Lock<CtfeBacktrace>,
 }
 
 pub struct PerfStats {
@@ -540,25 +555,34 @@ pub fn overflow_checks(&self) -> bool {
             .unwrap_or(self.opts.debug_assertions)
     }
 
-    pub fn crt_static(&self) -> bool {
+    /// Check whether this compile session and crate type use static crt.
+    pub fn crt_static(&self, crate_type: Option<config::CrateType>) -> bool {
         // If the target does not opt in to crt-static support, use its default.
         if self.target.target.options.crt_static_respected {
-            self.crt_static_feature()
+            self.crt_static_feature(crate_type)
         } else {
             self.target.target.options.crt_static_default
         }
     }
 
-    pub fn crt_static_feature(&self) -> bool {
+    /// Check whether this compile session and crate type use `crt-static` feature.
+    pub fn crt_static_feature(&self, crate_type: Option<config::CrateType>) -> bool {
         let requested_features = self.opts.cg.target_feature.split(',');
         let found_negative = requested_features.clone().any(|r| r == "-crt-static");
         let found_positive = requested_features.clone().any(|r| r == "+crt-static");
 
-        // If the target we're compiling for requests a static crt by default,
-        // then see if the `-crt-static` feature was passed to disable that.
-        // Otherwise if we don't have a static crt by default then see if the
-        // `+crt-static` feature was passed.
-        if self.target.target.options.crt_static_default { !found_negative } else { found_positive }
+        if found_positive || found_negative {
+            found_positive
+        } else if crate_type == Some(config::CrateType::ProcMacro)
+            || crate_type == None && self.opts.crate_types.contains(&config::CrateType::ProcMacro)
+        {
+            // FIXME: When crate_type is not available,
+            // we use compiler options to determine the crate_type.
+            // We can't check `#![crate_type = "proc-macro"]` here.
+            false
+        } else {
+            self.target.target.options.crt_static_default
+        }
     }
 
     pub fn must_not_eliminate_frame_pointers(&self) -> bool {
@@ -1037,6 +1061,12 @@ fn build_session_(
         sopts.debugging_opts.time_passes,
     );
 
+    let ctfe_backtrace = Lock::new(match env::var("RUSTC_CTFE_BACKTRACE") {
+        Ok(ref val) if val == "immediate" => CtfeBacktrace::Immediate,
+        Ok(ref val) if val != "0" => CtfeBacktrace::Capture,
+        _ => CtfeBacktrace::Disabled,
+    });
+
     let sess = Session {
         target: target_cfg,
         host,
@@ -1053,7 +1083,7 @@ fn build_session_(
         features: Once::new(),
         recursion_limit: Once::new(),
         type_length_limit: Once::new(),
-        imported_macro_spans: OneThread::new(RefCell::new(FxHashMap::default())),
+        const_eval_limit: Once::new(),
         incr_comp_session: OneThread::new(RefCell::new(IncrCompSession::NotInitialized)),
         cgu_reuse_tracker,
         prof,
@@ -1074,6 +1104,7 @@ fn build_session_(
         trait_methods_not_found: Lock::new(Default::default()),
         confused_type_with_std_module: Lock::new(Default::default()),
         system_library_path: OneThread::new(RefCell::new(Default::default())),
+        ctfe_backtrace,
     };
 
     validate_commandline_args_with_session_available(&sess);
index 6cdfd0500ca844a0e19bc4f10919e03d92a85ec3..29561c91f33184da39af3799f671045759dbdae3 100644 (file)
@@ -1,8 +1,11 @@
 use crate::HashStableContext;
+use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::AtomicRef;
 use rustc_index::vec::Idx;
+use rustc_macros::HashStable_Generic;
 use rustc_serialize::{Decoder, Encoder};
+use std::borrow::Borrow;
 use std::fmt;
 use std::{u32, u64};
 
@@ -22,7 +25,7 @@ pub enum CrateNum {
 
 /// Item definitions in the currently-compiled crate would have the `CrateNum`
 /// `LOCAL_CRATE` in their `DefId`.
-pub const LOCAL_CRATE: CrateNum = CrateNum::Index(CrateId::from_u32_const(0));
+pub const LOCAL_CRATE: CrateNum = CrateNum::Index(CrateId::from_u32(0));
 
 impl Idx for CrateNum {
     #[inline]
@@ -102,6 +105,28 @@ fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
     }
 }
 
+#[derive(
+    Copy,
+    Clone,
+    Hash,
+    PartialEq,
+    Eq,
+    PartialOrd,
+    Ord,
+    Debug,
+    RustcEncodable,
+    RustcDecodable,
+    HashStable_Generic
+)]
+pub struct DefPathHash(pub Fingerprint);
+
+impl Borrow<Fingerprint> for DefPathHash {
+    #[inline]
+    fn borrow(&self) -> &Fingerprint {
+        &self.0
+    }
+}
+
 rustc_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
@@ -130,7 +155,7 @@ impl DefId {
     /// Makes a local `DefId` from the given `DefIndex`.
     #[inline]
     pub fn local(index: DefIndex) -> DefId {
-        DefId { krate: LOCAL_CRATE, index: index }
+        DefId { krate: LOCAL_CRATE, index }
     }
 
     #[inline]
@@ -139,8 +164,13 @@ pub fn is_local(self) -> bool {
     }
 
     #[inline]
-    pub fn to_local(self) -> LocalDefId {
-        LocalDefId::from_def_id(self)
+    pub fn as_local(self) -> Option<LocalDefId> {
+        if self.is_local() { Some(LocalDefId { local_def_index: self.index }) } else { None }
+    }
+
+    #[inline]
+    pub fn expect_local(self) -> LocalDefId {
+        self.as_local().unwrap_or_else(|| panic!("DefId::expect_local: `{:?}` isn't local", self))
     }
 
     pub fn is_top_level_module(self) -> bool {
@@ -185,19 +215,26 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 /// few cases where we know that only DefIds from the local crate are expected
 /// and a DefId from a different crate would signify a bug somewhere. This
 /// is when LocalDefId comes in handy.
-#[derive(Clone, Copy, PartialEq, Eq, Hash)]
-pub struct LocalDefId(DefIndex);
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub struct LocalDefId {
+    pub local_def_index: DefIndex,
+}
 
-impl LocalDefId {
+impl Idx for LocalDefId {
     #[inline]
-    pub fn from_def_id(def_id: DefId) -> LocalDefId {
-        assert!(def_id.is_local());
-        LocalDefId(def_id.index)
+    fn new(idx: usize) -> Self {
+        LocalDefId { local_def_index: Idx::new(idx) }
     }
+    #[inline]
+    fn index(self) -> usize {
+        self.local_def_index.index()
+    }
+}
 
+impl LocalDefId {
     #[inline]
     pub fn to_def_id(self) -> DefId {
-        DefId { krate: LOCAL_CRATE, index: self.0 }
+        DefId { krate: LOCAL_CRATE, index: self.local_def_index }
     }
 }
 
index a368a881674d86fac4bb50077b8ca44f08b0a6ee..e073d735a1225a3db7194125b30ebca7ac2533c6 100644 (file)
@@ -201,11 +201,11 @@ fn is_descendant_of(&self, mut expn_id: ExpnId, ancestor: ExpnId) -> bool {
         true
     }
 
-    fn modern(&self, ctxt: SyntaxContext) -> SyntaxContext {
+    fn normalize_to_macros_2_0(&self, ctxt: SyntaxContext) -> SyntaxContext {
         self.syntax_context_data[ctxt.0 as usize].opaque
     }
 
-    fn modern_and_legacy(&self, ctxt: SyntaxContext) -> SyntaxContext {
+    fn normalize_to_macro_rules(&self, ctxt: SyntaxContext) -> SyntaxContext {
         self.syntax_context_data[ctxt.0 as usize].opaque_and_semitransparent
     }
 
@@ -266,9 +266,9 @@ fn apply_mark(
 
         let call_site_ctxt = self.expn_data(expn_id).call_site.ctxt();
         let mut call_site_ctxt = if transparency == Transparency::SemiTransparent {
-            self.modern(call_site_ctxt)
+            self.normalize_to_macros_2_0(call_site_ctxt)
         } else {
-            self.modern_and_legacy(call_site_ctxt)
+            self.normalize_to_macro_rules(call_site_ctxt)
         };
 
         if call_site_ctxt == SyntaxContext::root() {
@@ -491,10 +491,10 @@ pub fn adjust(&mut self, expn_id: ExpnId) -> Option<ExpnId> {
         HygieneData::with(|data| data.adjust(self, expn_id))
     }
 
-    /// Like `SyntaxContext::adjust`, but also modernizes `self`.
-    pub fn modernize_and_adjust(&mut self, expn_id: ExpnId) -> Option<ExpnId> {
+    /// Like `SyntaxContext::adjust`, but also normalizes `self` to macros 2.0.
+    pub fn normalize_to_macros_2_0_and_adjust(&mut self, expn_id: ExpnId) -> Option<ExpnId> {
         HygieneData::with(|data| {
-            *self = data.modern(*self);
+            *self = data.normalize_to_macros_2_0(*self);
             data.adjust(self, expn_id)
         })
     }
@@ -527,7 +527,7 @@ pub fn modernize_and_adjust(&mut self, expn_id: ExpnId) -> Option<ExpnId> {
     pub fn glob_adjust(&mut self, expn_id: ExpnId, glob_span: Span) -> Option<Option<ExpnId>> {
         HygieneData::with(|data| {
             let mut scope = None;
-            let mut glob_ctxt = data.modern(glob_span.ctxt());
+            let mut glob_ctxt = data.normalize_to_macros_2_0(glob_span.ctxt());
             while !data.is_descendant_of(expn_id, data.outer_expn(glob_ctxt)) {
                 scope = Some(data.remove_mark(&mut glob_ctxt).0);
                 if data.remove_mark(self).0 != scope.unwrap() {
@@ -558,7 +558,7 @@ pub fn reverse_glob_adjust(
                 return None;
             }
 
-            let mut glob_ctxt = data.modern(glob_span.ctxt());
+            let mut glob_ctxt = data.normalize_to_macros_2_0(glob_span.ctxt());
             let mut marks = Vec::new();
             while !data.is_descendant_of(expn_id, data.outer_expn(glob_ctxt)) {
                 marks.push(data.remove_mark(&mut glob_ctxt));
@@ -574,20 +574,20 @@ pub fn reverse_glob_adjust(
 
     pub fn hygienic_eq(self, other: SyntaxContext, expn_id: ExpnId) -> bool {
         HygieneData::with(|data| {
-            let mut self_modern = data.modern(self);
-            data.adjust(&mut self_modern, expn_id);
-            self_modern == data.modern(other)
+            let mut self_normalized = data.normalize_to_macros_2_0(self);
+            data.adjust(&mut self_normalized, expn_id);
+            self_normalized == data.normalize_to_macros_2_0(other)
         })
     }
 
     #[inline]
-    pub fn modern(self) -> SyntaxContext {
-        HygieneData::with(|data| data.modern(self))
+    pub fn normalize_to_macros_2_0(self) -> SyntaxContext {
+        HygieneData::with(|data| data.normalize_to_macros_2_0(self))
     }
 
     #[inline]
-    pub fn modern_and_legacy(self) -> SyntaxContext {
-        HygieneData::with(|data| data.modern_and_legacy(self))
+    pub fn normalize_to_macro_rules(self) -> SyntaxContext {
+        HygieneData::with(|data| data.normalize_to_macro_rules(self))
     }
 
     #[inline]
index 502ea64aab9b5360bb31cddbb39075e8ae283190..dbc180114f1c1dafd90a9f296a057d1023457736 100644 (file)
@@ -6,6 +6,9 @@
 
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
 #![feature(crate_visibility_modifier)]
+#![feature(const_if_match)]
+#![feature(const_fn)]
+#![feature(const_panic)]
 #![feature(nll)]
 #![feature(optin_builtin_traits)]
 #![feature(specialization)]
@@ -24,7 +27,7 @@
 use hygiene::Transparency;
 pub use hygiene::{DesugaringKind, ExpnData, ExpnId, ExpnKind, MacroKind, SyntaxContext};
 pub mod def_id;
-use def_id::DefId;
+use def_id::{CrateNum, DefId, LOCAL_CRATE};
 mod span_encoding;
 pub use span_encoding::{Span, DUMMY_SP};
 
@@ -83,8 +86,6 @@ pub fn new(edition: Edition) -> Globals {
 )]
 pub enum FileName {
     Real(PathBuf),
-    /// A macro. This includes the full name of the macro, so that there are no clashes.
-    Macros(String),
     /// Call to `quote!`.
     QuoteExpansion(u64),
     /// Command line.
@@ -107,7 +108,6 @@ fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         use FileName::*;
         match *self {
             Real(ref path) => write!(fmt, "{}", path.display()),
-            Macros(ref name) => write!(fmt, "<{} macros>", name),
             QuoteExpansion(_) => write!(fmt, "<quote expansion>"),
             MacroExpansion(_) => write!(fmt, "<macro expansion>"),
             Anon(_) => write!(fmt, "<anon>"),
@@ -132,8 +132,7 @@ pub fn is_real(&self) -> bool {
         use FileName::*;
         match *self {
             Real(_) => true,
-            Macros(_)
-            | Anon(_)
+            Anon(_)
             | MacroExpansion(_)
             | ProcMacroSourceCode(_)
             | CfgSpec(_)
@@ -144,22 +143,6 @@ pub fn is_real(&self) -> bool {
         }
     }
 
-    pub fn is_macros(&self) -> bool {
-        use FileName::*;
-        match *self {
-            Real(_)
-            | Anon(_)
-            | MacroExpansion(_)
-            | ProcMacroSourceCode(_)
-            | CfgSpec(_)
-            | CliCrateAttr(_)
-            | Custom(_)
-            | QuoteExpansion(_)
-            | DocTest(_, _) => false,
-            Macros(_) => true,
-        }
-    }
-
     pub fn quote_expansion_source_code(src: &str) -> FileName {
         let mut hasher = StableHasher::new();
         src.hash(&mut hasher);
@@ -568,9 +551,9 @@ pub fn adjust(&mut self, expn_id: ExpnId) -> Option<ExpnId> {
     }
 
     #[inline]
-    pub fn modernize_and_adjust(&mut self, expn_id: ExpnId) -> Option<ExpnId> {
+    pub fn normalize_to_macros_2_0_and_adjust(&mut self, expn_id: ExpnId) -> Option<ExpnId> {
         let mut span = self.data();
-        let mark = span.ctxt.modernize_and_adjust(expn_id);
+        let mark = span.ctxt.normalize_to_macros_2_0_and_adjust(expn_id);
         *self = Span::new(span.lo, span.hi, span.ctxt);
         mark
     }
@@ -596,15 +579,15 @@ pub fn reverse_glob_adjust(
     }
 
     #[inline]
-    pub fn modern(self) -> Span {
+    pub fn normalize_to_macros_2_0(self) -> Span {
         let span = self.data();
-        span.with_ctxt(span.ctxt.modern())
+        span.with_ctxt(span.ctxt.normalize_to_macros_2_0())
     }
 
     #[inline]
-    pub fn modern_and_legacy(self) -> Span {
+    pub fn normalize_to_macro_rules(self) -> Span {
         let span = self.data();
-        span.with_ctxt(span.ctxt.modern_and_legacy())
+        span.with_ctxt(span.ctxt.normalize_to_macro_rules())
     }
 }
 
@@ -856,30 +839,42 @@ pub struct NormalizedPos {
     pub diff: u32,
 }
 
-/// The state of the lazy external source loading mechanism of a `SourceFile`.
-#[derive(PartialEq, Eq, Clone)]
+#[derive(PartialEq, Eq, Clone, Debug)]
 pub enum ExternalSource {
+    /// No external source has to be loaded, since the `SourceFile` represents a local crate.
+    Unneeded,
+    Foreign {
+        kind: ExternalSourceKind,
+        /// This SourceFile's byte-offset within the source_map of its original crate
+        original_start_pos: BytePos,
+        /// The end of this SourceFile within the source_map of its original crate
+        original_end_pos: BytePos,
+    },
+}
+
+/// The state of the lazy external source loading mechanism of a `SourceFile`.
+#[derive(PartialEq, Eq, Clone, Debug)]
+pub enum ExternalSourceKind {
     /// The external source has been loaded already.
     Present(String),
     /// No attempt has been made to load the external source.
     AbsentOk,
     /// A failed attempt has been made to load the external source.
     AbsentErr,
-    /// No external source has to be loaded, since the `SourceFile` represents a local crate.
     Unneeded,
 }
 
 impl ExternalSource {
     pub fn is_absent(&self) -> bool {
-        match *self {
-            ExternalSource::Present(_) => false,
+        match self {
+            ExternalSource::Foreign { kind: ExternalSourceKind::Present(_), .. } => false,
             _ => true,
         }
     }
 
     pub fn get_source(&self) -> Option<&str> {
-        match *self {
-            ExternalSource::Present(ref src) => Some(src),
+        match self {
+            ExternalSource::Foreign { kind: ExternalSourceKind::Present(ref src), .. } => Some(src),
             _ => None,
         }
     }
@@ -900,8 +895,6 @@ pub struct SourceFile {
     /// The unmapped path of the file that the source came from.
     /// Set to `None` if the `SourceFile` was imported from an external crate.
     pub unmapped_path: Option<FileName>,
-    /// Indicates which crate this `SourceFile` was imported from.
-    pub crate_of_origin: u32,
     /// The complete source code.
     pub src: Option<Lrc<String>>,
     /// The source code's hash.
@@ -923,6 +916,8 @@ pub struct SourceFile {
     pub normalized_pos: Vec<NormalizedPos>,
     /// A hash of the filename, used for speeding up hashing in incremental compilation.
     pub name_hash: u128,
+    /// Indicates which crate this `SourceFile` was imported from.
+    pub cnum: CrateNum,
 }
 
 impl Encodable for SourceFile {
@@ -989,7 +984,8 @@ fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
             s.emit_struct_field("multibyte_chars", 6, |s| self.multibyte_chars.encode(s))?;
             s.emit_struct_field("non_narrow_chars", 7, |s| self.non_narrow_chars.encode(s))?;
             s.emit_struct_field("name_hash", 8, |s| self.name_hash.encode(s))?;
-            s.emit_struct_field("normalized_pos", 9, |s| self.normalized_pos.encode(s))
+            s.emit_struct_field("normalized_pos", 9, |s| self.normalized_pos.encode(s))?;
+            s.emit_struct_field("cnum", 10, |s| self.cnum.encode(s))
         })
     }
 }
@@ -1039,24 +1035,24 @@ fn decode<D: Decoder>(d: &mut D) -> Result<SourceFile, D::Error> {
             let name_hash: u128 = d.read_struct_field("name_hash", 8, |d| Decodable::decode(d))?;
             let normalized_pos: Vec<NormalizedPos> =
                 d.read_struct_field("normalized_pos", 9, |d| Decodable::decode(d))?;
+            let cnum: CrateNum = d.read_struct_field("cnum", 10, |d| Decodable::decode(d))?;
             Ok(SourceFile {
                 name,
                 name_was_remapped,
                 unmapped_path: None,
-                // `crate_of_origin` has to be set by the importer.
-                // This value matches up with `rustc_hir::def_id::INVALID_CRATE`.
-                // That constant is not available here, unfortunately.
-                crate_of_origin: std::u32::MAX - 1,
                 start_pos,
                 end_pos,
                 src: None,
                 src_hash,
-                external_src: Lock::new(ExternalSource::AbsentOk),
+                // Unused - the metadata decoder will construct
+                // a new SourceFile, filling in `external_src` properly
+                external_src: Lock::new(ExternalSource::Unneeded),
                 lines,
                 multibyte_chars,
                 non_narrow_chars,
                 normalized_pos,
                 name_hash,
+                cnum,
             })
         })
     }
@@ -1098,7 +1094,6 @@ pub fn new(
             name,
             name_was_remapped,
             unmapped_path: Some(unmapped_path),
-            crate_of_origin: 0,
             src: Some(Lrc::new(src)),
             src_hash,
             external_src: Lock::new(ExternalSource::Unneeded),
@@ -1109,6 +1104,7 @@ pub fn new(
             non_narrow_chars,
             normalized_pos,
             name_hash,
+            cnum: LOCAL_CRATE,
         }
     }
 
@@ -1126,21 +1122,27 @@ pub fn add_external_src<F>(&self, get_src: F) -> bool
     where
         F: FnOnce() -> Option<String>,
     {
-        if *self.external_src.borrow() == ExternalSource::AbsentOk {
+        if matches!(
+            *self.external_src.borrow(),
+            ExternalSource::Foreign { kind: ExternalSourceKind::AbsentOk, .. }
+        ) {
             let src = get_src();
             let mut external_src = self.external_src.borrow_mut();
             // Check that no-one else have provided the source while we were getting it
-            if *external_src == ExternalSource::AbsentOk {
+            if let ExternalSource::Foreign {
+                kind: src_kind @ ExternalSourceKind::AbsentOk, ..
+            } = &mut *external_src
+            {
                 if let Some(src) = src {
                     let mut hasher: StableHasher = StableHasher::new();
                     hasher.write(src.as_bytes());
 
                     if hasher.finish::<u128>() == self.src_hash {
-                        *external_src = ExternalSource::Present(src);
+                        *src_kind = ExternalSourceKind::Present(src);
                         return true;
                     }
                 } else {
-                    *external_src = ExternalSource::AbsentErr;
+                    *src_kind = ExternalSourceKind::AbsentErr;
                 }
 
                 false
@@ -1167,11 +1169,7 @@ fn get_until_newline(src: &str, begin: usize) -> &str {
         }
 
         let begin = {
-            let line = if let Some(line) = self.lines.get(line_number) {
-                line
-            } else {
-                return None;
-            };
+            let line = self.lines.get(line_number)?;
             let begin: BytePos = *line - self.start_pos;
             begin.to_usize()
         };
index 39601ad76222c8f4d631f82a960dc238c9db8553..7dd9e2f6316b41631dc899307893836499fe7f73 100644 (file)
@@ -296,14 +296,16 @@ pub fn new_imported_source_file(
         &self,
         filename: FileName,
         name_was_remapped: bool,
-        crate_of_origin: u32,
         src_hash: u128,
         name_hash: u128,
         source_len: usize,
+        cnum: CrateNum,
         mut file_local_lines: Vec<BytePos>,
         mut file_local_multibyte_chars: Vec<MultiByteChar>,
         mut file_local_non_narrow_chars: Vec<NonNarrowChar>,
         mut file_local_normalized_pos: Vec<NormalizedPos>,
+        original_start_pos: BytePos,
+        original_end_pos: BytePos,
     ) -> Lrc<SourceFile> {
         let start_pos = self
             .allocate_address_space(source_len)
@@ -332,10 +334,13 @@ pub fn new_imported_source_file(
             name: filename,
             name_was_remapped,
             unmapped_path: None,
-            crate_of_origin,
             src: None,
             src_hash,
-            external_src: Lock::new(ExternalSource::AbsentOk),
+            external_src: Lock::new(ExternalSource::Foreign {
+                kind: ExternalSourceKind::AbsentOk,
+                original_start_pos,
+                original_end_pos,
+            }),
             start_pos,
             end_pos,
             lines: file_local_lines,
@@ -343,6 +348,7 @@ pub fn new_imported_source_file(
             non_narrow_chars: file_local_non_narrow_chars,
             normalized_pos: file_local_normalized_pos,
             name_hash,
+            cnum,
         });
 
         let mut files = self.files.borrow_mut();
@@ -517,6 +523,13 @@ pub fn is_valid_span(&self, sp: Span) -> Result<(Loc, Loc), SpanLinesError> {
         Ok((lo, hi))
     }
 
+    pub fn is_line_before_span_empty(&self, sp: Span) -> bool {
+        match self.span_to_prev_source(sp) {
+            Ok(s) => s.split('\n').last().map(|l| l.trim_start().is_empty()).unwrap_or(false),
+            Err(_) => false,
+        }
+    }
+
     pub fn span_to_lines(&self, sp: Span) -> FileLinesResult {
         debug!("span_to_lines(sp={:?})", sp);
         let (lo, hi) = self.is_valid_span(sp)?;
@@ -620,7 +633,7 @@ pub fn span_to_prev_source(&self, sp: Span) -> Result<String, SpanSnippetError>
     /// if no character could be found or if an error occurred while retrieving the code snippet.
     pub fn span_extend_to_prev_char(&self, sp: Span, c: char) -> Span {
         if let Ok(prev_source) = self.span_to_prev_source(sp) {
-            let prev_source = prev_source.rsplit(c).nth(0).unwrap_or("").trim_start();
+            let prev_source = prev_source.rsplit(c).next().unwrap_or("").trim_start();
             if !prev_source.is_empty() && !prev_source.contains('\n') {
                 return sp.with_lo(BytePos(sp.lo().0 - prev_source.len() as u32));
             }
@@ -640,7 +653,7 @@ pub fn span_extend_to_prev_str(&self, sp: Span, pat: &str, accept_newlines: bool
         for ws in &[" ", "\t", "\n"] {
             let pat = pat.to_owned() + ws;
             if let Ok(prev_source) = self.span_to_prev_source(sp) {
-                let prev_source = prev_source.rsplit(&pat).nth(0).unwrap_or("").trim_start();
+                let prev_source = prev_source.rsplit(&pat).next().unwrap_or("").trim_start();
                 if !prev_source.is_empty() && (!prev_source.contains('\n') || accept_newlines) {
                     return sp.with_lo(BytePos(sp.lo().0 - prev_source.len() as u32));
                 }
@@ -655,7 +668,7 @@ pub fn span_extend_to_prev_str(&self, sp: Span, pat: &str, accept_newlines: bool
     pub fn span_until_char(&self, sp: Span, c: char) -> Span {
         match self.span_to_snippet(sp) {
             Ok(snippet) => {
-                let snippet = snippet.split(c).nth(0).unwrap_or("").trim_end();
+                let snippet = snippet.split(c).next().unwrap_or("").trim_end();
                 if !snippet.is_empty() && !snippet.contains('\n') {
                     sp.with_hi(BytePos(sp.lo().0 + snippet.len() as u32))
                 } else {
@@ -689,7 +702,7 @@ pub fn span_until_non_whitespace(&self, sp: Span) -> Span {
                 whitespace_found = true;
             }
 
-            if whitespace_found && !c.is_whitespace() { false } else { true }
+            !whitespace_found || c.is_whitespace()
         })
     }
 
@@ -975,6 +988,12 @@ pub fn ensure_source_file_source_present(&self, source_file: Lrc<SourceFile>) ->
             _ => None,
         })
     }
+
+    pub fn is_imported(&self, sp: Span) -> bool {
+        let source_file_index = self.lookup_source_file_idx(sp.lo());
+        let source_file = &self.files()[source_file_index];
+        source_file.is_imported()
+    }
 }
 
 #[derive(Clone)]
index d6232f32f4c1bf8e27a85861709d962846dfa6af..35a97cfd3c3c21f98b7e8438f90acf43d550dffb 100644 (file)
         abi_unadjusted,
         abi_vectorcall,
         abi_x86_interrupt,
+        abort,
         aborts,
         address,
         add_with_overflow,
         caller_location,
         cdylib,
         cfg,
+        cfg_accessible,
         cfg_attr,
         cfg_attr_multi,
         cfg_doctest,
         console,
         const_compare_raw_pointers,
         const_constructor,
+        const_eval_limit,
         const_extern_fn,
         const_fn,
         const_fn_union,
         derive,
         diagnostic,
         direct,
+        discriminant_value,
         doc,
         doc_alias,
         doc_cfg,
         doc_keyword,
         doc_masked,
-        doc_spotlight,
         doctest,
         document_private_items,
         dotdoteq_in_patterns,
         dylib,
         dyn_trait,
         eh_personality,
-        eh_unwind_resume,
         enable,
         Encodable,
         env,
         min_align_of,
         min_const_fn,
         min_const_unsafe_fn,
+        min_specialization,
         mips_target_feature,
         mmx_target_feature,
         module,
         plugin_registrar,
         plugins,
         Poll,
-        poll_with_tls_context,
+        poll_with_context,
         powerpc_target_feature,
         precise_pointer_size_matching,
         pref_align_of,
         rustc_proc_macro_decls,
         rustc_promotable,
         rustc_regions,
+        rustc_unsafe_specialization_marker,
+        rustc_specialization_trait,
         rustc_stable,
         rustc_std_internal_symbol,
         rustc_symbol_name,
         rustc_variance,
         rustfmt,
         rust_eh_personality,
-        rust_eh_unwind_resume,
         rust_oom,
         rvalue_static_promotion,
         sanitize,
         Some,
         specialization,
         speed,
-        spotlight,
         sse4a_target_feature,
         stable,
         staged_api,
         target_has_atomic_load_store,
         target_thread_local,
         task,
+        _task_context,
         tbm_target_feature,
         termination_trait,
         termination_trait_test,
@@ -854,12 +858,12 @@ pub fn without_first_quote(self) -> Ident {
     }
 
     /// "Normalize" ident for use in comparisons using "item hygiene".
-    /// Identifiers with same string value become same if they came from the same "modern" macro
+    /// Identifiers with same string value become same if they came from the same macro 2.0 macro
     /// (e.g., `macro` item, but not `macro_rules` item) and stay different if they came from
-    /// different "modern" macros.
+    /// different macro 2.0 macros.
     /// Technically, this operation strips all non-opaque marks from ident's syntactic context.
-    pub fn modern(self) -> Ident {
-        Ident::new(self.name, self.span.modern())
+    pub fn normalize_to_macros_2_0(self) -> Ident {
+        Ident::new(self.name, self.span.normalize_to_macros_2_0())
     }
 
     /// "Normalize" ident for use in comparisons using "local variable hygiene".
@@ -867,8 +871,8 @@ pub fn modern(self) -> Ident {
     /// macro (e.g., `macro` or `macro_rules!` items) and stay different if they came from different
     /// non-transparent macros.
     /// Technically, this operation strips all transparent marks from ident's syntactic context.
-    pub fn modern_and_legacy(self) -> Ident {
-        Ident::new(self.name, self.span.modern_and_legacy())
+    pub fn normalize_to_macro_rules(self) -> Ident {
+        Ident::new(self.name, self.span.normalize_to_macro_rules())
     }
 
     /// Convert the name to a `SymbolStr`. This is a slowish operation because
@@ -980,6 +984,31 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     }
 }
 
+/// An newtype around `Ident` that calls [Ident::normalize_to_macro_rules] on
+/// construction.
+// FIXME(matthewj, petrochenkov) Use this more often, add a similar
+// `ModernIdent` struct and use that as well.
+#[derive(Copy, Clone, Eq, PartialEq, Hash)]
+pub struct MacroRulesNormalizedIdent(Ident);
+
+impl MacroRulesNormalizedIdent {
+    pub fn new(ident: Ident) -> Self {
+        Self(ident.normalize_to_macro_rules())
+    }
+}
+
+impl fmt::Debug for MacroRulesNormalizedIdent {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::Debug::fmt(&self.0, f)
+    }
+}
+
+impl fmt::Display for MacroRulesNormalizedIdent {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::Display::fmt(&self.0, f)
+    }
+}
+
 /// An interned string.
 ///
 /// Internally, a `Symbol` is implemented as an index, and all operations
@@ -998,7 +1027,7 @@ pub struct SymbolIndex { .. }
 
 impl Symbol {
     const fn new(n: u32) -> Self {
-        Symbol(SymbolIndex::from_u32_const(n))
+        Symbol(SymbolIndex::from_u32(n))
     }
 
     /// Maps a string to its interned representation.
index a22000ea9d280479323472d01dadb8f3aac7e68b..ac1e03385d18110900afd26f45ac11394c205fe1 100644 (file)
@@ -1,6 +1,6 @@
 `librustc_target` contains some very low-level details that are
 specific to different compilation targets and so forth.
 
-For more information about how rustc works, see the [rustc guide].
+For more information about how rustc works, see the [rustc dev guide].
 
-[rustc guide]: https://rust-lang.github.io/rustc-guide/
+[rustc dev guide]: https://rustc-dev-guide.rust-lang.org/
index 8c7108229bd80b86b60cb93a4d93bfe6c0e3a21e..77e7ff1e2a738e5a76ac991c8ad4ddc51fa6134a 100644 (file)
@@ -365,11 +365,11 @@ pub fn homogeneous_aggregate<C>(&self, cx: &C) -> Result<HomogeneousAggregate, H
                         //
                         // NB: for all tagged `enum`s (which include all non-C-like
                         // `enum`s with defined FFI representation), this will
-                        // match the homogenous computation on the equivalent
+                        // match the homogeneous computation on the equivalent
                         // `struct { tag; union { variant1; ... } }` and/or
                         // `union { struct { tag; variant1; } ... }`
                         // (the offsets of variant fields should be identical
-                        // between the two for either to be a homogenous aggregate).
+                        // between the two for either to be a homogeneous aggregate).
                         let variant_start = total;
                         for variant_idx in variants.indices() {
                             let (variant_result, variant_total) =
@@ -542,7 +542,7 @@ pub struct FnAbi<'a, Ty> {
     /// The count of non-variadic arguments.
     ///
     /// Should only be different from args.len() when c_variadic is true.
-    /// This can be used to know wether an argument is variadic or not.
+    /// This can be used to know whether an argument is variadic or not.
     pub fixed_count: usize,
 
     pub conv: Conv,
index edd0ba46f7565e6f5d846b24f4d8cbead701fe8e..afa30e7e632a729bc0f51f32d291301648852f65 100644 (file)
@@ -401,7 +401,7 @@ pub fn restrict_for_offset(self, offset: Size) -> Align {
     }
 }
 
-/// A pair of aligments, ABI-mandated and preferred.
+/// A pair of alignments, ABI-mandated and preferred.
 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
 #[derive(HashStable_Generic)]
 pub struct AbiAndPrefAlign {
@@ -660,7 +660,10 @@ pub fn count(&self) -> usize {
 
     pub fn offset(&self, i: usize) -> Size {
         match *self {
-            FieldPlacement::Union(_) => Size::ZERO,
+            FieldPlacement::Union(count) => {
+                assert!(i < count, "tried to access field {} of union with {} fields", i, count);
+                Size::ZERO
+            }
             FieldPlacement::Array { stride, count } => {
                 let i = i as u64;
                 assert!(i < count);
@@ -871,8 +874,26 @@ pub fn reserve<C: HasDataLayout>(&self, cx: &C, count: u128) -> Option<(u128, Sc
 
 #[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)]
 pub struct LayoutDetails {
-    pub variants: Variants,
+    /// Says where the fields are located within the layout.
+    /// Primitives and uninhabited enums appear as unions without fields.
     pub fields: FieldPlacement,
+
+    /// Encodes information about multi-variant layouts.
+    /// Even with `Multiple` variants, a layout still has its own fields! Those are then
+    /// shared between all variants. One of them will be the discriminant,
+    /// but e.g. generators can have more.
+    ///
+    /// To access all fields of this layout, both `fields` and the fields of the active variant
+    /// must be taken into account.
+    pub variants: Variants,
+
+    /// The `abi` defines how this data is passed between functions, and it defines
+    /// value restrictions via `valid_range`.
+    ///
+    /// Note that this is entirely orthogonal to the recursive structure defined by
+    /// `variants` and `fields`; for example, `ManuallyDrop<Result<isize, isize>>` has
+    /// `Abi::ScalarPair`! So, even with non-`Aggregate` `abi`, `fields` and `variants`
+    /// have to be taken into account to find all fields of this layout.
     pub abi: Abi,
 
     /// The leaf scalar with the largest number of invalid values
@@ -919,6 +940,7 @@ fn deref(&self) -> &&'a LayoutDetails {
     }
 }
 
+/// Trait for context types that can compute layouts of things.
 pub trait LayoutOf {
     type Ty;
     type TyLayout;
@@ -929,6 +951,38 @@ fn spanned_layout_of(&self, ty: Self::Ty, _span: Span) -> Self::TyLayout {
     }
 }
 
+/// The `TyLayout` above will always be a `MaybeResult<TyLayout<'_, Self>>`.
+/// We can't add the bound due to the lifetime, but this trait is still useful when
+/// writing code that's generic over the `LayoutOf` impl.
+pub trait MaybeResult<T> {
+    type Error;
+
+    fn from(x: Result<T, Self::Error>) -> Self;
+    fn to_result(self) -> Result<T, Self::Error>;
+}
+
+impl<T> MaybeResult<T> for T {
+    type Error = !;
+
+    fn from(Ok(x): Result<T, Self::Error>) -> Self {
+        x
+    }
+    fn to_result(self) -> Result<T, Self::Error> {
+        Ok(self)
+    }
+}
+
+impl<T, E> MaybeResult<T> for Result<T, E> {
+    type Error = E;
+
+    fn from(x: Result<T, Self::Error>) -> Self {
+        x
+    }
+    fn to_result(self) -> Result<T, Self::Error> {
+        self
+    }
+}
+
 #[derive(Copy, Clone, PartialEq, Eq)]
 pub enum PointerKind {
     /// Most general case, we know no restrictions to tell LLVM.
@@ -969,6 +1023,9 @@ pub fn for_variant<C>(self, cx: &C, variant_index: VariantIdx) -> Self
     {
         Ty::for_variant(self, cx, variant_index)
     }
+
+    /// Callers might want to use `C: LayoutOf<Ty=Ty, TyLayout: MaybeResult<Self>>`
+    /// to allow recursion (see `might_permit_zero_init` below for an example).
     pub fn field<C>(self, cx: &C, i: usize) -> C::TyLayout
     where
         Ty: TyLayoutMethods<'a, C>,
@@ -976,6 +1033,7 @@ pub fn field<C>(self, cx: &C, i: usize) -> C::TyLayout
     {
         Ty::field(self, cx, i)
     }
+
     pub fn pointee_info_at<C>(self, cx: &C, offset: Size) -> Option<PointeeInfo>
     where
         Ty: TyLayoutMethods<'a, C>,
@@ -999,4 +1057,52 @@ pub fn is_zst(&self) -> bool {
             Abi::Aggregate { sized } => sized && self.size.bytes() == 0,
         }
     }
+
+    /// Determines if this type permits "raw" initialization by just transmuting some
+    /// memory into an instance of `T`.
+    /// `zero` indicates if the memory is zero-initialized, or alternatively
+    /// left entirely uninitialized.
+    /// This is conservative: in doubt, it will answer `true`.
+    ///
+    /// FIXME: Once we removed all the conservatism, we could alternatively
+    /// create an all-0/all-undef constant and run the const value validator to see if
+    /// this is a valid value for the given type.
+    pub fn might_permit_raw_init<C, E>(self, cx: &C, zero: bool) -> Result<bool, E>
+    where
+        Self: Copy,
+        Ty: TyLayoutMethods<'a, C>,
+        C: LayoutOf<Ty = Ty, TyLayout: MaybeResult<Self, Error = E>> + HasDataLayout,
+    {
+        let scalar_allows_raw_init = move |s: &Scalar| -> bool {
+            if zero {
+                let range = &s.valid_range;
+                // The range must contain 0.
+                range.contains(&0) || (*range.start() > *range.end()) // wrap-around allows 0
+            } else {
+                // The range must include all values. `valid_range_exclusive` handles
+                // the wrap-around using target arithmetic; with wrap-around then the full
+                // range is one where `start == end`.
+                let range = s.valid_range_exclusive(cx);
+                range.start == range.end
+            }
+        };
+
+        // Check the ABI.
+        let valid = match &self.abi {
+            Abi::Uninhabited => false, // definitely UB
+            Abi::Scalar(s) => scalar_allows_raw_init(s),
+            Abi::ScalarPair(s1, s2) => scalar_allows_raw_init(s1) && scalar_allows_raw_init(s2),
+            Abi::Vector { element: s, count } => *count == 0 || scalar_allows_raw_init(s),
+            Abi::Aggregate { .. } => true, // Cannot be excluded *right now*.
+        };
+        if !valid {
+            // This is definitely not okay.
+            trace!("might_permit_raw_init({:?}, zero={}): not valid", self.details, zero);
+            return Ok(false);
+        }
+
+        // If we have not found an error yet, we need to recursively descend.
+        // FIXME(#66151): For now, we are conservative and do not do this.
+        Ok(true)
+    }
 }
index 71150e74f70d45ddab3dd30cc73acac71ee4223d..98190867d493fc7daa4414a3405c1622c582fa91 100644 (file)
@@ -9,7 +9,13 @@
 
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
 #![feature(bool_to_option)]
+#![feature(const_if_match)]
+#![feature(const_fn)]
+#![feature(const_panic)]
 #![feature(nll)]
+#![feature(never_type)]
+#![feature(associated_type_bounds)]
+#![feature(exhaustive_patterns)]
 
 #[macro_use]
 extern crate log;
index 6549be41ea944875f2bec5c4cf2dceec5ba99555..e896b46da9a625a771c347cfaec147ceaddf3964 100644 (file)
@@ -1,8 +1,8 @@
-use super::apple_ios_base::{opts, Arch};
+use super::apple_sdk_base::{opts, AppleOS, Arch};
 use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
-    let base = opts(Arch::Arm64)?;
+    let base = opts(Arch::Arm64, AppleOS::iOS)?;
     Ok(Target {
         llvm_target: "arm64-apple-ios".to_string(),
         target_endian: "little".to_string(),
diff --git a/src/librustc_target/spec/aarch64_apple_tvos.rs b/src/librustc_target/spec/aarch64_apple_tvos.rs
new file mode 100644 (file)
index 0000000..794bc79
--- /dev/null
@@ -0,0 +1,25 @@
+use super::apple_sdk_base::{opts, AppleOS, Arch};
+use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
+
+pub fn target() -> TargetResult {
+    let base = opts(Arch::Arm64, AppleOS::tvOS)?;
+    Ok(Target {
+        llvm_target: "arm64-apple-tvos".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "64".to_string(),
+        target_c_int_width: "32".to_string(),
+        data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".to_string(),
+        arch: "aarch64".to_string(),
+        target_os: "tvos".to_string(),
+        target_env: String::new(),
+        target_vendor: "apple".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
+        options: TargetOptions {
+            features: "+neon,+fp-armv8,+cyclone".to_string(),
+            eliminate_frame_pointer: false,
+            max_atomic_width: Some(128),
+            abi_blacklist: super::arm_base::abi_blacklist(),
+            ..base
+        },
+    })
+}
diff --git a/src/librustc_target/spec/apple_ios_base.rs b/src/librustc_target/spec/apple_ios_base.rs
deleted file mode 100644 (file)
index 2673748..0000000
+++ /dev/null
@@ -1,143 +0,0 @@
-use crate::spec::{LinkArgs, LinkerFlavor, TargetOptions};
-use std::env;
-use std::io;
-use std::path::Path;
-use std::process::Command;
-
-use Arch::*;
-
-#[allow(non_camel_case_types)]
-#[derive(Copy, Clone)]
-pub enum Arch {
-    Armv7,
-    Armv7s,
-    Arm64,
-    I386,
-    X86_64,
-    X86_64_macabi,
-}
-
-impl Arch {
-    pub fn to_string(self) -> &'static str {
-        match self {
-            Armv7 => "armv7",
-            Armv7s => "armv7s",
-            Arm64 => "arm64",
-            I386 => "i386",
-            X86_64 => "x86_64",
-            X86_64_macabi => "x86_64",
-        }
-    }
-}
-
-pub fn get_sdk_root(sdk_name: &str) -> Result<String, String> {
-    // Following what clang does
-    // (https://github.com/llvm/llvm-project/blob/
-    // 296a80102a9b72c3eda80558fb78a3ed8849b341/clang/lib/Driver/ToolChains/Darwin.cpp#L1661-L1678)
-    // to allow the SDK path to be set. (For clang, xcrun sets
-    // SDKROOT; for rustc, the user or build system can set it, or we
-    // can fall back to checking for xcrun on PATH.)
-    if let Some(sdkroot) = env::var("SDKROOT").ok() {
-        let p = Path::new(&sdkroot);
-        match sdk_name {
-            // Ignore `SDKROOT` if it's clearly set for the wrong platform.
-            "iphoneos"
-                if sdkroot.contains("iPhoneSimulator.platform")
-                    || sdkroot.contains("MacOSX.platform") =>
-            {
-                ()
-            }
-            "iphonesimulator"
-                if sdkroot.contains("iPhoneOS.platform") || sdkroot.contains("MacOSX.platform") =>
-            {
-                ()
-            }
-            "macosx10.15"
-                if sdkroot.contains("iPhoneOS.platform")
-                    || sdkroot.contains("iPhoneSimulator.platform") =>
-            {
-                ()
-            }
-            // Ignore `SDKROOT` if it's not a valid path.
-            _ if !p.is_absolute() || p == Path::new("/") || !p.exists() => (),
-            _ => return Ok(sdkroot),
-        }
-    }
-    let res =
-        Command::new("xcrun").arg("--show-sdk-path").arg("-sdk").arg(sdk_name).output().and_then(
-            |output| {
-                if output.status.success() {
-                    Ok(String::from_utf8(output.stdout).unwrap())
-                } else {
-                    let error = String::from_utf8(output.stderr);
-                    let error = format!("process exit with error: {}", error.unwrap());
-                    Err(io::Error::new(io::ErrorKind::Other, &error[..]))
-                }
-            },
-        );
-
-    match res {
-        Ok(output) => Ok(output.trim().to_string()),
-        Err(e) => Err(format!("failed to get {} SDK path: {}", sdk_name, e)),
-    }
-}
-
-fn build_pre_link_args(arch: Arch) -> Result<LinkArgs, String> {
-    let sdk_name = match arch {
-        Armv7 | Armv7s | Arm64 => "iphoneos",
-        I386 | X86_64 => "iphonesimulator",
-        X86_64_macabi => "macosx10.15",
-    };
-
-    let arch_name = arch.to_string();
-
-    let sdk_root = get_sdk_root(sdk_name)?;
-
-    let mut args = LinkArgs::new();
-    args.insert(
-        LinkerFlavor::Gcc,
-        vec![
-            "-arch".to_string(),
-            arch_name.to_string(),
-            "-isysroot".to_string(),
-            sdk_root.clone(),
-            "-Wl,-syslibroot".to_string(),
-            sdk_root,
-        ],
-    );
-
-    Ok(args)
-}
-
-fn target_cpu(arch: Arch) -> String {
-    match arch {
-        Armv7 => "cortex-a8", // iOS7 is supported on iPhone 4 and higher
-        Armv7s => "cortex-a9",
-        Arm64 => "cyclone",
-        I386 => "yonah",
-        X86_64 => "core2",
-        X86_64_macabi => "core2",
-    }
-    .to_string()
-}
-
-fn link_env_remove(arch: Arch) -> Vec<String> {
-    match arch {
-        Armv7 | Armv7s | Arm64 | I386 | X86_64 => vec!["MACOSX_DEPLOYMENT_TARGET".to_string()],
-        X86_64_macabi => vec!["IPHONEOS_DEPLOYMENT_TARGET".to_string()],
-    }
-}
-
-pub fn opts(arch: Arch) -> Result<TargetOptions, String> {
-    let pre_link_args = build_pre_link_args(arch)?;
-    Ok(TargetOptions {
-        cpu: target_cpu(arch),
-        dynamic_linking: false,
-        executables: true,
-        pre_link_args,
-        link_env_remove: link_env_remove(arch),
-        has_elf_tls: false,
-        eliminate_frame_pointer: false,
-        ..super::apple_base::opts()
-    })
-}
diff --git a/src/librustc_target/spec/apple_sdk_base.rs b/src/librustc_target/spec/apple_sdk_base.rs
new file mode 100644 (file)
index 0000000..5137543
--- /dev/null
@@ -0,0 +1,166 @@
+use crate::spec::{LinkArgs, LinkerFlavor, TargetOptions};
+use std::env;
+use std::io;
+use std::path::Path;
+use std::process::Command;
+
+use Arch::*;
+#[allow(non_camel_case_types)]
+#[derive(Copy, Clone)]
+pub enum Arch {
+    Armv7,
+    Armv7s,
+    Arm64,
+    I386,
+    X86_64,
+    X86_64_macabi,
+}
+
+#[allow(non_camel_case_types)]
+#[derive(Copy, Clone)]
+pub enum AppleOS {
+    tvOS,
+    iOS,
+}
+
+impl Arch {
+    pub fn to_string(self) -> &'static str {
+        match self {
+            Armv7 => "armv7",
+            Armv7s => "armv7s",
+            Arm64 => "arm64",
+            I386 => "i386",
+            X86_64 => "x86_64",
+            X86_64_macabi => "x86_64",
+        }
+    }
+}
+
+pub fn get_sdk_root(sdk_name: &str) -> Result<String, String> {
+    // Following what clang does
+    // (https://github.com/llvm/llvm-project/blob/
+    // 296a80102a9b72c3eda80558fb78a3ed8849b341/clang/lib/Driver/ToolChains/Darwin.cpp#L1661-L1678)
+    // to allow the SDK path to be set. (For clang, xcrun sets
+    // SDKROOT; for rustc, the user or build system can set it, or we
+    // can fall back to checking for xcrun on PATH.)
+    if let Some(sdkroot) = env::var("SDKROOT").ok() {
+        let p = Path::new(&sdkroot);
+        match sdk_name {
+            // Ignore `SDKROOT` if it's clearly set for the wrong platform.
+            "appletvos"
+                if sdkroot.contains("TVSimulator.platform")
+                    || sdkroot.contains("MacOSX.platform") =>
+            {
+                ()
+            }
+            "appletvsimulator"
+                if sdkroot.contains("TVOS.platform") || sdkroot.contains("MacOSX.platform") =>
+            {
+                ()
+            }
+            "iphoneos"
+                if sdkroot.contains("iPhoneSimulator.platform")
+                    || sdkroot.contains("MacOSX.platform") =>
+            {
+                ()
+            }
+            "iphonesimulator"
+                if sdkroot.contains("iPhoneOS.platform") || sdkroot.contains("MacOSX.platform") =>
+            {
+                ()
+            }
+            "macosx10.15"
+                if sdkroot.contains("iPhoneOS.platform")
+                    || sdkroot.contains("iPhoneSimulator.platform") =>
+            {
+                ()
+            }
+            // Ignore `SDKROOT` if it's not a valid path.
+            _ if !p.is_absolute() || p == Path::new("/") || !p.exists() => (),
+            _ => return Ok(sdkroot),
+        }
+    }
+    let res =
+        Command::new("xcrun").arg("--show-sdk-path").arg("-sdk").arg(sdk_name).output().and_then(
+            |output| {
+                if output.status.success() {
+                    Ok(String::from_utf8(output.stdout).unwrap())
+                } else {
+                    let error = String::from_utf8(output.stderr);
+                    let error = format!("process exit with error: {}", error.unwrap());
+                    Err(io::Error::new(io::ErrorKind::Other, &error[..]))
+                }
+            },
+        );
+
+    match res {
+        Ok(output) => Ok(output.trim().to_string()),
+        Err(e) => Err(format!("failed to get {} SDK path: {}", sdk_name, e)),
+    }
+}
+
+fn build_pre_link_args(arch: Arch, os: AppleOS) -> Result<LinkArgs, String> {
+    let sdk_name = match (arch, os) {
+        (Arm64, AppleOS::tvOS) => "appletvos",
+        (X86_64, AppleOS::tvOS) => "appletvsimulator",
+        (Armv7, AppleOS::iOS) => "iphoneos",
+        (Armv7s, AppleOS::iOS) => "iphoneos",
+        (Arm64, AppleOS::iOS) => "iphoneos",
+        (I386, AppleOS::iOS) => "iphonesimulator",
+        (X86_64, AppleOS::iOS) => "iphonesimulator",
+        (X86_64_macabi, AppleOS::iOS) => "macosx10.15",
+        _ => unreachable!(),
+    };
+
+    let arch_name = arch.to_string();
+
+    let sdk_root = get_sdk_root(sdk_name)?;
+
+    let mut args = LinkArgs::new();
+    args.insert(
+        LinkerFlavor::Gcc,
+        vec![
+            "-arch".to_string(),
+            arch_name.to_string(),
+            "-isysroot".to_string(),
+            sdk_root.clone(),
+            "-Wl,-syslibroot".to_string(),
+            sdk_root,
+        ],
+    );
+
+    Ok(args)
+}
+
+fn target_cpu(arch: Arch) -> String {
+    match arch {
+        Armv7 => "cortex-a8", // iOS7 is supported on iPhone 4 and higher
+        Armv7s => "cortex-a9",
+        Arm64 => "cyclone",
+        I386 => "yonah",
+        X86_64 => "core2",
+        X86_64_macabi => "core2",
+    }
+    .to_string()
+}
+
+fn link_env_remove(arch: Arch) -> Vec<String> {
+    match arch {
+        Armv7 | Armv7s | Arm64 | I386 | X86_64 => vec!["MACOSX_DEPLOYMENT_TARGET".to_string()],
+        X86_64_macabi => vec!["IPHONEOS_DEPLOYMENT_TARGET".to_string()],
+    }
+}
+
+pub fn opts(arch: Arch, os: AppleOS) -> Result<TargetOptions, String> {
+    let pre_link_args = build_pre_link_args(arch, os)?;
+    Ok(TargetOptions {
+        cpu: target_cpu(arch),
+        dynamic_linking: false,
+        executables: true,
+        pre_link_args,
+        link_env_remove: link_env_remove(arch),
+        has_elf_tls: false,
+        eliminate_frame_pointer: false,
+        ..super::apple_base::opts()
+    })
+}
index aa2d32e2d7935f6d72054d4770752f617994c2d5..c0c2ae909f8f03c9ea1662fad8b1d92cae2c955c 100644 (file)
@@ -1,8 +1,8 @@
-use super::apple_ios_base::{opts, Arch};
+use super::apple_sdk_base::{opts, AppleOS, Arch};
 use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
-    let base = opts(Arch::Armv7)?;
+    let base = opts(Arch::Armv7, AppleOS::iOS)?;
     Ok(Target {
         llvm_target: "armv7-apple-ios".to_string(),
         target_endian: "little".to_string(),
index 6514643a64dae0712f32f939b8113fb67a584216..6a5654f10d4163dce5e0962ca52235c71c50afb5 100644 (file)
@@ -1,8 +1,8 @@
-use super::apple_ios_base::{opts, Arch};
+use super::apple_sdk_base::{opts, AppleOS, Arch};
 use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
-    let base = opts(Arch::Armv7s)?;
+    let base = opts(Arch::Armv7s, AppleOS::iOS)?;
     Ok(Target {
         llvm_target: "armv7s-apple-ios".to_string(),
         target_endian: "little".to_string(),
index a6c1d24fa62a17150f01c7012a71bf23130de087..a121d49769d61096fbd3d76b7676d3fc8715b5e5 100644 (file)
@@ -1,8 +1,8 @@
-use super::apple_ios_base::{opts, Arch};
+use super::apple_sdk_base::{opts, AppleOS, Arch};
 use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
-    let base = opts(Arch::I386)?;
+    let base = opts(Arch::I386, AppleOS::iOS)?;
     Ok(Target {
         llvm_target: "i386-apple-ios".to_string(),
         target_endian: "little".to_string(),
index 345590a00be8bbfae4b8a02a19376e12df547a72..e299f92fdeb637706bcfc438c8bd69770aa96397 100644 (file)
@@ -29,7 +29,7 @@ pub fn target() -> TargetResult {
     base.abi_return_struct_as_int = true;
 
     // Use -GNU here, because of the reason below:
-    // Backgound and Problem:
+    // Background and Problem:
     //   If we use i686-unknown-windows, the LLVM IA32 MSVC generates compiler intrinsic
     //   _alldiv, _aulldiv, _allrem, _aullrem, _allmul, which will cause undefined symbol.
     //   A real issue is __aulldiv() is referred by __udivdi3() - udivmod_inner!(), from
@@ -64,7 +64,7 @@ pub fn target() -> TargetResult {
     //      i386/umoddi3.S
     // Possible solution:
     //   1. Eliminate Intrinsics generation.
-    //      1.1 Choose differnt target to bypass isTargetKnownWindowsMSVC().
+    //      1.1 Choose different target to bypass isTargetKnownWindowsMSVC().
     //      1.2 Remove the "Setup Windows compiler runtime calls" in LLVM
     //   2. Implement Intrinsics.
     //   We evaluated all options.
index 67f45d3d230ef481c6d5ffa795a6673209833560..6e5111bd7018a460db2aaf627e5801b56f3be49c 100644 (file)
@@ -47,7 +47,7 @@
 pub mod abi;
 mod android_base;
 mod apple_base;
-mod apple_ios_base;
+mod apple_sdk_base;
 mod arm_base;
 mod cloudabi_base;
 mod dragonfly_base;
@@ -434,6 +434,8 @@ fn $module() {
     ("armv7-apple-ios", armv7_apple_ios),
     ("armv7s-apple-ios", armv7s_apple_ios),
     ("x86_64-apple-ios-macabi", x86_64_apple_ios_macabi),
+    ("aarch64-apple-tvos", aarch64_apple_tvos),
+    ("x86_64-apple-tvos", x86_64_apple_tvos),
 
     ("armebv7r-none-eabi", armebv7r_none_eabi),
     ("armebv7r-none-eabihf", armebv7r_none_eabihf),
@@ -579,6 +581,12 @@ pub struct TargetOptions {
     /// user-defined but before post_link_objects. Standard platform
     /// libraries that should be always be linked to, usually go here.
     pub late_link_args: LinkArgs,
+    /// Linker arguments used in addition to `late_link_args` if at least one
+    /// Rust dependency is dynamically linked.
+    pub late_link_args_dynamic: LinkArgs,
+    /// Linker arguments used in addition to `late_link_args` if aall Rust
+    /// dependencies are statically linked.
+    pub late_link_args_static: LinkArgs,
     /// Objects to link after all others, always found within the
     /// sysroot folder.
     pub post_link_objects: Vec<String>, // ... unconditionally
@@ -692,11 +700,6 @@ pub struct TargetOptions {
     pub archive_format: String,
     /// Is asm!() allowed? Defaults to true.
     pub allow_asm: bool,
-    /// Whether the target uses a custom unwind resumption routine.
-    /// By default LLVM lowers `resume` instructions into calls to `_Unwind_Resume`
-    /// 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,
@@ -863,10 +866,11 @@ fn default() -> TargetOptions {
             post_link_objects: Vec::new(),
             post_link_objects_crt: Vec::new(),
             late_link_args: LinkArgs::new(),
+            late_link_args_dynamic: LinkArgs::new(),
+            late_link_args_static: LinkArgs::new(),
             link_env: Vec::new(),
             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,
@@ -1142,6 +1146,8 @@ macro_rules! key {
         key!(pre_link_objects_exe_crt, list);
         key!(pre_link_objects_dll, list);
         key!(late_link_args, link_args);
+        key!(late_link_args_dynamic, link_args);
+        key!(late_link_args_static, link_args);
         key!(post_link_objects, list);
         key!(post_link_objects_crt, list);
         key!(post_link_args, link_args);
@@ -1182,7 +1188,6 @@ macro_rules! key {
         key!(relro_level, RelroLevel)?;
         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);
@@ -1370,6 +1375,8 @@ macro_rules! target_option_val {
         target_option_val!(pre_link_objects_exe_crt);
         target_option_val!(pre_link_objects_dll);
         target_option_val!(link_args - late_link_args);
+        target_option_val!(link_args - late_link_args_dynamic);
+        target_option_val!(link_args - late_link_args_static);
         target_option_val!(post_link_objects);
         target_option_val!(post_link_objects_crt);
         target_option_val!(link_args - post_link_args);
@@ -1410,7 +1417,6 @@ macro_rules! target_option_val {
         target_option_val!(relro_level);
         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);
index f070a3e5da4439e0d946f107a77a9c474b8a9c4a..e0a402533e7772ef9cddc11d21d292886283fe7f 100644 (file)
@@ -23,7 +23,7 @@ pub fn target() -> TargetResult {
             // The linker can be installed from `crates.io`.
             linker: Some("rust-ptx-linker".to_string()),
 
-            // With `ptx-linker` approach, it can be later overriden via link flags.
+            // With `ptx-linker` approach, it can be later overridden via link flags.
             cpu: "sm_30".to_string(),
 
             // FIXME: create tests for the atomics.
@@ -43,7 +43,7 @@ pub fn target() -> TargetResult {
             // Let the `ptx-linker` to handle LLVM lowering into MC / assembly.
             obj_is_bitcode: true,
 
-            // Convinient and predicable naming scheme.
+            // Convenient and predicable naming scheme.
             dll_prefix: "".to_string(),
             dll_suffix: ".ptx".to_string(),
             exe_suffix: ".ptx".to_string(),
index 693a343d5a5fb209683ebbc16f845d52e54c8b30..188548b41fe75fda00784adf71f26e4f4ff2e0e8 100644 (file)
@@ -17,12 +17,13 @@ pub fn opts() -> TargetOptions {
     );
 
     let mut late_link_args = LinkArgs::new();
+    let mut late_link_args_dynamic = LinkArgs::new();
+    let mut late_link_args_static = LinkArgs::new();
     late_link_args.insert(
         LinkerFlavor::Gcc,
         vec![
             "-lmingwex".to_string(),
             "-lmingw32".to_string(),
-            "-lgcc".to_string(), // alas, mingw* libraries above depend on libgcc
             "-lmsvcrt".to_string(),
             // mingw's msvcrt is a weird hybrid import library and static library.
             // And it seems that the linker fails to use import symbols from msvcrt
@@ -37,6 +38,31 @@ pub fn opts() -> TargetOptions {
             "-lkernel32".to_string(),
         ],
     );
+    late_link_args_dynamic.insert(
+        LinkerFlavor::Gcc,
+        vec![
+            // If any of our crates are dynamically linked then we need to use
+            // the shared libgcc_s-dw2-1.dll. This is required to support
+            // unwinding across DLL boundaries.
+            "-lgcc_s".to_string(),
+            "-lgcc".to_string(),
+            "-lkernel32".to_string(),
+        ],
+    );
+    late_link_args_static.insert(
+        LinkerFlavor::Gcc,
+        vec![
+            // If all of our crates are statically linked then we can get away
+            // with statically linking the libgcc unwinding code. This allows
+            // binaries to be redistributed without the libgcc_s-dw2-1.dll
+            // dependency, but unfortunately break unwinding across DLL
+            // boundaries when unwinding across FFI boundaries.
+            "-lgcc".to_string(),
+            "-lgcc_eh".to_string(),
+            "-lpthread".to_string(),
+            "-lkernel32".to_string(),
+        ],
+    );
 
     TargetOptions {
         // FIXME(#13846) this should be enabled for windows
@@ -63,8 +89,9 @@ pub fn opts() -> TargetOptions {
             "rsbegin.o".to_string(),
         ],
         late_link_args,
+        late_link_args_dynamic,
+        late_link_args_static,
         post_link_objects: vec!["rsend.o".to_string()],
-        custom_unwind_resume: true,
         abi_return_struct_as_int: true,
         emit_debug_gdb_scripts: false,
         requires_uwtable: true,
index b19c4dd7eb18c15cb624465e0791ae7f68a68cac..3f7eb442bbc73049d6a6bf58c212c9eaaa1b26ce 100644 (file)
@@ -54,7 +54,6 @@ pub fn opts() -> TargetOptions {
         pre_link_objects_dll: vec!["rsbegin.o".to_string()],
         late_link_args,
         post_link_objects: vec!["rsend.o".to_string()],
-        custom_unwind_resume: true,
         abi_return_struct_as_int: true,
         emit_debug_gdb_scripts: false,
         requires_uwtable: true,
index ca02e2deabcf2d0cd7e690b0d995fb448860a452..cfcf856836b14e78c070c20e3ef2de3ec4ad80ca 100644 (file)
@@ -1,8 +1,8 @@
-use super::apple_ios_base::{opts, Arch};
+use super::apple_sdk_base::{opts, AppleOS, Arch};
 use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
-    let base = opts(Arch::X86_64)?;
+    let base = opts(Arch::X86_64, AppleOS::iOS)?;
     Ok(Target {
         llvm_target: "x86_64-apple-ios".to_string(),
         target_endian: "little".to_string(),
index 5f4f6ade682d8138875a2cf39a65fddd1d5370ae..c42d09117259d4b76df90aab79e0e42255248d3e 100644 (file)
@@ -1,8 +1,8 @@
-use super::apple_ios_base::{opts, Arch};
+use super::apple_sdk_base::{opts, AppleOS, Arch};
 use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
-    let base = opts(Arch::X86_64_macabi)?;
+    let base = opts(Arch::X86_64_macabi, AppleOS::iOS)?;
     Ok(Target {
         llvm_target: "x86_64-apple-ios13.0-macabi".to_string(),
         target_endian: "little".to_string(),
diff --git a/src/librustc_target/spec/x86_64_apple_tvos.rs b/src/librustc_target/spec/x86_64_apple_tvos.rs
new file mode 100644 (file)
index 0000000..a56062c
--- /dev/null
@@ -0,0 +1,19 @@
+use super::apple_sdk_base::{opts, AppleOS, Arch};
+use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
+
+pub fn target() -> TargetResult {
+    let base = opts(Arch::X86_64, AppleOS::iOS)?;
+    Ok(Target {
+        llvm_target: "x86_64-apple-tvos".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "64".to_string(),
+        target_c_int_width: "32".to_string(),
+        data_layout: "e-m:o-i64:64-f80:128-n8:16:32:64-S128".to_string(),
+        arch: "x86_64".to_string(),
+        target_os: "tvos".to_string(),
+        target_env: String::new(),
+        target_vendor: "apple".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
+        options: TargetOptions { max_atomic_width: Some(64), stack_probes: true, ..base },
+    })
+}
diff --git a/src/librustc_trait_selection/Cargo.toml b/src/librustc_trait_selection/Cargo.toml
new file mode 100644 (file)
index 0000000..5b2da41
--- /dev/null
@@ -0,0 +1,27 @@
+[package]
+authors = ["The Rust Project Developers"]
+name = "rustc_trait_selection"
+version = "0.0.0"
+edition = "2018"
+
+[lib]
+name = "rustc_trait_selection"
+path = "lib.rs"
+doctest = false
+
+[dependencies]
+fmt_macros = { path = "../libfmt_macros" }
+log = { version = "0.4", features = ["release_max_level_info", "std"] }
+rustc_attr = { path = "../librustc_attr" }
+rustc = { path = "../librustc" }
+rustc_ast = { path = "../librustc_ast" }
+rustc_data_structures = { path = "../librustc_data_structures" }
+rustc_errors = { path = "../librustc_errors" }
+rustc_hir = { path = "../librustc_hir" }
+rustc_index = { path = "../librustc_index" }
+rustc_infer = { path = "../librustc_infer" }
+rustc_macros = { path = "../librustc_macros" }
+rustc_session = { path = "../librustc_session" }
+rustc_span = { path = "../librustc_span" }
+rustc_target = { path = "../librustc_target" }
+smallvec = { version = "1.0", features = ["union", "may_dangle"] }
diff --git a/src/librustc_trait_selection/infer.rs b/src/librustc_trait_selection/infer.rs
new file mode 100644 (file)
index 0000000..7abcbf4
--- /dev/null
@@ -0,0 +1,182 @@
+use crate::traits::query::outlives_bounds::InferCtxtExt as _;
+use crate::traits::{self, TraitEngine, TraitEngineExt};
+
+use rustc::arena::ArenaAllocatable;
+use rustc::infer::canonical::{Canonical, CanonicalizedQueryResponse, QueryResponse};
+use rustc::middle::lang_items;
+use rustc::traits::query::Fallible;
+use rustc::ty::{self, Ty, TypeFoldable};
+use rustc_hir as hir;
+use rustc_infer::infer::outlives::env::OutlivesEnvironment;
+use rustc_infer::traits::ObligationCause;
+use rustc_span::{Span, DUMMY_SP};
+
+use std::fmt::Debug;
+
+pub use rustc_infer::infer::*;
+
+pub trait InferCtxtExt<'tcx> {
+    fn type_is_copy_modulo_regions(
+        &self,
+        param_env: ty::ParamEnv<'tcx>,
+        ty: Ty<'tcx>,
+        span: Span,
+    ) -> bool;
+
+    fn partially_normalize_associated_types_in<T>(
+        &self,
+        span: Span,
+        body_id: hir::HirId,
+        param_env: ty::ParamEnv<'tcx>,
+        value: &T,
+    ) -> InferOk<'tcx, T>
+    where
+        T: TypeFoldable<'tcx>;
+}
+
+impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> {
+    fn type_is_copy_modulo_regions(
+        &self,
+        param_env: ty::ParamEnv<'tcx>,
+        ty: Ty<'tcx>,
+        span: Span,
+    ) -> bool {
+        let ty = self.resolve_vars_if_possible(&ty);
+
+        if !(param_env, ty).has_local_value() {
+            return ty.is_copy_modulo_regions(self.tcx, param_env, span);
+        }
+
+        let copy_def_id = self.tcx.require_lang_item(lang_items::CopyTraitLangItem, None);
+
+        // This can get called from typeck (by euv), and `moves_by_default`
+        // rightly refuses to work with inference variables, but
+        // moves_by_default has a cache, which we want to use in other
+        // cases.
+        traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, copy_def_id, span)
+    }
+
+    /// Normalizes associated types in `value`, potentially returning
+    /// new obligations that must further be processed.
+    fn partially_normalize_associated_types_in<T>(
+        &self,
+        span: Span,
+        body_id: hir::HirId,
+        param_env: ty::ParamEnv<'tcx>,
+        value: &T,
+    ) -> InferOk<'tcx, T>
+    where
+        T: TypeFoldable<'tcx>,
+    {
+        debug!("partially_normalize_associated_types_in(value={:?})", value);
+        let mut selcx = traits::SelectionContext::new(self);
+        let cause = ObligationCause::misc(span, body_id);
+        let traits::Normalized { value, obligations } =
+            traits::normalize(&mut selcx, param_env, cause, value);
+        debug!(
+            "partially_normalize_associated_types_in: result={:?} predicates={:?}",
+            value, obligations
+        );
+        InferOk { value, obligations }
+    }
+}
+
+pub trait InferCtxtBuilderExt<'tcx> {
+    fn enter_canonical_trait_query<K, R>(
+        &mut self,
+        canonical_key: &Canonical<'tcx, K>,
+        operation: impl FnOnce(&InferCtxt<'_, 'tcx>, &mut dyn TraitEngine<'tcx>, K) -> Fallible<R>,
+    ) -> Fallible<CanonicalizedQueryResponse<'tcx, R>>
+    where
+        K: TypeFoldable<'tcx>,
+        R: Debug + TypeFoldable<'tcx>,
+        Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable;
+}
+
+impl<'tcx> InferCtxtBuilderExt<'tcx> for InferCtxtBuilder<'tcx> {
+    /// The "main method" for a canonicalized trait query. Given the
+    /// canonical key `canonical_key`, this method will create a new
+    /// inference context, instantiate the key, and run your operation
+    /// `op`. The operation should yield up a result (of type `R`) as
+    /// well as a set of trait obligations that must be fully
+    /// satisfied. These obligations will be processed and the
+    /// canonical result created.
+    ///
+    /// Returns `NoSolution` in the event of any error.
+    ///
+    /// (It might be mildly nicer to implement this on `TyCtxt`, and
+    /// not `InferCtxtBuilder`, but that is a bit tricky right now.
+    /// In part because we would need a `for<'tcx>` sort of
+    /// bound for the closure and in part because it is convenient to
+    /// have `'tcx` be free on this function so that we can talk about
+    /// `K: TypeFoldable<'tcx>`.)
+    fn enter_canonical_trait_query<K, R>(
+        &mut self,
+        canonical_key: &Canonical<'tcx, K>,
+        operation: impl FnOnce(&InferCtxt<'_, 'tcx>, &mut dyn TraitEngine<'tcx>, K) -> Fallible<R>,
+    ) -> Fallible<CanonicalizedQueryResponse<'tcx, R>>
+    where
+        K: TypeFoldable<'tcx>,
+        R: Debug + TypeFoldable<'tcx>,
+        Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable,
+    {
+        self.enter_with_canonical(
+            DUMMY_SP,
+            canonical_key,
+            |ref infcx, key, canonical_inference_vars| {
+                let mut fulfill_cx = TraitEngine::new(infcx.tcx);
+                let value = operation(infcx, &mut *fulfill_cx, key)?;
+                infcx.make_canonicalized_query_response(
+                    canonical_inference_vars,
+                    value,
+                    &mut *fulfill_cx,
+                )
+            },
+        )
+    }
+}
+
+pub trait OutlivesEnvironmentExt<'tcx> {
+    fn add_implied_bounds(
+        &mut self,
+        infcx: &InferCtxt<'a, 'tcx>,
+        fn_sig_tys: &[Ty<'tcx>],
+        body_id: hir::HirId,
+        span: Span,
+    );
+}
+
+impl<'tcx> OutlivesEnvironmentExt<'tcx> for OutlivesEnvironment<'tcx> {
+    /// This method adds "implied bounds" into the outlives environment.
+    /// Implied bounds are outlives relationships that we can deduce
+    /// on the basis that certain types must be well-formed -- these are
+    /// either the types that appear in the function signature or else
+    /// the input types to an impl. For example, if you have a function
+    /// like
+    ///
+    /// ```
+    /// fn foo<'a, 'b, T>(x: &'a &'b [T]) { }
+    /// ```
+    ///
+    /// we can assume in the caller's body that `'b: 'a` and that `T:
+    /// 'b` (and hence, transitively, that `T: 'a`). This method would
+    /// add those assumptions into the outlives-environment.
+    ///
+    /// Tests: `src/test/compile-fail/regions-free-region-ordering-*.rs`
+    fn add_implied_bounds(
+        &mut self,
+        infcx: &InferCtxt<'a, 'tcx>,
+        fn_sig_tys: &[Ty<'tcx>],
+        body_id: hir::HirId,
+        span: Span,
+    ) {
+        debug!("add_implied_bounds()");
+
+        for &ty in fn_sig_tys {
+            let ty = infcx.resolve_vars_if_possible(&ty);
+            debug!("add_implied_bounds: ty = {}", ty);
+            let implied_bounds = infcx.implied_outlives_bounds(self.param_env, body_id, ty, span);
+            self.add_outlives_bounds(Some(infcx), implied_bounds)
+        }
+    }
+}
diff --git a/src/librustc_trait_selection/lib.rs b/src/librustc_trait_selection/lib.rs
new file mode 100644 (file)
index 0000000..739aff4
--- /dev/null
@@ -0,0 +1,32 @@
+//! This crates defines the trait resolution method.
+//!
+//! - **Traits.** Trait resolution is implemented in the `traits` module.
+//!
+//! For more information about how rustc works, see the [rustc guide].
+//!
+//! [rustc guide]: https://rust-lang.github.io/rustc-guide/
+//!
+//! # Note
+//!
+//! This API is completely unstable and subject to change.
+
+#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
+#![feature(bool_to_option)]
+#![feature(drain_filter)]
+#![feature(in_band_lifetimes)]
+#![feature(crate_visibility_modifier)]
+#![recursion_limit = "512"] // For rustdoc
+
+#[macro_use]
+extern crate rustc_macros;
+#[cfg(target_arch = "x86_64")]
+#[macro_use]
+extern crate rustc_data_structures;
+#[macro_use]
+extern crate log;
+#[macro_use]
+extern crate rustc;
+
+pub mod infer;
+pub mod opaque_types;
+pub mod traits;
diff --git a/src/librustc_trait_selection/opaque_types.rs b/src/librustc_trait_selection/opaque_types.rs
new file mode 100644 (file)
index 0000000..785d8b8
--- /dev/null
@@ -0,0 +1,1299 @@
+use crate::infer::InferCtxtExt as _;
+use crate::traits::{self, PredicateObligation};
+use rustc::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder, TypeVisitor};
+use rustc::ty::free_region_map::FreeRegionRelations;
+use rustc::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef};
+use rustc::ty::{self, GenericParamDefKind, Ty, TyCtxt};
+use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::sync::Lrc;
+use rustc_hir as hir;
+use rustc_hir::def_id::{DefId, DefIdMap};
+use rustc_hir::Node;
+use rustc_infer::infer::error_reporting::unexpected_hidden_region_diagnostic;
+use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use rustc_infer::infer::{self, InferCtxt, InferOk};
+use rustc_session::config::nightly_options;
+use rustc_span::Span;
+
+pub type OpaqueTypeMap<'tcx> = DefIdMap<OpaqueTypeDecl<'tcx>>;
+
+/// Information about the opaque types whose values we
+/// are inferring in this function (these are the `impl Trait` that
+/// appear in the return type).
+#[derive(Copy, Clone, Debug)]
+pub struct OpaqueTypeDecl<'tcx> {
+    /// The opaque type (`ty::Opaque`) for this declaration.
+    pub opaque_type: Ty<'tcx>,
+
+    /// The substitutions that we apply to the opaque type that this
+    /// `impl Trait` desugars to. e.g., if:
+    ///
+    ///     fn foo<'a, 'b, T>() -> impl Trait<'a>
+    ///
+    /// winds up desugared to:
+    ///
+    ///     type Foo<'x, X> = impl Trait<'x>
+    ///     fn foo<'a, 'b, T>() -> Foo<'a, T>
+    ///
+    /// then `substs` would be `['a, T]`.
+    pub substs: SubstsRef<'tcx>,
+
+    /// The span of this particular definition of the opaque type.  So
+    /// for example:
+    ///
+    /// ```
+    /// type Foo = impl Baz;
+    /// fn bar() -> Foo {
+    ///             ^^^ This is the span we are looking for!
+    /// ```
+    ///
+    /// In cases where the fn returns `(impl Trait, impl Trait)` or
+    /// other such combinations, the result is currently
+    /// over-approximated, but better than nothing.
+    pub definition_span: Span,
+
+    /// The type variable that represents the value of the opaque type
+    /// that we require. In other words, after we compile this function,
+    /// we will be created a constraint like:
+    ///
+    ///     Foo<'a, T> = ?C
+    ///
+    /// where `?C` is the value of this type variable. =) It may
+    /// naturally refer to the type and lifetime parameters in scope
+    /// in this function, though ultimately it should only reference
+    /// those that are arguments to `Foo` in the constraint above. (In
+    /// other words, `?C` should not include `'b`, even though it's a
+    /// lifetime parameter on `foo`.)
+    pub concrete_ty: Ty<'tcx>,
+
+    /// Returns `true` if the `impl Trait` bounds include region bounds.
+    /// For example, this would be true for:
+    ///
+    ///     fn foo<'a, 'b, 'c>() -> impl Trait<'c> + 'a + 'b
+    ///
+    /// but false for:
+    ///
+    ///     fn foo<'c>() -> impl Trait<'c>
+    ///
+    /// unless `Trait` was declared like:
+    ///
+    ///     trait Trait<'c>: 'c
+    ///
+    /// in which case it would be true.
+    ///
+    /// This is used during regionck to decide whether we need to
+    /// impose any additional constraints to ensure that region
+    /// variables in `concrete_ty` wind up being constrained to
+    /// something from `substs` (or, at minimum, things that outlive
+    /// the fn body). (Ultimately, writeback is responsible for this
+    /// check.)
+    pub has_required_region_bounds: bool,
+
+    /// The origin of the opaque type.
+    pub origin: hir::OpaqueTyOrigin,
+}
+
+/// Whether member constraints should be generated for all opaque types
+pub enum GenerateMemberConstraints {
+    /// The default, used by typeck
+    WhenRequired,
+    /// The borrow checker needs member constraints in any case where we don't
+    /// have a `'static` bound. This is because the borrow checker has more
+    /// flexibility in the values of regions. For example, given `f<'a, 'b>`
+    /// the borrow checker can have an inference variable outlive `'a` and `'b`,
+    /// but not be equal to `'static`.
+    IfNoStaticBound,
+}
+
+pub trait InferCtxtExt<'tcx> {
+    fn instantiate_opaque_types<T: TypeFoldable<'tcx>>(
+        &self,
+        parent_def_id: DefId,
+        body_id: hir::HirId,
+        param_env: ty::ParamEnv<'tcx>,
+        value: &T,
+        value_span: Span,
+    ) -> InferOk<'tcx, (T, OpaqueTypeMap<'tcx>)>;
+
+    fn constrain_opaque_types<FRR: FreeRegionRelations<'tcx>>(
+        &self,
+        opaque_types: &OpaqueTypeMap<'tcx>,
+        free_region_relations: &FRR,
+    );
+
+    fn constrain_opaque_type<FRR: FreeRegionRelations<'tcx>>(
+        &self,
+        def_id: DefId,
+        opaque_defn: &OpaqueTypeDecl<'tcx>,
+        mode: GenerateMemberConstraints,
+        free_region_relations: &FRR,
+    );
+
+    /*private*/
+    fn generate_member_constraint(
+        &self,
+        concrete_ty: Ty<'tcx>,
+        opaque_type_generics: &ty::Generics,
+        opaque_defn: &OpaqueTypeDecl<'tcx>,
+        opaque_type_def_id: DefId,
+    );
+
+    /*private*/
+    fn member_constraint_feature_gate(
+        &self,
+        opaque_defn: &OpaqueTypeDecl<'tcx>,
+        opaque_type_def_id: DefId,
+        conflict1: ty::Region<'tcx>,
+        conflict2: ty::Region<'tcx>,
+    ) -> bool;
+
+    fn infer_opaque_definition_from_instantiation(
+        &self,
+        def_id: DefId,
+        substs: SubstsRef<'tcx>,
+        instantiated_ty: Ty<'tcx>,
+        span: Span,
+    ) -> Ty<'tcx>;
+}
+
+impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
+    /// Replaces all opaque types in `value` with fresh inference variables
+    /// and creates appropriate obligations. For example, given the input:
+    ///
+    ///     impl Iterator<Item = impl Debug>
+    ///
+    /// this method would create two type variables, `?0` and `?1`. It would
+    /// return the type `?0` but also the obligations:
+    ///
+    ///     ?0: Iterator<Item = ?1>
+    ///     ?1: Debug
+    ///
+    /// Moreover, it returns a `OpaqueTypeMap` that would map `?0` to
+    /// info about the `impl Iterator<..>` type and `?1` to info about
+    /// the `impl Debug` type.
+    ///
+    /// # Parameters
+    ///
+    /// - `parent_def_id` -- the `DefId` of the function in which the opaque type
+    ///   is defined
+    /// - `body_id` -- the body-id with which the resulting obligations should
+    ///   be associated
+    /// - `param_env` -- the in-scope parameter environment to be used for
+    ///   obligations
+    /// - `value` -- the value within which we are instantiating opaque types
+    /// - `value_span` -- the span where the value came from, used in error reporting
+    fn instantiate_opaque_types<T: TypeFoldable<'tcx>>(
+        &self,
+        parent_def_id: DefId,
+        body_id: hir::HirId,
+        param_env: ty::ParamEnv<'tcx>,
+        value: &T,
+        value_span: Span,
+    ) -> InferOk<'tcx, (T, OpaqueTypeMap<'tcx>)> {
+        debug!(
+            "instantiate_opaque_types(value={:?}, parent_def_id={:?}, body_id={:?}, \
+             param_env={:?}, value_span={:?})",
+            value, parent_def_id, body_id, param_env, value_span,
+        );
+        let mut instantiator = Instantiator {
+            infcx: self,
+            parent_def_id,
+            body_id,
+            param_env,
+            value_span,
+            opaque_types: Default::default(),
+            obligations: vec![],
+        };
+        let value = instantiator.instantiate_opaque_types_in_map(value);
+        InferOk { value: (value, instantiator.opaque_types), obligations: instantiator.obligations }
+    }
+
+    /// Given the map `opaque_types` containing the opaque
+    /// `impl Trait` types whose underlying, hidden types are being
+    /// inferred, this method adds constraints to the regions
+    /// appearing in those underlying hidden types to ensure that they
+    /// at least do not refer to random scopes within the current
+    /// function. These constraints are not (quite) sufficient to
+    /// guarantee that the regions are actually legal values; that
+    /// final condition is imposed after region inference is done.
+    ///
+    /// # The Problem
+    ///
+    /// Let's work through an example to explain how it works. Assume
+    /// the current function is as follows:
+    ///
+    /// ```text
+    /// fn foo<'a, 'b>(..) -> (impl Bar<'a>, impl Bar<'b>)
+    /// ```
+    ///
+    /// Here, we have two `impl Trait` types whose values are being
+    /// inferred (the `impl Bar<'a>` and the `impl
+    /// Bar<'b>`). Conceptually, this is sugar for a setup where we
+    /// define underlying opaque types (`Foo1`, `Foo2`) and then, in
+    /// the return type of `foo`, we *reference* those definitions:
+    ///
+    /// ```text
+    /// type Foo1<'x> = impl Bar<'x>;
+    /// type Foo2<'x> = impl Bar<'x>;
+    /// fn foo<'a, 'b>(..) -> (Foo1<'a>, Foo2<'b>) { .. }
+    ///                    //  ^^^^ ^^
+    ///                    //  |    |
+    ///                    //  |    substs
+    ///                    //  def_id
+    /// ```
+    ///
+    /// As indicating in the comments above, each of those references
+    /// is (in the compiler) basically a substitution (`substs`)
+    /// applied to the type of a suitable `def_id` (which identifies
+    /// `Foo1` or `Foo2`).
+    ///
+    /// Now, at this point in compilation, what we have done is to
+    /// replace each of the references (`Foo1<'a>`, `Foo2<'b>`) with
+    /// fresh inference variables C1 and C2. We wish to use the values
+    /// of these variables to infer the underlying types of `Foo1` and
+    /// `Foo2`. That is, this gives rise to higher-order (pattern) unification
+    /// constraints like:
+    ///
+    /// ```text
+    /// for<'a> (Foo1<'a> = C1)
+    /// for<'b> (Foo1<'b> = C2)
+    /// ```
+    ///
+    /// For these equation to be satisfiable, the types `C1` and `C2`
+    /// can only refer to a limited set of regions. For example, `C1`
+    /// can only refer to `'static` and `'a`, and `C2` can only refer
+    /// to `'static` and `'b`. The job of this function is to impose that
+    /// constraint.
+    ///
+    /// Up to this point, C1 and C2 are basically just random type
+    /// inference variables, and hence they may contain arbitrary
+    /// regions. In fact, it is fairly likely that they do! Consider
+    /// this possible definition of `foo`:
+    ///
+    /// ```text
+    /// fn foo<'a, 'b>(x: &'a i32, y: &'b i32) -> (impl Bar<'a>, impl Bar<'b>) {
+    ///         (&*x, &*y)
+    ///     }
+    /// ```
+    ///
+    /// Here, the values for the concrete types of the two impl
+    /// traits will include inference variables:
+    ///
+    /// ```text
+    /// &'0 i32
+    /// &'1 i32
+    /// ```
+    ///
+    /// Ordinarily, the subtyping rules would ensure that these are
+    /// sufficiently large. But since `impl Bar<'a>` isn't a specific
+    /// type per se, we don't get such constraints by default. This
+    /// is where this function comes into play. It adds extra
+    /// constraints to ensure that all the regions which appear in the
+    /// inferred type are regions that could validly appear.
+    ///
+    /// This is actually a bit of a tricky constraint in general. We
+    /// want to say that each variable (e.g., `'0`) can only take on
+    /// values that were supplied as arguments to the opaque type
+    /// (e.g., `'a` for `Foo1<'a>`) or `'static`, which is always in
+    /// scope. We don't have a constraint quite of this kind in the current
+    /// region checker.
+    ///
+    /// # The Solution
+    ///
+    /// We generally prefer to make `<=` constraints, since they
+    /// integrate best into the region solver. To do that, we find the
+    /// "minimum" of all the arguments that appear in the substs: that
+    /// is, some region which is less than all the others. In the case
+    /// of `Foo1<'a>`, that would be `'a` (it's the only choice, after
+    /// all). Then we apply that as a least bound to the variables
+    /// (e.g., `'a <= '0`).
+    ///
+    /// In some cases, there is no minimum. Consider this example:
+    ///
+    /// ```text
+    /// fn baz<'a, 'b>() -> impl Trait<'a, 'b> { ... }
+    /// ```
+    ///
+    /// Here we would report a more complex "in constraint", like `'r
+    /// in ['a, 'b, 'static]` (where `'r` is some region appearing in
+    /// the hidden type).
+    ///
+    /// # Constrain regions, not the hidden concrete type
+    ///
+    /// Note that generating constraints on each region `Rc` is *not*
+    /// the same as generating an outlives constraint on `Tc` iself.
+    /// For example, if we had a function like this:
+    ///
+    /// ```rust
+    /// fn foo<'a, T>(x: &'a u32, y: T) -> impl Foo<'a> {
+    ///   (x, y)
+    /// }
+    ///
+    /// // Equivalent to:
+    /// type FooReturn<'a, T> = impl Foo<'a>;
+    /// fn foo<'a, T>(..) -> FooReturn<'a, T> { .. }
+    /// ```
+    ///
+    /// then the hidden type `Tc` would be `(&'0 u32, T)` (where `'0`
+    /// is an inference variable). If we generated a constraint that
+    /// `Tc: 'a`, then this would incorrectly require that `T: 'a` --
+    /// but this is not necessary, because the opaque type we
+    /// create will be allowed to reference `T`. So we only generate a
+    /// constraint that `'0: 'a`.
+    ///
+    /// # The `free_region_relations` parameter
+    ///
+    /// The `free_region_relations` argument is used to find the
+    /// "minimum" of the regions supplied to a given opaque type.
+    /// It must be a relation that can answer whether `'a <= 'b`,
+    /// where `'a` and `'b` are regions that appear in the "substs"
+    /// for the opaque type references (the `<'a>` in `Foo1<'a>`).
+    ///
+    /// Note that we do not impose the constraints based on the
+    /// generic regions from the `Foo1` definition (e.g., `'x`). This
+    /// is because the constraints we are imposing here is basically
+    /// the concern of the one generating the constraining type C1,
+    /// which is the current function. It also means that we can
+    /// take "implied bounds" into account in some cases:
+    ///
+    /// ```text
+    /// trait SomeTrait<'a, 'b> { }
+    /// fn foo<'a, 'b>(_: &'a &'b u32) -> impl SomeTrait<'a, 'b> { .. }
+    /// ```
+    ///
+    /// Here, the fact that `'b: 'a` is known only because of the
+    /// implied bounds from the `&'a &'b u32` parameter, and is not
+    /// "inherent" to the opaque type definition.
+    ///
+    /// # Parameters
+    ///
+    /// - `opaque_types` -- the map produced by `instantiate_opaque_types`
+    /// - `free_region_relations` -- something that can be used to relate
+    ///   the free regions (`'a`) that appear in the impl trait.
+    fn constrain_opaque_types<FRR: FreeRegionRelations<'tcx>>(
+        &self,
+        opaque_types: &OpaqueTypeMap<'tcx>,
+        free_region_relations: &FRR,
+    ) {
+        debug!("constrain_opaque_types()");
+
+        for (&def_id, opaque_defn) in opaque_types {
+            self.constrain_opaque_type(
+                def_id,
+                opaque_defn,
+                GenerateMemberConstraints::WhenRequired,
+                free_region_relations,
+            );
+        }
+    }
+
+    /// See `constrain_opaque_types` for documentation.
+    fn constrain_opaque_type<FRR: FreeRegionRelations<'tcx>>(
+        &self,
+        def_id: DefId,
+        opaque_defn: &OpaqueTypeDecl<'tcx>,
+        mode: GenerateMemberConstraints,
+        free_region_relations: &FRR,
+    ) {
+        debug!("constrain_opaque_type()");
+        debug!("constrain_opaque_type: def_id={:?}", def_id);
+        debug!("constrain_opaque_type: opaque_defn={:#?}", opaque_defn);
+
+        let tcx = self.tcx;
+
+        let concrete_ty = self.resolve_vars_if_possible(&opaque_defn.concrete_ty);
+
+        debug!("constrain_opaque_type: concrete_ty={:?}", concrete_ty);
+
+        let opaque_type_generics = tcx.generics_of(def_id);
+
+        let span = tcx.def_span(def_id);
+
+        // If there are required region bounds, we can use them.
+        if opaque_defn.has_required_region_bounds {
+            let predicates_of = tcx.predicates_of(def_id);
+            debug!("constrain_opaque_type: predicates: {:#?}", predicates_of,);
+            let bounds = predicates_of.instantiate(tcx, opaque_defn.substs);
+            debug!("constrain_opaque_type: bounds={:#?}", bounds);
+            let opaque_type = tcx.mk_opaque(def_id, opaque_defn.substs);
+
+            let required_region_bounds =
+                required_region_bounds(tcx, opaque_type, bounds.predicates);
+            debug_assert!(!required_region_bounds.is_empty());
+
+            for required_region in required_region_bounds {
+                concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor {
+                    tcx: self.tcx,
+                    op: |r| self.sub_regions(infer::CallReturn(span), required_region, r),
+                });
+            }
+            if let GenerateMemberConstraints::IfNoStaticBound = mode {
+                self.generate_member_constraint(
+                    concrete_ty,
+                    opaque_type_generics,
+                    opaque_defn,
+                    def_id,
+                );
+            }
+            return;
+        }
+
+        // There were no `required_region_bounds`,
+        // so we have to search for a `least_region`.
+        // Go through all the regions used as arguments to the
+        // opaque type. These are the parameters to the opaque
+        // type; so in our example above, `substs` would contain
+        // `['a]` for the first impl trait and `'b` for the
+        // second.
+        let mut least_region = None;
+        for param in &opaque_type_generics.params {
+            match param.kind {
+                GenericParamDefKind::Lifetime => {}
+                _ => continue,
+            }
+
+            // Get the value supplied for this region from the substs.
+            let subst_arg = opaque_defn.substs.region_at(param.index as usize);
+
+            // Compute the least upper bound of it with the other regions.
+            debug!("constrain_opaque_types: least_region={:?}", least_region);
+            debug!("constrain_opaque_types: subst_arg={:?}", subst_arg);
+            match least_region {
+                None => least_region = Some(subst_arg),
+                Some(lr) => {
+                    if free_region_relations.sub_free_regions(self.tcx, lr, subst_arg) {
+                        // keep the current least region
+                    } else if free_region_relations.sub_free_regions(self.tcx, subst_arg, lr) {
+                        // switch to `subst_arg`
+                        least_region = Some(subst_arg);
+                    } else {
+                        // There are two regions (`lr` and
+                        // `subst_arg`) which are not relatable. We
+                        // can't find a best choice. Therefore,
+                        // instead of creating a single bound like
+                        // `'r: 'a` (which is our preferred choice),
+                        // we will create a "in bound" like `'r in
+                        // ['a, 'b, 'c]`, where `'a..'c` are the
+                        // regions that appear in the impl trait.
+
+                        // For now, enforce a feature gate outside of async functions.
+                        self.member_constraint_feature_gate(opaque_defn, def_id, lr, subst_arg);
+
+                        return self.generate_member_constraint(
+                            concrete_ty,
+                            opaque_type_generics,
+                            opaque_defn,
+                            def_id,
+                        );
+                    }
+                }
+            }
+        }
+
+        let least_region = least_region.unwrap_or(tcx.lifetimes.re_static);
+        debug!("constrain_opaque_types: least_region={:?}", least_region);
+
+        if let GenerateMemberConstraints::IfNoStaticBound = mode {
+            if least_region != tcx.lifetimes.re_static {
+                self.generate_member_constraint(
+                    concrete_ty,
+                    opaque_type_generics,
+                    opaque_defn,
+                    def_id,
+                );
+            }
+        }
+        concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor {
+            tcx: self.tcx,
+            op: |r| self.sub_regions(infer::CallReturn(span), least_region, r),
+        });
+    }
+
+    /// As a fallback, we sometimes generate an "in constraint". For
+    /// a case like `impl Foo<'a, 'b>`, where `'a` and `'b` cannot be
+    /// related, we would generate a constraint `'r in ['a, 'b,
+    /// 'static]` for each region `'r` that appears in the hidden type
+    /// (i.e., it must be equal to `'a`, `'b`, or `'static`).
+    ///
+    /// `conflict1` and `conflict2` are the two region bounds that we
+    /// detected which were unrelated. They are used for diagnostics.
+    fn generate_member_constraint(
+        &self,
+        concrete_ty: Ty<'tcx>,
+        opaque_type_generics: &ty::Generics,
+        opaque_defn: &OpaqueTypeDecl<'tcx>,
+        opaque_type_def_id: DefId,
+    ) {
+        // Create the set of choice regions: each region in the hidden
+        // type can be equal to any of the region parameters of the
+        // opaque type definition.
+        let choice_regions: Lrc<Vec<ty::Region<'tcx>>> = Lrc::new(
+            opaque_type_generics
+                .params
+                .iter()
+                .filter(|param| match param.kind {
+                    GenericParamDefKind::Lifetime => true,
+                    GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => false,
+                })
+                .map(|param| opaque_defn.substs.region_at(param.index as usize))
+                .chain(std::iter::once(self.tcx.lifetimes.re_static))
+                .collect(),
+        );
+
+        concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor {
+            tcx: self.tcx,
+            op: |r| {
+                self.member_constraint(
+                    opaque_type_def_id,
+                    opaque_defn.definition_span,
+                    concrete_ty,
+                    r,
+                    &choice_regions,
+                )
+            },
+        });
+    }
+
+    /// Member constraints are presently feature-gated except for
+    /// async-await. We expect to lift this once we've had a bit more
+    /// time.
+    fn member_constraint_feature_gate(
+        &self,
+        opaque_defn: &OpaqueTypeDecl<'tcx>,
+        opaque_type_def_id: DefId,
+        conflict1: ty::Region<'tcx>,
+        conflict2: ty::Region<'tcx>,
+    ) -> bool {
+        // If we have `#![feature(member_constraints)]`, no problems.
+        if self.tcx.features().member_constraints {
+            return false;
+        }
+
+        let span = self.tcx.def_span(opaque_type_def_id);
+
+        // Without a feature-gate, we only generate member-constraints for async-await.
+        let context_name = match opaque_defn.origin {
+            // No feature-gate required for `async fn`.
+            hir::OpaqueTyOrigin::AsyncFn => return false,
+
+            // Otherwise, generate the label we'll use in the error message.
+            hir::OpaqueTyOrigin::TypeAlias
+            | hir::OpaqueTyOrigin::FnReturn
+            | hir::OpaqueTyOrigin::Misc => "impl Trait",
+        };
+        let msg = format!("ambiguous lifetime bound in `{}`", context_name);
+        let mut err = self.tcx.sess.struct_span_err(span, &msg);
+
+        let conflict1_name = conflict1.to_string();
+        let conflict2_name = conflict2.to_string();
+        let label_owned;
+        let label = match (&*conflict1_name, &*conflict2_name) {
+            ("'_", "'_") => "the elided lifetimes here do not outlive one another",
+            _ => {
+                label_owned = format!(
+                    "neither `{}` nor `{}` outlives the other",
+                    conflict1_name, conflict2_name,
+                );
+                &label_owned
+            }
+        };
+        err.span_label(span, label);
+
+        if nightly_options::is_nightly_build() {
+            err.help("add #![feature(member_constraints)] to the crate attributes to enable");
+        }
+
+        err.emit();
+        true
+    }
+
+    /// Given the fully resolved, instantiated type for an opaque
+    /// type, i.e., the value of an inference variable like C1 or C2
+    /// (*), computes the "definition type" for an opaque type
+    /// definition -- that is, the inferred value of `Foo1<'x>` or
+    /// `Foo2<'x>` that we would conceptually use in its definition:
+    ///
+    ///     type Foo1<'x> = impl Bar<'x> = AAA; <-- this type AAA
+    ///     type Foo2<'x> = impl Bar<'x> = BBB; <-- or this type BBB
+    ///     fn foo<'a, 'b>(..) -> (Foo1<'a>, Foo2<'b>) { .. }
+    ///
+    /// Note that these values are defined in terms of a distinct set of
+    /// generic parameters (`'x` instead of `'a`) from C1 or C2. The main
+    /// purpose of this function is to do that translation.
+    ///
+    /// (*) C1 and C2 were introduced in the comments on
+    /// `constrain_opaque_types`. Read that comment for more context.
+    ///
+    /// # Parameters
+    ///
+    /// - `def_id`, the `impl Trait` type
+    /// - `substs`, the substs  used to instantiate this opaque type
+    /// - `instantiated_ty`, the inferred type C1 -- fully resolved, lifted version of
+    ///   `opaque_defn.concrete_ty`
+    fn infer_opaque_definition_from_instantiation(
+        &self,
+        def_id: DefId,
+        substs: SubstsRef<'tcx>,
+        instantiated_ty: Ty<'tcx>,
+        span: Span,
+    ) -> Ty<'tcx> {
+        debug!(
+            "infer_opaque_definition_from_instantiation(def_id={:?}, instantiated_ty={:?})",
+            def_id, instantiated_ty
+        );
+
+        // Use substs to build up a reverse map from regions to their
+        // identity mappings. This is necessary because of `impl
+        // Trait` lifetimes are computed by replacing existing
+        // lifetimes with 'static and remapping only those used in the
+        // `impl Trait` return type, resulting in the parameters
+        // shifting.
+        let id_substs = InternalSubsts::identity_for_item(self.tcx, def_id);
+        let map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>> =
+            substs.iter().enumerate().map(|(index, subst)| (*subst, id_substs[index])).collect();
+
+        // Convert the type from the function into a type valid outside
+        // the function, by replacing invalid regions with 'static,
+        // after producing an error for each of them.
+        let definition_ty = instantiated_ty.fold_with(&mut ReverseMapper::new(
+            self.tcx,
+            self.is_tainted_by_errors(),
+            def_id,
+            map,
+            instantiated_ty,
+            span,
+        ));
+        debug!("infer_opaque_definition_from_instantiation: definition_ty={:?}", definition_ty);
+
+        definition_ty
+    }
+}
+
+// Visitor that requires that (almost) all regions in the type visited outlive
+// `least_region`. We cannot use `push_outlives_components` because regions in
+// closure signatures are not included in their outlives components. We need to
+// ensure all regions outlive the given bound so that we don't end up with,
+// say, `ReScope` appearing in a return type and causing ICEs when other
+// functions end up with region constraints involving regions from other
+// functions.
+//
+// We also cannot use `for_each_free_region` because for closures it includes
+// the regions parameters from the enclosing item.
+//
+// We ignore any type parameters because impl trait values are assumed to
+// capture all the in-scope type parameters.
+struct ConstrainOpaqueTypeRegionVisitor<'tcx, OP>
+where
+    OP: FnMut(ty::Region<'tcx>),
+{
+    tcx: TyCtxt<'tcx>,
+    op: OP,
+}
+
+impl<'tcx, OP> TypeVisitor<'tcx> for ConstrainOpaqueTypeRegionVisitor<'tcx, OP>
+where
+    OP: FnMut(ty::Region<'tcx>),
+{
+    fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &ty::Binder<T>) -> bool {
+        t.skip_binder().visit_with(self);
+        false // keep visiting
+    }
+
+    fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
+        match *r {
+            // ignore bound regions, keep visiting
+            ty::ReLateBound(_, _) => false,
+            _ => {
+                (self.op)(r);
+                false
+            }
+        }
+    }
+
+    fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
+        // We're only interested in types involving regions
+        if !ty.flags.intersects(ty::TypeFlags::HAS_FREE_REGIONS) {
+            return false; // keep visiting
+        }
+
+        match ty.kind {
+            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) {
+                    upvar_ty.visit_with(self);
+                }
+
+                substs.as_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) {
+                    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.as_generator().resume_ty(def_id, self.tcx).visit_with(self);
+            }
+            _ => {
+                ty.super_visit_with(self);
+            }
+        }
+
+        false
+    }
+}
+
+struct ReverseMapper<'tcx> {
+    tcx: TyCtxt<'tcx>,
+
+    /// If errors have already been reported in this fn, we suppress
+    /// our own errors because they are sometimes derivative.
+    tainted_by_errors: bool,
+
+    opaque_type_def_id: DefId,
+    map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>>,
+    map_missing_regions_to_empty: bool,
+
+    /// initially `Some`, set to `None` once error has been reported
+    hidden_ty: Option<Ty<'tcx>>,
+
+    /// Span of function being checked.
+    span: Span,
+}
+
+impl ReverseMapper<'tcx> {
+    fn new(
+        tcx: TyCtxt<'tcx>,
+        tainted_by_errors: bool,
+        opaque_type_def_id: DefId,
+        map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>>,
+        hidden_ty: Ty<'tcx>,
+        span: Span,
+    ) -> Self {
+        Self {
+            tcx,
+            tainted_by_errors,
+            opaque_type_def_id,
+            map,
+            map_missing_regions_to_empty: false,
+            hidden_ty: Some(hidden_ty),
+            span,
+        }
+    }
+
+    fn fold_kind_mapping_missing_regions_to_empty(
+        &mut self,
+        kind: GenericArg<'tcx>,
+    ) -> GenericArg<'tcx> {
+        assert!(!self.map_missing_regions_to_empty);
+        self.map_missing_regions_to_empty = true;
+        let kind = kind.fold_with(self);
+        self.map_missing_regions_to_empty = false;
+        kind
+    }
+
+    fn fold_kind_normally(&mut self, kind: GenericArg<'tcx>) -> GenericArg<'tcx> {
+        assert!(!self.map_missing_regions_to_empty);
+        kind.fold_with(self)
+    }
+}
+
+impl TypeFolder<'tcx> for ReverseMapper<'tcx> {
+    fn tcx(&self) -> TyCtxt<'tcx> {
+        self.tcx
+    }
+
+    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
+        match r {
+            // Ignore bound regions and `'static` regions that appear in the
+            // type, we only need to remap regions that reference lifetimes
+            // from the function declaraion.
+            // This would ignore `'r` in a type like `for<'r> fn(&'r u32)`.
+            ty::ReLateBound(..) | ty::ReStatic => return r,
+
+            // If regions have been erased (by writeback), don't try to unerase
+            // them.
+            ty::ReErased => return r,
+
+            // The regions that we expect from borrow checking.
+            ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReEmpty(ty::UniverseIndex::ROOT) => {}
+
+            ty::ReEmpty(_)
+            | ty::RePlaceholder(_)
+            | ty::ReVar(_)
+            | ty::ReScope(_)
+            | ty::ReClosureBound(_) => {
+                // All of the regions in the type should either have been
+                // erased by writeback, or mapped back to named regions by
+                // borrow checking.
+                bug!("unexpected region kind in opaque type: {:?}", r);
+            }
+        }
+
+        let generics = self.tcx().generics_of(self.opaque_type_def_id);
+        match self.map.get(&r.into()).map(|k| k.unpack()) {
+            Some(GenericArgKind::Lifetime(r1)) => r1,
+            Some(u) => panic!("region mapped to unexpected kind: {:?}", u),
+            None if self.map_missing_regions_to_empty || self.tainted_by_errors => {
+                self.tcx.lifetimes.re_root_empty
+            }
+            None if generics.parent.is_some() => {
+                if let Some(hidden_ty) = self.hidden_ty.take() {
+                    unexpected_hidden_region_diagnostic(
+                        self.tcx,
+                        None,
+                        self.tcx.def_span(self.opaque_type_def_id),
+                        hidden_ty,
+                        r,
+                    )
+                    .emit();
+                }
+                self.tcx.lifetimes.re_root_empty
+            }
+            None => {
+                self.tcx
+                    .sess
+                    .struct_span_err(self.span, "non-defining opaque type use in defining scope")
+                    .span_label(
+                        self.span,
+                        format!(
+                            "lifetime `{}` is part of concrete type but not used in \
+                                 parameter list of the `impl Trait` type alias",
+                            r
+                        ),
+                    )
+                    .emit();
+
+                self.tcx().lifetimes.re_static
+            }
+        }
+    }
+
+    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
+        match ty.kind {
+            ty::Closure(def_id, substs) => {
+                // I am a horrible monster and I pray for death. When
+                // we encounter a closure here, it is always a closure
+                // from within the function that we are currently
+                // type-checking -- one that is now being encapsulated
+                // in an opaque type. Ideally, we would
+                // go through the types/lifetimes that it references
+                // and treat them just like we would any other type,
+                // which means we would error out if we find any
+                // reference to a type/region that is not in the
+                // "reverse map".
+                //
+                // **However,** in the case of closures, there is a
+                // somewhat subtle (read: hacky) consideration. The
+                // problem is that our closure types currently include
+                // all the lifetime parameters declared on the
+                // enclosing function, even if they are unused by the
+                // closure itself. We can't readily filter them out,
+                // so here we replace those values with `'empty`. This
+                // can't really make a difference to the rest of the
+                // compiler; those regions are ignored for the
+                // outlives relation, and hence don't affect trait
+                // selection or auto traits, and they are erased
+                // during codegen.
+
+                let generics = self.tcx.generics_of(def_id);
+                let substs = self.tcx.mk_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)
+                    } else {
+                        // ...but not elsewhere.
+                        self.fold_kind_normally(kind)
+                    }
+                }));
+
+                self.tcx.mk_closure(def_id, 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)| {
+                    if index < generics.parent_count {
+                        // Accommodate missing regions in the parent kinds...
+                        self.fold_kind_mapping_missing_regions_to_empty(kind)
+                    } else {
+                        // ...but not elsewhere.
+                        self.fold_kind_normally(kind)
+                    }
+                }));
+
+                self.tcx.mk_generator(def_id, substs, movability)
+            }
+
+            ty::Param(..) => {
+                // Look it up in the substitution list.
+                match self.map.get(&ty.into()).map(|k| k.unpack()) {
+                    // Found it in the substitution list; replace with the parameter from the
+                    // opaque type.
+                    Some(GenericArgKind::Type(t1)) => t1,
+                    Some(u) => panic!("type mapped to unexpected kind: {:?}", u),
+                    None => {
+                        self.tcx
+                            .sess
+                            .struct_span_err(
+                                self.span,
+                                &format!(
+                                    "type parameter `{}` is part of concrete type but not \
+                                          used in parameter list for the `impl Trait` type alias",
+                                    ty
+                                ),
+                            )
+                            .emit();
+
+                        self.tcx().types.err
+                    }
+                }
+            }
+
+            _ => ty.super_fold_with(self),
+        }
+    }
+
+    fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
+        trace!("checking const {:?}", ct);
+        // Find a const parameter
+        match ct.val {
+            ty::ConstKind::Param(..) => {
+                // Look it up in the substitution list.
+                match self.map.get(&ct.into()).map(|k| k.unpack()) {
+                    // Found it in the substitution list, replace with the parameter from the
+                    // opaque type.
+                    Some(GenericArgKind::Const(c1)) => c1,
+                    Some(u) => panic!("const mapped to unexpected kind: {:?}", u),
+                    None => {
+                        self.tcx
+                            .sess
+                            .struct_span_err(
+                                self.span,
+                                &format!(
+                                    "const parameter `{}` is part of concrete type but not \
+                                          used in parameter list for the `impl Trait` type alias",
+                                    ct
+                                ),
+                            )
+                            .emit();
+
+                        self.tcx().consts.err
+                    }
+                }
+            }
+
+            _ => ct,
+        }
+    }
+}
+
+struct Instantiator<'a, 'tcx> {
+    infcx: &'a InferCtxt<'a, 'tcx>,
+    parent_def_id: DefId,
+    body_id: hir::HirId,
+    param_env: ty::ParamEnv<'tcx>,
+    value_span: Span,
+    opaque_types: OpaqueTypeMap<'tcx>,
+    obligations: Vec<PredicateObligation<'tcx>>,
+}
+
+impl<'a, 'tcx> Instantiator<'a, 'tcx> {
+    fn instantiate_opaque_types_in_map<T: TypeFoldable<'tcx>>(&mut self, value: &T) -> T {
+        debug!("instantiate_opaque_types_in_map(value={:?})", value);
+        let tcx = self.infcx.tcx;
+        value.fold_with(&mut BottomUpFolder {
+            tcx,
+            ty_op: |ty| {
+                if ty.references_error() {
+                    return tcx.types.err;
+                } else if let ty::Opaque(def_id, substs) = ty.kind {
+                    // Check that this is `impl Trait` type is
+                    // declared by `parent_def_id` -- i.e., one whose
+                    // value we are inferring.  At present, this is
+                    // always true during the first phase of
+                    // type-check, but not always true later on during
+                    // NLL. Once we support named opaque types more fully,
+                    // this same scenario will be able to arise during all phases.
+                    //
+                    // Here is an example using type alias `impl Trait`
+                    // that indicates the distinction we are checking for:
+                    //
+                    // ```rust
+                    // mod a {
+                    //   pub type Foo = impl Iterator;
+                    //   pub fn make_foo() -> Foo { .. }
+                    // }
+                    //
+                    // mod b {
+                    //   fn foo() -> a::Foo { a::make_foo() }
+                    // }
+                    // ```
+                    //
+                    // Here, the return type of `foo` references a
+                    // `Opaque` indeed, but not one whose value is
+                    // presently being inferred. You can get into a
+                    // similar situation with closure return types
+                    // today:
+                    //
+                    // ```rust
+                    // fn foo() -> impl Iterator { .. }
+                    // fn bar() {
+                    //     let x = || foo(); // returns the Opaque assoc with `foo`
+                    // }
+                    // ```
+                    if let Some(opaque_hir_id) = tcx.hir().as_local_hir_id(def_id) {
+                        let parent_def_id = self.parent_def_id;
+                        let def_scope_default = || {
+                            let opaque_parent_hir_id = tcx.hir().get_parent_item(opaque_hir_id);
+                            parent_def_id == tcx.hir().local_def_id(opaque_parent_hir_id)
+                        };
+                        let (in_definition_scope, origin) = match tcx.hir().find(opaque_hir_id) {
+                            Some(Node::Item(item)) => match item.kind {
+                                // Anonymous `impl Trait`
+                                hir::ItemKind::OpaqueTy(hir::OpaqueTy {
+                                    impl_trait_fn: Some(parent),
+                                    origin,
+                                    ..
+                                }) => (parent == self.parent_def_id, origin),
+                                // Named `type Foo = impl Bar;`
+                                hir::ItemKind::OpaqueTy(hir::OpaqueTy {
+                                    impl_trait_fn: None,
+                                    origin,
+                                    ..
+                                }) => (
+                                    may_define_opaque_type(tcx, self.parent_def_id, opaque_hir_id),
+                                    origin,
+                                ),
+                                _ => (def_scope_default(), hir::OpaqueTyOrigin::TypeAlias),
+                            },
+                            Some(Node::ImplItem(item)) => match item.kind {
+                                hir::ImplItemKind::OpaqueTy(_) => (
+                                    may_define_opaque_type(tcx, self.parent_def_id, opaque_hir_id),
+                                    hir::OpaqueTyOrigin::TypeAlias,
+                                ),
+                                _ => (def_scope_default(), hir::OpaqueTyOrigin::TypeAlias),
+                            },
+                            _ => bug!(
+                                "expected (impl) item, found {}",
+                                tcx.hir().node_to_string(opaque_hir_id),
+                            ),
+                        };
+                        if in_definition_scope {
+                            return self.fold_opaque_ty(ty, def_id, substs, origin);
+                        }
+
+                        debug!(
+                            "instantiate_opaque_types_in_map: \
+                             encountered opaque outside its definition scope \
+                             def_id={:?}",
+                            def_id,
+                        );
+                    }
+                }
+
+                ty
+            },
+            lt_op: |lt| lt,
+            ct_op: |ct| ct,
+        })
+    }
+
+    fn fold_opaque_ty(
+        &mut self,
+        ty: Ty<'tcx>,
+        def_id: DefId,
+        substs: SubstsRef<'tcx>,
+        origin: hir::OpaqueTyOrigin,
+    ) -> Ty<'tcx> {
+        let infcx = self.infcx;
+        let tcx = infcx.tcx;
+
+        debug!("instantiate_opaque_types: Opaque(def_id={:?}, substs={:?})", def_id, substs);
+
+        // Use the same type variable if the exact same opaque type appears more
+        // than once in the return type (e.g., if it's passed to a type alias).
+        if let Some(opaque_defn) = self.opaque_types.get(&def_id) {
+            debug!("instantiate_opaque_types: returning concrete ty {:?}", opaque_defn.concrete_ty);
+            return opaque_defn.concrete_ty;
+        }
+        let span = tcx.def_span(def_id);
+        debug!("fold_opaque_ty {:?} {:?}", self.value_span, span);
+        let ty_var = infcx
+            .next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span });
+
+        let predicates_of = tcx.predicates_of(def_id);
+        debug!("instantiate_opaque_types: predicates={:#?}", predicates_of,);
+        let bounds = predicates_of.instantiate(tcx, substs);
+
+        let param_env = tcx.param_env(def_id);
+        let InferOk { value: bounds, obligations } =
+            infcx.partially_normalize_associated_types_in(span, self.body_id, param_env, &bounds);
+        self.obligations.extend(obligations);
+
+        debug!("instantiate_opaque_types: bounds={:?}", bounds);
+
+        let required_region_bounds = required_region_bounds(tcx, ty, bounds.predicates.clone());
+        debug!("instantiate_opaque_types: required_region_bounds={:?}", required_region_bounds);
+
+        // Make sure that we are in fact defining the *entire* type
+        // (e.g., `type Foo<T: Bound> = impl Bar;` needs to be
+        // defined by a function like `fn foo<T: Bound>() -> Foo<T>`).
+        debug!("instantiate_opaque_types: param_env={:#?}", self.param_env,);
+        debug!("instantiate_opaque_types: generics={:#?}", tcx.generics_of(def_id),);
+
+        // Ideally, we'd get the span where *this specific `ty` came
+        // from*, but right now we just use the span from the overall
+        // value being folded. In simple cases like `-> impl Foo`,
+        // these are the same span, but not in cases like `-> (impl
+        // Foo, impl Bar)`.
+        let definition_span = self.value_span;
+
+        self.opaque_types.insert(
+            def_id,
+            OpaqueTypeDecl {
+                opaque_type: ty,
+                substs,
+                definition_span,
+                concrete_ty: ty_var,
+                has_required_region_bounds: !required_region_bounds.is_empty(),
+                origin,
+            },
+        );
+        debug!("instantiate_opaque_types: ty_var={:?}", ty_var);
+
+        for predicate in &bounds.predicates {
+            if let ty::Predicate::Projection(projection) = &predicate {
+                if projection.skip_binder().ty.references_error() {
+                    // No point on adding these obligations since there's a type error involved.
+                    return ty_var;
+                }
+            }
+        }
+
+        self.obligations.reserve(bounds.predicates.len());
+        for predicate in bounds.predicates {
+            // Change the predicate to refer to the type variable,
+            // which will be the concrete type instead of the opaque type.
+            // This also instantiates nested instances of `impl Trait`.
+            let predicate = self.instantiate_opaque_types_in_map(&predicate);
+
+            let cause = traits::ObligationCause::new(span, self.body_id, traits::SizedReturnType);
+
+            // Require that the predicate holds for the concrete type.
+            debug!("instantiate_opaque_types: predicate={:?}", predicate);
+            self.obligations.push(traits::Obligation::new(cause, self.param_env, predicate));
+        }
+
+        ty_var
+    }
+}
+
+/// Returns `true` if `opaque_hir_id` is a sibling or a child of a sibling of `def_id`.
+///
+/// Example:
+/// ```rust
+/// pub mod foo {
+///     pub mod bar {
+///         pub trait Bar { .. }
+///
+///         pub type Baz = impl Bar;
+///
+///         fn f1() -> Baz { .. }
+///     }
+///
+///     fn f2() -> bar::Baz { .. }
+/// }
+/// ```
+///
+/// Here, `def_id` is the `DefId` of the defining use of the opaque type (e.g., `f1` or `f2`),
+/// and `opaque_hir_id` is the `HirId` of the definition of the opaque type `Baz`.
+/// For the above example, this function returns `true` for `f1` and `false` for `f2`.
+pub fn may_define_opaque_type(tcx: TyCtxt<'_>, def_id: DefId, opaque_hir_id: hir::HirId) -> bool {
+    let mut hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
+
+    // Named opaque types can be defined by any siblings or children of siblings.
+    let scope = tcx.hir().get_defining_scope(opaque_hir_id);
+    // We walk up the node tree until we hit the root or the scope of the opaque type.
+    while hir_id != scope && hir_id != hir::CRATE_HIR_ID {
+        hir_id = tcx.hir().get_parent_item(hir_id);
+    }
+    // Syntactically, we are allowed to define the concrete type if:
+    let res = hir_id == scope;
+    trace!(
+        "may_define_opaque_type(def={:?}, opaque_node={:?}) = {}",
+        tcx.hir().find(hir_id),
+        tcx.hir().get(opaque_hir_id),
+        res
+    );
+    res
+}
+
+/// Given a set of predicates that apply to an object type, returns
+/// the region bounds that the (erased) `Self` type must
+/// outlive. Precisely *because* the `Self` type is erased, the
+/// parameter `erased_self_ty` must be supplied to indicate what type
+/// has been used to represent `Self` in the predicates
+/// themselves. This should really be a unique type; `FreshTy(0)` is a
+/// popular choice.
+///
+/// N.B., in some cases, particularly around higher-ranked bounds,
+/// this function returns a kind of conservative approximation.
+/// That is, all regions returned by this function are definitely
+/// required, but there may be other region bounds that are not
+/// returned, as well as requirements like `for<'a> T: 'a`.
+///
+/// Requires that trait definitions have been processed so that we can
+/// elaborate predicates and walk supertraits.
+//
+// FIXME: callers may only have a `&[Predicate]`, not a `Vec`, so that's
+// what this code should accept.
+crate fn required_region_bounds(
+    tcx: TyCtxt<'tcx>,
+    erased_self_ty: Ty<'tcx>,
+    predicates: Vec<ty::Predicate<'tcx>>,
+) -> Vec<ty::Region<'tcx>> {
+    debug!(
+        "required_region_bounds(erased_self_ty={:?}, predicates={:?})",
+        erased_self_ty, predicates
+    );
+
+    assert!(!erased_self_ty.has_escaping_bound_vars());
+
+    traits::elaborate_predicates(tcx, predicates)
+        .filter_map(|predicate| {
+            match predicate {
+                ty::Predicate::Projection(..)
+                | ty::Predicate::Trait(..)
+                | ty::Predicate::Subtype(..)
+                | ty::Predicate::WellFormed(..)
+                | ty::Predicate::ObjectSafe(..)
+                | ty::Predicate::ClosureKind(..)
+                | ty::Predicate::RegionOutlives(..)
+                | ty::Predicate::ConstEvaluatable(..) => None,
+                ty::Predicate::TypeOutlives(predicate) => {
+                    // Search for a bound of the form `erased_self_ty
+                    // : 'a`, but be wary of something like `for<'a>
+                    // erased_self_ty : 'a` (we interpret a
+                    // higher-ranked bound like that as 'static,
+                    // though at present the code in `fulfill.rs`
+                    // considers such bounds to be unsatisfiable, so
+                    // it's kind of a moot point since you could never
+                    // construct such an object, but this seems
+                    // correct even if that code changes).
+                    let ty::OutlivesPredicate(ref t, ref r) = predicate.skip_binder();
+                    if t == &erased_self_ty && !r.has_escaping_bound_vars() {
+                        Some(*r)
+                    } else {
+                        None
+                    }
+                }
+            }
+        })
+        .collect()
+}
diff --git a/src/librustc_trait_selection/traits/auto_trait.rs b/src/librustc_trait_selection/traits/auto_trait.rs
new file mode 100644 (file)
index 0000000..d221d68
--- /dev/null
@@ -0,0 +1,837 @@
+//! Support code for rustdoc and external tools.
+//! You really don't want to be using this unless you need to.
+
+use super::*;
+
+use crate::infer::region_constraints::{Constraint, RegionConstraintData};
+use crate::infer::InferCtxt;
+use rustc::ty::fold::TypeFolder;
+use rustc::ty::{Region, RegionVid};
+
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+
+use std::collections::hash_map::Entry;
+use std::collections::VecDeque;
+
+// FIXME(twk): this is obviously not nice to duplicate like that
+#[derive(Eq, PartialEq, Hash, Copy, Clone, Debug)]
+pub enum RegionTarget<'tcx> {
+    Region(Region<'tcx>),
+    RegionVid(RegionVid),
+}
+
+#[derive(Default, Debug, Clone)]
+pub struct RegionDeps<'tcx> {
+    larger: FxHashSet<RegionTarget<'tcx>>,
+    smaller: FxHashSet<RegionTarget<'tcx>>,
+}
+
+pub enum AutoTraitResult<A> {
+    ExplicitImpl,
+    PositiveImpl(A),
+    NegativeImpl,
+}
+
+impl<A> AutoTraitResult<A> {
+    fn is_auto(&self) -> bool {
+        match *self {
+            AutoTraitResult::PositiveImpl(_) | AutoTraitResult::NegativeImpl => true,
+            _ => false,
+        }
+    }
+}
+
+pub struct AutoTraitInfo<'cx> {
+    pub full_user_env: ty::ParamEnv<'cx>,
+    pub region_data: RegionConstraintData<'cx>,
+    pub vid_to_region: FxHashMap<ty::RegionVid, ty::Region<'cx>>,
+}
+
+pub struct AutoTraitFinder<'tcx> {
+    tcx: TyCtxt<'tcx>,
+}
+
+impl<'tcx> AutoTraitFinder<'tcx> {
+    pub fn new(tcx: TyCtxt<'tcx>) -> Self {
+        AutoTraitFinder { tcx }
+    }
+
+    /// Makes a best effort to determine whether and under which conditions an auto trait is
+    /// implemented for a type. For example, if you have
+    ///
+    /// ```
+    /// struct Foo<T> { data: Box<T> }
+    /// ```
+    ///
+    /// then this might return that Foo<T>: Send if T: Send (encoded in the AutoTraitResult type).
+    /// The analysis attempts to account for custom impls as well as other complex cases. This
+    /// result is intended for use by rustdoc and other such consumers.
+    ///
+    /// (Note that due to the coinductive nature of Send, the full and correct result is actually
+    /// quite simple to generate. That is, when a type has no custom impl, it is Send iff its field
+    /// types are all Send. So, in our example, we might have that Foo<T>: Send if Box<T>: Send.
+    /// But this is often not the best way to present to the user.)
+    ///
+    /// Warning: The API should be considered highly unstable, and it may be refactored or removed
+    /// in the future.
+    pub fn find_auto_trait_generics<A>(
+        &self,
+        ty: Ty<'tcx>,
+        orig_env: ty::ParamEnv<'tcx>,
+        trait_did: DefId,
+        auto_trait_callback: impl Fn(&InferCtxt<'_, 'tcx>, AutoTraitInfo<'tcx>) -> A,
+    ) -> AutoTraitResult<A> {
+        let tcx = self.tcx;
+
+        let trait_ref = ty::TraitRef { def_id: trait_did, substs: tcx.mk_substs_trait(ty, &[]) };
+
+        let trait_pred = ty::Binder::bind(trait_ref);
+
+        let bail_out = tcx.infer_ctxt().enter(|infcx| {
+            let mut selcx = SelectionContext::with_negative(&infcx, true);
+            let result = selcx.select(&Obligation::new(
+                ObligationCause::dummy(),
+                orig_env,
+                trait_pred.to_poly_trait_predicate(),
+            ));
+
+            match result {
+                Ok(Some(Vtable::VtableImpl(_))) => {
+                    debug!(
+                        "find_auto_trait_generics({:?}): \
+                         manual impl found, bailing out",
+                        trait_ref
+                    );
+                    true
+                }
+                _ => false,
+            }
+        });
+
+        // If an explicit impl exists, it always takes priority over an auto impl
+        if bail_out {
+            return AutoTraitResult::ExplicitImpl;
+        }
+
+        return tcx.infer_ctxt().enter(|infcx| {
+            let mut fresh_preds = FxHashSet::default();
+
+            // Due to the way projections are handled by SelectionContext, we need to run
+            // evaluate_predicates twice: once on the original param env, and once on the result of
+            // the first evaluate_predicates call.
+            //
+            // The problem is this: most of rustc, including SelectionContext and traits::project,
+            // are designed to work with a concrete usage of a type (e.g., Vec<u8>
+            // fn<T>() { Vec<T> }. This information will generally never change - given
+            // the 'T' in fn<T>() { ... }, we'll never know anything else about 'T'.
+            // If we're unable to prove that 'T' implements a particular trait, we're done -
+            // there's nothing left to do but error out.
+            //
+            // However, synthesizing an auto trait impl works differently. Here, we start out with
+            // a set of initial conditions - the ParamEnv of the struct/enum/union we're dealing
+            // with - and progressively discover the conditions we need to fulfill for it to
+            // implement a certain auto trait. This ends up breaking two assumptions made by trait
+            // selection and projection:
+            //
+            // * We can always cache the result of a particular trait selection for the lifetime of
+            // an InfCtxt
+            // * Given a projection bound such as '<T as SomeTrait>::SomeItem = K', if 'T:
+            // SomeTrait' doesn't hold, then we don't need to care about the 'SomeItem = K'
+            //
+            // We fix the first assumption by manually clearing out all of the InferCtxt's caches
+            // in between calls to SelectionContext.select. This allows us to keep all of the
+            // intermediate types we create bound to the 'tcx lifetime, rather than needing to lift
+            // them between calls.
+            //
+            // We fix the second assumption by reprocessing the result of our first call to
+            // evaluate_predicates. Using the example of '<T as SomeTrait>::SomeItem = K', our first
+            // pass will pick up 'T: SomeTrait', but not 'SomeItem = K'. On our second pass,
+            // traits::project will see that 'T: SomeTrait' is in our ParamEnv, allowing
+            // SelectionContext to return it back to us.
+
+            let (new_env, user_env) = match self.evaluate_predicates(
+                &infcx,
+                trait_did,
+                ty,
+                orig_env,
+                orig_env,
+                &mut fresh_preds,
+                false,
+            ) {
+                Some(e) => e,
+                None => return AutoTraitResult::NegativeImpl,
+            };
+
+            let (full_env, full_user_env) = self
+                .evaluate_predicates(
+                    &infcx,
+                    trait_did,
+                    ty,
+                    new_env,
+                    user_env,
+                    &mut fresh_preds,
+                    true,
+                )
+                .unwrap_or_else(|| {
+                    panic!("Failed to fully process: {:?} {:?} {:?}", ty, trait_did, orig_env)
+                });
+
+            debug!(
+                "find_auto_trait_generics({:?}): fulfilling \
+                 with {:?}",
+                trait_ref, full_env
+            );
+            infcx.clear_caches();
+
+            // At this point, we already have all of the bounds we need. FulfillmentContext is used
+            // to store all of the necessary region/lifetime bounds in the InferContext, as well as
+            // an additional sanity check.
+            let mut fulfill = FulfillmentContext::new();
+            fulfill.register_bound(
+                &infcx,
+                full_env,
+                ty,
+                trait_did,
+                ObligationCause::misc(DUMMY_SP, hir::DUMMY_HIR_ID),
+            );
+            fulfill.select_all_or_error(&infcx).unwrap_or_else(|e| {
+                panic!("Unable to fulfill trait {:?} for '{:?}': {:?}", trait_did, ty, e)
+            });
+
+            let body_id_map: FxHashMap<_, _> = infcx
+                .inner
+                .borrow()
+                .region_obligations
+                .iter()
+                .map(|&(id, _)| (id, vec![]))
+                .collect();
+
+            infcx.process_registered_region_obligations(&body_id_map, None, full_env);
+
+            let region_data = infcx
+                .inner
+                .borrow_mut()
+                .unwrap_region_constraints()
+                .region_constraint_data()
+                .clone();
+
+            let vid_to_region = self.map_vid_to_region(&region_data);
+
+            let info = AutoTraitInfo { full_user_env, region_data, vid_to_region };
+
+            return AutoTraitResult::PositiveImpl(auto_trait_callback(&infcx, info));
+        });
+    }
+}
+
+impl AutoTraitFinder<'tcx> {
+    /// The core logic responsible for computing the bounds for our synthesized impl.
+    ///
+    /// To calculate the bounds, we call `SelectionContext.select` in a loop. Like
+    /// `FulfillmentContext`, we recursively select the nested obligations of predicates we
+    /// encounter. However, whenever we encounter an `UnimplementedError` involving a type
+    /// parameter, we add it to our `ParamEnv`. Since our goal is to determine when a particular
+    /// type implements an auto trait, Unimplemented errors tell us what conditions need to be met.
+    ///
+    /// This method ends up working somewhat similarly to `FulfillmentContext`, but with a few key
+    /// differences. `FulfillmentContext` works under the assumption that it's dealing with concrete
+    /// user code. According, it considers all possible ways that a `Predicate` could be met, which
+    /// isn't always what we want for a synthesized impl. For example, given the predicate `T:
+    /// Iterator`, `FulfillmentContext` can end up reporting an Unimplemented error for `T:
+    /// IntoIterator` -- since there's an implementation of `Iterator` where `T: IntoIterator`,
+    /// `FulfillmentContext` will drive `SelectionContext` to consider that impl before giving up.
+    /// If we were to rely on `FulfillmentContext`s decision, we might end up synthesizing an impl
+    /// like this:
+    ///
+    ///     impl<T> Send for Foo<T> where T: IntoIterator
+    ///
+    /// While it might be technically true that Foo implements Send where `T: IntoIterator`,
+    /// the bound is overly restrictive - it's really only necessary that `T: Iterator`.
+    ///
+    /// For this reason, `evaluate_predicates` handles predicates with type variables specially.
+    /// When we encounter an `Unimplemented` error for a bound such as `T: Iterator`, we immediately
+    /// add it to our `ParamEnv`, and add it to our stack for recursive evaluation. When we later
+    /// select it, we'll pick up any nested bounds, without ever inferring that `T: IntoIterator`
+    /// needs to hold.
+    ///
+    /// One additional consideration is supertrait bounds. Normally, a `ParamEnv` is only ever
+    /// constructed once for a given type. As part of the construction process, the `ParamEnv` will
+    /// have any supertrait bounds normalized -- e.g., if we have a type `struct Foo<T: Copy>`, the
+    /// `ParamEnv` will contain `T: Copy` and `T: Clone`, since `Copy: Clone`. When we construct our
+    /// own `ParamEnv`, we need to do this ourselves, through `traits::elaborate_predicates`, or
+    /// else `SelectionContext` will choke on the missing predicates. However, this should never
+    /// show up in the final synthesized generics: we don't want our generated docs page to contain
+    /// something like `T: Copy + Clone`, as that's redundant. Therefore, we keep track of a
+    /// separate `user_env`, which only holds the predicates that will actually be displayed to the
+    /// user.
+    fn evaluate_predicates(
+        &self,
+        infcx: &InferCtxt<'_, 'tcx>,
+        trait_did: DefId,
+        ty: Ty<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+        user_env: ty::ParamEnv<'tcx>,
+        fresh_preds: &mut FxHashSet<ty::Predicate<'tcx>>,
+        only_projections: bool,
+    ) -> Option<(ty::ParamEnv<'tcx>, ty::ParamEnv<'tcx>)> {
+        let tcx = infcx.tcx;
+
+        let mut select = SelectionContext::with_negative(&infcx, true);
+
+        let mut already_visited = FxHashSet::default();
+        let mut predicates = VecDeque::new();
+        predicates.push_back(ty::Binder::bind(ty::TraitPredicate {
+            trait_ref: ty::TraitRef {
+                def_id: trait_did,
+                substs: infcx.tcx.mk_substs_trait(ty, &[]),
+            },
+        }));
+
+        let mut computed_preds: FxHashSet<_> = param_env.caller_bounds.iter().cloned().collect();
+        let mut user_computed_preds: FxHashSet<_> =
+            user_env.caller_bounds.iter().cloned().collect();
+
+        let mut new_env = param_env;
+        let dummy_cause = ObligationCause::misc(DUMMY_SP, hir::DUMMY_HIR_ID);
+
+        while let Some(pred) = predicates.pop_front() {
+            infcx.clear_caches();
+
+            if !already_visited.insert(pred) {
+                continue;
+            }
+
+            // Call `infcx.resolve_vars_if_possible` to see if we can
+            // get rid of any inference variables.
+            let obligation = infcx.resolve_vars_if_possible(&Obligation::new(
+                dummy_cause.clone(),
+                new_env,
+                pred,
+            ));
+            let result = select.select(&obligation);
+
+            match &result {
+                &Ok(Some(ref vtable)) => {
+                    // If we see an explicit negative impl (e.g., `impl !Send for MyStruct`),
+                    // we immediately bail out, since it's impossible for us to continue.
+                    match vtable {
+                        Vtable::VtableImpl(VtableImplData { impl_def_id, .. }) => {
+                            // Blame 'tidy' for the weird bracket placement.
+                            if infcx.tcx.impl_polarity(*impl_def_id) == ty::ImplPolarity::Negative {
+                                debug!(
+                                    "evaluate_nested_obligations: found explicit negative impl\
+                                        {:?}, bailing out",
+                                    impl_def_id
+                                );
+                                return None;
+                            }
+                        }
+                        _ => {}
+                    }
+
+                    let obligations = vtable.clone().nested_obligations().into_iter();
+
+                    if !self.evaluate_nested_obligations(
+                        ty,
+                        obligations,
+                        &mut user_computed_preds,
+                        fresh_preds,
+                        &mut predicates,
+                        &mut select,
+                        only_projections,
+                    ) {
+                        return None;
+                    }
+                }
+                &Ok(None) => {}
+                &Err(SelectionError::Unimplemented) => {
+                    if self.is_param_no_infer(pred.skip_binder().trait_ref.substs) {
+                        already_visited.remove(&pred);
+                        self.add_user_pred(
+                            &mut user_computed_preds,
+                            ty::Predicate::Trait(pred, hir::Constness::NotConst),
+                        );
+                        predicates.push_back(pred);
+                    } else {
+                        debug!(
+                            "evaluate_nested_obligations: `Unimplemented` found, bailing: \
+                             {:?} {:?} {:?}",
+                            ty,
+                            pred,
+                            pred.skip_binder().trait_ref.substs
+                        );
+                        return None;
+                    }
+                }
+                _ => panic!("Unexpected error for '{:?}': {:?}", ty, result),
+            };
+
+            computed_preds.extend(user_computed_preds.iter().cloned());
+            let normalized_preds =
+                elaborate_predicates(tcx, computed_preds.iter().cloned().collect());
+            new_env =
+                ty::ParamEnv::new(tcx.mk_predicates(normalized_preds), param_env.reveal, None);
+        }
+
+        let final_user_env = ty::ParamEnv::new(
+            tcx.mk_predicates(user_computed_preds.into_iter()),
+            user_env.reveal,
+            None,
+        );
+        debug!(
+            "evaluate_nested_obligations(ty={:?}, trait_did={:?}): succeeded with '{:?}' \
+             '{:?}'",
+            ty, trait_did, new_env, final_user_env
+        );
+
+        return Some((new_env, final_user_env));
+    }
+
+    /// This method is designed to work around the following issue:
+    /// When we compute auto trait bounds, we repeatedly call `SelectionContext.select`,
+    /// progressively building a `ParamEnv` based on the results we get.
+    /// However, our usage of `SelectionContext` differs from its normal use within the compiler,
+    /// in that we capture and re-reprocess predicates from `Unimplemented` errors.
+    ///
+    /// This can lead to a corner case when dealing with region parameters.
+    /// During our selection loop in `evaluate_predicates`, we might end up with
+    /// two trait predicates that differ only in their region parameters:
+    /// one containing a HRTB lifetime parameter, and one containing a 'normal'
+    /// lifetime parameter. For example:
+    ///
+    ///     T as MyTrait<'a>
+    ///     T as MyTrait<'static>
+    ///
+    /// If we put both of these predicates in our computed `ParamEnv`, we'll
+    /// confuse `SelectionContext`, since it will (correctly) view both as being applicable.
+    ///
+    /// To solve this, we pick the 'more strict' lifetime bound -- i.e., the HRTB
+    /// Our end goal is to generate a user-visible description of the conditions
+    /// under which a type implements an auto trait. A trait predicate involving
+    /// a HRTB means that the type needs to work with any choice of lifetime,
+    /// not just one specific lifetime (e.g., `'static`).
+    fn add_user_pred<'c>(
+        &self,
+        user_computed_preds: &mut FxHashSet<ty::Predicate<'c>>,
+        new_pred: ty::Predicate<'c>,
+    ) {
+        let mut should_add_new = true;
+        user_computed_preds.retain(|&old_pred| {
+            match (&new_pred, old_pred) {
+                (&ty::Predicate::Trait(new_trait, _), ty::Predicate::Trait(old_trait, _)) => {
+                    if new_trait.def_id() == old_trait.def_id() {
+                        let new_substs = new_trait.skip_binder().trait_ref.substs;
+                        let old_substs = old_trait.skip_binder().trait_ref.substs;
+
+                        if !new_substs.types().eq(old_substs.types()) {
+                            // We can't compare lifetimes if the types are different,
+                            // so skip checking `old_pred`.
+                            return true;
+                        }
+
+                        for (new_region, old_region) in
+                            new_substs.regions().zip(old_substs.regions())
+                        {
+                            match (new_region, old_region) {
+                                // If both predicates have an `ReLateBound` (a HRTB) in the
+                                // same spot, we do nothing.
+                                (
+                                    ty::RegionKind::ReLateBound(_, _),
+                                    ty::RegionKind::ReLateBound(_, _),
+                                ) => {}
+
+                                (ty::RegionKind::ReLateBound(_, _), _)
+                                | (_, ty::RegionKind::ReVar(_)) => {
+                                    // One of these is true:
+                                    // The new predicate has a HRTB in a spot where the old
+                                    // predicate does not (if they both had a HRTB, the previous
+                                    // match arm would have executed). A HRBT is a 'stricter'
+                                    // bound than anything else, so we want to keep the newer
+                                    // predicate (with the HRBT) in place of the old predicate.
+                                    //
+                                    // OR
+                                    //
+                                    // The old predicate has a region variable where the new
+                                    // predicate has some other kind of region. An region
+                                    // variable isn't something we can actually display to a user,
+                                    // so we choose their new predicate (which doesn't have a region
+                                    // variable).
+                                    //
+                                    // In both cases, we want to remove the old predicate,
+                                    // from `user_computed_preds`, and replace it with the new
+                                    // one. Having both the old and the new
+                                    // predicate in a `ParamEnv` would confuse `SelectionContext`.
+                                    //
+                                    // We're currently in the predicate passed to 'retain',
+                                    // so we return `false` to remove the old predicate from
+                                    // `user_computed_preds`.
+                                    return false;
+                                }
+                                (_, ty::RegionKind::ReLateBound(_, _))
+                                | (ty::RegionKind::ReVar(_), _) => {
+                                    // This is the opposite situation as the previous arm.
+                                    // One of these is true:
+                                    //
+                                    // The old predicate has a HRTB lifetime in a place where the
+                                    // new predicate does not.
+                                    //
+                                    // OR
+                                    //
+                                    // The new predicate has a region variable where the old
+                                    // predicate has some other type of region.
+                                    //
+                                    // We want to leave the old
+                                    // predicate in `user_computed_preds`, and skip adding
+                                    // new_pred to `user_computed_params`.
+                                    should_add_new = false
+                                }
+                                _ => {}
+                            }
+                        }
+                    }
+                }
+                _ => {}
+            }
+            return true;
+        });
+
+        if should_add_new {
+            user_computed_preds.insert(new_pred);
+        }
+    }
+
+    /// This is very similar to `handle_lifetimes`. However, instead of matching `ty::Region`s
+    /// to each other, we match `ty::RegionVid`s to `ty::Region`s.
+    fn map_vid_to_region<'cx>(
+        &self,
+        regions: &RegionConstraintData<'cx>,
+    ) -> FxHashMap<ty::RegionVid, ty::Region<'cx>> {
+        let mut vid_map: FxHashMap<RegionTarget<'cx>, RegionDeps<'cx>> = FxHashMap::default();
+        let mut finished_map = FxHashMap::default();
+
+        for constraint in regions.constraints.keys() {
+            match constraint {
+                &Constraint::VarSubVar(r1, r2) => {
+                    {
+                        let deps1 = vid_map.entry(RegionTarget::RegionVid(r1)).or_default();
+                        deps1.larger.insert(RegionTarget::RegionVid(r2));
+                    }
+
+                    let deps2 = vid_map.entry(RegionTarget::RegionVid(r2)).or_default();
+                    deps2.smaller.insert(RegionTarget::RegionVid(r1));
+                }
+                &Constraint::RegSubVar(region, vid) => {
+                    {
+                        let deps1 = vid_map.entry(RegionTarget::Region(region)).or_default();
+                        deps1.larger.insert(RegionTarget::RegionVid(vid));
+                    }
+
+                    let deps2 = vid_map.entry(RegionTarget::RegionVid(vid)).or_default();
+                    deps2.smaller.insert(RegionTarget::Region(region));
+                }
+                &Constraint::VarSubReg(vid, region) => {
+                    finished_map.insert(vid, region);
+                }
+                &Constraint::RegSubReg(r1, r2) => {
+                    {
+                        let deps1 = vid_map.entry(RegionTarget::Region(r1)).or_default();
+                        deps1.larger.insert(RegionTarget::Region(r2));
+                    }
+
+                    let deps2 = vid_map.entry(RegionTarget::Region(r2)).or_default();
+                    deps2.smaller.insert(RegionTarget::Region(r1));
+                }
+            }
+        }
+
+        while !vid_map.is_empty() {
+            let target = *vid_map.keys().next().expect("Keys somehow empty");
+            let deps = vid_map.remove(&target).expect("Entry somehow missing");
+
+            for smaller in deps.smaller.iter() {
+                for larger in deps.larger.iter() {
+                    match (smaller, larger) {
+                        (&RegionTarget::Region(_), &RegionTarget::Region(_)) => {
+                            if let Entry::Occupied(v) = vid_map.entry(*smaller) {
+                                let smaller_deps = v.into_mut();
+                                smaller_deps.larger.insert(*larger);
+                                smaller_deps.larger.remove(&target);
+                            }
+
+                            if let Entry::Occupied(v) = vid_map.entry(*larger) {
+                                let larger_deps = v.into_mut();
+                                larger_deps.smaller.insert(*smaller);
+                                larger_deps.smaller.remove(&target);
+                            }
+                        }
+                        (&RegionTarget::RegionVid(v1), &RegionTarget::Region(r1)) => {
+                            finished_map.insert(v1, r1);
+                        }
+                        (&RegionTarget::Region(_), &RegionTarget::RegionVid(_)) => {
+                            // Do nothing; we don't care about regions that are smaller than vids.
+                        }
+                        (&RegionTarget::RegionVid(_), &RegionTarget::RegionVid(_)) => {
+                            if let Entry::Occupied(v) = vid_map.entry(*smaller) {
+                                let smaller_deps = v.into_mut();
+                                smaller_deps.larger.insert(*larger);
+                                smaller_deps.larger.remove(&target);
+                            }
+
+                            if let Entry::Occupied(v) = vid_map.entry(*larger) {
+                                let larger_deps = v.into_mut();
+                                larger_deps.smaller.insert(*smaller);
+                                larger_deps.smaller.remove(&target);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        finished_map
+    }
+
+    fn is_param_no_infer(&self, substs: SubstsRef<'_>) -> bool {
+        return self.is_of_param(substs.type_at(0)) && !substs.types().any(|t| t.has_infer_types());
+    }
+
+    pub fn is_of_param(&self, ty: Ty<'_>) -> bool {
+        return match ty.kind {
+            ty::Param(_) => true,
+            ty::Projection(p) => self.is_of_param(p.self_ty()),
+            _ => false,
+        };
+    }
+
+    fn is_self_referential_projection(&self, p: ty::PolyProjectionPredicate<'_>) -> bool {
+        match p.ty().skip_binder().kind {
+            ty::Projection(proj) if proj == p.skip_binder().projection_ty => true,
+            _ => false,
+        }
+    }
+
+    fn evaluate_nested_obligations(
+        &self,
+        ty: Ty<'_>,
+        nested: impl Iterator<Item = Obligation<'tcx, ty::Predicate<'tcx>>>,
+        computed_preds: &mut FxHashSet<ty::Predicate<'tcx>>,
+        fresh_preds: &mut FxHashSet<ty::Predicate<'tcx>>,
+        predicates: &mut VecDeque<ty::PolyTraitPredicate<'tcx>>,
+        select: &mut SelectionContext<'_, 'tcx>,
+        only_projections: bool,
+    ) -> bool {
+        let dummy_cause = ObligationCause::misc(DUMMY_SP, hir::DUMMY_HIR_ID);
+
+        for (obligation, mut predicate) in nested.map(|o| (o.clone(), o.predicate)) {
+            let is_new_pred = fresh_preds.insert(self.clean_pred(select.infcx(), predicate));
+
+            // Resolve any inference variables that we can, to help selection succeed
+            predicate = select.infcx().resolve_vars_if_possible(&predicate);
+
+            // We only add a predicate as a user-displayable bound if
+            // it involves a generic parameter, and doesn't contain
+            // any inference variables.
+            //
+            // Displaying a bound involving a concrete type (instead of a generic
+            // parameter) would be pointless, since it's always true
+            // (e.g. u8: Copy)
+            // Displaying an inference variable is impossible, since they're
+            // an internal compiler detail without a defined visual representation
+            //
+            // We check this by calling is_of_param on the relevant types
+            // from the various possible predicates
+            match &predicate {
+                &ty::Predicate::Trait(p, _) => {
+                    if self.is_param_no_infer(p.skip_binder().trait_ref.substs)
+                        && !only_projections
+                        && is_new_pred
+                    {
+                        self.add_user_pred(computed_preds, predicate);
+                    }
+                    predicates.push_back(p);
+                }
+                &ty::Predicate::Projection(p) => {
+                    debug!(
+                        "evaluate_nested_obligations: examining projection predicate {:?}",
+                        predicate
+                    );
+
+                    // As described above, we only want to display
+                    // bounds which include a generic parameter but don't include
+                    // an inference variable.
+                    // Additionally, we check if we've seen this predicate before,
+                    // to avoid rendering duplicate bounds to the user.
+                    if self.is_param_no_infer(p.skip_binder().projection_ty.substs)
+                        && !p.ty().skip_binder().has_infer_types()
+                        && is_new_pred
+                    {
+                        debug!(
+                            "evaluate_nested_obligations: adding projection predicate\
+                            to computed_preds: {:?}",
+                            predicate
+                        );
+
+                        // Under unusual circumstances, we can end up with a self-refeential
+                        // projection predicate. For example:
+                        // <T as MyType>::Value == <T as MyType>::Value
+                        // Not only is displaying this to the user pointless,
+                        // having it in the ParamEnv will cause an issue if we try to call
+                        // poly_project_and_unify_type on the predicate, since this kind of
+                        // predicate will normally never end up in a ParamEnv.
+                        //
+                        // For these reasons, we ignore these weird predicates,
+                        // ensuring that we're able to properly synthesize an auto trait impl
+                        if self.is_self_referential_projection(p) {
+                            debug!(
+                                "evaluate_nested_obligations: encountered a projection
+                                 predicate equating a type with itself! Skipping"
+                            );
+                        } else {
+                            self.add_user_pred(computed_preds, predicate);
+                        }
+                    }
+
+                    // There are three possible cases when we project a predicate:
+                    //
+                    // 1. We encounter an error. This means that it's impossible for
+                    // our current type to implement the auto trait - there's bound
+                    // that we could add to our ParamEnv that would 'fix' this kind
+                    // of error, as it's not caused by an unimplemented type.
+                    //
+                    // 2. We successfully project the predicate (Ok(Some(_))), generating
+                    //  some subobligations. We then process these subobligations
+                    //  like any other generated sub-obligations.
+                    //
+                    // 3. We receive an 'ambiguous' result (Ok(None))
+                    // If we were actually trying to compile a crate,
+                    // we would need to re-process this obligation later.
+                    // However, all we care about is finding out what bounds
+                    // are needed for our type to implement a particular auto trait.
+                    // We've already added this obligation to our computed ParamEnv
+                    // above (if it was necessary). Therefore, we don't need
+                    // to do any further processing of the obligation.
+                    //
+                    // Note that we *must* try to project *all* projection predicates
+                    // we encounter, even ones without inference variable.
+                    // This ensures that we detect any projection errors,
+                    // which indicate that our type can *never* implement the given
+                    // auto trait. In that case, we will generate an explicit negative
+                    // impl (e.g. 'impl !Send for MyType'). However, we don't
+                    // try to process any of the generated subobligations -
+                    // they contain no new information, since we already know
+                    // that our type implements the projected-through trait,
+                    // and can lead to weird region issues.
+                    //
+                    // Normally, we'll generate a negative impl as a result of encountering
+                    // a type with an explicit negative impl of an auto trait
+                    // (for example, raw pointers have !Send and !Sync impls)
+                    // However, through some **interesting** manipulations of the type
+                    // system, it's actually possible to write a type that never
+                    // implements an auto trait due to a projection error, not a normal
+                    // negative impl error. To properly handle this case, we need
+                    // to ensure that we catch any potential projection errors,
+                    // and turn them into an explicit negative impl for our type.
+                    debug!("Projecting and unifying projection predicate {:?}", predicate);
+
+                    match poly_project_and_unify_type(select, &obligation.with(p)) {
+                        Err(e) => {
+                            debug!(
+                                "evaluate_nested_obligations: Unable to unify predicate \
+                                 '{:?}' '{:?}', bailing out",
+                                ty, e
+                            );
+                            return false;
+                        }
+                        Ok(Some(v)) => {
+                            // We only care about sub-obligations
+                            // when we started out trying to unify
+                            // some inference variables. See the comment above
+                            // for more infomration
+                            if p.ty().skip_binder().has_infer_types() {
+                                if !self.evaluate_nested_obligations(
+                                    ty,
+                                    v.clone().iter().cloned(),
+                                    computed_preds,
+                                    fresh_preds,
+                                    predicates,
+                                    select,
+                                    only_projections,
+                                ) {
+                                    return false;
+                                }
+                            }
+                        }
+                        Ok(None) => {
+                            // It's ok not to make progress when hvave no inference variables -
+                            // in that case, we were only performing unifcation to check if an
+                            // error occurred (which would indicate that it's impossible for our
+                            // type to implement the auto trait).
+                            // However, we should always make progress (either by generating
+                            // subobligations or getting an error) when we started off with
+                            // inference variables
+                            if p.ty().skip_binder().has_infer_types() {
+                                panic!("Unexpected result when selecting {:?} {:?}", ty, obligation)
+                            }
+                        }
+                    }
+                }
+                &ty::Predicate::RegionOutlives(ref binder) => {
+                    if select.infcx().region_outlives_predicate(&dummy_cause, binder).is_err() {
+                        return false;
+                    }
+                }
+                &ty::Predicate::TypeOutlives(ref binder) => {
+                    match (
+                        binder.no_bound_vars(),
+                        binder.map_bound_ref(|pred| pred.0).no_bound_vars(),
+                    ) {
+                        (None, Some(t_a)) => {
+                            select.infcx().register_region_obligation_with_cause(
+                                t_a,
+                                select.infcx().tcx.lifetimes.re_static,
+                                &dummy_cause,
+                            );
+                        }
+                        (Some(ty::OutlivesPredicate(t_a, r_b)), _) => {
+                            select.infcx().register_region_obligation_with_cause(
+                                t_a,
+                                r_b,
+                                &dummy_cause,
+                            );
+                        }
+                        _ => {}
+                    };
+                }
+                _ => panic!("Unexpected predicate {:?} {:?}", ty, predicate),
+            };
+        }
+        return true;
+    }
+
+    pub fn clean_pred(
+        &self,
+        infcx: &InferCtxt<'_, 'tcx>,
+        p: ty::Predicate<'tcx>,
+    ) -> ty::Predicate<'tcx> {
+        infcx.freshen(p)
+    }
+}
+
+// Replaces all ReVars in a type with ty::Region's, using the provided map
+pub struct RegionReplacer<'a, 'tcx> {
+    vid_to_region: &'a FxHashMap<ty::RegionVid, ty::Region<'tcx>>,
+    tcx: TyCtxt<'tcx>,
+}
+
+impl<'a, 'tcx> TypeFolder<'tcx> for RegionReplacer<'a, 'tcx> {
+    fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
+        self.tcx
+    }
+
+    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
+        (match r {
+            &ty::ReVar(vid) => self.vid_to_region.get(&vid).cloned(),
+            _ => None,
+        })
+        .unwrap_or_else(|| r.super_fold_with(self))
+    }
+}
diff --git a/src/librustc_trait_selection/traits/codegen/mod.rs b/src/librustc_trait_selection/traits/codegen/mod.rs
new file mode 100644 (file)
index 0000000..5c2fc3f
--- /dev/null
@@ -0,0 +1,112 @@
+// This file contains various trait resolution methods used by codegen.
+// They all assume regions can be erased and monomorphic types.  It
+// seems likely that they should eventually be merged into more
+// general routines.
+
+use crate::infer::{InferCtxt, TyCtxtInferExt};
+use crate::traits::{
+    FulfillmentContext, Obligation, ObligationCause, SelectionContext, TraitEngine, Vtable,
+};
+use rustc::ty::fold::TypeFoldable;
+use rustc::ty::{self, TyCtxt};
+
+/// Attempts to resolve an obligation to a vtable. The result is
+/// a shallow vtable resolution, meaning that we do not
+/// (necessarily) resolve all nested obligations on the impl. Note
+/// that type check should guarantee to us that all nested
+/// obligations *could be* resolved if we wanted to.
+/// Assumes that this is run after the entire crate has been successfully type-checked.
+pub fn codegen_fulfill_obligation<'tcx>(
+    ty: TyCtxt<'tcx>,
+    (param_env, trait_ref): (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>),
+) -> Option<Vtable<'tcx, ()>> {
+    // Remove any references to regions; this helps improve caching.
+    let trait_ref = ty.erase_regions(&trait_ref);
+
+    debug!(
+        "codegen_fulfill_obligation(trait_ref={:?}, def_id={:?})",
+        (param_env, trait_ref),
+        trait_ref.def_id()
+    );
+
+    // Do the initial selection for the obligation. This yields the
+    // shallow result we are looking for -- that is, what specific impl.
+    ty.infer_ctxt().enter(|infcx| {
+        let mut selcx = SelectionContext::new(&infcx);
+
+        let obligation_cause = ObligationCause::dummy();
+        let obligation =
+            Obligation::new(obligation_cause, param_env, trait_ref.to_poly_trait_predicate());
+
+        let selection = match selcx.select(&obligation) {
+            Ok(Some(selection)) => selection,
+            Ok(None) => {
+                // Ambiguity can happen when monomorphizing during trans
+                // expands to some humongo type that never occurred
+                // statically -- this humongo type can then overflow,
+                // leading to an ambiguous result. So report this as an
+                // overflow bug, since I believe this is the only case
+                // where ambiguity can result.
+                infcx.tcx.sess.delay_span_bug(
+                    rustc_span::DUMMY_SP,
+                    &format!(
+                        "encountered ambiguity selecting `{:?}` during codegen, presuming due to \
+                         overflow or prior type error",
+                        trait_ref
+                    ),
+                );
+                return None;
+            }
+            Err(e) => {
+                bug!("Encountered error `{:?}` selecting `{:?}` during codegen", e, trait_ref)
+            }
+        };
+
+        debug!("fulfill_obligation: selection={:?}", selection);
+
+        // Currently, we use a fulfillment context to completely resolve
+        // all nested obligations. This is because they can inform the
+        // inference of the impl's type parameters.
+        let mut fulfill_cx = FulfillmentContext::new();
+        let vtable = selection.map(|predicate| {
+            debug!("fulfill_obligation: register_predicate_obligation {:?}", predicate);
+            fulfill_cx.register_predicate_obligation(&infcx, predicate);
+        });
+        let vtable = drain_fulfillment_cx_or_panic(&infcx, &mut fulfill_cx, &vtable);
+
+        info!("Cache miss: {:?} => {:?}", trait_ref, vtable);
+        Some(vtable)
+    })
+}
+
+// # Global Cache
+
+/// Finishes processes any obligations that remain in the
+/// fulfillment context, and then returns the result with all type
+/// variables removed and regions erased. Because this is intended
+/// for use after type-check has completed, if any errors occur,
+/// it will panic. It is used during normalization and other cases
+/// where processing the obligations in `fulfill_cx` may cause
+/// type inference variables that appear in `result` to be
+/// unified, and hence we need to process those obligations to get
+/// the complete picture of the type.
+fn drain_fulfillment_cx_or_panic<T>(
+    infcx: &InferCtxt<'_, 'tcx>,
+    fulfill_cx: &mut FulfillmentContext<'tcx>,
+    result: &T,
+) -> T
+where
+    T: TypeFoldable<'tcx>,
+{
+    debug!("drain_fulfillment_cx_or_panic()");
+
+    // In principle, we only need to do this so long as `result`
+    // contains unbound type parameters. It could be a slight
+    // optimization to stop iterating early.
+    if let Err(errors) = fulfill_cx.select_all_or_error(infcx) {
+        bug!("Encountered errors `{:?}` resolving bounds after type-checking", errors);
+    }
+
+    let result = infcx.resolve_vars_if_possible(result);
+    infcx.tcx.erase_regions(&result)
+}
diff --git a/src/librustc_trait_selection/traits/coherence.rs b/src/librustc_trait_selection/traits/coherence.rs
new file mode 100644 (file)
index 0000000..5f542e7
--- /dev/null
@@ -0,0 +1,540 @@
+//! See Rustc Dev Guide chapters on [trait-resolution] and [trait-specialization] for more info on
+//! how this works.
+//!
+//! [trait-resolution]: https://rustc-dev-guide.rust-lang.org/traits/resolution.html
+//! [trait-specialization]: https://rustc-dev-guide.rust-lang.org/traits/specialization.html
+
+use crate::infer::{CombinedSnapshot, InferOk, TyCtxtInferExt};
+use crate::traits::select::IntercrateAmbiguityCause;
+use crate::traits::SkipLeakCheck;
+use crate::traits::{self, Normalized, Obligation, ObligationCause, SelectionContext};
+use rustc::ty::fold::TypeFoldable;
+use rustc::ty::subst::Subst;
+use rustc::ty::{self, Ty, TyCtxt};
+use rustc_hir::def_id::{DefId, LOCAL_CRATE};
+use rustc_span::symbol::sym;
+use rustc_span::DUMMY_SP;
+
+/// Whether we do the orphan check relative to this crate or
+/// to some remote crate.
+#[derive(Copy, Clone, Debug)]
+enum InCrate {
+    Local,
+    Remote,
+}
+
+#[derive(Debug, Copy, Clone)]
+pub enum Conflict {
+    Upstream,
+    Downstream,
+}
+
+pub struct OverlapResult<'tcx> {
+    pub impl_header: ty::ImplHeader<'tcx>,
+    pub intercrate_ambiguity_causes: Vec<IntercrateAmbiguityCause>,
+
+    /// `true` if the overlap might've been permitted before the shift
+    /// to universes.
+    pub involves_placeholder: bool,
+}
+
+pub fn add_placeholder_note(err: &mut rustc_errors::DiagnosticBuilder<'_>) {
+    err.note(
+        "this behavior recently changed as a result of a bug fix; \
+         see rust-lang/rust#56105 for details",
+    );
+}
+
+/// If there are types that satisfy both impls, invokes `on_overlap`
+/// with a suitably-freshened `ImplHeader` with those types
+/// substituted. Otherwise, invokes `no_overlap`.
+pub fn overlapping_impls<F1, F2, R>(
+    tcx: TyCtxt<'_>,
+    impl1_def_id: DefId,
+    impl2_def_id: DefId,
+    skip_leak_check: SkipLeakCheck,
+    on_overlap: F1,
+    no_overlap: F2,
+) -> R
+where
+    F1: FnOnce(OverlapResult<'_>) -> R,
+    F2: FnOnce() -> R,
+{
+    debug!(
+        "overlapping_impls(\
+           impl1_def_id={:?}, \
+           impl2_def_id={:?})",
+        impl1_def_id, impl2_def_id,
+    );
+
+    let overlaps = tcx.infer_ctxt().enter(|infcx| {
+        let selcx = &mut SelectionContext::intercrate(&infcx);
+        overlap(selcx, skip_leak_check, impl1_def_id, impl2_def_id).is_some()
+    });
+
+    if !overlaps {
+        return no_overlap();
+    }
+
+    // In the case where we detect an error, run the check again, but
+    // this time tracking intercrate ambuiguity causes for better
+    // diagnostics. (These take time and can lead to false errors.)
+    tcx.infer_ctxt().enter(|infcx| {
+        let selcx = &mut SelectionContext::intercrate(&infcx);
+        selcx.enable_tracking_intercrate_ambiguity_causes();
+        on_overlap(overlap(selcx, skip_leak_check, impl1_def_id, impl2_def_id).unwrap())
+    })
+}
+
+fn with_fresh_ty_vars<'cx, 'tcx>(
+    selcx: &mut SelectionContext<'cx, 'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    impl_def_id: DefId,
+) -> ty::ImplHeader<'tcx> {
+    let tcx = selcx.tcx();
+    let impl_substs = selcx.infcx().fresh_substs_for_item(DUMMY_SP, impl_def_id);
+
+    let header = ty::ImplHeader {
+        impl_def_id,
+        self_ty: tcx.type_of(impl_def_id).subst(tcx, impl_substs),
+        trait_ref: tcx.impl_trait_ref(impl_def_id).subst(tcx, impl_substs),
+        predicates: tcx.predicates_of(impl_def_id).instantiate(tcx, impl_substs).predicates,
+    };
+
+    let Normalized { value: mut header, obligations } =
+        traits::normalize(selcx, param_env, ObligationCause::dummy(), &header);
+
+    header.predicates.extend(obligations.into_iter().map(|o| o.predicate));
+    header
+}
+
+/// Can both impl `a` and impl `b` be satisfied by a common type (including
+/// where-clauses)? If so, returns an `ImplHeader` that unifies the two impls.
+fn overlap<'cx, 'tcx>(
+    selcx: &mut SelectionContext<'cx, 'tcx>,
+    skip_leak_check: SkipLeakCheck,
+    a_def_id: DefId,
+    b_def_id: DefId,
+) -> Option<OverlapResult<'tcx>> {
+    debug!("overlap(a_def_id={:?}, b_def_id={:?})", a_def_id, b_def_id);
+
+    selcx.infcx().probe_maybe_skip_leak_check(skip_leak_check.is_yes(), |snapshot| {
+        overlap_within_probe(selcx, a_def_id, b_def_id, snapshot)
+    })
+}
+
+fn overlap_within_probe(
+    selcx: &mut SelectionContext<'cx, 'tcx>,
+    a_def_id: DefId,
+    b_def_id: DefId,
+    snapshot: &CombinedSnapshot<'_, 'tcx>,
+) -> Option<OverlapResult<'tcx>> {
+    // For the purposes of this check, we don't bring any placeholder
+    // types into scope; instead, we replace the generic types with
+    // fresh type variables, and hence we do our evaluations in an
+    // empty environment.
+    let param_env = ty::ParamEnv::empty();
+
+    let a_impl_header = with_fresh_ty_vars(selcx, param_env, a_def_id);
+    let b_impl_header = with_fresh_ty_vars(selcx, param_env, b_def_id);
+
+    debug!("overlap: a_impl_header={:?}", a_impl_header);
+    debug!("overlap: b_impl_header={:?}", b_impl_header);
+
+    // Do `a` and `b` unify? If not, no overlap.
+    let obligations = match selcx
+        .infcx()
+        .at(&ObligationCause::dummy(), param_env)
+        .eq_impl_headers(&a_impl_header, &b_impl_header)
+    {
+        Ok(InferOk { obligations, value: () }) => obligations,
+        Err(_) => {
+            return None;
+        }
+    };
+
+    debug!("overlap: unification check succeeded");
+
+    // Are any of the obligations unsatisfiable? If so, no overlap.
+    let infcx = selcx.infcx();
+    let opt_failing_obligation = a_impl_header
+        .predicates
+        .iter()
+        .chain(&b_impl_header.predicates)
+        .map(|p| infcx.resolve_vars_if_possible(p))
+        .map(|p| Obligation {
+            cause: ObligationCause::dummy(),
+            param_env,
+            recursion_depth: 0,
+            predicate: p,
+        })
+        .chain(obligations)
+        .find(|o| !selcx.predicate_may_hold_fatal(o));
+    // FIXME: the call to `selcx.predicate_may_hold_fatal` above should be ported
+    // to the canonical trait query form, `infcx.predicate_may_hold`, once
+    // the new system supports intercrate mode (which coherence needs).
+
+    if let Some(failing_obligation) = opt_failing_obligation {
+        debug!("overlap: obligation unsatisfiable {:?}", failing_obligation);
+        return None;
+    }
+
+    let impl_header = selcx.infcx().resolve_vars_if_possible(&a_impl_header);
+    let intercrate_ambiguity_causes = selcx.take_intercrate_ambiguity_causes();
+    debug!("overlap: intercrate_ambiguity_causes={:#?}", intercrate_ambiguity_causes);
+
+    let involves_placeholder = match selcx.infcx().region_constraints_added_in_snapshot(snapshot) {
+        Some(true) => true,
+        _ => false,
+    };
+
+    Some(OverlapResult { impl_header, intercrate_ambiguity_causes, involves_placeholder })
+}
+
+pub fn trait_ref_is_knowable<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    trait_ref: ty::TraitRef<'tcx>,
+) -> Option<Conflict> {
+    debug!("trait_ref_is_knowable(trait_ref={:?})", trait_ref);
+    if orphan_check_trait_ref(tcx, trait_ref, InCrate::Remote).is_ok() {
+        // A downstream or cousin crate is allowed to implement some
+        // substitution of this trait-ref.
+        return Some(Conflict::Downstream);
+    }
+
+    if trait_ref_is_local_or_fundamental(tcx, trait_ref) {
+        // This is a local or fundamental trait, so future-compatibility
+        // is no concern. We know that downstream/cousin crates are not
+        // allowed to implement a substitution of this trait ref, which
+        // means impls could only come from dependencies of this crate,
+        // which we already know about.
+        return None;
+    }
+
+    // This is a remote non-fundamental trait, so if another crate
+    // can be the "final owner" of a substitution of this trait-ref,
+    // they are allowed to implement it future-compatibly.
+    //
+    // However, if we are a final owner, then nobody else can be,
+    // and if we are an intermediate owner, then we don't care
+    // about future-compatibility, which means that we're OK if
+    // we are an owner.
+    if orphan_check_trait_ref(tcx, trait_ref, InCrate::Local).is_ok() {
+        debug!("trait_ref_is_knowable: orphan check passed");
+        return None;
+    } else {
+        debug!("trait_ref_is_knowable: nonlocal, nonfundamental, unowned");
+        return Some(Conflict::Upstream);
+    }
+}
+
+pub fn trait_ref_is_local_or_fundamental<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    trait_ref: ty::TraitRef<'tcx>,
+) -> bool {
+    trait_ref.def_id.krate == LOCAL_CRATE || tcx.has_attr(trait_ref.def_id, sym::fundamental)
+}
+
+pub enum OrphanCheckErr<'tcx> {
+    NonLocalInputType(Vec<(Ty<'tcx>, bool /* Is this the first input type? */)>),
+    UncoveredTy(Ty<'tcx>, Option<Ty<'tcx>>),
+}
+
+/// Checks the coherence orphan rules. `impl_def_id` should be the
+/// `DefId` of a trait impl. To pass, either the trait must be local, or else
+/// two conditions must be satisfied:
+///
+/// 1. All type parameters in `Self` must be "covered" by some local type constructor.
+/// 2. Some local type must appear in `Self`.
+pub fn orphan_check(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Result<(), OrphanCheckErr<'_>> {
+    debug!("orphan_check({:?})", impl_def_id);
+
+    // We only except this routine to be invoked on implementations
+    // of a trait, not inherent implementations.
+    let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
+    debug!("orphan_check: trait_ref={:?}", trait_ref);
+
+    // If the *trait* is local to the crate, ok.
+    if trait_ref.def_id.is_local() {
+        debug!("trait {:?} is local to current crate", trait_ref.def_id);
+        return Ok(());
+    }
+
+    orphan_check_trait_ref(tcx, trait_ref, InCrate::Local)
+}
+
+/// Checks whether a trait-ref is potentially implementable by a crate.
+///
+/// The current rule is that a trait-ref orphan checks in a crate C:
+///
+/// 1. Order the parameters in the trait-ref in subst order - Self first,
+///    others linearly (e.g., `<U as Foo<V, W>>` is U < V < W).
+/// 2. Of these type parameters, there is at least one type parameter
+///    in which, walking the type as a tree, you can reach a type local
+///    to C where all types in-between are fundamental types. Call the
+///    first such parameter the "local key parameter".
+///     - e.g., `Box<LocalType>` is OK, because you can visit LocalType
+///       going through `Box`, which is fundamental.
+///     - similarly, `FundamentalPair<Vec<()>, Box<LocalType>>` is OK for
+///       the same reason.
+///     - but (knowing that `Vec<T>` is non-fundamental, and assuming it's
+///       not local), `Vec<LocalType>` is bad, because `Vec<->` is between
+///       the local type and the type parameter.
+/// 3. Every type parameter before the local key parameter is fully known in C.
+///     - e.g., `impl<T> T: Trait<LocalType>` is bad, because `T` might be
+///       an unknown type.
+///     - but `impl<T> LocalType: Trait<T>` is OK, because `LocalType`
+///       occurs before `T`.
+/// 4. Every type in the local key parameter not known in C, going
+///    through the parameter's type tree, must appear only as a subtree of
+///    a type local to C, with only fundamental types between the type
+///    local to C and the local key parameter.
+///     - e.g., `Vec<LocalType<T>>>` (or equivalently `Box<Vec<LocalType<T>>>`)
+///     is bad, because the only local type with `T` as a subtree is
+///     `LocalType<T>`, and `Vec<->` is between it and the type parameter.
+///     - similarly, `FundamentalPair<LocalType<T>, T>` is bad, because
+///     the second occurrence of `T` is not a subtree of *any* local type.
+///     - however, `LocalType<Vec<T>>` is OK, because `T` is a subtree of
+///     `LocalType<Vec<T>>`, which is local and has no types between it and
+///     the type parameter.
+///
+/// The orphan rules actually serve several different purposes:
+///
+/// 1. They enable link-safety - i.e., 2 mutually-unknowing crates (where
+///    every type local to one crate is unknown in the other) can't implement
+///    the same trait-ref. This follows because it can be seen that no such
+///    type can orphan-check in 2 such crates.
+///
+///    To check that a local impl follows the orphan rules, we check it in
+///    InCrate::Local mode, using type parameters for the "generic" types.
+///
+/// 2. They ground negative reasoning for coherence. If a user wants to
+///    write both a conditional blanket impl and a specific impl, we need to
+///    make sure they do not overlap. For example, if we write
+///    ```
+///    impl<T> IntoIterator for Vec<T>
+///    impl<T: Iterator> IntoIterator for T
+///    ```
+///    We need to be able to prove that `Vec<$0>: !Iterator` for every type $0.
+///    We can observe that this holds in the current crate, but we need to make
+///    sure this will also hold in all unknown crates (both "independent" crates,
+///    which we need for link-safety, and also child crates, because we don't want
+///    child crates to get error for impl conflicts in a *dependency*).
+///
+///    For that, we only allow negative reasoning if, for every assignment to the
+///    inference variables, every unknown crate would get an orphan error if they
+///    try to implement this trait-ref. To check for this, we use InCrate::Remote
+///    mode. That is sound because we already know all the impls from known crates.
+///
+/// 3. For non-#[fundamental] traits, they guarantee that parent crates can
+///    add "non-blanket" impls without breaking negative reasoning in dependent
+///    crates. This is the "rebalancing coherence" (RFC 1023) restriction.
+///
+///    For that, we only a allow crate to perform negative reasoning on
+///    non-local-non-#[fundamental] only if there's a local key parameter as per (2).
+///
+///    Because we never perform negative reasoning generically (coherence does
+///    not involve type parameters), this can be interpreted as doing the full
+///    orphan check (using InCrate::Local mode), substituting non-local known
+///    types for all inference variables.
+///
+///    This allows for crates to future-compatibly add impls as long as they
+///    can't apply to types with a key parameter in a child crate - applying
+///    the rules, this basically means that every type parameter in the impl
+///    must appear behind a non-fundamental type (because this is not a
+///    type-system requirement, crate owners might also go for "semantic
+///    future-compatibility" involving things such as sealed traits, but
+///    the above requirement is sufficient, and is necessary in "open world"
+///    cases).
+///
+/// Note that this function is never called for types that have both type
+/// parameters and inference variables.
+fn orphan_check_trait_ref<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    trait_ref: ty::TraitRef<'tcx>,
+    in_crate: InCrate,
+) -> Result<(), OrphanCheckErr<'tcx>> {
+    debug!("orphan_check_trait_ref(trait_ref={:?}, in_crate={:?})", trait_ref, in_crate);
+
+    if trait_ref.needs_infer() && trait_ref.needs_subst() {
+        bug!(
+            "can't orphan check a trait ref with both params and inference variables {:?}",
+            trait_ref
+        );
+    }
+
+    // Given impl<P1..=Pn> Trait<T1..=Tn> for T0, an impl is valid only
+    // if at least one of the following is true:
+    //
+    // - Trait is a local trait
+    // (already checked in orphan_check prior to calling this function)
+    // - All of
+    //     - At least one of the types T0..=Tn must be a local type.
+    //      Let Ti be the first such type.
+    //     - No uncovered type parameters P1..=Pn may appear in T0..Ti (excluding Ti)
+    //
+    fn uncover_fundamental_ty<'tcx>(
+        tcx: TyCtxt<'tcx>,
+        ty: Ty<'tcx>,
+        in_crate: InCrate,
+    ) -> Vec<Ty<'tcx>> {
+        if fundamental_ty(ty) && ty_is_non_local(ty, in_crate).is_some() {
+            ty.walk_shallow().flat_map(|ty| uncover_fundamental_ty(tcx, ty, in_crate)).collect()
+        } else {
+            vec![ty]
+        }
+    }
+
+    let mut non_local_spans = vec![];
+    for (i, input_ty) in
+        trait_ref.input_types().flat_map(|ty| uncover_fundamental_ty(tcx, ty, in_crate)).enumerate()
+    {
+        debug!("orphan_check_trait_ref: check ty `{:?}`", input_ty);
+        let non_local_tys = ty_is_non_local(input_ty, in_crate);
+        if non_local_tys.is_none() {
+            debug!("orphan_check_trait_ref: ty_is_local `{:?}`", input_ty);
+            return Ok(());
+        } else if let ty::Param(_) = input_ty.kind {
+            debug!("orphan_check_trait_ref: uncovered ty: `{:?}`", input_ty);
+            let local_type = trait_ref
+                .input_types()
+                .flat_map(|ty| uncover_fundamental_ty(tcx, ty, in_crate))
+                .find(|ty| ty_is_non_local_constructor(ty, in_crate).is_none());
+
+            debug!("orphan_check_trait_ref: uncovered ty local_type: `{:?}`", local_type);
+
+            return Err(OrphanCheckErr::UncoveredTy(input_ty, local_type));
+        }
+        if let Some(non_local_tys) = non_local_tys {
+            for input_ty in non_local_tys {
+                non_local_spans.push((input_ty, i == 0));
+            }
+        }
+    }
+    // If we exit above loop, never found a local type.
+    debug!("orphan_check_trait_ref: no local type");
+    Err(OrphanCheckErr::NonLocalInputType(non_local_spans))
+}
+
+fn ty_is_non_local<'t>(ty: Ty<'t>, in_crate: InCrate) -> Option<Vec<Ty<'t>>> {
+    match ty_is_non_local_constructor(ty, in_crate) {
+        Some(ty) => {
+            if !fundamental_ty(ty) {
+                Some(vec![ty])
+            } else {
+                let tys: Vec<_> = ty
+                    .walk_shallow()
+                    .filter_map(|t| ty_is_non_local(t, in_crate))
+                    .flat_map(|i| i)
+                    .collect();
+                if tys.is_empty() { None } else { Some(tys) }
+            }
+        }
+        None => None,
+    }
+}
+
+fn fundamental_ty(ty: Ty<'_>) -> bool {
+    match ty.kind {
+        ty::Ref(..) => true,
+        ty::Adt(def, _) => def.is_fundamental(),
+        _ => false,
+    }
+}
+
+fn def_id_is_local(def_id: DefId, in_crate: InCrate) -> bool {
+    match in_crate {
+        // The type is local to *this* crate - it will not be
+        // local in any other crate.
+        InCrate::Remote => false,
+        InCrate::Local => def_id.is_local(),
+    }
+}
+
+fn ty_is_non_local_constructor(ty: Ty<'_>, in_crate: InCrate) -> Option<Ty<'_>> {
+    debug!("ty_is_non_local_constructor({:?})", ty);
+
+    match ty.kind {
+        ty::Bool
+        | ty::Char
+        | ty::Int(..)
+        | ty::Uint(..)
+        | ty::Float(..)
+        | ty::Str
+        | ty::FnDef(..)
+        | ty::FnPtr(_)
+        | ty::Array(..)
+        | ty::Slice(..)
+        | ty::RawPtr(..)
+        | ty::Ref(..)
+        | ty::Never
+        | ty::Tuple(..)
+        | ty::Param(..)
+        | ty::Projection(..) => Some(ty),
+
+        ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) => match in_crate {
+            InCrate::Local => Some(ty),
+            // The inference variable might be unified with a local
+            // type in that remote crate.
+            InCrate::Remote => None,
+        },
+
+        ty::Adt(def, _) => {
+            if def_id_is_local(def.did, in_crate) {
+                None
+            } else {
+                Some(ty)
+            }
+        }
+        ty::Foreign(did) => {
+            if def_id_is_local(did, in_crate) {
+                None
+            } else {
+                Some(ty)
+            }
+        }
+        ty::Opaque(..) => {
+            // This merits some explanation.
+            // Normally, opaque types are not involed when performing
+            // coherence checking, since it is illegal to directly
+            // implement a trait on an opaque type. However, we might
+            // end up looking at an opaque type during coherence checking
+            // if an opaque type gets used within another type (e.g. as
+            // a type parameter). This requires us to decide whether or
+            // not an opaque type should be considered 'local' or not.
+            //
+            // We choose to treat all opaque types as non-local, even
+            // those that appear within the same crate. This seems
+            // somewhat surprising at first, but makes sense when
+            // you consider that opaque types are supposed to hide
+            // the underlying type *within the same crate*. When an
+            // opaque type is used from outside the module
+            // where it is declared, it should be impossible to observe
+            // anyything about it other than the traits that it implements.
+            //
+            // The alternative would be to look at the underlying type
+            // to determine whether or not the opaque type itself should
+            // be considered local. However, this could make it a breaking change
+            // to switch the underlying ('defining') type from a local type
+            // to a remote type. This would violate the rule that opaque
+            // types should be completely opaque apart from the traits
+            // that they implement, so we don't use this behavior.
+            Some(ty)
+        }
+
+        ty::Dynamic(ref tt, ..) => {
+            if let Some(principal) = tt.principal() {
+                if def_id_is_local(principal.def_id(), in_crate) { None } else { Some(ty) }
+            } else {
+                Some(ty)
+            }
+        }
+
+        ty::Error => None,
+
+        ty::UnnormalizedProjection(..)
+        | ty::Closure(..)
+        | ty::Generator(..)
+        | ty::GeneratorWitness(..) => bug!("ty_is_local invoked on unexpected type: {:?}", ty),
+    }
+}
diff --git a/src/librustc_trait_selection/traits/engine.rs b/src/librustc_trait_selection/traits/engine.rs
new file mode 100644 (file)
index 0000000..ee4715e
--- /dev/null
@@ -0,0 +1,14 @@
+use rustc::ty::TyCtxt;
+
+use super::FulfillmentContext;
+use super::TraitEngine;
+
+pub trait TraitEngineExt<'tcx> {
+    fn new(tcx: TyCtxt<'tcx>) -> Box<Self>;
+}
+
+impl<'tcx> TraitEngineExt<'tcx> for dyn TraitEngine<'tcx> {
+    fn new(_tcx: TyCtxt<'tcx>) -> Box<Self> {
+        Box::new(FulfillmentContext::new())
+    }
+}
diff --git a/src/librustc_trait_selection/traits/error_reporting/mod.rs b/src/librustc_trait_selection/traits/error_reporting/mod.rs
new file mode 100644 (file)
index 0000000..ef62958
--- /dev/null
@@ -0,0 +1,1900 @@
+pub mod on_unimplemented;
+pub mod suggestions;
+
+use super::{
+    ConstEvalFailure, EvaluationResult, FulfillmentError, FulfillmentErrorCode,
+    MismatchedProjectionTypes, Obligation, ObligationCause, ObligationCauseCode,
+    OnUnimplementedDirective, OnUnimplementedNote, OutputTypeParameterMismatch, Overflow,
+    PredicateObligation, SelectionContext, SelectionError, TraitNotObjectSafe,
+};
+
+use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode};
+use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use crate::infer::{self, InferCtxt, TyCtxtInferExt};
+use rustc::mir::interpret::ErrorHandled;
+use rustc::ty::error::ExpectedFound;
+use rustc::ty::fast_reject;
+use rustc::ty::fold::TypeFolder;
+use rustc::ty::SubtypePredicate;
+use rustc::ty::{
+    self, AdtKind, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness,
+};
+use rustc_data_structures::fx::FxHashMap;
+use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
+use rustc_hir as hir;
+use rustc_hir::def_id::{DefId, LOCAL_CRATE};
+use rustc_hir::{Node, QPath, TyKind, WhereBoundPredicate, WherePredicate};
+use rustc_session::DiagnosticMessageId;
+use rustc_span::source_map::SourceMap;
+use rustc_span::{ExpnKind, Span, DUMMY_SP};
+use std::fmt;
+
+use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
+use crate::traits::query::normalize::AtExt as _;
+use on_unimplemented::InferCtxtExt as _;
+use suggestions::InferCtxtExt as _;
+
+pub use rustc_infer::traits::error_reporting::*;
+
+pub trait InferCtxtExt<'tcx> {
+    fn report_fulfillment_errors(
+        &self,
+        errors: &[FulfillmentError<'tcx>],
+        body_id: Option<hir::BodyId>,
+        fallback_has_occurred: bool,
+    );
+
+    fn report_overflow_error<T>(
+        &self,
+        obligation: &Obligation<'tcx, T>,
+        suggest_increasing_limit: bool,
+    ) -> !
+    where
+        T: fmt::Display + TypeFoldable<'tcx>;
+
+    fn report_overflow_error_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> !;
+
+    fn report_selection_error(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        error: &SelectionError<'tcx>,
+        fallback_has_occurred: bool,
+        points_at_arg: bool,
+    );
+
+    /// Given some node representing a fn-like thing in the HIR map,
+    /// returns a span and `ArgKind` information that describes the
+    /// arguments it expects. This can be supplied to
+    /// `report_arg_count_mismatch`.
+    fn get_fn_like_arguments(&self, node: Node<'_>) -> (Span, Vec<ArgKind>);
+
+    /// Reports an error when the number of arguments needed by a
+    /// trait match doesn't match the number that the expression
+    /// provides.
+    fn report_arg_count_mismatch(
+        &self,
+        span: Span,
+        found_span: Option<Span>,
+        expected_args: Vec<ArgKind>,
+        found_args: Vec<ArgKind>,
+        is_closure: bool,
+    ) -> DiagnosticBuilder<'tcx>;
+}
+
+impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
+    fn report_fulfillment_errors(
+        &self,
+        errors: &[FulfillmentError<'tcx>],
+        body_id: Option<hir::BodyId>,
+        fallback_has_occurred: bool,
+    ) {
+        #[derive(Debug)]
+        struct ErrorDescriptor<'tcx> {
+            predicate: ty::Predicate<'tcx>,
+            index: Option<usize>, // None if this is an old error
+        }
+
+        let mut error_map: FxHashMap<_, Vec<_>> = self
+            .reported_trait_errors
+            .borrow()
+            .iter()
+            .map(|(&span, predicates)| {
+                (
+                    span,
+                    predicates
+                        .iter()
+                        .map(|&predicate| ErrorDescriptor { predicate, index: None })
+                        .collect(),
+                )
+            })
+            .collect();
+
+        for (index, error) in errors.iter().enumerate() {
+            // We want to ignore desugarings here: spans are equivalent even
+            // if one is the result of a desugaring and the other is not.
+            let mut span = error.obligation.cause.span;
+            let expn_data = span.ctxt().outer_expn_data();
+            if let ExpnKind::Desugaring(_) = expn_data.kind {
+                span = expn_data.call_site;
+            }
+
+            error_map.entry(span).or_default().push(ErrorDescriptor {
+                predicate: error.obligation.predicate,
+                index: Some(index),
+            });
+
+            self.reported_trait_errors
+                .borrow_mut()
+                .entry(span)
+                .or_default()
+                .push(error.obligation.predicate.clone());
+        }
+
+        // We do this in 2 passes because we want to display errors in order, though
+        // maybe it *is* better to sort errors by span or something.
+        let mut is_suppressed = vec![false; errors.len()];
+        for (_, error_set) in error_map.iter() {
+            // We want to suppress "duplicate" errors with the same span.
+            for error in error_set {
+                if let Some(index) = error.index {
+                    // Suppress errors that are either:
+                    // 1) strictly implied by another error.
+                    // 2) implied by an error with a smaller index.
+                    for error2 in error_set {
+                        if error2.index.map_or(false, |index2| is_suppressed[index2]) {
+                            // Avoid errors being suppressed by already-suppressed
+                            // errors, to prevent all errors from being suppressed
+                            // at once.
+                            continue;
+                        }
+
+                        if self.error_implies(&error2.predicate, &error.predicate)
+                            && !(error2.index >= error.index
+                                && self.error_implies(&error.predicate, &error2.predicate))
+                        {
+                            info!("skipping {:?} (implied by {:?})", error, error2);
+                            is_suppressed[index] = true;
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+
+        for (error, suppressed) in errors.iter().zip(is_suppressed) {
+            if !suppressed {
+                self.report_fulfillment_error(error, body_id, fallback_has_occurred);
+            }
+        }
+    }
+
+    /// Reports that an overflow has occurred and halts compilation. We
+    /// halt compilation unconditionally because it is important that
+    /// overflows never be masked -- they basically represent computations
+    /// whose result could not be truly determined and thus we can't say
+    /// if the program type checks or not -- and they are unusual
+    /// occurrences in any case.
+    fn report_overflow_error<T>(
+        &self,
+        obligation: &Obligation<'tcx, T>,
+        suggest_increasing_limit: bool,
+    ) -> !
+    where
+        T: fmt::Display + TypeFoldable<'tcx>,
+    {
+        let predicate = self.resolve_vars_if_possible(&obligation.predicate);
+        let mut err = struct_span_err!(
+            self.tcx.sess,
+            obligation.cause.span,
+            E0275,
+            "overflow evaluating the requirement `{}`",
+            predicate
+        );
+
+        if suggest_increasing_limit {
+            self.suggest_new_overflow_limit(&mut err);
+        }
+
+        self.note_obligation_cause_code(
+            &mut err,
+            &obligation.predicate,
+            &obligation.cause.code,
+            &mut vec![],
+        );
+
+        err.emit();
+        self.tcx.sess.abort_if_errors();
+        bug!();
+    }
+
+    /// Reports that a cycle was detected which led to overflow and halts
+    /// compilation. This is equivalent to `report_overflow_error` except
+    /// that we can give a more helpful error message (and, in particular,
+    /// we do not suggest increasing the overflow limit, which is not
+    /// going to help).
+    fn report_overflow_error_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> ! {
+        let cycle = self.resolve_vars_if_possible(&cycle.to_owned());
+        assert!(!cycle.is_empty());
+
+        debug!("report_overflow_error_cycle: cycle={:?}", cycle);
+
+        self.report_overflow_error(&cycle[0], false);
+    }
+
+    fn report_selection_error(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        error: &SelectionError<'tcx>,
+        fallback_has_occurred: bool,
+        points_at_arg: bool,
+    ) {
+        let tcx = self.tcx;
+        let span = obligation.cause.span;
+
+        let mut err = match *error {
+            SelectionError::Unimplemented => {
+                if let ObligationCauseCode::CompareImplMethodObligation {
+                    item_name,
+                    impl_item_def_id,
+                    trait_item_def_id,
+                }
+                | ObligationCauseCode::CompareImplTypeObligation {
+                    item_name,
+                    impl_item_def_id,
+                    trait_item_def_id,
+                } = obligation.cause.code
+                {
+                    self.report_extra_impl_obligation(
+                        span,
+                        item_name,
+                        impl_item_def_id,
+                        trait_item_def_id,
+                        &format!("`{}`", obligation.predicate),
+                    )
+                    .emit();
+                    return;
+                }
+                match obligation.predicate {
+                    ty::Predicate::Trait(ref trait_predicate, _) => {
+                        let trait_predicate = self.resolve_vars_if_possible(trait_predicate);
+
+                        if self.tcx.sess.has_errors() && trait_predicate.references_error() {
+                            return;
+                        }
+                        let trait_ref = trait_predicate.to_poly_trait_ref();
+                        let (post_message, pre_message, type_def) = self
+                            .get_parent_trait_ref(&obligation.cause.code)
+                            .map(|(t, s)| {
+                                (
+                                    format!(" in `{}`", t),
+                                    format!("within `{}`, ", t),
+                                    s.map(|s| (format!("within this `{}`", t), s)),
+                                )
+                            })
+                            .unwrap_or_default();
+
+                        let OnUnimplementedNote { message, label, note, enclosing_scope } =
+                            self.on_unimplemented_note(trait_ref, obligation);
+                        let have_alt_message = message.is_some() || label.is_some();
+                        let is_try = self
+                            .tcx
+                            .sess
+                            .source_map()
+                            .span_to_snippet(span)
+                            .map(|s| &s == "?")
+                            .unwrap_or(false);
+                        let is_from = format!("{}", trait_ref.print_only_trait_path())
+                            .starts_with("std::convert::From<");
+                        let (message, note) = if is_try && is_from {
+                            (
+                                Some(format!(
+                                    "`?` couldn't convert the error to `{}`",
+                                    trait_ref.self_ty(),
+                                )),
+                                Some(
+                                    "the question mark operation (`?`) implicitly performs a \
+                                     conversion on the error value using the `From` trait"
+                                        .to_owned(),
+                                ),
+                            )
+                        } else {
+                            (message, note)
+                        };
+
+                        let mut err = struct_span_err!(
+                            self.tcx.sess,
+                            span,
+                            E0277,
+                            "{}",
+                            message.unwrap_or_else(|| format!(
+                                "the trait bound `{}` is not satisfied{}",
+                                trait_ref.without_const().to_predicate(),
+                                post_message,
+                            ))
+                        );
+
+                        let explanation =
+                            if obligation.cause.code == ObligationCauseCode::MainFunctionType {
+                                "consider using `()`, or a `Result`".to_owned()
+                            } else {
+                                format!(
+                                    "{}the trait `{}` is not implemented for `{}`",
+                                    pre_message,
+                                    trait_ref.print_only_trait_path(),
+                                    trait_ref.self_ty(),
+                                )
+                            };
+
+                        if self.suggest_add_reference_to_arg(
+                            &obligation,
+                            &mut err,
+                            &trait_ref,
+                            points_at_arg,
+                            have_alt_message,
+                        ) {
+                            self.note_obligation_cause(&mut err, obligation);
+                            err.emit();
+                            return;
+                        }
+                        if let Some(ref s) = label {
+                            // If it has a custom `#[rustc_on_unimplemented]`
+                            // error message, let's display it as the label!
+                            err.span_label(span, s.as_str());
+                            err.help(&explanation);
+                        } else {
+                            err.span_label(span, explanation);
+                        }
+                        if let Some((msg, span)) = type_def {
+                            err.span_label(span, &msg);
+                        }
+                        if let Some(ref s) = note {
+                            // If it has a custom `#[rustc_on_unimplemented]` note, let's display it
+                            err.note(s.as_str());
+                        }
+                        if let Some(ref s) = enclosing_scope {
+                            let enclosing_scope_span = tcx.def_span(
+                                tcx.hir()
+                                    .opt_local_def_id(obligation.cause.body_id)
+                                    .unwrap_or_else(|| {
+                                        tcx.hir().body_owner_def_id(hir::BodyId {
+                                            hir_id: obligation.cause.body_id,
+                                        })
+                                    }),
+                            );
+
+                            err.span_label(enclosing_scope_span, s.as_str());
+                        }
+
+                        self.suggest_borrow_on_unsized_slice(&obligation.cause.code, &mut err);
+                        self.suggest_fn_call(&obligation, &mut err, &trait_ref, points_at_arg);
+                        self.suggest_remove_reference(&obligation, &mut err, &trait_ref);
+                        self.suggest_semicolon_removal(&obligation, &mut err, span, &trait_ref);
+                        self.note_version_mismatch(&mut err, &trait_ref);
+                        if self.suggest_impl_trait(&mut err, span, &obligation, &trait_ref) {
+                            err.emit();
+                            return;
+                        }
+
+                        // Try to report a help message
+                        if !trait_ref.has_infer_types_or_consts()
+                            && self.predicate_can_apply(obligation.param_env, trait_ref)
+                        {
+                            // If a where-clause may be useful, remind the
+                            // user that they can add it.
+                            //
+                            // don't display an on-unimplemented note, as
+                            // 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,
+                            );
+                        }
+
+                        // If this error is due to `!: Trait` not implemented but `(): Trait` is
+                        // implemented, and fallback has occurred, then it could be due to a
+                        // variable that used to fallback to `()` now falling back to `!`. Issue a
+                        // note informing about the change in behaviour.
+                        if trait_predicate.skip_binder().self_ty().is_never()
+                            && fallback_has_occurred
+                        {
+                            let predicate = trait_predicate.map_bound(|mut trait_pred| {
+                                trait_pred.trait_ref.substs = self.tcx.mk_substs_trait(
+                                    self.tcx.mk_unit(),
+                                    &trait_pred.trait_ref.substs[1..],
+                                );
+                                trait_pred
+                            });
+                            let unit_obligation = Obligation {
+                                predicate: ty::Predicate::Trait(
+                                    predicate,
+                                    hir::Constness::NotConst,
+                                ),
+                                ..obligation.clone()
+                            };
+                            if self.predicate_may_hold(&unit_obligation) {
+                                err.note(
+                                    "the trait is implemented for `()`. \
+                                     Possibly this error has been caused by changes to \
+                                     Rust's type-inference algorithm (see issue #48950 \
+                                     <https://github.com/rust-lang/rust/issues/48950> \
+                                     for more information). Consider whether you meant to use \
+                                     the type `()` here instead.",
+                                );
+                            }
+                        }
+
+                        err
+                    }
+
+                    ty::Predicate::Subtype(ref predicate) => {
+                        // Errors for Subtype predicates show up as
+                        // `FulfillmentErrorCode::CodeSubtypeError`,
+                        // not selection error.
+                        span_bug!(span, "subtype requirement gave wrong error: `{:?}`", predicate)
+                    }
+
+                    ty::Predicate::RegionOutlives(ref predicate) => {
+                        let predicate = self.resolve_vars_if_possible(predicate);
+                        let err = self
+                            .region_outlives_predicate(&obligation.cause, &predicate)
+                            .err()
+                            .unwrap();
+                        struct_span_err!(
+                            self.tcx.sess,
+                            span,
+                            E0279,
+                            "the requirement `{}` is not satisfied (`{}`)",
+                            predicate,
+                            err,
+                        )
+                    }
+
+                    ty::Predicate::Projection(..) | ty::Predicate::TypeOutlives(..) => {
+                        let predicate = self.resolve_vars_if_possible(&obligation.predicate);
+                        struct_span_err!(
+                            self.tcx.sess,
+                            span,
+                            E0280,
+                            "the requirement `{}` is not satisfied",
+                            predicate
+                        )
+                    }
+
+                    ty::Predicate::ObjectSafe(trait_def_id) => {
+                        let violations = self.tcx.object_safety_violations(trait_def_id);
+                        report_object_safety_error(self.tcx, span, trait_def_id, violations)
+                    }
+
+                    ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => {
+                        let found_kind = self.closure_kind(closure_def_id, closure_substs).unwrap();
+                        let closure_span = self
+                            .tcx
+                            .sess
+                            .source_map()
+                            .def_span(self.tcx.hir().span_if_local(closure_def_id).unwrap());
+                        let hir_id = self.tcx.hir().as_local_hir_id(closure_def_id).unwrap();
+                        let mut err = struct_span_err!(
+                            self.tcx.sess,
+                            closure_span,
+                            E0525,
+                            "expected a closure that implements the `{}` trait, \
+                             but this closure only implements `{}`",
+                            kind,
+                            found_kind
+                        );
+
+                        err.span_label(
+                            closure_span,
+                            format!("this closure implements `{}`, not `{}`", found_kind, kind),
+                        );
+                        err.span_label(
+                            obligation.cause.span,
+                            format!("the requirement to implement `{}` derives from here", kind),
+                        );
+
+                        // Additional context information explaining why the closure only implements
+                        // a particular trait.
+                        if let Some(tables) = self.in_progress_tables {
+                            let tables = tables.borrow();
+                            match (found_kind, tables.closure_kind_origins().get(hir_id)) {
+                                (ty::ClosureKind::FnOnce, Some((span, name))) => {
+                                    err.span_label(
+                                        *span,
+                                        format!(
+                                            "closure is `FnOnce` because it moves the \
+                                         variable `{}` out of its environment",
+                                            name
+                                        ),
+                                    );
+                                }
+                                (ty::ClosureKind::FnMut, Some((span, name))) => {
+                                    err.span_label(
+                                        *span,
+                                        format!(
+                                            "closure is `FnMut` because it mutates the \
+                                         variable `{}` here",
+                                            name
+                                        ),
+                                    );
+                                }
+                                _ => {}
+                            }
+                        }
+
+                        err.emit();
+                        return;
+                    }
+
+                    ty::Predicate::WellFormed(ty) => {
+                        // WF predicates cannot themselves make
+                        // errors. They can only block due to
+                        // ambiguity; otherwise, they always
+                        // degenerate into other obligations
+                        // (which may fail).
+                        span_bug!(span, "WF predicate not satisfied for {:?}", ty);
+                    }
+
+                    ty::Predicate::ConstEvaluatable(..) => {
+                        // Errors for `ConstEvaluatable` predicates show up as
+                        // `SelectionError::ConstEvalFailure`,
+                        // not `Unimplemented`.
+                        span_bug!(
+                            span,
+                            "const-evaluatable requirement gave wrong error: `{:?}`",
+                            obligation
+                        )
+                    }
+                }
+            }
+
+            OutputTypeParameterMismatch(ref found_trait_ref, ref expected_trait_ref, _) => {
+                let found_trait_ref = self.resolve_vars_if_possible(&*found_trait_ref);
+                let expected_trait_ref = self.resolve_vars_if_possible(&*expected_trait_ref);
+
+                if expected_trait_ref.self_ty().references_error() {
+                    return;
+                }
+
+                let found_trait_ty = found_trait_ref.self_ty();
+
+                let found_did = match found_trait_ty.kind {
+                    ty::Closure(did, _) | ty::Foreign(did) | ty::FnDef(did, _) => Some(did),
+                    ty::Adt(def, _) => Some(def.did),
+                    _ => None,
+                };
+
+                let found_span = found_did
+                    .and_then(|did| 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()],
+                };
+
+                let expected_ty = expected_trait_ref.skip_binder().substs.type_at(1);
+                let expected = match expected_ty.kind {
+                    ty::Tuple(ref tys) => tys
+                        .iter()
+                        .map(|t| ArgKind::from_expected_ty(t.expect_ty(), Some(span)))
+                        .collect(),
+                    _ => vec![ArgKind::Arg("_".to_owned(), expected_ty.to_string())],
+                };
+
+                if found.len() == expected.len() {
+                    self.report_closure_arg_mismatch(
+                        span,
+                        found_span,
+                        found_trait_ref,
+                        expected_trait_ref,
+                    )
+                } else {
+                    let (closure_span, found) = found_did
+                        .and_then(|did| self.tcx.hir().get_if_local(did))
+                        .map(|node| {
+                            let (found_span, found) = self.get_fn_like_arguments(node);
+                            (Some(found_span), found)
+                        })
+                        .unwrap_or((found_span, found));
+
+                    self.report_arg_count_mismatch(
+                        span,
+                        closure_span,
+                        expected,
+                        found,
+                        found_trait_ty.is_closure(),
+                    )
+                }
+            }
+
+            TraitNotObjectSafe(did) => {
+                let violations = self.tcx.object_safety_violations(did);
+                report_object_safety_error(self.tcx, span, did, violations)
+            }
+
+            ConstEvalFailure(ErrorHandled::TooGeneric) => {
+                // In this instance, we have a const expression containing an unevaluated
+                // generic parameter. We have no idea whether this expression is valid or
+                // not (e.g. it might result in an error), but we don't want to just assume
+                // that it's okay, because that might result in post-monomorphisation time
+                // errors. The onus is really on the caller to provide values that it can
+                // prove are well-formed.
+                let mut err = self
+                    .tcx
+                    .sess
+                    .struct_span_err(span, "constant expression depends on a generic parameter");
+                // FIXME(const_generics): we should suggest to the user how they can resolve this
+                // issue. However, this is currently not actually possible
+                // (see https://github.com/rust-lang/rust/issues/66962#issuecomment-575907083).
+                err.note("this may fail depending on what value the parameter takes");
+                err
+            }
+
+            // Already reported in the query.
+            ConstEvalFailure(ErrorHandled::Reported) => {
+                self.tcx.sess.delay_span_bug(span, "constant in type had an ignored error");
+                return;
+            }
+
+            Overflow => {
+                bug!("overflow should be handled before the `report_selection_error` path");
+            }
+        };
+
+        self.note_obligation_cause(&mut err, obligation);
+        self.point_at_returns_when_relevant(&mut err, &obligation);
+
+        err.emit();
+    }
+
+    /// Given some node representing a fn-like thing in the HIR map,
+    /// returns a span and `ArgKind` information that describes the
+    /// arguments it expects. This can be supplied to
+    /// `report_arg_count_mismatch`.
+    fn get_fn_like_arguments(&self, node: Node<'_>) -> (Span, Vec<ArgKind>) {
+        match node {
+            Node::Expr(&hir::Expr {
+                kind: hir::ExprKind::Closure(_, ref _decl, id, span, _),
+                ..
+            }) => (
+                self.tcx.sess.source_map().def_span(span),
+                self.tcx
+                    .hir()
+                    .body(id)
+                    .params
+                    .iter()
+                    .map(|arg| {
+                        if let hir::Pat { kind: hir::PatKind::Tuple(ref args, _), span, .. } =
+                            *arg.pat
+                        {
+                            ArgKind::Tuple(
+                                Some(span),
+                                args.iter()
+                                    .map(|pat| {
+                                        let snippet = self
+                                            .tcx
+                                            .sess
+                                            .source_map()
+                                            .span_to_snippet(pat.span)
+                                            .unwrap();
+                                        (snippet, "_".to_owned())
+                                    })
+                                    .collect::<Vec<_>>(),
+                            )
+                        } else {
+                            let name =
+                                self.tcx.sess.source_map().span_to_snippet(arg.pat.span).unwrap();
+                            ArgKind::Arg(name, "_".to_owned())
+                        }
+                    })
+                    .collect::<Vec<ArgKind>>(),
+            ),
+            Node::Item(&hir::Item { span, kind: hir::ItemKind::Fn(ref sig, ..), .. })
+            | Node::ImplItem(&hir::ImplItem {
+                span,
+                kind: hir::ImplItemKind::Fn(ref sig, _),
+                ..
+            })
+            | Node::TraitItem(&hir::TraitItem {
+                span,
+                kind: hir::TraitItemKind::Fn(ref sig, _),
+                ..
+            }) => (
+                self.tcx.sess.source_map().def_span(span),
+                sig.decl
+                    .inputs
+                    .iter()
+                    .map(|arg| match arg.clone().kind {
+                        hir::TyKind::Tup(ref tys) => ArgKind::Tuple(
+                            Some(arg.span),
+                            vec![("_".to_owned(), "_".to_owned()); tys.len()],
+                        ),
+                        _ => ArgKind::empty(),
+                    })
+                    .collect::<Vec<ArgKind>>(),
+            ),
+            Node::Ctor(ref variant_data) => {
+                let span = variant_data
+                    .ctor_hir_id()
+                    .map(|hir_id| self.tcx.hir().span(hir_id))
+                    .unwrap_or(DUMMY_SP);
+                let span = self.tcx.sess.source_map().def_span(span);
+
+                (span, vec![ArgKind::empty(); variant_data.fields().len()])
+            }
+            _ => panic!("non-FnLike node found: {:?}", node),
+        }
+    }
+
+    /// Reports an error when the number of arguments needed by a
+    /// trait match doesn't match the number that the expression
+    /// provides.
+    fn report_arg_count_mismatch(
+        &self,
+        span: Span,
+        found_span: Option<Span>,
+        expected_args: Vec<ArgKind>,
+        found_args: Vec<ArgKind>,
+        is_closure: bool,
+    ) -> DiagnosticBuilder<'tcx> {
+        let kind = if is_closure { "closure" } else { "function" };
+
+        let args_str = |arguments: &[ArgKind], other: &[ArgKind]| {
+            let arg_length = arguments.len();
+            let distinct = match &other[..] {
+                &[ArgKind::Tuple(..)] => true,
+                _ => false,
+            };
+            match (arg_length, arguments.get(0)) {
+                (1, Some(&ArgKind::Tuple(_, ref fields))) => {
+                    format!("a single {}-tuple as argument", fields.len())
+                }
+                _ => format!(
+                    "{} {}argument{}",
+                    arg_length,
+                    if distinct && arg_length > 1 { "distinct " } else { "" },
+                    pluralize!(arg_length)
+                ),
+            }
+        };
+
+        let expected_str = args_str(&expected_args, &found_args);
+        let found_str = args_str(&found_args, &expected_args);
+
+        let mut err = struct_span_err!(
+            self.tcx.sess,
+            span,
+            E0593,
+            "{} is expected to take {}, but it takes {}",
+            kind,
+            expected_str,
+            found_str,
+        );
+
+        err.span_label(span, format!("expected {} that takes {}", kind, expected_str));
+
+        if let Some(found_span) = found_span {
+            err.span_label(found_span, format!("takes {}", found_str));
+
+            // move |_| { ... }
+            // ^^^^^^^^-- def_span
+            //
+            // move |_| { ... }
+            // ^^^^^-- prefix
+            let prefix_span = self.tcx.sess.source_map().span_until_non_whitespace(found_span);
+            // move |_| { ... }
+            //      ^^^-- pipe_span
+            let pipe_span =
+                if let Some(span) = found_span.trim_start(prefix_span) { span } else { found_span };
+
+            // Suggest to take and ignore the arguments with expected_args_length `_`s if
+            // found arguments is empty (assume the user just wants to ignore args in this case).
+            // For example, if `expected_args_length` is 2, suggest `|_, _|`.
+            if found_args.is_empty() && is_closure {
+                let underscores = vec!["_"; expected_args.len()].join(", ");
+                err.span_suggestion(
+                    pipe_span,
+                    &format!(
+                        "consider changing the closure to take and ignore the expected argument{}",
+                        if expected_args.len() < 2 { "" } else { "s" }
+                    ),
+                    format!("|{}|", underscores),
+                    Applicability::MachineApplicable,
+                );
+            }
+
+            if let &[ArgKind::Tuple(_, ref fields)] = &found_args[..] {
+                if fields.len() == expected_args.len() {
+                    let sugg = fields
+                        .iter()
+                        .map(|(name, _)| name.to_owned())
+                        .collect::<Vec<String>>()
+                        .join(", ");
+                    err.span_suggestion(
+                        found_span,
+                        "change the closure to take multiple arguments instead of a single tuple",
+                        format!("|{}|", sugg),
+                        Applicability::MachineApplicable,
+                    );
+                }
+            }
+            if let &[ArgKind::Tuple(_, ref fields)] = &expected_args[..] {
+                if fields.len() == found_args.len() && is_closure {
+                    let sugg = format!(
+                        "|({}){}|",
+                        found_args
+                            .iter()
+                            .map(|arg| match arg {
+                                ArgKind::Arg(name, _) => name.to_owned(),
+                                _ => "_".to_owned(),
+                            })
+                            .collect::<Vec<String>>()
+                            .join(", "),
+                        // add type annotations if available
+                        if found_args.iter().any(|arg| match arg {
+                            ArgKind::Arg(_, ty) => ty != "_",
+                            _ => false,
+                        }) {
+                            format!(
+                                ": ({})",
+                                fields
+                                    .iter()
+                                    .map(|(_, ty)| ty.to_owned())
+                                    .collect::<Vec<String>>()
+                                    .join(", ")
+                            )
+                        } else {
+                            String::new()
+                        },
+                    );
+                    err.span_suggestion(
+                        found_span,
+                        "change the closure to accept a tuple instead of individual arguments",
+                        sugg,
+                        Applicability::MachineApplicable,
+                    );
+                }
+            }
+        }
+
+        err
+    }
+}
+
+trait InferCtxtPrivExt<'tcx> {
+    // returns if `cond` not occurring implies that `error` does not occur - i.e., that
+    // `error` occurring implies that `cond` occurs.
+    fn error_implies(&self, cond: &ty::Predicate<'tcx>, error: &ty::Predicate<'tcx>) -> bool;
+
+    fn report_fulfillment_error(
+        &self,
+        error: &FulfillmentError<'tcx>,
+        body_id: Option<hir::BodyId>,
+        fallback_has_occurred: bool,
+    );
+
+    fn report_projection_error(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        error: &MismatchedProjectionTypes<'tcx>,
+    );
+
+    fn fuzzy_match_tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool;
+
+    fn describe_generator(&self, body_id: hir::BodyId) -> Option<&'static str>;
+
+    fn find_similar_impl_candidates(
+        &self,
+        trait_ref: ty::PolyTraitRef<'tcx>,
+    ) -> Vec<ty::TraitRef<'tcx>>;
+
+    fn report_similar_impl_candidates(
+        &self,
+        impl_candidates: Vec<ty::TraitRef<'tcx>>,
+        err: &mut DiagnosticBuilder<'_>,
+    );
+
+    /// Gets the parent trait chain start
+    fn get_parent_trait_ref(
+        &self,
+        code: &ObligationCauseCode<'tcx>,
+    ) -> Option<(String, Option<Span>)>;
+
+    /// If the `Self` type of the unsatisfied trait `trait_ref` implements a trait
+    /// with the same path as `trait_ref`, a help message about
+    /// a probable version mismatch is added to `err`
+    fn note_version_mismatch(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        trait_ref: &ty::PolyTraitRef<'tcx>,
+    );
+
+    fn mk_obligation_for_def_id(
+        &self,
+        def_id: DefId,
+        output_ty: Ty<'tcx>,
+        cause: ObligationCause<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+    ) -> PredicateObligation<'tcx>;
+
+    fn maybe_report_ambiguity(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        body_id: Option<hir::BodyId>,
+    );
+
+    fn predicate_can_apply(
+        &self,
+        param_env: ty::ParamEnv<'tcx>,
+        pred: ty::PolyTraitRef<'tcx>,
+    ) -> bool;
+
+    fn note_obligation_cause(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        obligation: &PredicateObligation<'tcx>,
+    );
+
+    fn suggest_unsized_bound_if_applicable(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        obligation: &PredicateObligation<'tcx>,
+    );
+
+    fn is_recursive_obligation(
+        &self,
+        obligated_types: &mut Vec<&ty::TyS<'tcx>>,
+        cause_code: &ObligationCauseCode<'tcx>,
+    ) -> bool;
+}
+
+impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
+    // returns if `cond` not occurring implies that `error` does not occur - i.e., that
+    // `error` occurring implies that `cond` occurs.
+    fn error_implies(&self, cond: &ty::Predicate<'tcx>, error: &ty::Predicate<'tcx>) -> bool {
+        if cond == error {
+            return true;
+        }
+
+        let (cond, error) = match (cond, error) {
+            (&ty::Predicate::Trait(..), &ty::Predicate::Trait(ref error, _)) => (cond, error),
+            _ => {
+                // FIXME: make this work in other cases too.
+                return false;
+            }
+        };
+
+        for implication in super::elaborate_predicates(self.tcx, vec![*cond]) {
+            if let ty::Predicate::Trait(implication, _) = implication {
+                let error = error.to_poly_trait_ref();
+                let implication = implication.to_poly_trait_ref();
+                // FIXME: I'm just not taking associated types at all here.
+                // Eventually I'll need to implement param-env-aware
+                // `Γ₁ ⊦ φ₁ => Γ₂ ⊦ φ₂` logic.
+                let param_env = ty::ParamEnv::empty();
+                if self.can_sub(param_env, error, implication).is_ok() {
+                    debug!("error_implies: {:?} -> {:?} -> {:?}", cond, error, implication);
+                    return true;
+                }
+            }
+        }
+
+        false
+    }
+
+    fn report_fulfillment_error(
+        &self,
+        error: &FulfillmentError<'tcx>,
+        body_id: Option<hir::BodyId>,
+        fallback_has_occurred: bool,
+    ) {
+        debug!("report_fulfillment_error({:?})", error);
+        match error.code {
+            FulfillmentErrorCode::CodeSelectionError(ref selection_error) => {
+                self.report_selection_error(
+                    &error.obligation,
+                    selection_error,
+                    fallback_has_occurred,
+                    error.points_at_arg_span,
+                );
+            }
+            FulfillmentErrorCode::CodeProjectionError(ref e) => {
+                self.report_projection_error(&error.obligation, e);
+            }
+            FulfillmentErrorCode::CodeAmbiguity => {
+                self.maybe_report_ambiguity(&error.obligation, body_id);
+            }
+            FulfillmentErrorCode::CodeSubtypeError(ref expected_found, ref err) => {
+                self.report_mismatched_types(
+                    &error.obligation.cause,
+                    expected_found.expected,
+                    expected_found.found,
+                    err.clone(),
+                )
+                .emit();
+            }
+        }
+    }
+
+    fn report_projection_error(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        error: &MismatchedProjectionTypes<'tcx>,
+    ) {
+        let predicate = self.resolve_vars_if_possible(&obligation.predicate);
+
+        if predicate.references_error() {
+            return;
+        }
+
+        self.probe(|_| {
+            let err_buf;
+            let mut err = &error.err;
+            let mut values = None;
+
+            // try to find the mismatched types to report the error with.
+            //
+            // this can fail if the problem was higher-ranked, in which
+            // cause I have no idea for a good error message.
+            if let ty::Predicate::Projection(ref data) = predicate {
+                let mut selcx = SelectionContext::new(self);
+                let (data, _) = self.replace_bound_vars_with_fresh_vars(
+                    obligation.cause.span,
+                    infer::LateBoundRegionConversionTime::HigherRankedType,
+                    data,
+                );
+                let mut obligations = vec![];
+                let normalized_ty = super::normalize_projection_type(
+                    &mut selcx,
+                    obligation.param_env,
+                    data.projection_ty,
+                    obligation.cause.clone(),
+                    0,
+                    &mut obligations,
+                );
+
+                debug!(
+                    "report_projection_error obligation.cause={:?} obligation.param_env={:?}",
+                    obligation.cause, obligation.param_env
+                );
+
+                debug!(
+                    "report_projection_error normalized_ty={:?} data.ty={:?}",
+                    normalized_ty, data.ty
+                );
+
+                let is_normalized_ty_expected = match &obligation.cause.code {
+                    ObligationCauseCode::ItemObligation(_)
+                    | ObligationCauseCode::BindingObligation(_, _)
+                    | ObligationCauseCode::ObjectCastObligation(_) => false,
+                    _ => true,
+                };
+
+                if let Err(error) = self.at(&obligation.cause, obligation.param_env).eq_exp(
+                    is_normalized_ty_expected,
+                    normalized_ty,
+                    data.ty,
+                ) {
+                    values = Some(infer::ValuePairs::Types(ExpectedFound::new(
+                        is_normalized_ty_expected,
+                        normalized_ty,
+                        data.ty,
+                    )));
+
+                    err_buf = error;
+                    err = &err_buf;
+                }
+            }
+
+            let msg = format!("type mismatch resolving `{}`", predicate);
+            let error_id = (DiagnosticMessageId::ErrorId(271), Some(obligation.cause.span), msg);
+            let fresh = self.tcx.sess.one_time_diagnostics.borrow_mut().insert(error_id);
+            if fresh {
+                let mut diag = struct_span_err!(
+                    self.tcx.sess,
+                    obligation.cause.span,
+                    E0271,
+                    "type mismatch resolving `{}`",
+                    predicate
+                );
+                self.note_type_err(&mut diag, &obligation.cause, None, values, err);
+                self.note_obligation_cause(&mut diag, obligation);
+                diag.emit();
+            }
+        });
+    }
+
+    fn fuzzy_match_tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
+        /// returns the fuzzy category of a given type, or None
+        /// if the type can be equated to any type.
+        fn type_category(t: Ty<'_>) -> Option<u32> {
+            match t.kind {
+                ty::Bool => Some(0),
+                ty::Char => Some(1),
+                ty::Str => Some(2),
+                ty::Int(..) | ty::Uint(..) | ty::Infer(ty::IntVar(..)) => Some(3),
+                ty::Float(..) | ty::Infer(ty::FloatVar(..)) => Some(4),
+                ty::Ref(..) | ty::RawPtr(..) => Some(5),
+                ty::Array(..) | ty::Slice(..) => Some(6),
+                ty::FnDef(..) | ty::FnPtr(..) => Some(7),
+                ty::Dynamic(..) => Some(8),
+                ty::Closure(..) => Some(9),
+                ty::Tuple(..) => Some(10),
+                ty::Projection(..) => Some(11),
+                ty::Param(..) => Some(12),
+                ty::Opaque(..) => Some(13),
+                ty::Never => Some(14),
+                ty::Adt(adt, ..) => match adt.adt_kind() {
+                    AdtKind::Struct => Some(15),
+                    AdtKind::Union => Some(16),
+                    AdtKind::Enum => Some(17),
+                },
+                ty::Generator(..) => Some(18),
+                ty::Foreign(..) => Some(19),
+                ty::GeneratorWitness(..) => Some(20),
+                ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error => None,
+                ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
+            }
+        }
+
+        match (type_category(a), type_category(b)) {
+            (Some(cat_a), Some(cat_b)) => match (&a.kind, &b.kind) {
+                (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => def_a == def_b,
+                _ => cat_a == cat_b,
+            },
+            // infer and error can be equated to all types
+            _ => true,
+        }
+    }
+
+    fn describe_generator(&self, body_id: hir::BodyId) -> Option<&'static str> {
+        self.tcx.hir().body(body_id).generator_kind.map(|gen_kind| match gen_kind {
+            hir::GeneratorKind::Gen => "a generator",
+            hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block) => "an async block",
+            hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Fn) => "an async function",
+            hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Closure) => "an async closure",
+        })
+    }
+
+    fn find_similar_impl_candidates(
+        &self,
+        trait_ref: ty::PolyTraitRef<'tcx>,
+    ) -> Vec<ty::TraitRef<'tcx>> {
+        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);
+                    if let Some(imp_simp) = imp_simp {
+                        if simp != imp_simp {
+                            return None;
+                        }
+                    }
+
+                    Some(imp)
+                })
+                .collect(),
+            None => {
+                all_impls.iter().map(|&def_id| self.tcx.impl_trait_ref(def_id).unwrap()).collect()
+            }
+        }
+    }
+
+    fn report_similar_impl_candidates(
+        &self,
+        impl_candidates: Vec<ty::TraitRef<'tcx>>,
+        err: &mut DiagnosticBuilder<'_>,
+    ) {
+        if impl_candidates.is_empty() {
+            return;
+        }
+
+        let len = impl_candidates.len();
+        let end = if impl_candidates.len() <= 5 { impl_candidates.len() } else { 4 };
+
+        let normalize = |candidate| {
+            self.tcx.infer_ctxt().enter(|ref infcx| {
+                let normalized = infcx
+                    .at(&ObligationCause::dummy(), ty::ParamEnv::empty())
+                    .normalize(candidate)
+                    .ok();
+                match normalized {
+                    Some(normalized) => format!("\n  {:?}", normalized.value),
+                    None => format!("\n  {:?}", candidate),
+                }
+            })
+        };
+
+        // Sort impl candidates so that ordering is consistent for UI tests.
+        let mut normalized_impl_candidates =
+            impl_candidates.iter().map(normalize).collect::<Vec<String>>();
+
+        // Sort before taking the `..end` range,
+        // because the ordering of `impl_candidates` may not be deterministic:
+        // https://github.com/rust-lang/rust/pull/57475#issuecomment-455519507
+        normalized_impl_candidates.sort();
+
+        err.help(&format!(
+            "the following implementations were found:{}{}",
+            normalized_impl_candidates[..end].join(""),
+            if len > 5 { format!("\nand {} others", len - 4) } else { String::new() }
+        ));
+    }
+
+    /// Gets the parent trait chain start
+    fn get_parent_trait_ref(
+        &self,
+        code: &ObligationCauseCode<'tcx>,
+    ) -> Option<(String, Option<Span>)> {
+        match code {
+            &ObligationCauseCode::BuiltinDerivedObligation(ref data) => {
+                let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref);
+                match self.get_parent_trait_ref(&data.parent_code) {
+                    Some(t) => Some(t),
+                    None => {
+                        let ty = parent_trait_ref.skip_binder().self_ty();
+                        let span =
+                            TyCategory::from_ty(ty).map(|(_, def_id)| self.tcx.def_span(def_id));
+                        Some((ty.to_string(), span))
+                    }
+                }
+            }
+            _ => None,
+        }
+    }
+
+    /// If the `Self` type of the unsatisfied trait `trait_ref` implements a trait
+    /// with the same path as `trait_ref`, a help message about
+    /// a probable version mismatch is added to `err`
+    fn note_version_mismatch(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        trait_ref: &ty::PolyTraitRef<'tcx>,
+    ) {
+        let get_trait_impl = |trait_def_id| {
+            let mut trait_impl = None;
+            self.tcx.for_each_relevant_impl(trait_def_id, trait_ref.self_ty(), |impl_def_id| {
+                if trait_impl.is_none() {
+                    trait_impl = Some(impl_def_id);
+                }
+            });
+            trait_impl
+        };
+        let required_trait_path = self.tcx.def_path_str(trait_ref.def_id());
+        let all_traits = self.tcx.all_traits(LOCAL_CRATE);
+        let traits_with_same_path: std::collections::BTreeSet<_> = all_traits
+            .iter()
+            .filter(|trait_def_id| **trait_def_id != trait_ref.def_id())
+            .filter(|trait_def_id| self.tcx.def_path_str(**trait_def_id) == required_trait_path)
+            .collect();
+        for trait_with_same_path in traits_with_same_path {
+            if let Some(impl_def_id) = get_trait_impl(*trait_with_same_path) {
+                let impl_span = self.tcx.def_span(impl_def_id);
+                err.span_help(impl_span, "trait impl with same name found");
+                let trait_crate = self.tcx.crate_name(trait_with_same_path.krate);
+                let crate_msg = format!(
+                    "perhaps two different versions of crate `{}` are being used?",
+                    trait_crate
+                );
+                err.note(&crate_msg);
+            }
+        }
+    }
+
+    fn mk_obligation_for_def_id(
+        &self,
+        def_id: DefId,
+        output_ty: Ty<'tcx>,
+        cause: ObligationCause<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+    ) -> PredicateObligation<'tcx> {
+        let new_trait_ref =
+            ty::TraitRef { def_id, substs: self.tcx.mk_substs_trait(output_ty, &[]) };
+        Obligation::new(cause, param_env, new_trait_ref.without_const().to_predicate())
+    }
+
+    fn maybe_report_ambiguity(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        body_id: Option<hir::BodyId>,
+    ) {
+        // Unable to successfully determine, probably means
+        // insufficient type information, but could mean
+        // ambiguous impls. The latter *ought* to be a
+        // coherence violation, so we don't report it here.
+
+        let predicate = self.resolve_vars_if_possible(&obligation.predicate);
+        let span = obligation.cause.span;
+
+        debug!(
+            "maybe_report_ambiguity(predicate={:?}, obligation={:?} body_id={:?}, code={:?})",
+            predicate, obligation, body_id, obligation.cause.code,
+        );
+
+        // Ambiguity errors are often caused as fallout from earlier
+        // errors. So just ignore them if this infcx is tainted.
+        if self.is_tainted_by_errors() {
+            return;
+        }
+
+        let mut err = match predicate {
+            ty::Predicate::Trait(ref data, _) => {
+                let trait_ref = data.to_poly_trait_ref();
+                let self_ty = trait_ref.self_ty();
+                debug!("self_ty {:?} {:?} trait_ref {:?}", self_ty, self_ty.kind, trait_ref);
+
+                if predicate.references_error() {
+                    return;
+                }
+                // Typically, this ambiguity should only happen if
+                // there are unresolved type inference variables
+                // (otherwise it would suggest a coherence
+                // failure). But given #21974 that is not necessarily
+                // the case -- we can have multiple where clauses that
+                // are only distinguished by a region, which results
+                // in an ambiguity even when all types are fully
+                // known, since we don't dispatch based on region
+                // relationships.
+
+                // This is kind of a hack: it frequently happens that some earlier
+                // error prevents types from being fully inferred, and then we get
+                // a bunch of uninteresting errors saying something like "<generic
+                // #0> doesn't implement Sized".  It may even be true that we
+                // could just skip over all checks where the self-ty is an
+                // inference variable, but I was afraid that there might be an
+                // inference variable created, registered as an obligation, and
+                // then never forced by writeback, and hence by skipping here we'd
+                // be ignoring the fact that we don't KNOW the type works
+                // out. Though even that would probably be harmless, given that
+                // we're only talking about builtin traits, which are known to be
+                // inhabited. We used to check for `self.tcx.sess.has_errors()` to
+                // avoid inundating the user with unnecessary errors, but we now
+                // check upstream for type errors and don't add the obligations to
+                // begin with in those cases.
+                if self
+                    .tcx
+                    .lang_items()
+                    .sized_trait()
+                    .map_or(false, |sized_id| sized_id == trait_ref.def_id())
+                {
+                    self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0282).emit();
+                    return;
+                }
+                let mut err = self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0283);
+                err.note(&format!("cannot resolve `{}`", predicate));
+                if let ObligationCauseCode::ItemObligation(def_id) = obligation.cause.code {
+                    self.suggest_fully_qualified_path(&mut err, def_id, span, trait_ref.def_id());
+                } else if let (
+                    Ok(ref snippet),
+                    ObligationCauseCode::BindingObligation(ref def_id, _),
+                ) =
+                    (self.tcx.sess.source_map().span_to_snippet(span), &obligation.cause.code)
+                {
+                    let generics = self.tcx.generics_of(*def_id);
+                    if !generics.params.is_empty() && !snippet.ends_with('>') {
+                        // FIXME: To avoid spurious suggestions in functions where type arguments
+                        // where already supplied, we check the snippet to make sure it doesn't
+                        // end with a turbofish. Ideally we would have access to a `PathSegment`
+                        // instead. Otherwise we would produce the following output:
+                        //
+                        // error[E0283]: type annotations needed
+                        //   --> $DIR/issue-54954.rs:3:24
+                        //    |
+                        // LL | const ARR_LEN: usize = Tt::const_val::<[i8; 123]>();
+                        //    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^
+                        //    |                        |
+                        //    |                        cannot infer type
+                        //    |                        help: consider specifying the type argument
+                        //    |                        in the function call:
+                        //    |                        `Tt::const_val::<[i8; 123]>::<T>`
+                        // ...
+                        // LL |     const fn const_val<T: Sized>() -> usize {
+                        //    |              --------- - required by this bound in `Tt::const_val`
+                        //    |
+                        //    = note: cannot resolve `_: Tt`
+
+                        err.span_suggestion(
+                            span,
+                            &format!(
+                                "consider specifying the type argument{} in the function call",
+                                if generics.params.len() > 1 { "s" } else { "" },
+                            ),
+                            format!(
+                                "{}::<{}>",
+                                snippet,
+                                generics
+                                    .params
+                                    .iter()
+                                    .map(|p| p.name.to_string())
+                                    .collect::<Vec<String>>()
+                                    .join(", ")
+                            ),
+                            Applicability::HasPlaceholders,
+                        );
+                    }
+                }
+                err
+            }
+
+            ty::Predicate::WellFormed(ty) => {
+                // Same hacky approach as above to avoid deluging user
+                // with error messages.
+                if ty.references_error() || self.tcx.sess.has_errors() {
+                    return;
+                }
+                self.need_type_info_err(body_id, span, ty, ErrorCode::E0282)
+            }
+
+            ty::Predicate::Subtype(ref data) => {
+                if data.references_error() || self.tcx.sess.has_errors() {
+                    // no need to overload user in such cases
+                    return;
+                }
+                let &SubtypePredicate { a_is_expected: _, a, b } = data.skip_binder();
+                // both must be type variables, or the other would've been instantiated
+                assert!(a.is_ty_var() && b.is_ty_var());
+                self.need_type_info_err(body_id, span, a, ErrorCode::E0282)
+            }
+            ty::Predicate::Projection(ref data) => {
+                let trait_ref = data.to_poly_trait_ref(self.tcx);
+                let self_ty = trait_ref.self_ty();
+                if predicate.references_error() {
+                    return;
+                }
+                let mut err = self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0284);
+                err.note(&format!("cannot resolve `{}`", predicate));
+                err
+            }
+
+            _ => {
+                if self.tcx.sess.has_errors() {
+                    return;
+                }
+                let mut err = struct_span_err!(
+                    self.tcx.sess,
+                    span,
+                    E0284,
+                    "type annotations needed: cannot resolve `{}`",
+                    predicate,
+                );
+                err.span_label(span, &format!("cannot resolve `{}`", predicate));
+                err
+            }
+        };
+        self.note_obligation_cause(&mut err, obligation);
+        err.emit();
+    }
+
+    /// Returns `true` if the trait predicate may apply for *some* assignment
+    /// to the type parameters.
+    fn predicate_can_apply(
+        &self,
+        param_env: ty::ParamEnv<'tcx>,
+        pred: ty::PolyTraitRef<'tcx>,
+    ) -> bool {
+        struct ParamToVarFolder<'a, 'tcx> {
+            infcx: &'a InferCtxt<'a, 'tcx>,
+            var_map: FxHashMap<Ty<'tcx>, Ty<'tcx>>,
+        }
+
+        impl<'a, 'tcx> TypeFolder<'tcx> for ParamToVarFolder<'a, 'tcx> {
+            fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
+                self.infcx.tcx
+            }
+
+            fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
+                if let ty::Param(ty::ParamTy { name, .. }) = ty.kind {
+                    let infcx = self.infcx;
+                    self.var_map.entry(ty).or_insert_with(|| {
+                        infcx.next_ty_var(TypeVariableOrigin {
+                            kind: TypeVariableOriginKind::TypeParameterDefinition(name, None),
+                            span: DUMMY_SP,
+                        })
+                    })
+                } else {
+                    ty.super_fold_with(self)
+                }
+            }
+        }
+
+        self.probe(|_| {
+            let mut selcx = SelectionContext::new(self);
+
+            let cleaned_pred =
+                pred.fold_with(&mut ParamToVarFolder { infcx: self, var_map: Default::default() });
+
+            let cleaned_pred = super::project::normalize(
+                &mut selcx,
+                param_env,
+                ObligationCause::dummy(),
+                &cleaned_pred,
+            )
+            .value;
+
+            let obligation = Obligation::new(
+                ObligationCause::dummy(),
+                param_env,
+                cleaned_pred.without_const().to_predicate(),
+            );
+
+            self.predicate_may_hold(&obligation)
+        })
+    }
+
+    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.maybe_note_obligation_cause_for_async_await(err, obligation) {
+            self.note_obligation_cause_code(
+                err,
+                &obligation.predicate,
+                &obligation.cause.code,
+                &mut vec![],
+            );
+            self.suggest_unsized_bound_if_applicable(err, obligation);
+        }
+    }
+
+    fn suggest_unsized_bound_if_applicable(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        obligation: &PredicateObligation<'tcx>,
+    ) {
+        if let (
+            ty::Predicate::Trait(pred, _),
+            ObligationCauseCode::BindingObligation(item_def_id, span),
+        ) = (&obligation.predicate, &obligation.cause.code)
+        {
+            if let (Some(generics), true) = (
+                self.tcx.hir().get_if_local(*item_def_id).as_ref().and_then(|n| n.generics()),
+                Some(pred.def_id()) == self.tcx.lang_items().sized_trait(),
+            ) {
+                for param in generics.params {
+                    if param.span == *span
+                        && !param.bounds.iter().any(|bound| {
+                            bound.trait_def_id() == self.tcx.lang_items().sized_trait()
+                        })
+                    {
+                        let (span, separator) = match param.bounds {
+                            [] => (span.shrink_to_hi(), ":"),
+                            [.., bound] => (bound.span().shrink_to_hi(), " + "),
+                        };
+                        err.span_suggestion(
+                            span,
+                            "consider relaxing the implicit `Sized` restriction",
+                            format!("{} ?Sized", separator),
+                            Applicability::MachineApplicable,
+                        );
+                        return;
+                    }
+                }
+            }
+        }
+    }
+
+    fn is_recursive_obligation(
+        &self,
+        obligated_types: &mut Vec<&ty::TyS<'tcx>>,
+        cause_code: &ObligationCauseCode<'tcx>,
+    ) -> bool {
+        if let ObligationCauseCode::BuiltinDerivedObligation(ref data) = cause_code {
+            let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref);
+
+            if obligated_types.iter().any(|ot| ot == &parent_trait_ref.skip_binder().self_ty()) {
+                return true;
+            }
+        }
+        false
+    }
+}
+
+pub fn recursive_type_with_infinite_size_error(
+    tcx: TyCtxt<'tcx>,
+    type_def_id: DefId,
+) -> DiagnosticBuilder<'tcx> {
+    assert!(type_def_id.is_local());
+    let span = tcx.hir().span_if_local(type_def_id).unwrap();
+    let span = tcx.sess.source_map().def_span(span);
+    let mut err = struct_span_err!(
+        tcx.sess,
+        span,
+        E0072,
+        "recursive type `{}` has infinite size",
+        tcx.def_path_str(type_def_id)
+    );
+    err.span_label(span, "recursive type has infinite size");
+    err.help(&format!(
+        "insert indirection (e.g., a `Box`, `Rc`, or `&`) \
+                           at some point to make `{}` representable",
+        tcx.def_path_str(type_def_id)
+    ));
+    err
+}
+
+/// Summarizes information
+#[derive(Clone)]
+pub enum ArgKind {
+    /// An argument of non-tuple type. Parameters are (name, ty)
+    Arg(String, String),
+
+    /// An argument of tuple type. For a "found" argument, the span is
+    /// the locationo in the source of the pattern. For a "expected"
+    /// argument, it will be None. The vector is a list of (name, ty)
+    /// strings for the components of the tuple.
+    Tuple(Option<Span>, Vec<(String, String)>),
+}
+
+impl ArgKind {
+    fn empty() -> ArgKind {
+        ArgKind::Arg("_".to_owned(), "_".to_owned())
+    }
+
+    /// Creates an `ArgKind` from the expected type of an
+    /// argument. It has no name (`_`) and an optional source span.
+    pub fn from_expected_ty(t: Ty<'_>, span: Option<Span>) -> ArgKind {
+        match t.kind {
+            ty::Tuple(ref tys) => ArgKind::Tuple(
+                span,
+                tys.iter().map(|ty| ("_".to_owned(), ty.to_string())).collect::<Vec<_>>(),
+            ),
+            _ => ArgKind::Arg("_".to_owned(), t.to_string()),
+        }
+    }
+}
+
+/// Suggest restricting a type param with a new bound.
+pub fn suggest_constraining_type_param(
+    tcx: TyCtxt<'_>,
+    generics: &hir::Generics<'_>,
+    err: &mut DiagnosticBuilder<'_>,
+    param_name: &str,
+    constraint: &str,
+    source_map: &SourceMap,
+    span: Span,
+    def_id: Option<DefId>,
+) -> bool {
+    const MSG_RESTRICT_BOUND_FURTHER: &str = "consider further restricting this bound with";
+    const MSG_RESTRICT_TYPE: &str = "consider restricting this type parameter with";
+    const MSG_RESTRICT_TYPE_FURTHER: &str = "consider further restricting this type parameter with";
+
+    let param = generics.params.iter().find(|p| p.name.ident().as_str() == param_name);
+
+    let param = if let Some(param) = param {
+        param
+    } else {
+        return false;
+    };
+
+    if def_id == tcx.lang_items().sized_trait() {
+        // Type parameters are already `Sized` by default.
+        err.span_label(param.span, &format!("this type parameter needs to be `{}`", constraint));
+        return true;
+    }
+
+    if param_name.starts_with("impl ") {
+        // If there's an `impl Trait` used in argument position, suggest
+        // restricting it:
+        //
+        //   fn foo(t: impl Foo) { ... }
+        //             --------
+        //             |
+        //             help: consider further restricting this bound with `+ Bar`
+        //
+        // Suggestion for tools in this case is:
+        //
+        //   fn foo(t: impl Foo) { ... }
+        //             --------
+        //             |
+        //             replace with: `impl Foo + Bar`
+
+        err.span_help(param.span, &format!("{} `+ {}`", MSG_RESTRICT_BOUND_FURTHER, constraint));
+
+        err.tool_only_span_suggestion(
+            param.span,
+            MSG_RESTRICT_BOUND_FURTHER,
+            format!("{} + {}", param_name, constraint),
+            Applicability::MachineApplicable,
+        );
+
+        return true;
+    }
+
+    if generics.where_clause.predicates.is_empty() {
+        if let Some(bounds_span) = param.bounds_span() {
+            // If user has provided some bounds, suggest restricting them:
+            //
+            //   fn foo<T: Foo>(t: T) { ... }
+            //             ---
+            //             |
+            //             help: consider further restricting this bound with `+ Bar`
+            //
+            // Suggestion for tools in this case is:
+            //
+            //   fn foo<T: Foo>(t: T) { ... }
+            //          --
+            //          |
+            //          replace with: `T: Bar +`
+
+            err.span_help(
+                bounds_span,
+                &format!("{} `+ {}`", MSG_RESTRICT_BOUND_FURTHER, constraint),
+            );
+
+            let span_hi = param.span.with_hi(span.hi());
+            let span_with_colon = source_map.span_through_char(span_hi, ':');
+
+            if span_hi != param.span && span_with_colon != span_hi {
+                err.tool_only_span_suggestion(
+                    span_with_colon,
+                    MSG_RESTRICT_BOUND_FURTHER,
+                    format!("{}: {} + ", param_name, constraint),
+                    Applicability::MachineApplicable,
+                );
+            }
+        } else {
+            // If user hasn't provided any bounds, suggest adding a new one:
+            //
+            //   fn foo<T>(t: T) { ... }
+            //          - help: consider restricting this type parameter with `T: Foo`
+
+            err.span_help(
+                param.span,
+                &format!("{} `{}: {}`", MSG_RESTRICT_TYPE, param_name, constraint),
+            );
+
+            err.tool_only_span_suggestion(
+                param.span,
+                MSG_RESTRICT_TYPE,
+                format!("{}: {}", param_name, constraint),
+                Applicability::MachineApplicable,
+            );
+        }
+
+        true
+    } else {
+        // This part is a bit tricky, because using the `where` clause user can
+        // provide zero, one or many bounds for the same type parameter, so we
+        // have following cases to consider:
+        //
+        // 1) When the type parameter has been provided zero bounds
+        //
+        //    Message:
+        //      fn foo<X, Y>(x: X, y: Y) where Y: Foo { ... }
+        //             - help: consider restricting this type parameter with `where X: Bar`
+        //
+        //    Suggestion:
+        //      fn foo<X, Y>(x: X, y: Y) where Y: Foo { ... }
+        //                                           - insert: `, X: Bar`
+        //
+        //
+        // 2) When the type parameter has been provided one bound
+        //
+        //    Message:
+        //      fn foo<T>(t: T) where T: Foo { ... }
+        //                            ^^^^^^
+        //                            |
+        //                            help: consider further restricting this bound with `+ Bar`
+        //
+        //    Suggestion:
+        //      fn foo<T>(t: T) where T: Foo { ... }
+        //                            ^^
+        //                            |
+        //                            replace with: `T: Bar +`
+        //
+        //
+        // 3) When the type parameter has been provided many bounds
+        //
+        //    Message:
+        //      fn foo<T>(t: T) where T: Foo, T: Bar {... }
+        //             - help: consider further restricting this type parameter with `where T: Zar`
+        //
+        //    Suggestion:
+        //      fn foo<T>(t: T) where T: Foo, T: Bar {... }
+        //                                          - insert: `, T: Zar`
+
+        let mut param_spans = Vec::new();
+
+        for predicate in generics.where_clause.predicates {
+            if let WherePredicate::BoundPredicate(WhereBoundPredicate {
+                span, bounded_ty, ..
+            }) = predicate
+            {
+                if let TyKind::Path(QPath::Resolved(_, path)) = &bounded_ty.kind {
+                    if let Some(segment) = path.segments.first() {
+                        if segment.ident.to_string() == param_name {
+                            param_spans.push(span);
+                        }
+                    }
+                }
+            }
+        }
+
+        let where_clause_span =
+            generics.where_clause.span_for_predicates_or_empty_place().shrink_to_hi();
+
+        match &param_spans[..] {
+            &[] => {
+                err.span_help(
+                    param.span,
+                    &format!("{} `where {}: {}`", MSG_RESTRICT_TYPE, param_name, constraint),
+                );
+
+                err.tool_only_span_suggestion(
+                    where_clause_span,
+                    MSG_RESTRICT_TYPE,
+                    format!(", {}: {}", param_name, constraint),
+                    Applicability::MachineApplicable,
+                );
+            }
+
+            &[&param_span] => {
+                err.span_help(
+                    param_span,
+                    &format!("{} `+ {}`", MSG_RESTRICT_BOUND_FURTHER, constraint),
+                );
+
+                let span_hi = param_span.with_hi(span.hi());
+                let span_with_colon = source_map.span_through_char(span_hi, ':');
+
+                if span_hi != param_span && span_with_colon != span_hi {
+                    err.tool_only_span_suggestion(
+                        span_with_colon,
+                        MSG_RESTRICT_BOUND_FURTHER,
+                        format!("{}: {} +", param_name, constraint),
+                        Applicability::MachineApplicable,
+                    );
+                }
+            }
+
+            _ => {
+                err.span_help(
+                    param.span,
+                    &format!(
+                        "{} `where {}: {}`",
+                        MSG_RESTRICT_TYPE_FURTHER, param_name, constraint,
+                    ),
+                );
+
+                err.tool_only_span_suggestion(
+                    where_clause_span,
+                    MSG_RESTRICT_BOUND_FURTHER,
+                    format!(", {}: {}", param_name, constraint),
+                    Applicability::MachineApplicable,
+                );
+            }
+        }
+
+        true
+    }
+}
diff --git a/src/librustc_trait_selection/traits/error_reporting/on_unimplemented.rs b/src/librustc_trait_selection/traits/error_reporting/on_unimplemented.rs
new file mode 100644 (file)
index 0000000..3d0dd73
--- /dev/null
@@ -0,0 +1,243 @@
+use super::{
+    ObligationCauseCode, OnUnimplementedDirective, OnUnimplementedNote, PredicateObligation,
+};
+use crate::infer::InferCtxt;
+use rustc::ty::subst::Subst;
+use rustc::ty::{self, GenericParamDefKind};
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
+use rustc_span::symbol::sym;
+
+use super::InferCtxtPrivExt;
+
+crate trait InferCtxtExt<'tcx> {
+    /*private*/
+    fn impl_similar_to(
+        &self,
+        trait_ref: ty::PolyTraitRef<'tcx>,
+        obligation: &PredicateObligation<'tcx>,
+    ) -> Option<DefId>;
+
+    /*private*/
+    fn describe_enclosure(&self, hir_id: hir::HirId) -> Option<&'static str>;
+
+    fn on_unimplemented_note(
+        &self,
+        trait_ref: ty::PolyTraitRef<'tcx>,
+        obligation: &PredicateObligation<'tcx>,
+    ) -> OnUnimplementedNote;
+}
+
+impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
+    fn impl_similar_to(
+        &self,
+        trait_ref: ty::PolyTraitRef<'tcx>,
+        obligation: &PredicateObligation<'tcx>,
+    ) -> Option<DefId> {
+        let tcx = self.tcx;
+        let param_env = obligation.param_env;
+        let trait_ref = tcx.erase_late_bound_regions(&trait_ref);
+        let trait_self_ty = trait_ref.self_ty();
+
+        let mut self_match_impls = vec![];
+        let mut fuzzy_match_impls = vec![];
+
+        self.tcx.for_each_relevant_impl(trait_ref.def_id, trait_self_ty, |def_id| {
+            let impl_substs = self.fresh_substs_for_item(obligation.cause.span, def_id);
+            let impl_trait_ref = tcx.impl_trait_ref(def_id).unwrap().subst(tcx, impl_substs);
+
+            let impl_self_ty = impl_trait_ref.self_ty();
+
+            if let Ok(..) = self.can_eq(param_env, trait_self_ty, impl_self_ty) {
+                self_match_impls.push(def_id);
+
+                if trait_ref
+                    .substs
+                    .types()
+                    .skip(1)
+                    .zip(impl_trait_ref.substs.types().skip(1))
+                    .all(|(u, v)| self.fuzzy_match_tys(u, v))
+                {
+                    fuzzy_match_impls.push(def_id);
+                }
+            }
+        });
+
+        let impl_def_id = if self_match_impls.len() == 1 {
+            self_match_impls[0]
+        } else if fuzzy_match_impls.len() == 1 {
+            fuzzy_match_impls[0]
+        } else {
+            return None;
+        };
+
+        tcx.has_attr(impl_def_id, sym::rustc_on_unimplemented).then_some(impl_def_id)
+    }
+
+    /// Used to set on_unimplemented's `ItemContext`
+    /// to be the enclosing (async) block/function/closure
+    fn describe_enclosure(&self, hir_id: hir::HirId) -> Option<&'static str> {
+        let hir = &self.tcx.hir();
+        let node = hir.find(hir_id)?;
+        match &node {
+            hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, _, body_id), .. }) => {
+                self.describe_generator(*body_id).or_else(|| {
+                    Some(if let hir::FnHeader { asyncness: hir::IsAsync::Async, .. } = sig.header {
+                        "an async function"
+                    } else {
+                        "a function"
+                    })
+                })
+            }
+            hir::Node::TraitItem(hir::TraitItem {
+                kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(body_id)),
+                ..
+            }) => self.describe_generator(*body_id).or_else(|| Some("a trait method")),
+            hir::Node::ImplItem(hir::ImplItem {
+                kind: hir::ImplItemKind::Fn(sig, body_id),
+                ..
+            }) => self.describe_generator(*body_id).or_else(|| {
+                Some(if let hir::FnHeader { asyncness: hir::IsAsync::Async, .. } = sig.header {
+                    "an async method"
+                } else {
+                    "a method"
+                })
+            }),
+            hir::Node::Expr(hir::Expr {
+                kind: hir::ExprKind::Closure(_is_move, _, body_id, _, gen_movability),
+                ..
+            }) => self.describe_generator(*body_id).or_else(|| {
+                Some(if gen_movability.is_some() { "an async closure" } else { "a closure" })
+            }),
+            hir::Node::Expr(hir::Expr { .. }) => {
+                let parent_hid = hir.get_parent_node(hir_id);
+                if parent_hid != hir_id {
+                    return self.describe_enclosure(parent_hid);
+                } else {
+                    None
+                }
+            }
+            _ => None,
+        }
+    }
+
+    fn on_unimplemented_note(
+        &self,
+        trait_ref: ty::PolyTraitRef<'tcx>,
+        obligation: &PredicateObligation<'tcx>,
+    ) -> OnUnimplementedNote {
+        let def_id =
+            self.impl_similar_to(trait_ref, obligation).unwrap_or_else(|| trait_ref.def_id());
+        let trait_ref = *trait_ref.skip_binder();
+
+        let mut flags = vec![];
+        flags.push((
+            sym::item_context,
+            self.describe_enclosure(obligation.cause.body_id).map(|s| s.to_owned()),
+        ));
+
+        match obligation.cause.code {
+            ObligationCauseCode::BuiltinDerivedObligation(..)
+            | ObligationCauseCode::ImplDerivedObligation(..) => {}
+            _ => {
+                // this is a "direct", user-specified, rather than derived,
+                // obligation.
+                flags.push((sym::direct, None));
+            }
+        }
+
+        if let ObligationCauseCode::ItemObligation(item) = obligation.cause.code {
+            // FIXME: maybe also have some way of handling methods
+            // from other traits? That would require name resolution,
+            // which we might want to be some sort of hygienic.
+            //
+            // Currently I'm leaving it for what I need for `try`.
+            if self.tcx.trait_of_item(item) == Some(trait_ref.def_id) {
+                let method = self.tcx.item_name(item);
+                flags.push((sym::from_method, None));
+                flags.push((sym::from_method, Some(method.to_string())));
+            }
+        }
+        if let Some((t, _)) = self.get_parent_trait_ref(&obligation.cause.code) {
+            flags.push((sym::parent_trait, Some(t)));
+        }
+
+        if let Some(k) = obligation.cause.span.desugaring_kind() {
+            flags.push((sym::from_desugaring, None));
+            flags.push((sym::from_desugaring, Some(format!("{:?}", k))));
+        }
+        let generics = self.tcx.generics_of(def_id);
+        let self_ty = trait_ref.self_ty();
+        // This is also included through the generics list as `Self`,
+        // but the parser won't allow you to use it
+        flags.push((sym::_Self, Some(self_ty.to_string())));
+        if let Some(def) = self_ty.ty_adt_def() {
+            // We also want to be able to select self's original
+            // signature with no type arguments resolved
+            flags.push((sym::_Self, Some(self.tcx.type_of(def.did).to_string())));
+        }
+
+        for param in generics.params.iter() {
+            let value = match param.kind {
+                GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => {
+                    trait_ref.substs[param.index as usize].to_string()
+                }
+                GenericParamDefKind::Lifetime => continue,
+            };
+            let name = param.name;
+            flags.push((name, Some(value)));
+        }
+
+        if let Some(true) = self_ty.ty_adt_def().map(|def| def.did.is_local()) {
+            flags.push((sym::crate_local, None));
+        }
+
+        // Allow targeting all integers using `{integral}`, even if the exact type was resolved
+        if self_ty.is_integral() {
+            flags.push((sym::_Self, Some("{integral}".to_owned())));
+        }
+
+        if let ty::Array(aty, len) = self_ty.kind {
+            flags.push((sym::_Self, Some("[]".to_owned())));
+            flags.push((sym::_Self, Some(format!("[{}]", aty))));
+            if let Some(def) = aty.ty_adt_def() {
+                // We also want to be able to select the array's type's original
+                // signature with no type arguments resolved
+                flags.push((
+                    sym::_Self,
+                    Some(format!("[{}]", self.tcx.type_of(def.did).to_string())),
+                ));
+                let tcx = self.tcx;
+                if let Some(len) = len.try_eval_usize(tcx, ty::ParamEnv::empty()) {
+                    flags.push((
+                        sym::_Self,
+                        Some(format!("[{}; {}]", self.tcx.type_of(def.did).to_string(), len)),
+                    ));
+                } else {
+                    flags.push((
+                        sym::_Self,
+                        Some(format!("[{}; _]", self.tcx.type_of(def.did).to_string())),
+                    ));
+                }
+            }
+        }
+        if let ty::Dynamic(traits, _) = self_ty.kind {
+            for t in *traits.skip_binder() {
+                match t {
+                    ty::ExistentialPredicate::Trait(trait_ref) => {
+                        flags.push((sym::_Self, Some(self.tcx.def_path_str(trait_ref.def_id))))
+                    }
+                    _ => {}
+                }
+            }
+        }
+
+        if let Ok(Some(command)) =
+            OnUnimplementedDirective::of_item(self.tcx, trait_ref.def_id, def_id)
+        {
+            command.evaluate(self.tcx, trait_ref, &flags[..])
+        } else {
+            OnUnimplementedNote::default()
+        }
+    }
+}
diff --git a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs
new file mode 100644 (file)
index 0000000..0523a20
--- /dev/null
@@ -0,0 +1,1617 @@
+use super::{
+    EvaluationResult, Obligation, ObligationCause, ObligationCauseCode, PredicateObligation,
+};
+
+use crate::infer::InferCtxt;
+use crate::traits::error_reporting::suggest_constraining_type_param;
+
+use rustc::ty::TypeckTables;
+use rustc::ty::{self, AdtKind, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
+use rustc_errors::{error_code, struct_span_err, Applicability, DiagnosticBuilder, Style};
+use rustc_hir as hir;
+use rustc_hir::def::DefKind;
+use rustc_hir::def_id::DefId;
+use rustc_hir::intravisit::Visitor;
+use rustc_hir::Node;
+use rustc_span::symbol::{kw, sym};
+use rustc_span::{MultiSpan, Span, DUMMY_SP};
+use std::fmt;
+
+use super::InferCtxtPrivExt;
+use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
+
+crate trait InferCtxtExt<'tcx> {
+    fn suggest_restricting_param_bound(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        trait_ref: &ty::PolyTraitRef<'_>,
+        body_id: hir::HirId,
+    );
+
+    fn suggest_borrow_on_unsized_slice(
+        &self,
+        code: &ObligationCauseCode<'tcx>,
+        err: &mut DiagnosticBuilder<'tcx>,
+    );
+
+    fn get_closure_name(
+        &self,
+        def_id: DefId,
+        err: &mut DiagnosticBuilder<'_>,
+        msg: &str,
+    ) -> Option<String>;
+
+    fn suggest_fn_call(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        err: &mut DiagnosticBuilder<'_>,
+        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
+        points_at_arg: bool,
+    );
+
+    fn suggest_add_reference_to_arg(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        err: &mut DiagnosticBuilder<'tcx>,
+        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
+        points_at_arg: bool,
+        has_custom_message: bool,
+    ) -> bool;
+
+    fn suggest_remove_reference(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        err: &mut DiagnosticBuilder<'tcx>,
+        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
+    );
+
+    fn suggest_change_mut(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        err: &mut DiagnosticBuilder<'tcx>,
+        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
+        points_at_arg: bool,
+    );
+
+    fn suggest_semicolon_removal(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        err: &mut DiagnosticBuilder<'tcx>,
+        span: Span,
+        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
+    );
+
+    fn suggest_impl_trait(
+        &self,
+        err: &mut DiagnosticBuilder<'tcx>,
+        span: Span,
+        obligation: &PredicateObligation<'tcx>,
+        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
+    ) -> bool;
+
+    fn point_at_returns_when_relevant(
+        &self,
+        err: &mut DiagnosticBuilder<'tcx>,
+        obligation: &PredicateObligation<'tcx>,
+    );
+
+    fn report_closure_arg_mismatch(
+        &self,
+        span: Span,
+        found_span: Option<Span>,
+        expected_ref: ty::PolyTraitRef<'tcx>,
+        found: ty::PolyTraitRef<'tcx>,
+    ) -> DiagnosticBuilder<'tcx>;
+
+    fn suggest_fully_qualified_path(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        def_id: DefId,
+        span: Span,
+        trait_ref: DefId,
+    );
+
+    fn maybe_note_obligation_cause_for_async_await(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        obligation: &PredicateObligation<'tcx>,
+    ) -> bool;
+
+    fn note_obligation_cause_for_async_await(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        target_span: Span,
+        scope_span: &Option<Span>,
+        expr: Option<hir::HirId>,
+        snippet: String,
+        first_generator: DefId,
+        last_generator: Option<DefId>,
+        trait_ref: ty::TraitRef<'_>,
+        target_ty: Ty<'tcx>,
+        tables: &ty::TypeckTables<'_>,
+        obligation: &PredicateObligation<'tcx>,
+        next_code: Option<&ObligationCauseCode<'tcx>>,
+    );
+
+    fn note_obligation_cause_code<T>(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        predicate: &T,
+        cause_code: &ObligationCauseCode<'tcx>,
+        obligated_types: &mut Vec<&ty::TyS<'tcx>>,
+    ) where
+        T: fmt::Display;
+
+    fn suggest_new_overflow_limit(&self, err: &mut DiagnosticBuilder<'_>);
+}
+
+impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
+    fn suggest_restricting_param_bound(
+        &self,
+        mut 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 suggest_restriction =
+            |generics: &hir::Generics<'_>, msg, err: &mut DiagnosticBuilder<'_>| {
+                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.without_const().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::Fn(..),
+                    ..
+                }) if param_ty && self_ty == self.tcx.types.self_param => {
+                    // Restricting `Self` for a single method.
+                    suggest_restriction(&generics, "`Self`", err);
+                    return;
+                }
+
+                hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. })
+                | hir::Node::TraitItem(hir::TraitItem {
+                    generics,
+                    kind: hir::TraitItemKind::Fn(..),
+                    ..
+                })
+                | hir::Node::ImplItem(hir::ImplItem {
+                    generics,
+                    kind: hir::ImplItemKind::Fn(..),
+                    ..
+                })
+                | 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", err);
+                    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 param_name = self_ty.to_string();
+                    let constraint = trait_ref.print_only_trait_path().to_string();
+                    if suggest_constraining_type_param(
+                        self.tcx,
+                        generics,
+                        &mut err,
+                        &param_name,
+                        &constraint,
+                        self.tcx.sess.source_map(),
+                        *span,
+                        Some(trait_ref.def_id()),
+                    ) {
+                        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(
+        &self,
+        code: &ObligationCauseCode<'tcx>,
+        err: &mut DiagnosticBuilder<'tcx>,
+    ) {
+        if let &ObligationCauseCode::VariableType(hir_id) = code {
+            let parent_node = self.tcx.hir().get_parent_node(hir_id);
+            if let Some(Node::Local(ref local)) = self.tcx.hir().find(parent_node) {
+                if let Some(ref expr) = local.init {
+                    if let hir::ExprKind::Index(_, _) = expr.kind {
+                        if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(expr.span) {
+                            err.span_suggestion(
+                                expr.span,
+                                "consider borrowing here",
+                                format!("&{}", snippet),
+                                Applicability::MachineApplicable,
+                            );
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    /// Given a closure's `DefId`, return the given name of the closure.
+    ///
+    /// This doesn't account for reassignments, but it's only used for suggestions.
+    fn get_closure_name(
+        &self,
+        def_id: DefId,
+        err: &mut DiagnosticBuilder<'_>,
+        msg: &str,
+    ) -> Option<String> {
+        let get_name =
+            |err: &mut DiagnosticBuilder<'_>, kind: &hir::PatKind<'_>| -> Option<String> {
+                // Get the local name of this closure. This can be inaccurate because
+                // of the possibility of reassignment, but this should be good enough.
+                match &kind {
+                    hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, _, name, None) => {
+                        Some(format!("{}", name))
+                    }
+                    _ => {
+                        err.note(&msg);
+                        None
+                    }
+                }
+            };
+
+        let hir = self.tcx.hir();
+        let hir_id = hir.as_local_hir_id(def_id)?;
+        let parent_node = hir.get_parent_node(hir_id);
+        match hir.find(parent_node) {
+            Some(hir::Node::Stmt(hir::Stmt { kind: hir::StmtKind::Local(local), .. })) => {
+                get_name(err, &local.pat.kind)
+            }
+            // Different to previous arm because one is `&hir::Local` and the other
+            // is `P<hir::Local>`.
+            Some(hir::Node::Local(local)) => get_name(err, &local.pat.kind),
+            _ => return None,
+        }
+    }
+
+    /// We tried to apply the bound to an `fn` or closure. Check whether calling it would
+    /// evaluate to a type that *would* satisfy the trait binding. If it would, suggest calling
+    /// it: `bar(foo)` → `bar(foo())`. This case is *very* likely to be hit if `foo` is `async`.
+    fn suggest_fn_call(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        err: &mut DiagnosticBuilder<'_>,
+        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
+        points_at_arg: bool,
+    ) {
+        let self_ty = trait_ref.self_ty();
+        let (def_id, output_ty, callable) = match self_ty.kind {
+            ty::Closure(def_id, substs) => {
+                (def_id, self.closure_sig(def_id, substs).output(), "closure")
+            }
+            ty::FnDef(def_id, _) => (def_id, self_ty.fn_sig(self.tcx).output(), "function"),
+            _ => return,
+        };
+        let msg = format!("use parentheses to call the {}", callable);
+
+        let obligation = self.mk_obligation_for_def_id(
+            trait_ref.def_id(),
+            output_ty.skip_binder(),
+            obligation.cause.clone(),
+            obligation.param_env,
+        );
+
+        match self.evaluate_obligation(&obligation) {
+            Ok(EvaluationResult::EvaluatedToOk)
+            | Ok(EvaluationResult::EvaluatedToOkModuloRegions)
+            | Ok(EvaluationResult::EvaluatedToAmbig) => {}
+            _ => return,
+        }
+        let hir = self.tcx.hir();
+        // Get the name of the callable and the arguments to be used in the suggestion.
+        let snippet = match hir.get_if_local(def_id) {
+            Some(hir::Node::Expr(hir::Expr {
+                kind: hir::ExprKind::Closure(_, decl, _, span, ..),
+                ..
+            })) => {
+                err.span_label(*span, "consider calling this closure");
+                let name = match self.get_closure_name(def_id, err, &msg) {
+                    Some(name) => name,
+                    None => return,
+                };
+                let args = decl.inputs.iter().map(|_| "_").collect::<Vec<_>>().join(", ");
+                format!("{}({})", name, args)
+            }
+            Some(hir::Node::Item(hir::Item {
+                ident,
+                kind: hir::ItemKind::Fn(.., body_id),
+                ..
+            })) => {
+                err.span_label(ident.span, "consider calling this function");
+                let body = hir.body(*body_id);
+                let args = body
+                    .params
+                    .iter()
+                    .map(|arg| match &arg.pat.kind {
+                        hir::PatKind::Binding(_, _, ident, None)
+                        // FIXME: provide a better suggestion when encountering `SelfLower`, it
+                        // should suggest a method call.
+                        if ident.name != kw::SelfLower => ident.to_string(),
+                        _ => "_".to_string(),
+                    })
+                    .collect::<Vec<_>>()
+                    .join(", ");
+                format!("{}({})", ident, args)
+            }
+            _ => return,
+        };
+        if points_at_arg {
+            // When the obligation error has been ensured to have been caused by
+            // an argument, the `obligation.cause.span` points at the expression
+            // of the argument, so we can provide a suggestion. This is signaled
+            // by `points_at_arg`. Otherwise, we give a more general note.
+            err.span_suggestion(
+                obligation.cause.span,
+                &msg,
+                snippet,
+                Applicability::HasPlaceholders,
+            );
+        } else {
+            err.help(&format!("{}: `{}`", msg, snippet));
+        }
+    }
+
+    fn suggest_add_reference_to_arg(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        err: &mut DiagnosticBuilder<'tcx>,
+        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
+        points_at_arg: bool,
+        has_custom_message: bool,
+    ) -> bool {
+        if !points_at_arg {
+            return false;
+        }
+
+        let span = obligation.cause.span;
+        let param_env = obligation.param_env;
+        let trait_ref = trait_ref.skip_binder();
+
+        if let ObligationCauseCode::ImplDerivedObligation(obligation) = &obligation.cause.code {
+            // Try to apply the original trait binding obligation by borrowing.
+            let self_ty = trait_ref.self_ty();
+            let found = self_ty.to_string();
+            let new_self_ty = self.tcx.mk_imm_ref(self.tcx.lifetimes.re_static, self_ty);
+            let substs = self.tcx.mk_substs_trait(new_self_ty, &[]);
+            let new_trait_ref = ty::TraitRef::new(obligation.parent_trait_ref.def_id(), substs);
+            let new_obligation = Obligation::new(
+                ObligationCause::dummy(),
+                param_env,
+                new_trait_ref.without_const().to_predicate(),
+            );
+            if self.predicate_must_hold_modulo_regions(&new_obligation) {
+                if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
+                    // We have a very specific type of error, where just borrowing this argument
+                    // might solve the problem. In cases like this, the important part is the
+                    // original type obligation, not the last one that failed, which is arbitrary.
+                    // Because of this, we modify the error to refer to the original obligation and
+                    // return early in the caller.
+                    let msg = format!(
+                        "the trait bound `{}: {}` is not satisfied",
+                        found,
+                        obligation.parent_trait_ref.skip_binder().print_only_trait_path(),
+                    );
+                    if has_custom_message {
+                        err.note(&msg);
+                    } else {
+                        err.message = vec![(msg, Style::NoStyle)];
+                    }
+                    if snippet.starts_with('&') {
+                        // This is already a literal borrow and the obligation is failing
+                        // somewhere else in the obligation chain. Do not suggest non-sense.
+                        return false;
+                    }
+                    err.span_label(
+                        span,
+                        &format!(
+                            "expected an implementor of trait `{}`",
+                            obligation.parent_trait_ref.skip_binder().print_only_trait_path(),
+                        ),
+                    );
+                    err.span_suggestion(
+                        span,
+                        "consider borrowing here",
+                        format!("&{}", snippet),
+                        Applicability::MaybeIncorrect,
+                    );
+                    return true;
+                }
+            }
+        }
+        false
+    }
+
+    /// Whenever references are used by mistake, like `for (i, e) in &vec.iter().enumerate()`,
+    /// suggest removing these references until we reach a type that implements the trait.
+    fn suggest_remove_reference(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        err: &mut DiagnosticBuilder<'tcx>,
+        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
+    ) {
+        let trait_ref = trait_ref.skip_binder();
+        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()).nth(refs_number) {
+                // Do not suggest removal of borrow from type arguments.
+                return;
+            }
+
+            let mut trait_type = trait_ref.self_ty();
+
+            for refs_remaining in 0..refs_number {
+                if let ty::Ref(_, t_type, _) = trait_type.kind {
+                    trait_type = t_type;
+
+                    let new_obligation = self.mk_obligation_for_def_id(
+                        trait_ref.def_id,
+                        trait_type,
+                        ObligationCause::dummy(),
+                        obligation.param_env,
+                    );
+
+                    if self.predicate_may_hold(&new_obligation) {
+                        let sp = self
+                            .tcx
+                            .sess
+                            .source_map()
+                            .span_take_while(span, |c| c.is_whitespace() || *c == '&');
+
+                        let remove_refs = refs_remaining + 1;
+
+                        let msg = if remove_refs == 1 {
+                            "consider removing the leading `&`-reference".to_string()
+                        } else {
+                            format!("consider removing {} leading `&`-references", remove_refs)
+                        };
+
+                        err.span_suggestion_short(
+                            sp,
+                            &msg,
+                            String::new(),
+                            Applicability::MachineApplicable,
+                        );
+                        break;
+                    }
+                } else {
+                    break;
+                }
+            }
+        }
+    }
+
+    /// 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<ty::TraitRef<'tcx>>,
+        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()).nth(refs_number) {
+                // 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_or_consts() {
+                // 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::Mut => self.tcx.mk_imm_ref(region, t_type),
+                    hir::Mutability::Not => self.tcx.mk_mut_ref(region, t_type),
+                };
+
+                let new_obligation = self.mk_obligation_for_def_id(
+                    trait_ref.skip_binder().def_id,
+                    trait_type,
+                    ObligationCause::dummy(),
+                    obligation.param_env,
+                );
+
+                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::Not && 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.print_only_trait_path(),
+                            trait_type,
+                            trait_ref.skip_binder().self_ty(),
+                        ));
+                    }
+                }
+            }
+        }
+    }
+
+    fn suggest_semicolon_removal(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        err: &mut DiagnosticBuilder<'tcx>,
+        span: Span,
+        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
+    ) {
+        let hir = self.tcx.hir();
+        let parent_node = hir.get_parent_node(obligation.cause.body_id);
+        let node = hir.find(parent_node);
+        if let Some(hir::Node::Item(hir::Item {
+            kind: hir::ItemKind::Fn(sig, _, body_id), ..
+        })) = node
+        {
+            let body = hir.body(*body_id);
+            if let hir::ExprKind::Block(blk, _) = &body.value.kind {
+                if sig.decl.output.span().overlaps(span)
+                    && blk.expr.is_none()
+                    && "()" == &trait_ref.self_ty().to_string()
+                {
+                    // FIXME(estebank): When encountering a method with a trait
+                    // bound not satisfied in the return type with a body that has
+                    // no return, suggest removal of semicolon on last statement.
+                    // Once that is added, close #54771.
+                    if let Some(ref stmt) = blk.stmts.last() {
+                        let sp = self.tcx.sess.source_map().end_point(stmt.span);
+                        err.span_label(sp, "consider removing this semicolon");
+                    }
+                }
+            }
+        }
+    }
+
+    /// If all conditions are met to identify a returned `dyn Trait`, suggest using `impl Trait` if
+    /// applicable and signal that the error has been expanded appropriately and needs to be
+    /// emitted.
+    fn suggest_impl_trait(
+        &self,
+        err: &mut DiagnosticBuilder<'tcx>,
+        span: Span,
+        obligation: &PredicateObligation<'tcx>,
+        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
+    ) -> bool {
+        match obligation.cause.code.peel_derives() {
+            // Only suggest `impl Trait` if the return type is unsized because it is `dyn Trait`.
+            ObligationCauseCode::SizedReturnType => {}
+            _ => return false,
+        }
+
+        let hir = self.tcx.hir();
+        let parent_node = hir.get_parent_node(obligation.cause.body_id);
+        let node = hir.find(parent_node);
+        let (sig, body_id) = if let Some(hir::Node::Item(hir::Item {
+            kind: hir::ItemKind::Fn(sig, _, body_id),
+            ..
+        })) = node
+        {
+            (sig, body_id)
+        } else {
+            return false;
+        };
+        let body = hir.body(*body_id);
+        let trait_ref = self.resolve_vars_if_possible(trait_ref);
+        let ty = trait_ref.skip_binder().self_ty();
+        let is_object_safe = match ty.kind {
+            ty::Dynamic(predicates, _) => {
+                // If the `dyn Trait` is not object safe, do not suggest `Box<dyn Trait>`.
+                predicates
+                    .principal_def_id()
+                    .map_or(true, |def_id| self.tcx.object_safety_violations(def_id).is_empty())
+            }
+            // We only want to suggest `impl Trait` to `dyn Trait`s.
+            // For example, `fn foo() -> str` needs to be filtered out.
+            _ => return false,
+        };
+
+        let ret_ty = if let hir::FnRetTy::Return(ret_ty) = sig.decl.output {
+            ret_ty
+        } else {
+            return false;
+        };
+
+        // Use `TypeVisitor` instead of the output type directly to find the span of `ty` for
+        // cases like `fn foo() -> (dyn Trait, i32) {}`.
+        // Recursively look for `TraitObject` types and if there's only one, use that span to
+        // suggest `impl Trait`.
+
+        // Visit to make sure there's a single `return` type to suggest `impl Trait`,
+        // otherwise suggest using `Box<dyn Trait>` or an enum.
+        let mut visitor = ReturnsVisitor::default();
+        visitor.visit_body(&body);
+
+        let tables = self.in_progress_tables.map(|t| t.borrow()).unwrap();
+
+        let mut ret_types = visitor
+            .returns
+            .iter()
+            .filter_map(|expr| tables.node_type_opt(expr.hir_id))
+            .map(|ty| self.resolve_vars_if_possible(&ty));
+        let (last_ty, all_returns_have_same_type) = ret_types.clone().fold(
+            (None, true),
+            |(last_ty, mut same): (std::option::Option<Ty<'_>>, bool), ty| {
+                let ty = self.resolve_vars_if_possible(&ty);
+                same &= last_ty.map_or(true, |last_ty| last_ty == ty) && ty.kind != ty::Error;
+                (Some(ty), same)
+            },
+        );
+        let all_returns_conform_to_trait =
+            if let Some(ty_ret_ty) = tables.node_type_opt(ret_ty.hir_id) {
+                match ty_ret_ty.kind {
+                    ty::Dynamic(predicates, _) => {
+                        let cause = ObligationCause::misc(ret_ty.span, ret_ty.hir_id);
+                        let param_env = ty::ParamEnv::empty();
+                        ret_types.all(|returned_ty| {
+                            predicates.iter().all(|predicate| {
+                                let pred = predicate.with_self_ty(self.tcx, returned_ty);
+                                let obl = Obligation::new(cause.clone(), param_env, pred);
+                                self.predicate_may_hold(&obl)
+                            })
+                        })
+                    }
+                    _ => false,
+                }
+            } else {
+                true
+            };
+
+        let (snippet, last_ty) =
+            if let (true, hir::TyKind::TraitObject(..), Ok(snippet), true, Some(last_ty)) = (
+                // Verify that we're dealing with a return `dyn Trait`
+                ret_ty.span.overlaps(span),
+                &ret_ty.kind,
+                self.tcx.sess.source_map().span_to_snippet(ret_ty.span),
+                // If any of the return types does not conform to the trait, then we can't
+                // suggest `impl Trait` nor trait objects, it is a type mismatch error.
+                all_returns_conform_to_trait,
+                last_ty,
+            ) {
+                (snippet, last_ty)
+            } else {
+                return false;
+            };
+        err.code(error_code!(E0746));
+        err.set_primary_message("return type cannot have an unboxed trait object");
+        err.children.clear();
+        let impl_trait_msg = "for information on `impl Trait`, see \
+            <https://doc.rust-lang.org/book/ch10-02-traits.html\
+            #returning-types-that-implement-traits>";
+        let trait_obj_msg = "for information on trait objects, see \
+            <https://doc.rust-lang.org/book/ch17-02-trait-objects.html\
+            #using-trait-objects-that-allow-for-values-of-different-types>";
+        let has_dyn = snippet.split_whitespace().next().map_or(false, |s| s == "dyn");
+        let trait_obj = if has_dyn { &snippet[4..] } else { &snippet[..] };
+        if all_returns_have_same_type {
+            // Suggest `-> impl Trait`.
+            err.span_suggestion(
+                ret_ty.span,
+                &format!(
+                    "return `impl {1}` instead, as all return paths are of type `{}`, \
+                        which implements `{1}`",
+                    last_ty, trait_obj,
+                ),
+                format!("impl {}", trait_obj),
+                Applicability::MachineApplicable,
+            );
+            err.note(impl_trait_msg);
+        } else {
+            if is_object_safe {
+                // Suggest `-> Box<dyn Trait>` and `Box::new(returned_value)`.
+                // Get all the return values and collect their span and suggestion.
+                let mut suggestions = visitor
+                    .returns
+                    .iter()
+                    .map(|expr| {
+                        (
+                            expr.span,
+                            format!(
+                                "Box::new({})",
+                                self.tcx.sess.source_map().span_to_snippet(expr.span).unwrap()
+                            ),
+                        )
+                    })
+                    .collect::<Vec<_>>();
+                // Add the suggestion for the return type.
+                suggestions.push((ret_ty.span, format!("Box<dyn {}>", trait_obj)));
+                err.multipart_suggestion(
+                    "return a boxed trait object instead",
+                    suggestions,
+                    Applicability::MaybeIncorrect,
+                );
+            } else {
+                // This is currently not possible to trigger because E0038 takes precedence, but
+                // leave it in for completeness in case anything changes in an earlier stage.
+                err.note(&format!(
+                    "if trait `{}` was object safe, you could return a trait object",
+                    trait_obj,
+                ));
+            }
+            err.note(trait_obj_msg);
+            err.note(&format!(
+                "if all the returned values were of the same type you could use \
+                    `impl {}` as the return type",
+                trait_obj,
+            ));
+            err.note(impl_trait_msg);
+            err.note("you can create a new `enum` with a variant for each returned type");
+        }
+        true
+    }
+
+    fn point_at_returns_when_relevant(
+        &self,
+        err: &mut DiagnosticBuilder<'tcx>,
+        obligation: &PredicateObligation<'tcx>,
+    ) {
+        match obligation.cause.code.peel_derives() {
+            ObligationCauseCode::SizedReturnType => {}
+            _ => return,
+        }
+
+        let hir = self.tcx.hir();
+        let parent_node = hir.get_parent_node(obligation.cause.body_id);
+        let node = hir.find(parent_node);
+        if let Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. })) =
+            node
+        {
+            let body = hir.body(*body_id);
+            // Point at all the `return`s in the function as they have failed trait bounds.
+            let mut visitor = ReturnsVisitor::default();
+            visitor.visit_body(&body);
+            let tables = self.in_progress_tables.map(|t| t.borrow()).unwrap();
+            for expr in &visitor.returns {
+                if let Some(returned_ty) = tables.node_type_opt(expr.hir_id) {
+                    let ty = self.resolve_vars_if_possible(&returned_ty);
+                    err.span_label(expr.span, &format!("this returned value is of type `{}`", ty));
+                }
+            }
+        }
+    }
+
+    fn report_closure_arg_mismatch(
+        &self,
+        span: Span,
+        found_span: Option<Span>,
+        expected_ref: ty::PolyTraitRef<'tcx>,
+        found: ty::PolyTraitRef<'tcx>,
+    ) -> DiagnosticBuilder<'tcx> {
+        crate fn build_fn_sig_string<'tcx>(
+            tcx: TyCtxt<'tcx>,
+            trait_ref: &ty::TraitRef<'tcx>,
+        ) -> String {
+            let inputs = trait_ref.substs.type_at(1);
+            let sig = if let ty::Tuple(inputs) = inputs.kind {
+                tcx.mk_fn_sig(
+                    inputs.iter().map(|k| k.expect_ty()),
+                    tcx.mk_ty_infer(ty::TyVar(ty::TyVid { index: 0 })),
+                    false,
+                    hir::Unsafety::Normal,
+                    ::rustc_target::spec::abi::Abi::Rust,
+                )
+            } else {
+                tcx.mk_fn_sig(
+                    ::std::iter::once(inputs),
+                    tcx.mk_ty_infer(ty::TyVar(ty::TyVid { index: 0 })),
+                    false,
+                    hir::Unsafety::Normal,
+                    ::rustc_target::spec::abi::Abi::Rust,
+                )
+            };
+            ty::Binder::bind(sig).to_string()
+        }
+
+        let argument_is_closure = expected_ref.skip_binder().substs.type_at(0).is_closure();
+        let mut err = struct_span_err!(
+            self.tcx.sess,
+            span,
+            E0631,
+            "type mismatch in {} arguments",
+            if argument_is_closure { "closure" } else { "function" }
+        );
+
+        let found_str = format!(
+            "expected signature of `{}`",
+            build_fn_sig_string(self.tcx, found.skip_binder())
+        );
+        err.span_label(span, found_str);
+
+        let found_span = found_span.unwrap_or(span);
+        let expected_str = format!(
+            "found signature of `{}`",
+            build_fn_sig_string(self.tcx, expected_ref.skip_binder())
+        );
+        err.span_label(found_span, expected_str);
+
+        err
+    }
+
+    fn suggest_fully_qualified_path(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        def_id: DefId,
+        span: Span,
+        trait_ref: DefId,
+    ) {
+        if let Some(assoc_item) = self.tcx.opt_associated_item(def_id) {
+            if let ty::AssocKind::Const | ty::AssocKind::Type = assoc_item.kind {
+                err.note(&format!(
+                    "{}s cannot be accessed directly on a `trait`, they can only be \
+                        accessed through a specific `impl`",
+                    assoc_item.kind.suggestion_descr(),
+                ));
+                err.span_suggestion(
+                    span,
+                    "use the fully qualified path to an implementation",
+                    format!("<Type as {}>::{}", self.tcx.def_path_str(trait_ref), assoc_item.ident),
+                    Applicability::HasPlaceholders,
+                );
+            }
+        }
+    }
+
+    /// Adds an async-await specific note to the diagnostic when the future does not implement
+    /// an auto trait because of a captured type.
+    ///
+    /// ```ignore (diagnostic)
+    /// note: future does not implement `Qux` as this value is used across an await
+    ///   --> $DIR/issue-64130-3-other.rs:17:5
+    ///    |
+    /// LL |     let x = Foo;
+    ///    |         - has type `Foo`
+    /// LL |     baz().await;
+    ///    |     ^^^^^^^^^^^ await occurs here, with `x` maybe used later
+    /// LL | }
+    ///    | - `x` is later dropped here
+    /// ```
+    ///
+    /// When the diagnostic does not implement `Send` or `Sync` specifically, then the diagnostic
+    /// is "replaced" with a different message and a more specific error.
+    ///
+    /// ```ignore (diagnostic)
+    /// error: future cannot be sent between threads safely
+    ///   --> $DIR/issue-64130-2-send.rs:21:5
+    ///    |
+    /// LL | fn is_send<T: Send>(t: T) { }
+    ///    |    -------    ---- required by this bound in `is_send`
+    /// ...
+    /// LL |     is_send(bar());
+    ///    |     ^^^^^^^ future returned by `bar` is not send
+    ///    |
+    ///    = help: within `impl std::future::Future`, the trait `std::marker::Send` is not
+    ///            implemented for `Foo`
+    /// note: future is not send as this value is used across an await
+    ///   --> $DIR/issue-64130-2-send.rs:15:5
+    ///    |
+    /// LL |     let x = Foo;
+    ///    |         - has type `Foo`
+    /// LL |     baz().await;
+    ///    |     ^^^^^^^^^^^ await occurs here, with `x` maybe used later
+    /// LL | }
+    ///    | - `x` is later dropped here
+    /// ```
+    ///
+    /// Returns `true` if an async-await specific note was added to the diagnostic.
+    fn maybe_note_obligation_cause_for_async_await(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        obligation: &PredicateObligation<'tcx>,
+    ) -> bool {
+        debug!(
+            "maybe_note_obligation_cause_for_async_await: obligation.predicate={:?} \
+                obligation.cause.span={:?}",
+            obligation.predicate, obligation.cause.span
+        );
+        let source_map = self.tcx.sess.source_map();
+
+        // Attempt to detect an async-await error by looking at the obligation causes, looking
+        // for a generator 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 obligation in the chain is the most useful and has the generator that captured
+        // the type. The last generator has information about where the bound was introduced. At
+        // least one generator should be present for this diagnostic to be modified.
+        let (mut trait_ref, mut target_ty) = match obligation.predicate {
+            ty::Predicate::Trait(p, _) => {
+                (Some(p.skip_binder().trait_ref), Some(p.skip_binder().self_ty()))
+            }
+            _ => (None, None),
+        };
+        let mut generator = None;
+        let mut last_generator = None;
+        let mut next_code = Some(&obligation.cause.code);
+        while let Some(code) = next_code {
+            debug!("maybe_note_obligation_cause_for_async_await: code={:?}", code);
+            match code {
+                ObligationCauseCode::BuiltinDerivedObligation(derived_obligation)
+                | ObligationCauseCode::ImplDerivedObligation(derived_obligation) => {
+                    let ty = derived_obligation.parent_trait_ref.self_ty();
+                    debug!(
+                        "maybe_note_obligation_cause_for_async_await: \
+                            parent_trait_ref={:?} self_ty.kind={:?}",
+                        derived_obligation.parent_trait_ref, ty.kind
+                    );
+
+                    match ty.kind {
+                        ty::Generator(did, ..) => {
+                            generator = generator.or(Some(did));
+                            last_generator = Some(did);
+                        }
+                        ty::GeneratorWitness(..) => {}
+                        _ if generator.is_none() => {
+                            trait_ref = Some(*derived_obligation.parent_trait_ref.skip_binder());
+                            target_ty = Some(ty);
+                        }
+                        _ => {}
+                    }
+
+                    next_code = Some(derived_obligation.parent_code.as_ref());
+                }
+                _ => break,
+            }
+        }
+
+        // Only continue if a generator was found.
+        debug!(
+            "maybe_note_obligation_cause_for_async_await: generator={:?} trait_ref={:?} \
+                target_ty={:?}",
+            generator, trait_ref, target_ty
+        );
+        let (generator_did, trait_ref, target_ty) = match (generator, trait_ref, target_ty) {
+            (Some(generator_did), Some(trait_ref), Some(target_ty)) => {
+                (generator_did, trait_ref, target_ty)
+            }
+            _ => return false,
+        };
+
+        let span = self.tcx.def_span(generator_did);
+
+        // Do not ICE on closure typeck (#66868).
+        if self.tcx.hir().as_local_hir_id(generator_did).is_none() {
+            return false;
+        }
+
+        // Get the tables from the infcx if the generator is the function we are
+        // currently type-checking; otherwise, get them by performing a query.
+        // This is needed to avoid cycles.
+        let in_progress_tables = self.in_progress_tables.map(|t| t.borrow());
+        let generator_did_root = self.tcx.closure_base_def_id(generator_did);
+        debug!(
+            "maybe_note_obligation_cause_for_async_await: generator_did={:?} \
+             generator_did_root={:?} in_progress_tables.local_id_root={:?} span={:?}",
+            generator_did,
+            generator_did_root,
+            in_progress_tables.as_ref().map(|t| t.local_id_root),
+            span
+        );
+        let query_tables;
+        let tables: &TypeckTables<'tcx> = match &in_progress_tables {
+            Some(t) if t.local_id_root == Some(generator_did_root) => t,
+            _ => {
+                query_tables = self.tcx.typeck_tables_of(generator_did);
+                &query_tables
+            }
+        };
+
+        // Look for a type inside the generator interior that matches the target type to get
+        // a span.
+        let target_ty_erased = self.tcx.erase_regions(&target_ty);
+        let target_span = tables
+            .generator_interior_types
+            .iter()
+            .find(|ty::GeneratorInteriorTypeCause { ty, .. }| {
+                // Careful: the regions for types that appear in the
+                // generator interior are not generally known, so we
+                // want to erase them when comparing (and anyway,
+                // `Send` and other bounds are generally unaffected by
+                // the choice of region).  When erasing regions, we
+                // also have to erase late-bound regions. This is
+                // because the types that appear in the generator
+                // interior generally contain "bound regions" to
+                // represent regions that are part of the suspended
+                // generator frame. Bound regions are preserved by
+                // `erase_regions` and so we must also call
+                // `erase_late_bound_regions`.
+                let ty_erased = self.tcx.erase_late_bound_regions(&ty::Binder::bind(*ty));
+                let ty_erased = self.tcx.erase_regions(&ty_erased);
+                let eq = ty::TyS::same_type(ty_erased, target_ty_erased);
+                debug!(
+                    "maybe_note_obligation_cause_for_async_await: ty_erased={:?} \
+                        target_ty_erased={:?} eq={:?}",
+                    ty_erased, target_ty_erased, eq
+                );
+                eq
+            })
+            .map(|ty::GeneratorInteriorTypeCause { span, scope_span, expr, .. }| {
+                (span, source_map.span_to_snippet(*span), scope_span, expr)
+            });
+
+        debug!(
+            "maybe_note_obligation_cause_for_async_await: target_ty={:?} \
+                generator_interior_types={:?} target_span={:?}",
+            target_ty, tables.generator_interior_types, target_span
+        );
+        if let Some((target_span, Ok(snippet), scope_span, expr)) = target_span {
+            self.note_obligation_cause_for_async_await(
+                err,
+                *target_span,
+                scope_span,
+                *expr,
+                snippet,
+                generator_did,
+                last_generator,
+                trait_ref,
+                target_ty,
+                tables,
+                obligation,
+                next_code,
+            );
+            true
+        } else {
+            false
+        }
+    }
+
+    /// Unconditionally adds the diagnostic note described in
+    /// `maybe_note_obligation_cause_for_async_await`'s documentation comment.
+    fn note_obligation_cause_for_async_await(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        target_span: Span,
+        scope_span: &Option<Span>,
+        expr: Option<hir::HirId>,
+        snippet: String,
+        first_generator: DefId,
+        last_generator: Option<DefId>,
+        trait_ref: ty::TraitRef<'_>,
+        target_ty: Ty<'tcx>,
+        tables: &ty::TypeckTables<'_>,
+        obligation: &PredicateObligation<'tcx>,
+        next_code: Option<&ObligationCauseCode<'tcx>>,
+    ) {
+        let source_map = self.tcx.sess.source_map();
+
+        let is_async_fn = self
+            .tcx
+            .parent(first_generator)
+            .map(|parent_did| self.tcx.asyncness(parent_did))
+            .map(|parent_asyncness| parent_asyncness == hir::IsAsync::Async)
+            .unwrap_or(false);
+        let is_async_move = self
+            .tcx
+            .hir()
+            .as_local_hir_id(first_generator)
+            .and_then(|hir_id| self.tcx.hir().maybe_body_owned_by(hir_id))
+            .map(|body_id| self.tcx.hir().body(body_id))
+            .and_then(|body| body.generator_kind())
+            .map(|generator_kind| match generator_kind {
+                hir::GeneratorKind::Async(..) => true,
+                _ => false,
+            })
+            .unwrap_or(false);
+        let await_or_yield = if is_async_fn || is_async_move { "await" } else { "yield" };
+
+        // Special case the primary error message when send or sync is the trait that was
+        // not implemented.
+        let is_send = self.tcx.is_diagnostic_item(sym::send_trait, trait_ref.def_id);
+        let is_sync = self.tcx.is_diagnostic_item(sym::sync_trait, trait_ref.def_id);
+        let hir = self.tcx.hir();
+        let trait_explanation = if is_send || is_sync {
+            let (trait_name, trait_verb) =
+                if is_send { ("`Send`", "sent") } else { ("`Sync`", "shared") };
+
+            err.clear_code();
+            err.set_primary_message(format!(
+                "future cannot be {} between threads safely",
+                trait_verb
+            ));
+
+            let original_span = err.span.primary_span().unwrap();
+            let mut span = MultiSpan::from_span(original_span);
+
+            let message = if let Some(name) = last_generator
+                .and_then(|generator_did| self.tcx.parent(generator_did))
+                .and_then(|parent_did| hir.as_local_hir_id(parent_did))
+                .and_then(|parent_hir_id| hir.opt_name(parent_hir_id))
+            {
+                format!("future returned by `{}` is not {}", name, trait_name)
+            } else {
+                format!("future is not {}", trait_name)
+            };
+
+            span.push_span_label(original_span, message);
+            err.set_span(span);
+
+            format!("is not {}", trait_name)
+        } else {
+            format!("does not implement `{}`", trait_ref.print_only_trait_path())
+        };
+
+        // Look at the last interior type to get a span for the `.await`.
+        let await_span = tables.generator_interior_types.iter().map(|t| t.span).last().unwrap();
+        let mut span = MultiSpan::from_span(await_span);
+        span.push_span_label(
+            await_span,
+            format!("{} occurs here, with `{}` maybe used later", await_or_yield, 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 {} as this value is used across an {}",
+                trait_explanation, await_or_yield,
+            ),
+        );
+
+        if let Some(expr_id) = expr {
+            let expr = hir.expect_expr(expr_id);
+            debug!("target_ty evaluated from {:?}", expr);
+
+            let parent = hir.get_parent_node(expr_id);
+            if let Some(hir::Node::Expr(e)) = hir.find(parent) {
+                let parent_span = hir.span(parent);
+                let parent_did = parent.owner.to_def_id();
+                // ```rust
+                // impl T {
+                //     fn foo(&self) -> i32 {}
+                // }
+                // T.foo();
+                // ^^^^^^^ a temporary `&T` created inside this method call due to `&self`
+                // ```
+                //
+                let is_region_borrow =
+                    tables.expr_adjustments(expr).iter().any(|adj| adj.is_region_borrow());
+
+                // ```rust
+                // struct Foo(*const u8);
+                // bar(Foo(std::ptr::null())).await;
+                //     ^^^^^^^^^^^^^^^^^^^^^ raw-ptr `*T` created inside this struct ctor.
+                // ```
+                debug!("parent_def_kind: {:?}", self.tcx.def_kind(parent_did));
+                let is_raw_borrow_inside_fn_like_call = match self.tcx.def_kind(parent_did) {
+                    Some(DefKind::Fn) | Some(DefKind::Ctor(..)) => target_ty.is_unsafe_ptr(),
+                    _ => false,
+                };
+
+                if (tables.is_method_call(e) && is_region_borrow)
+                    || is_raw_borrow_inside_fn_like_call
+                {
+                    err.span_help(
+                        parent_span,
+                        "consider moving this into a `let` \
+                        binding to create a shorter lived borrow",
+                    );
+                }
+            }
+        }
+
+        // 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(),
+        );
+    }
+
+    fn note_obligation_cause_code<T>(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        predicate: &T,
+        cause_code: &ObligationCauseCode<'tcx>,
+        obligated_types: &mut Vec<&ty::TyS<'tcx>>,
+    ) where
+        T: fmt::Display,
+    {
+        let tcx = self.tcx;
+        match *cause_code {
+            ObligationCauseCode::ExprAssignable
+            | ObligationCauseCode::MatchExpressionArm { .. }
+            | ObligationCauseCode::Pattern { .. }
+            | ObligationCauseCode::IfExpression { .. }
+            | ObligationCauseCode::IfExpressionWithNoElse
+            | ObligationCauseCode::MainFunctionType
+            | ObligationCauseCode::StartFunctionType
+            | ObligationCauseCode::IntrinsicType
+            | ObligationCauseCode::MethodReceiver
+            | ObligationCauseCode::ReturnNoExpression
+            | ObligationCauseCode::MiscObligation => {}
+            ObligationCauseCode::SliceOrArrayElem => {
+                err.note("slice and array elements must have `Sized` type");
+            }
+            ObligationCauseCode::TupleElem => {
+                err.note("only the last element of a tuple may have a dynamically sized type");
+            }
+            ObligationCauseCode::ProjectionWf(data) => {
+                err.note(&format!("required so that the projection `{}` is well-formed", data,));
+            }
+            ObligationCauseCode::ReferenceOutlivesReferent(ref_ty) => {
+                err.note(&format!(
+                    "required so that reference `{}` does not outlive its referent",
+                    ref_ty,
+                ));
+            }
+            ObligationCauseCode::ObjectTypeBound(object_ty, region) => {
+                err.note(&format!(
+                    "required so that the lifetime bound of `{}` for `{}` is satisfied",
+                    region, object_ty,
+                ));
+            }
+            ObligationCauseCode::ItemObligation(item_def_id) => {
+                let item_name = tcx.def_path_str(item_def_id);
+                let msg = format!("required by `{}`", item_name);
+
+                if let Some(sp) = tcx.hir().span_if_local(item_def_id) {
+                    let sp = tcx.sess.source_map().def_span(sp);
+                    err.span_label(sp, &msg);
+                } else {
+                    err.note(&msg);
+                }
+            }
+            ObligationCauseCode::BindingObligation(item_def_id, span) => {
+                let item_name = tcx.def_path_str(item_def_id);
+                let msg = format!("required by this bound in `{}`", item_name);
+                if let Some(ident) = tcx.opt_item_name(item_def_id) {
+                    err.span_label(ident.span, "");
+                }
+                if span != DUMMY_SP {
+                    err.span_label(span, &msg);
+                } else {
+                    err.note(&msg);
+                }
+            }
+            ObligationCauseCode::ObjectCastObligation(object_ty) => {
+                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(suggest_const_in_array_repeat_expressions) => {
+                err.note(
+                    "the `Copy` trait is required because the repeated element will be copied",
+                );
+                if suggest_const_in_array_repeat_expressions {
+                    err.note(
+                        "this array initializer can be evaluated at compile-time, see issue \
+                         #48147 <https://github.com/rust-lang/rust/issues/49147> \
+                         for more information",
+                    );
+                    if tcx.sess.opts.unstable_features.is_nightly_build() {
+                        err.help(
+                            "add `#![feature(const_in_array_repeat_expressions)]` to the \
+                             crate attributes to enable",
+                        );
+                    }
+                }
+            }
+            ObligationCauseCode::VariableType(_) => {
+                err.note("all local variables must have a statically known size");
+                if !self.tcx.features().unsized_locals {
+                    err.help("unsized locals are gated as an unstable feature");
+                }
+            }
+            ObligationCauseCode::SizedArgumentType => {
+                err.note("all function arguments must have a statically known size");
+                if !self.tcx.features().unsized_locals {
+                    err.help("unsized locals are gated as an unstable feature");
+                }
+            }
+            ObligationCauseCode::SizedReturnType => {
+                err.note("the return type of a function must have a statically known size");
+            }
+            ObligationCauseCode::SizedYieldType => {
+                err.note("the yield type of a generator must have a statically known size");
+            }
+            ObligationCauseCode::AssignmentLhsSized => {
+                err.note("the left-hand-side of an assignment must have a statically known size");
+            }
+            ObligationCauseCode::TupleInitializerSized => {
+                err.note("tuples must have a statically known size to be initialized");
+            }
+            ObligationCauseCode::StructInitializerSized => {
+                err.note("structs must have a statically known size to be initialized");
+            }
+            ObligationCauseCode::FieldSized { adt_kind: ref item, last } => match *item {
+                AdtKind::Struct => {
+                    if last {
+                        err.note(
+                            "the last field of a packed struct may only have a \
+                             dynamically sized type if it does not need drop to be run",
+                        );
+                    } else {
+                        err.note(
+                            "only the last field of a struct may have a dynamically sized type",
+                        );
+                    }
+                }
+                AdtKind::Union => {
+                    err.note("no field of a union may have a dynamically sized type");
+                }
+                AdtKind::Enum => {
+                    err.note("no field of an enum variant may have a dynamically sized type");
+                }
+            },
+            ObligationCauseCode::ConstSized => {
+                err.note("constant expressions must have a statically known size");
+            }
+            ObligationCauseCode::ConstPatternStructural => {
+                err.note("constants used for pattern-matching must derive `PartialEq` and `Eq`");
+            }
+            ObligationCauseCode::SharedStatic => {
+                err.note("shared static variables must have a type that implements `Sync`");
+            }
+            ObligationCauseCode::BuiltinDerivedObligation(ref data) => {
+                let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref);
+                let ty = parent_trait_ref.skip_binder().self_ty();
+                err.note(&format!("required because it appears within the type `{}`", ty));
+                obligated_types.push(ty);
+
+                let parent_predicate = parent_trait_ref.without_const().to_predicate();
+                if !self.is_recursive_obligation(obligated_types, &data.parent_code) {
+                    self.note_obligation_cause_code(
+                        err,
+                        &parent_predicate,
+                        &data.parent_code,
+                        obligated_types,
+                    );
+                }
+            }
+            ObligationCauseCode::ImplDerivedObligation(ref data) => {
+                let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref);
+                err.note(&format!(
+                    "required because of the requirements on the impl of `{}` for `{}`",
+                    parent_trait_ref.print_only_trait_path(),
+                    parent_trait_ref.skip_binder().self_ty()
+                ));
+                let parent_predicate = parent_trait_ref.without_const().to_predicate();
+                self.note_obligation_cause_code(
+                    err,
+                    &parent_predicate,
+                    &data.parent_code,
+                    obligated_types,
+                );
+            }
+            ObligationCauseCode::CompareImplMethodObligation { .. } => {
+                err.note(&format!(
+                    "the requirement `{}` appears on the impl method \
+                     but not on the corresponding trait method",
+                    predicate
+                ));
+            }
+            ObligationCauseCode::CompareImplTypeObligation { .. } => {
+                err.note(&format!(
+                    "the requirement `{}` appears on the associated impl type \
+                     but not on the corresponding associated trait type",
+                    predicate
+                ));
+            }
+            ObligationCauseCode::ReturnType
+            | ObligationCauseCode::ReturnValue(_)
+            | ObligationCauseCode::BlockTailExpression(_) => (),
+            ObligationCauseCode::TrivialBound => {
+                err.help("see issue #48214");
+                if tcx.sess.opts.unstable_features.is_nightly_build() {
+                    err.help("add `#![feature(trivial_bounds)]` to the crate attributes to enable");
+                }
+            }
+            ObligationCauseCode::AssocTypeBound(ref data) => {
+                err.span_label(data.original, "associated type defined here");
+                if let Some(sp) = data.impl_span {
+                    err.span_label(sp, "in this `impl` item");
+                }
+                for sp in &data.bounds {
+                    err.span_label(*sp, "restricted in this bound");
+                }
+            }
+        }
+    }
+
+    fn suggest_new_overflow_limit(&self, err: &mut DiagnosticBuilder<'_>) {
+        let current_limit = self.tcx.sess.recursion_limit.get();
+        let suggested_limit = current_limit * 2;
+        err.help(&format!(
+            "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate (`{}`)",
+            suggested_limit, self.tcx.crate_name,
+        ));
+    }
+}
+
+/// Collect all the returned expressions within the input expression.
+/// Used to point at the return spans when we want to suggest some change to them.
+#[derive(Default)]
+struct ReturnsVisitor<'v> {
+    returns: Vec<&'v hir::Expr<'v>>,
+    in_block_tail: bool,
+}
+
+impl<'v> Visitor<'v> for ReturnsVisitor<'v> {
+    type Map = hir::intravisit::ErasedMap<'v>;
+
+    fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap<Self::Map> {
+        hir::intravisit::NestedVisitorMap::None
+    }
+
+    fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
+        // Visit every expression to detect `return` paths, either through the function's tail
+        // expression or `return` statements. We walk all nodes to find `return` statements, but
+        // we only care about tail expressions when `in_block_tail` is `true`, which means that
+        // they're in the return path of the function body.
+        match ex.kind {
+            hir::ExprKind::Ret(Some(ex)) => {
+                self.returns.push(ex);
+            }
+            hir::ExprKind::Block(block, _) if self.in_block_tail => {
+                self.in_block_tail = false;
+                for stmt in block.stmts {
+                    hir::intravisit::walk_stmt(self, stmt);
+                }
+                self.in_block_tail = true;
+                if let Some(expr) = block.expr {
+                    self.visit_expr(expr);
+                }
+            }
+            hir::ExprKind::Match(_, arms, _) if self.in_block_tail => {
+                for arm in arms {
+                    self.visit_expr(arm.body);
+                }
+            }
+            // We need to walk to find `return`s in the entire body.
+            _ if !self.in_block_tail => hir::intravisit::walk_expr(self, ex),
+            _ => self.returns.push(ex),
+        }
+    }
+
+    fn visit_body(&mut self, body: &'v hir::Body<'v>) {
+        assert!(!self.in_block_tail);
+        if body.generator_kind().is_none() {
+            if let hir::ExprKind::Block(block, None) = body.value.kind {
+                if block.expr.is_some() {
+                    self.in_block_tail = true;
+                }
+            }
+        }
+        hir::intravisit::walk_body(self, body);
+    }
+}
diff --git a/src/librustc_trait_selection/traits/fulfill.rs b/src/librustc_trait_selection/traits/fulfill.rs
new file mode 100644 (file)
index 0000000..5def77c
--- /dev/null
@@ -0,0 +1,559 @@
+use crate::infer::{InferCtxt, ShallowResolver};
+use rustc::ty::error::ExpectedFound;
+use rustc::ty::{self, ToPolyTraitRef, Ty, TypeFoldable};
+use rustc_data_structures::obligation_forest::ProcessResult;
+use rustc_data_structures::obligation_forest::{DoCompleted, Error, ForestObligation};
+use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor};
+use rustc_infer::traits::{TraitEngine, TraitEngineExt as _};
+use std::marker::PhantomData;
+
+use super::project;
+use super::select::SelectionContext;
+use super::wf;
+use super::CodeAmbiguity;
+use super::CodeProjectionError;
+use super::CodeSelectionError;
+use super::{ConstEvalFailure, Unimplemented};
+use super::{FulfillmentError, FulfillmentErrorCode};
+use super::{ObligationCause, PredicateObligation};
+
+use crate::traits::error_reporting::InferCtxtExt as _;
+use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
+
+impl<'tcx> ForestObligation for PendingPredicateObligation<'tcx> {
+    /// Note that we include both the `ParamEnv` and the `Predicate`,
+    /// as the `ParamEnv` can influence whether fulfillment succeeds
+    /// or fails.
+    type CacheKey = ty::ParamEnvAnd<'tcx, ty::Predicate<'tcx>>;
+
+    fn as_cache_key(&self) -> Self::CacheKey {
+        self.obligation.param_env.and(self.obligation.predicate)
+    }
+}
+
+/// The fulfillment context is used to drive trait resolution. It
+/// consists of a list of obligations that must be (eventually)
+/// satisfied. The job is to track which are satisfied, which yielded
+/// errors, and which are still pending. At any point, users can call
+/// `select_where_possible`, and the fulfillment context will try to do
+/// selection, retaining only those obligations that remain
+/// ambiguous. This may be helpful in pushing type inference
+/// along. Once all type inference constraints have been generated, the
+/// method `select_all_or_error` can be used to report any remaining
+/// ambiguous cases as errors.
+pub struct FulfillmentContext<'tcx> {
+    // A list of all obligations that have been registered with this
+    // fulfillment context.
+    predicates: ObligationForest<PendingPredicateObligation<'tcx>>,
+    // Should this fulfillment context register type-lives-for-region
+    // obligations on its parent infcx? In some cases, region
+    // obligations are either already known to hold (normalization) or
+    // hopefully verifed elsewhere (type-impls-bound), and therefore
+    // should not be checked.
+    //
+    // Note that if we are normalizing a type that we already
+    // know is well-formed, there should be no harm setting this
+    // to true - all the region variables should be determinable
+    // using the RFC 447 rules, which don't depend on
+    // type-lives-for-region constraints, and because the type
+    // is well-formed, the constraints should hold.
+    register_region_obligations: bool,
+    // Is it OK to register obligations into this infcx inside
+    // an infcx snapshot?
+    //
+    // The "primary fulfillment" in many cases in typeck lives
+    // outside of any snapshot, so any use of it inside a snapshot
+    // will lead to trouble and therefore is checked against, but
+    // other fulfillment contexts sometimes do live inside of
+    // a snapshot (they don't *straddle* a snapshot, so there
+    // is no trouble there).
+    usable_in_snapshot: bool,
+}
+
+#[derive(Clone, Debug)]
+pub struct PendingPredicateObligation<'tcx> {
+    pub obligation: PredicateObligation<'tcx>,
+    pub stalled_on: Vec<ty::InferTy>,
+}
+
+// `PendingPredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger.
+#[cfg(target_arch = "x86_64")]
+static_assert_size!(PendingPredicateObligation<'_>, 136);
+
+impl<'a, 'tcx> FulfillmentContext<'tcx> {
+    /// Creates a new fulfillment context.
+    pub fn new() -> FulfillmentContext<'tcx> {
+        FulfillmentContext {
+            predicates: ObligationForest::new(),
+            register_region_obligations: true,
+            usable_in_snapshot: false,
+        }
+    }
+
+    pub fn new_in_snapshot() -> FulfillmentContext<'tcx> {
+        FulfillmentContext {
+            predicates: ObligationForest::new(),
+            register_region_obligations: true,
+            usable_in_snapshot: true,
+        }
+    }
+
+    pub fn new_ignoring_regions() -> FulfillmentContext<'tcx> {
+        FulfillmentContext {
+            predicates: ObligationForest::new(),
+            register_region_obligations: false,
+            usable_in_snapshot: false,
+        }
+    }
+
+    /// Attempts to select obligations using `selcx`.
+    fn select(
+        &mut self,
+        selcx: &mut SelectionContext<'a, 'tcx>,
+    ) -> Result<(), Vec<FulfillmentError<'tcx>>> {
+        debug!("select(obligation-forest-size={})", self.predicates.len());
+
+        let mut errors = Vec::new();
+
+        loop {
+            debug!("select: starting another iteration");
+
+            // Process pending obligations.
+            let outcome = self.predicates.process_obligations(
+                &mut FulfillProcessor {
+                    selcx,
+                    register_region_obligations: self.register_region_obligations,
+                },
+                DoCompleted::No,
+            );
+            debug!("select: outcome={:#?}", outcome);
+
+            // FIXME: if we kept the original cache key, we could mark projection
+            // obligations as complete for the projection cache here.
+
+            errors.extend(outcome.errors.into_iter().map(|e| to_fulfillment_error(e)));
+
+            // If nothing new was added, no need to keep looping.
+            if outcome.stalled {
+                break;
+            }
+        }
+
+        debug!(
+            "select({} predicates remaining, {} errors) done",
+            self.predicates.len(),
+            errors.len()
+        );
+
+        if errors.is_empty() { Ok(()) } else { Err(errors) }
+    }
+}
+
+impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
+    /// "Normalize" a projection type `<SomeType as SomeTrait>::X` by
+    /// creating a fresh type variable `$0` as well as a projection
+    /// predicate `<SomeType as SomeTrait>::X == $0`. When the
+    /// inference engine runs, it will attempt to find an impl of
+    /// `SomeTrait` or a where-clause that lets us unify `$0` with
+    /// something concrete. If this fails, we'll unify `$0` with
+    /// `projection_ty` again.
+    fn normalize_projection_type(
+        &mut self,
+        infcx: &InferCtxt<'_, 'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+        projection_ty: ty::ProjectionTy<'tcx>,
+        cause: ObligationCause<'tcx>,
+    ) -> Ty<'tcx> {
+        debug!("normalize_projection_type(projection_ty={:?})", projection_ty);
+
+        debug_assert!(!projection_ty.has_escaping_bound_vars());
+
+        // FIXME(#20304) -- cache
+
+        let mut selcx = SelectionContext::new(infcx);
+        let mut obligations = vec![];
+        let normalized_ty = project::normalize_projection_type(
+            &mut selcx,
+            param_env,
+            projection_ty,
+            cause,
+            0,
+            &mut obligations,
+        );
+        self.register_predicate_obligations(infcx, obligations);
+
+        debug!("normalize_projection_type: result={:?}", normalized_ty);
+
+        normalized_ty
+    }
+
+    fn register_predicate_obligation(
+        &mut self,
+        infcx: &InferCtxt<'_, 'tcx>,
+        obligation: PredicateObligation<'tcx>,
+    ) {
+        // this helps to reduce duplicate errors, as well as making
+        // debug output much nicer to read and so on.
+        let obligation = infcx.resolve_vars_if_possible(&obligation);
+
+        debug!("register_predicate_obligation(obligation={:?})", obligation);
+
+        assert!(!infcx.is_in_snapshot() || self.usable_in_snapshot);
+
+        self.predicates
+            .register_obligation(PendingPredicateObligation { obligation, stalled_on: vec![] });
+    }
+
+    fn select_all_or_error(
+        &mut self,
+        infcx: &InferCtxt<'_, 'tcx>,
+    ) -> Result<(), Vec<FulfillmentError<'tcx>>> {
+        self.select_where_possible(infcx)?;
+
+        let errors: Vec<_> = self
+            .predicates
+            .to_errors(CodeAmbiguity)
+            .into_iter()
+            .map(|e| to_fulfillment_error(e))
+            .collect();
+        if errors.is_empty() { Ok(()) } else { Err(errors) }
+    }
+
+    fn select_where_possible(
+        &mut self,
+        infcx: &InferCtxt<'_, 'tcx>,
+    ) -> Result<(), Vec<FulfillmentError<'tcx>>> {
+        let mut selcx = SelectionContext::new(infcx);
+        self.select(&mut selcx)
+    }
+
+    fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>> {
+        self.predicates.map_pending_obligations(|o| o.obligation.clone())
+    }
+}
+
+struct FulfillProcessor<'a, 'b, 'tcx> {
+    selcx: &'a mut SelectionContext<'b, 'tcx>,
+    register_region_obligations: bool,
+}
+
+fn mk_pending(os: Vec<PredicateObligation<'tcx>>) -> Vec<PendingPredicateObligation<'tcx>> {
+    os.into_iter()
+        .map(|o| PendingPredicateObligation { obligation: o, stalled_on: vec![] })
+        .collect()
+}
+
+impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
+    type Obligation = PendingPredicateObligation<'tcx>;
+    type Error = FulfillmentErrorCode<'tcx>;
+
+    /// Processes a predicate obligation and returns either:
+    /// - `Changed(v)` if the predicate is true, presuming that `v` are also true
+    /// - `Unchanged` if we don't have enough info to be sure
+    /// - `Error(e)` if the predicate does not hold
+    ///
+    /// This is always inlined, despite its size, because it has a single
+    /// callsite and it is called *very* frequently.
+    #[inline(always)]
+    fn process_obligation(
+        &mut self,
+        pending_obligation: &mut Self::Obligation,
+    ) -> ProcessResult<Self::Obligation, Self::Error> {
+        // If we were stalled on some unresolved variables, first check whether
+        // any of them have been resolved; if not, don't bother doing more work
+        // yet.
+        let change = match pending_obligation.stalled_on.len() {
+            // Match arms are in order of frequency, which matters because this
+            // code is so hot. 1 and 0 dominate; 2+ is fairly rare.
+            1 => {
+                let infer = pending_obligation.stalled_on[0];
+                ShallowResolver::new(self.selcx.infcx()).shallow_resolve_changed(infer)
+            }
+            0 => {
+                // In this case we haven't changed, but wish to make a change.
+                true
+            }
+            _ => {
+                // This `for` loop was once a call to `all()`, but this lower-level
+                // form was a perf win. See #64545 for details.
+                (|| {
+                    for &infer in &pending_obligation.stalled_on {
+                        if ShallowResolver::new(self.selcx.infcx()).shallow_resolve_changed(infer) {
+                            return true;
+                        }
+                    }
+                    false
+                })()
+            }
+        };
+
+        if !change {
+            debug!(
+                "process_predicate: pending obligation {:?} still stalled on {:?}",
+                self.selcx.infcx().resolve_vars_if_possible(&pending_obligation.obligation),
+                pending_obligation.stalled_on
+            );
+            return ProcessResult::Unchanged;
+        }
+
+        // This part of the code is much colder.
+
+        pending_obligation.stalled_on.truncate(0);
+
+        let obligation = &mut pending_obligation.obligation;
+
+        if obligation.predicate.has_infer_types_or_consts() {
+            obligation.predicate =
+                self.selcx.infcx().resolve_vars_if_possible(&obligation.predicate);
+        }
+
+        debug!("process_obligation: obligation = {:?} cause = {:?}", obligation, obligation.cause);
+
+        fn infer_ty(ty: Ty<'tcx>) -> ty::InferTy {
+            match ty.kind {
+                ty::Infer(infer) => infer,
+                _ => panic!(),
+            }
+        }
+
+        match obligation.predicate {
+            ty::Predicate::Trait(ref data, _) => {
+                let trait_obligation = obligation.with(data.clone());
+
+                if data.is_global() {
+                    // no type variables present, can use evaluation for better caching.
+                    // FIXME: consider caching errors too.
+                    if self.selcx.infcx().predicate_must_hold_considering_regions(&obligation) {
+                        debug!(
+                            "selecting trait `{:?}` at depth {} evaluated to holds",
+                            data, obligation.recursion_depth
+                        );
+                        return ProcessResult::Changed(vec![]);
+                    }
+                }
+
+                match self.selcx.select(&trait_obligation) {
+                    Ok(Some(vtable)) => {
+                        debug!(
+                            "selecting trait `{:?}` at depth {} yielded Ok(Some)",
+                            data, obligation.recursion_depth
+                        );
+                        ProcessResult::Changed(mk_pending(vtable.nested_obligations()))
+                    }
+                    Ok(None) => {
+                        debug!(
+                            "selecting trait `{:?}` at depth {} yielded Ok(None)",
+                            data, obligation.recursion_depth
+                        );
+
+                        // This is a bit subtle: for the most part, the
+                        // only reason we can fail to make progress on
+                        // trait selection is because we don't have enough
+                        // information about the types in the trait.
+                        pending_obligation.stalled_on =
+                            trait_ref_type_vars(self.selcx, data.to_poly_trait_ref());
+
+                        debug!(
+                            "process_predicate: pending obligation {:?} now stalled on {:?}",
+                            self.selcx.infcx().resolve_vars_if_possible(obligation),
+                            pending_obligation.stalled_on
+                        );
+
+                        ProcessResult::Unchanged
+                    }
+                    Err(selection_err) => {
+                        info!(
+                            "selecting trait `{:?}` at depth {} yielded Err",
+                            data, obligation.recursion_depth
+                        );
+
+                        ProcessResult::Error(CodeSelectionError(selection_err))
+                    }
+                }
+            }
+
+            ty::Predicate::RegionOutlives(ref binder) => {
+                match self.selcx.infcx().region_outlives_predicate(&obligation.cause, binder) {
+                    Ok(()) => ProcessResult::Changed(vec![]),
+                    Err(_) => ProcessResult::Error(CodeSelectionError(Unimplemented)),
+                }
+            }
+
+            ty::Predicate::TypeOutlives(ref binder) => {
+                // Check if there are higher-ranked vars.
+                match binder.no_bound_vars() {
+                    // If there are, inspect the underlying type further.
+                    None => {
+                        // Convert from `Binder<OutlivesPredicate<Ty, Region>>` to `Binder<Ty>`.
+                        let binder = binder.map_bound_ref(|pred| pred.0);
+
+                        // Check if the type has any bound vars.
+                        match binder.no_bound_vars() {
+                            // If so, this obligation is an error (for now). Eventually we should be
+                            // able to support additional cases here, like `for<'a> &'a str: 'a`.
+                            // NOTE: this is duplicate-implemented between here and fulfillment.
+                            None => ProcessResult::Error(CodeSelectionError(Unimplemented)),
+                            // Otherwise, we have something of the form
+                            // `for<'a> T: 'a where 'a not in T`, which we can treat as
+                            // `T: 'static`.
+                            Some(t_a) => {
+                                let r_static = self.selcx.tcx().lifetimes.re_static;
+                                if self.register_region_obligations {
+                                    self.selcx.infcx().register_region_obligation_with_cause(
+                                        t_a,
+                                        r_static,
+                                        &obligation.cause,
+                                    );
+                                }
+                                ProcessResult::Changed(vec![])
+                            }
+                        }
+                    }
+                    // If there aren't, register the obligation.
+                    Some(ty::OutlivesPredicate(t_a, r_b)) => {
+                        if self.register_region_obligations {
+                            self.selcx.infcx().register_region_obligation_with_cause(
+                                t_a,
+                                r_b,
+                                &obligation.cause,
+                            );
+                        }
+                        ProcessResult::Changed(vec![])
+                    }
+                }
+            }
+
+            ty::Predicate::Projection(ref data) => {
+                let project_obligation = obligation.with(data.clone());
+                match project::poly_project_and_unify_type(self.selcx, &project_obligation) {
+                    Ok(None) => {
+                        let tcx = self.selcx.tcx();
+                        pending_obligation.stalled_on =
+                            trait_ref_type_vars(self.selcx, data.to_poly_trait_ref(tcx));
+                        ProcessResult::Unchanged
+                    }
+                    Ok(Some(os)) => ProcessResult::Changed(mk_pending(os)),
+                    Err(e) => ProcessResult::Error(CodeProjectionError(e)),
+                }
+            }
+
+            ty::Predicate::ObjectSafe(trait_def_id) => {
+                if !self.selcx.tcx().is_object_safe(trait_def_id) {
+                    ProcessResult::Error(CodeSelectionError(Unimplemented))
+                } else {
+                    ProcessResult::Changed(vec![])
+                }
+            }
+
+            ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => {
+                match self.selcx.infcx().closure_kind(closure_def_id, closure_substs) {
+                    Some(closure_kind) => {
+                        if closure_kind.extends(kind) {
+                            ProcessResult::Changed(vec![])
+                        } else {
+                            ProcessResult::Error(CodeSelectionError(Unimplemented))
+                        }
+                    }
+                    None => ProcessResult::Unchanged,
+                }
+            }
+
+            ty::Predicate::WellFormed(ty) => {
+                match wf::obligations(
+                    self.selcx.infcx(),
+                    obligation.param_env,
+                    obligation.cause.body_id,
+                    ty,
+                    obligation.cause.span,
+                ) {
+                    None => {
+                        pending_obligation.stalled_on = vec![infer_ty(ty)];
+                        ProcessResult::Unchanged
+                    }
+                    Some(os) => ProcessResult::Changed(mk_pending(os)),
+                }
+            }
+
+            ty::Predicate::Subtype(ref subtype) => {
+                match self.selcx.infcx().subtype_predicate(
+                    &obligation.cause,
+                    obligation.param_env,
+                    subtype,
+                ) {
+                    None => {
+                        // None means that both are unresolved.
+                        pending_obligation.stalled_on = vec![
+                            infer_ty(subtype.skip_binder().a),
+                            infer_ty(subtype.skip_binder().b),
+                        ];
+                        ProcessResult::Unchanged
+                    }
+                    Some(Ok(ok)) => ProcessResult::Changed(mk_pending(ok.obligations)),
+                    Some(Err(err)) => {
+                        let expected_found = ExpectedFound::new(
+                            subtype.skip_binder().a_is_expected,
+                            subtype.skip_binder().a,
+                            subtype.skip_binder().b,
+                        );
+                        ProcessResult::Error(FulfillmentErrorCode::CodeSubtypeError(
+                            expected_found,
+                            err,
+                        ))
+                    }
+                }
+            }
+
+            ty::Predicate::ConstEvaluatable(def_id, substs) => {
+                match self.selcx.infcx().const_eval_resolve(
+                    obligation.param_env,
+                    def_id,
+                    substs,
+                    None,
+                    Some(obligation.cause.span),
+                ) {
+                    Ok(_) => ProcessResult::Changed(vec![]),
+                    Err(err) => ProcessResult::Error(CodeSelectionError(ConstEvalFailure(err))),
+                }
+            }
+        }
+    }
+
+    fn process_backedge<'c, I>(
+        &mut self,
+        cycle: I,
+        _marker: PhantomData<&'c PendingPredicateObligation<'tcx>>,
+    ) where
+        I: Clone + Iterator<Item = &'c PendingPredicateObligation<'tcx>>,
+    {
+        if self.selcx.coinductive_match(cycle.clone().map(|s| s.obligation.predicate)) {
+            debug!("process_child_obligations: coinductive match");
+        } else {
+            let cycle: Vec<_> = cycle.map(|c| c.obligation.clone()).collect();
+            self.selcx.infcx().report_overflow_error_cycle(&cycle);
+        }
+    }
+}
+
+/// Returns the set of type variables contained in a trait ref
+fn trait_ref_type_vars<'a, 'tcx>(
+    selcx: &mut SelectionContext<'a, 'tcx>,
+    t: ty::PolyTraitRef<'tcx>,
+) -> Vec<ty::InferTy> {
+    t.skip_binder() // ok b/c this check doesn't care about regions
+        .input_types()
+        .map(|t| selcx.infcx().resolve_vars_if_possible(&t))
+        .filter(|t| t.has_infer_types())
+        .flat_map(|t| t.walk())
+        .filter_map(|t| match t.kind {
+            ty::Infer(infer) => Some(infer),
+            _ => None,
+        })
+        .collect()
+}
+
+fn to_fulfillment_error<'tcx>(
+    error: Error<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>>,
+) -> FulfillmentError<'tcx> {
+    let obligation = error.backtrace.into_iter().next().unwrap().obligation;
+    FulfillmentError::new(obligation, error.error)
+}
diff --git a/src/librustc_trait_selection/traits/misc.rs b/src/librustc_trait_selection/traits/misc.rs
new file mode 100644 (file)
index 0000000..d500cff
--- /dev/null
@@ -0,0 +1,74 @@
+//! Miscellaneous type-system utilities that are too small to deserve their own modules.
+
+use crate::infer::InferCtxtExt as _;
+use crate::traits::{self, ObligationCause};
+
+use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
+use rustc_hir as hir;
+use rustc_infer::infer::TyCtxtInferExt;
+
+use crate::traits::error_reporting::InferCtxtExt;
+
+#[derive(Clone)]
+pub enum CopyImplementationError<'tcx> {
+    InfrigingFields(Vec<&'tcx ty::FieldDef>),
+    NotAnAdt,
+    HasDestructor,
+}
+
+pub fn can_type_implement_copy(
+    tcx: TyCtxt<'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    self_type: Ty<'tcx>,
+) -> Result<(), CopyImplementationError<'tcx>> {
+    // FIXME: (@jroesch) float this code up
+    tcx.infer_ctxt().enter(|infcx| {
+        let (adt, substs) = match self_type.kind {
+            // These types used to have a builtin impl.
+            // Now libcore provides that impl.
+            ty::Uint(_)
+            | ty::Int(_)
+            | ty::Bool
+            | ty::Float(_)
+            | ty::Char
+            | ty::RawPtr(..)
+            | ty::Never
+            | ty::Ref(_, _, hir::Mutability::Not) => return Ok(()),
+
+            ty::Adt(adt, substs) => (adt, substs),
+
+            _ => return Err(CopyImplementationError::NotAnAdt),
+        };
+
+        let mut infringing = Vec::new();
+        for variant in &adt.variants {
+            for field in &variant.fields {
+                let ty = field.ty(tcx, substs);
+                if ty.references_error() {
+                    continue;
+                }
+                let span = tcx.def_span(field.did);
+                let cause = ObligationCause { span, ..ObligationCause::dummy() };
+                let ctx = traits::FulfillmentContext::new();
+                match traits::fully_normalize(&infcx, ctx, cause, param_env, &ty) {
+                    Ok(ty) => {
+                        if !infcx.type_is_copy_modulo_regions(param_env, ty, span) {
+                            infringing.push(field);
+                        }
+                    }
+                    Err(errors) => {
+                        infcx.report_fulfillment_errors(&errors, None, false);
+                    }
+                };
+            }
+        }
+        if !infringing.is_empty() {
+            return Err(CopyImplementationError::InfrigingFields(infringing));
+        }
+        if adt.has_dtor(tcx) {
+            return Err(CopyImplementationError::HasDestructor);
+        }
+
+        Ok(())
+    })
+}
diff --git a/src/librustc_trait_selection/traits/mod.rs b/src/librustc_trait_selection/traits/mod.rs
new file mode 100644 (file)
index 0000000..43a90c4
--- /dev/null
@@ -0,0 +1,533 @@
+//! Trait Resolution. See the [rustc dev guide] for more information on how this works.
+//!
+//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/resolution.html
+
+#[allow(dead_code)]
+pub mod auto_trait;
+pub mod codegen;
+mod coherence;
+mod engine;
+pub mod error_reporting;
+mod fulfill;
+pub mod misc;
+mod object_safety;
+mod on_unimplemented;
+mod project;
+pub mod query;
+mod select;
+mod specialize;
+mod structural_match;
+mod util;
+pub mod wf;
+
+use crate::infer::outlives::env::OutlivesEnvironment;
+use crate::infer::{InferCtxt, RegionckMode, TyCtxtInferExt};
+use crate::traits::error_reporting::InferCtxtExt as _;
+use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
+use rustc::middle::region;
+use rustc::ty::fold::TypeFoldable;
+use rustc::ty::subst::{InternalSubsts, SubstsRef};
+use rustc::ty::{self, GenericParamDefKind, ToPredicate, Ty, TyCtxt, WithConstness};
+use rustc::util::common::ErrorReported;
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
+use rustc_span::{Span, DUMMY_SP};
+
+use std::fmt::Debug;
+
+pub use self::FulfillmentErrorCode::*;
+pub use self::ObligationCauseCode::*;
+pub use self::SelectionError::*;
+pub use self::Vtable::*;
+
+pub use self::coherence::{add_placeholder_note, orphan_check, overlapping_impls};
+pub use self::coherence::{OrphanCheckErr, OverlapResult};
+pub use self::engine::TraitEngineExt;
+pub use self::fulfill::{FulfillmentContext, PendingPredicateObligation};
+pub use self::object_safety::astconv_object_safety_violations;
+pub use self::object_safety::is_vtable_safe_method;
+pub use self::object_safety::MethodViolationCode;
+pub use self::object_safety::ObjectSafetyViolation;
+pub use self::on_unimplemented::{OnUnimplementedDirective, OnUnimplementedNote};
+pub use self::project::{
+    normalize, normalize_projection_type, normalize_to, poly_project_and_unify_type,
+};
+pub use self::select::{EvaluationCache, SelectionCache, SelectionContext};
+pub use self::select::{EvaluationResult, IntercrateAmbiguityCause, OverflowError};
+pub use self::specialize::find_associated_item;
+pub use self::specialize::specialization_graph::FutureCompatOverlapError;
+pub use self::specialize::specialization_graph::FutureCompatOverlapErrorKind;
+pub use self::specialize::{specialization_graph, translate_substs, OverlapError};
+pub use self::structural_match::search_for_structural_match_violation;
+pub use self::structural_match::type_marked_structural;
+pub use self::structural_match::NonStructuralMatchTy;
+pub use self::util::{elaborate_predicates, elaborate_trait_ref, elaborate_trait_refs};
+pub use self::util::{expand_trait_aliases, TraitAliasExpander};
+pub use self::util::{
+    get_vtable_index_of_object_method, impl_is_default, impl_item_is_final,
+    predicate_for_trait_def, upcast_choices,
+};
+pub use self::util::{
+    supertrait_def_ids, supertraits, transitive_bounds, SupertraitDefIds, Supertraits,
+};
+
+pub use rustc_infer::traits::*;
+
+/// Whether to skip the leak check, as part of a future compatibility warning step.
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+pub enum SkipLeakCheck {
+    Yes,
+    No,
+}
+
+impl SkipLeakCheck {
+    fn is_yes(self) -> bool {
+        self == SkipLeakCheck::Yes
+    }
+}
+
+/// The "default" for skip-leak-check corresponds to the current
+/// behavior (do not skip the leak check) -- not the behavior we are
+/// transitioning into.
+impl Default for SkipLeakCheck {
+    fn default() -> Self {
+        SkipLeakCheck::No
+    }
+}
+
+/// The mode that trait queries run in.
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+pub enum TraitQueryMode {
+    // Standard/un-canonicalized queries get accurate
+    // spans etc. passed in and hence can do reasonable
+    // error reporting on their own.
+    Standard,
+    // Canonicalized queries get dummy spans and hence
+    // must generally propagate errors to
+    // pre-canonicalization callsites.
+    Canonical,
+}
+
+/// Creates predicate obligations from the generic bounds.
+pub fn predicates_for_generics<'tcx>(
+    cause: ObligationCause<'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    generic_bounds: &ty::InstantiatedPredicates<'tcx>,
+) -> PredicateObligations<'tcx> {
+    util::predicates_for_generics(cause, 0, param_env, generic_bounds)
+}
+
+/// Determines whether the type `ty` is known to meet `bound` and
+/// returns true if so. Returns false if `ty` either does not meet
+/// `bound` or is not known to meet bound (note that this is
+/// conservative towards *no impl*, which is the opposite of the
+/// `evaluate` methods).
+pub fn type_known_to_meet_bound_modulo_regions<'a, 'tcx>(
+    infcx: &InferCtxt<'a, 'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    ty: Ty<'tcx>,
+    def_id: DefId,
+    span: Span,
+) -> bool {
+    debug!(
+        "type_known_to_meet_bound_modulo_regions(ty={:?}, bound={:?})",
+        ty,
+        infcx.tcx.def_path_str(def_id)
+    );
+
+    let trait_ref = ty::TraitRef { def_id, substs: infcx.tcx.mk_substs_trait(ty, &[]) };
+    let obligation = Obligation {
+        param_env,
+        cause: ObligationCause::misc(span, hir::DUMMY_HIR_ID),
+        recursion_depth: 0,
+        predicate: trait_ref.without_const().to_predicate(),
+    };
+
+    let result = infcx.predicate_must_hold_modulo_regions(&obligation);
+    debug!(
+        "type_known_to_meet_ty={:?} bound={} => {:?}",
+        ty,
+        infcx.tcx.def_path_str(def_id),
+        result
+    );
+
+    if result && ty.has_infer_types_or_consts() {
+        // Because of inference "guessing", selection can sometimes claim
+        // to succeed while the success requires a guess. To ensure
+        // this function's result remains infallible, we must confirm
+        // that guess. While imperfect, I believe this is sound.
+
+        // The handling of regions in this area of the code is terrible,
+        // see issue #29149. We should be able to improve on this with
+        // NLL.
+        let mut fulfill_cx = FulfillmentContext::new_ignoring_regions();
+
+        // We can use a dummy node-id here because we won't pay any mind
+        // to region obligations that arise (there shouldn't really be any
+        // anyhow).
+        let cause = ObligationCause::misc(span, hir::DUMMY_HIR_ID);
+
+        fulfill_cx.register_bound(infcx, param_env, ty, def_id, cause);
+
+        // Note: we only assume something is `Copy` if we can
+        // *definitively* show that it implements `Copy`. Otherwise,
+        // assume it is move; linear is always ok.
+        match fulfill_cx.select_all_or_error(infcx) {
+            Ok(()) => {
+                debug!(
+                    "type_known_to_meet_bound_modulo_regions: ty={:?} bound={} success",
+                    ty,
+                    infcx.tcx.def_path_str(def_id)
+                );
+                true
+            }
+            Err(e) => {
+                debug!(
+                    "type_known_to_meet_bound_modulo_regions: ty={:?} bound={} errors={:?}",
+                    ty,
+                    infcx.tcx.def_path_str(def_id),
+                    e
+                );
+                false
+            }
+        }
+    } else {
+        result
+    }
+}
+
+fn do_normalize_predicates<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    region_context: DefId,
+    cause: ObligationCause<'tcx>,
+    elaborated_env: ty::ParamEnv<'tcx>,
+    predicates: Vec<ty::Predicate<'tcx>>,
+) -> Result<Vec<ty::Predicate<'tcx>>, ErrorReported> {
+    debug!(
+        "do_normalize_predicates(predicates={:?}, region_context={:?}, cause={:?})",
+        predicates, region_context, cause,
+    );
+    let span = cause.span;
+    tcx.infer_ctxt().enter(|infcx| {
+        // FIXME. We should really... do something with these region
+        // obligations. But this call just continues the older
+        // behavior (i.e., doesn't cause any new bugs), and it would
+        // take some further refactoring to actually solve them. In
+        // particular, we would have to handle implied bounds
+        // properly, and that code is currently largely confined to
+        // regionck (though I made some efforts to extract it
+        // out). -nmatsakis
+        //
+        // @arielby: In any case, these obligations are checked
+        // by wfcheck anyway, so I'm not sure we have to check
+        // them here too, and we will remove this function when
+        // we move over to lazy normalization *anyway*.
+        let fulfill_cx = FulfillmentContext::new_ignoring_regions();
+        let predicates =
+            match fully_normalize(&infcx, fulfill_cx, cause, elaborated_env, &predicates) {
+                Ok(predicates) => predicates,
+                Err(errors) => {
+                    infcx.report_fulfillment_errors(&errors, None, false);
+                    return Err(ErrorReported);
+                }
+            };
+
+        debug!("do_normalize_predictes: normalized predicates = {:?}", predicates);
+
+        let region_scope_tree = region::ScopeTree::default();
+
+        // We can use the `elaborated_env` here; the region code only
+        // cares about declarations like `'a: 'b`.
+        let outlives_env = OutlivesEnvironment::new(elaborated_env);
+
+        infcx.resolve_regions_and_report_errors(
+            region_context,
+            &region_scope_tree,
+            &outlives_env,
+            RegionckMode::default(),
+        );
+
+        let predicates = match infcx.fully_resolve(&predicates) {
+            Ok(predicates) => predicates,
+            Err(fixup_err) => {
+                // If we encounter a fixup error, it means that some type
+                // variable wound up unconstrained. I actually don't know
+                // if this can happen, and I certainly don't expect it to
+                // happen often, but if it did happen it probably
+                // represents a legitimate failure due to some kind of
+                // unconstrained variable, and it seems better not to ICE,
+                // all things considered.
+                tcx.sess.span_err(span, &fixup_err.to_string());
+                return Err(ErrorReported);
+            }
+        };
+        if predicates.has_local_value() {
+            // FIXME: shouldn't we, you know, actually report an error here? or an ICE?
+            Err(ErrorReported)
+        } else {
+            Ok(predicates)
+        }
+    })
+}
+
+// FIXME: this is gonna need to be removed ...
+/// Normalizes the parameter environment, reporting errors if they occur.
+pub fn normalize_param_env_or_error<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    region_context: DefId,
+    unnormalized_env: ty::ParamEnv<'tcx>,
+    cause: ObligationCause<'tcx>,
+) -> ty::ParamEnv<'tcx> {
+    // I'm not wild about reporting errors here; I'd prefer to
+    // have the errors get reported at a defined place (e.g.,
+    // during typeck). Instead I have all parameter
+    // environments, in effect, going through this function
+    // and hence potentially reporting errors. This ensures of
+    // course that we never forget to normalize (the
+    // alternative seemed like it would involve a lot of
+    // manual invocations of this fn -- and then we'd have to
+    // deal with the errors at each of those sites).
+    //
+    // In any case, in practice, typeck constructs all the
+    // parameter environments once for every fn as it goes,
+    // and errors will get reported then; so after typeck we
+    // can be sure that no errors should occur.
+
+    debug!(
+        "normalize_param_env_or_error(region_context={:?}, unnormalized_env={:?}, cause={:?})",
+        region_context, unnormalized_env, cause
+    );
+
+    let mut predicates: Vec<_> =
+        util::elaborate_predicates(tcx, unnormalized_env.caller_bounds.to_vec()).collect();
+
+    debug!("normalize_param_env_or_error: elaborated-predicates={:?}", predicates);
+
+    let elaborated_env = ty::ParamEnv::new(
+        tcx.intern_predicates(&predicates),
+        unnormalized_env.reveal,
+        unnormalized_env.def_id,
+    );
+
+    // HACK: we are trying to normalize the param-env inside *itself*. The problem is that
+    // normalization expects its param-env to be already normalized, which means we have
+    // a circularity.
+    //
+    // The way we handle this is by normalizing the param-env inside an unnormalized version
+    // of the param-env, which means that if the param-env contains unnormalized projections,
+    // we'll have some normalization failures. This is unfortunate.
+    //
+    // Lazy normalization would basically handle this by treating just the
+    // normalizing-a-trait-ref-requires-itself cycles as evaluation failures.
+    //
+    // Inferred outlives bounds can create a lot of `TypeOutlives` predicates for associated
+    // types, so to make the situation less bad, we normalize all the predicates *but*
+    // the `TypeOutlives` predicates first inside the unnormalized parameter environment, and
+    // then we normalize the `TypeOutlives` bounds inside the normalized parameter environment.
+    //
+    // This works fairly well because trait matching  does not actually care about param-env
+    // TypeOutlives predicates - these are normally used by regionck.
+    let outlives_predicates: Vec<_> = predicates
+        .drain_filter(|predicate| match predicate {
+            ty::Predicate::TypeOutlives(..) => true,
+            _ => false,
+        })
+        .collect();
+
+    debug!(
+        "normalize_param_env_or_error: predicates=(non-outlives={:?}, outlives={:?})",
+        predicates, outlives_predicates
+    );
+    let non_outlives_predicates = match do_normalize_predicates(
+        tcx,
+        region_context,
+        cause.clone(),
+        elaborated_env,
+        predicates,
+    ) {
+        Ok(predicates) => predicates,
+        // An unnormalized env is better than nothing.
+        Err(ErrorReported) => {
+            debug!("normalize_param_env_or_error: errored resolving non-outlives predicates");
+            return elaborated_env;
+        }
+    };
+
+    debug!("normalize_param_env_or_error: non-outlives predicates={:?}", non_outlives_predicates);
+
+    // Not sure whether it is better to include the unnormalized TypeOutlives predicates
+    // here. I believe they should not matter, because we are ignoring TypeOutlives param-env
+    // predicates here anyway. Keeping them here anyway because it seems safer.
+    let outlives_env: Vec<_> =
+        non_outlives_predicates.iter().chain(&outlives_predicates).cloned().collect();
+    let outlives_env =
+        ty::ParamEnv::new(tcx.intern_predicates(&outlives_env), unnormalized_env.reveal, None);
+    let outlives_predicates = match do_normalize_predicates(
+        tcx,
+        region_context,
+        cause,
+        outlives_env,
+        outlives_predicates,
+    ) {
+        Ok(predicates) => predicates,
+        // An unnormalized env is better than nothing.
+        Err(ErrorReported) => {
+            debug!("normalize_param_env_or_error: errored resolving outlives predicates");
+            return elaborated_env;
+        }
+    };
+    debug!("normalize_param_env_or_error: outlives predicates={:?}", outlives_predicates);
+
+    let mut predicates = non_outlives_predicates;
+    predicates.extend(outlives_predicates);
+    debug!("normalize_param_env_or_error: final predicates={:?}", predicates);
+    ty::ParamEnv::new(
+        tcx.intern_predicates(&predicates),
+        unnormalized_env.reveal,
+        unnormalized_env.def_id,
+    )
+}
+
+pub fn fully_normalize<'a, 'tcx, T>(
+    infcx: &InferCtxt<'a, 'tcx>,
+    mut fulfill_cx: FulfillmentContext<'tcx>,
+    cause: ObligationCause<'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    value: &T,
+) -> Result<T, Vec<FulfillmentError<'tcx>>>
+where
+    T: TypeFoldable<'tcx>,
+{
+    debug!("fully_normalize_with_fulfillcx(value={:?})", value);
+    let selcx = &mut SelectionContext::new(infcx);
+    let Normalized { value: normalized_value, obligations } =
+        project::normalize(selcx, param_env, cause, value);
+    debug!(
+        "fully_normalize: normalized_value={:?} obligations={:?}",
+        normalized_value, obligations
+    );
+    for obligation in obligations {
+        fulfill_cx.register_predicate_obligation(selcx.infcx(), obligation);
+    }
+
+    debug!("fully_normalize: select_all_or_error start");
+    fulfill_cx.select_all_or_error(infcx)?;
+    debug!("fully_normalize: select_all_or_error complete");
+    let resolved_value = infcx.resolve_vars_if_possible(&normalized_value);
+    debug!("fully_normalize: resolved_value={:?}", resolved_value);
+    Ok(resolved_value)
+}
+
+/// Normalizes the predicates and checks whether they hold in an empty
+/// environment. If this returns false, then either normalize
+/// encountered an error or one of the predicates did not hold. Used
+/// when creating vtables to check for unsatisfiable methods.
+pub fn normalize_and_test_predicates<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    predicates: Vec<ty::Predicate<'tcx>>,
+) -> bool {
+    debug!("normalize_and_test_predicates(predicates={:?})", predicates);
+
+    let result = tcx.infer_ctxt().enter(|infcx| {
+        let param_env = ty::ParamEnv::reveal_all();
+        let mut selcx = SelectionContext::new(&infcx);
+        let mut fulfill_cx = FulfillmentContext::new();
+        let cause = ObligationCause::dummy();
+        let Normalized { value: predicates, obligations } =
+            normalize(&mut selcx, param_env, cause.clone(), &predicates);
+        for obligation in obligations {
+            fulfill_cx.register_predicate_obligation(&infcx, obligation);
+        }
+        for predicate in predicates {
+            let obligation = Obligation::new(cause.clone(), param_env, predicate);
+            fulfill_cx.register_predicate_obligation(&infcx, obligation);
+        }
+
+        fulfill_cx.select_all_or_error(&infcx).is_ok()
+    });
+    debug!("normalize_and_test_predicates(predicates={:?}) = {:?}", predicates, result);
+    result
+}
+
+fn substitute_normalize_and_test_predicates<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    key: (DefId, SubstsRef<'tcx>),
+) -> bool {
+    debug!("substitute_normalize_and_test_predicates(key={:?})", key);
+
+    let predicates = tcx.predicates_of(key.0).instantiate(tcx, key.1).predicates;
+    let result = normalize_and_test_predicates(tcx, predicates);
+
+    debug!("substitute_normalize_and_test_predicates(key={:?}) = {:?}", key, result);
+    result
+}
+
+/// Given a trait `trait_ref`, iterates the vtable entries
+/// that come from `trait_ref`, including its supertraits.
+#[inline] // FIXME(#35870): avoid closures being unexported due to `impl Trait`.
+fn vtable_methods<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    trait_ref: ty::PolyTraitRef<'tcx>,
+) -> &'tcx [Option<(DefId, SubstsRef<'tcx>)>] {
+    debug!("vtable_methods({:?})", trait_ref);
+
+    tcx.arena.alloc_from_iter(supertraits(tcx, trait_ref).flat_map(move |trait_ref| {
+        let trait_methods = tcx
+            .associated_items(trait_ref.def_id())
+            .in_definition_order()
+            .filter(|item| item.kind == ty::AssocKind::Method);
+
+        // Now list each method's DefId and InternalSubsts (for within its trait).
+        // If the method can never be called from this object, produce None.
+        trait_methods.map(move |trait_method| {
+            debug!("vtable_methods: trait_method={:?}", trait_method);
+            let def_id = trait_method.def_id;
+
+            // Some methods cannot be called on an object; skip those.
+            if !is_vtable_safe_method(tcx, trait_ref.def_id(), &trait_method) {
+                debug!("vtable_methods: not vtable safe");
+                return None;
+            }
+
+            // The method may have some early-bound lifetimes; add regions for those.
+            let substs = trait_ref.map_bound(|trait_ref| {
+                InternalSubsts::for_item(tcx, def_id, |param, _| match param.kind {
+                    GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(),
+                    GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => {
+                        trait_ref.substs[param.index as usize]
+                    }
+                })
+            });
+
+            // The trait type may have higher-ranked lifetimes in it;
+            // erase them if they appear, so that we get the type
+            // at some particular call site.
+            let substs =
+                tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &substs);
+
+            // It's possible that the method relies on where-clauses that
+            // do not hold for this particular set of type parameters.
+            // Note that this method could then never be called, so we
+            // do not want to try and codegen it, in that case (see #23435).
+            let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, substs);
+            if !normalize_and_test_predicates(tcx, predicates.predicates) {
+                debug!("vtable_methods: predicates do not hold");
+                return None;
+            }
+
+            Some((def_id, substs))
+        })
+    }))
+}
+
+pub fn provide(providers: &mut ty::query::Providers<'_>) {
+    object_safety::provide(providers);
+    *providers = ty::query::Providers {
+        specialization_graph_of: specialize::specialization_graph_provider,
+        specializes: specialize::specializes,
+        codegen_fulfill_obligation: codegen::codegen_fulfill_obligation,
+        vtable_methods,
+        substitute_normalize_and_test_predicates,
+        ..*providers
+    };
+}
diff --git a/src/librustc_trait_selection/traits/object_safety.rs b/src/librustc_trait_selection/traits/object_safety.rs
new file mode 100644 (file)
index 0000000..452f965
--- /dev/null
@@ -0,0 +1,778 @@
+//! "Object safety" refers to the ability for a trait to be converted
+//! to an object. In general, traits may only be converted to an
+//! object if all of their methods meet certain criteria. In particular,
+//! they must:
+//!
+//!   - have a suitable receiver from which we can extract a vtable and coerce to a "thin" version
+//!     that doesn't contain the vtable;
+//!   - not reference the erased type `Self` except for in this receiver;
+//!   - not have generic type parameters.
+
+use super::elaborate_predicates;
+
+use crate::infer::TyCtxtInferExt;
+use crate::traits::query::evaluate_obligation::InferCtxtExt;
+use crate::traits::{self, Obligation, ObligationCause};
+use rustc::ty::subst::{InternalSubsts, Subst};
+use rustc::ty::{self, Predicate, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
+use rustc_errors::Applicability;
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
+use rustc_session::lint::builtin::WHERE_CLAUSES_OBJECT_SAFETY;
+use rustc_span::symbol::Symbol;
+use rustc_span::Span;
+use smallvec::SmallVec;
+
+use std::iter;
+
+pub use crate::traits::{MethodViolationCode, ObjectSafetyViolation};
+
+/// Returns the object safety violations that affect
+/// astconv -- currently, `Self` in supertraits. This is needed
+/// because `object_safety_violations` can't be used during
+/// type collection.
+pub fn astconv_object_safety_violations(
+    tcx: TyCtxt<'_>,
+    trait_def_id: DefId,
+) -> Vec<ObjectSafetyViolation> {
+    debug_assert!(tcx.generics_of(trait_def_id).has_self);
+    let violations = traits::supertrait_def_ids(tcx, trait_def_id)
+        .map(|def_id| predicates_reference_self(tcx, def_id, true))
+        .filter(|spans| !spans.is_empty())
+        .map(|spans| ObjectSafetyViolation::SupertraitSelf(spans))
+        .collect();
+
+    debug!("astconv_object_safety_violations(trait_def_id={:?}) = {:?}", trait_def_id, violations);
+
+    violations
+}
+
+fn object_safety_violations(tcx: TyCtxt<'_>, trait_def_id: DefId) -> Vec<ObjectSafetyViolation> {
+    debug_assert!(tcx.generics_of(trait_def_id).has_self);
+    debug!("object_safety_violations: {:?}", trait_def_id);
+
+    traits::supertrait_def_ids(tcx, trait_def_id)
+        .flat_map(|def_id| object_safety_violations_for_trait(tcx, def_id))
+        .collect()
+}
+
+/// We say a method is *vtable safe* if it can be invoked on a trait
+/// object. Note that object-safe traits can have some
+/// non-vtable-safe methods, so long as they require `Self: Sized` or
+/// otherwise ensure that they cannot be used when `Self = Trait`.
+pub fn is_vtable_safe_method(tcx: TyCtxt<'_>, trait_def_id: DefId, method: &ty::AssocItem) -> bool {
+    debug_assert!(tcx.generics_of(trait_def_id).has_self);
+    debug!("is_vtable_safe_method({:?}, {:?})", trait_def_id, method);
+    // Any method that has a `Self: Sized` bound cannot be called.
+    if generics_require_sized_self(tcx, method.def_id) {
+        return false;
+    }
+
+    match virtual_call_violation_for_method(tcx, trait_def_id, method) {
+        None | Some(MethodViolationCode::WhereClauseReferencesSelf) => true,
+        Some(_) => false,
+    }
+}
+
+fn object_safety_violations_for_trait(
+    tcx: TyCtxt<'_>,
+    trait_def_id: DefId,
+) -> Vec<ObjectSafetyViolation> {
+    // Check methods for violations.
+    let mut violations: Vec<_> = tcx
+        .associated_items(trait_def_id)
+        .in_definition_order()
+        .filter(|item| item.kind == ty::AssocKind::Method)
+        .filter_map(|item| {
+            object_safety_violation_for_method(tcx, trait_def_id, &item)
+                .map(|(code, span)| ObjectSafetyViolation::Method(item.ident.name, code, span))
+        })
+        .filter(|violation| {
+            if let ObjectSafetyViolation::Method(
+                _,
+                MethodViolationCode::WhereClauseReferencesSelf,
+                span,
+            ) = violation
+            {
+                // Using `CRATE_NODE_ID` is wrong, but it's hard to get a more precise id.
+                // It's also hard to get a use site span, so we use the method definition span.
+                tcx.struct_span_lint_hir(
+                    WHERE_CLAUSES_OBJECT_SAFETY,
+                    hir::CRATE_HIR_ID,
+                    *span,
+                    |lint| {
+                        let mut err = lint.build(&format!(
+                            "the trait `{}` cannot be made into an object",
+                            tcx.def_path_str(trait_def_id)
+                        ));
+                        let node = tcx.hir().get_if_local(trait_def_id);
+                        let msg = if let Some(hir::Node::Item(item)) = node {
+                            err.span_label(
+                                item.ident.span,
+                                "this trait cannot be made into an object...",
+                            );
+                            format!("...because {}", violation.error_msg())
+                        } else {
+                            format!(
+                                "the trait cannot be made into an object because {}",
+                                violation.error_msg()
+                            )
+                        };
+                        err.span_label(*span, &msg);
+                        match (node, violation.solution()) {
+                            (Some(_), Some((note, None))) => {
+                                err.help(&note);
+                            }
+                            (Some(_), Some((note, Some((sugg, span))))) => {
+                                err.span_suggestion(
+                                    span,
+                                    &note,
+                                    sugg,
+                                    Applicability::MachineApplicable,
+                                );
+                            }
+                            // Only provide the help if its a local trait, otherwise it's not actionable.
+                            _ => {}
+                        }
+                        err.emit();
+                    },
+                );
+                false
+            } else {
+                true
+            }
+        })
+        .collect();
+
+    // Check the trait itself.
+    if trait_has_sized_self(tcx, trait_def_id) {
+        // We don't want to include the requirement from `Sized` itself to be `Sized` in the list.
+        let spans = get_sized_bounds(tcx, trait_def_id);
+        violations.push(ObjectSafetyViolation::SizedSelf(spans));
+    }
+    let spans = predicates_reference_self(tcx, trait_def_id, false);
+    if !spans.is_empty() {
+        violations.push(ObjectSafetyViolation::SupertraitSelf(spans));
+    }
+
+    violations.extend(
+        tcx.associated_items(trait_def_id)
+            .in_definition_order()
+            .filter(|item| item.kind == ty::AssocKind::Const)
+            .map(|item| ObjectSafetyViolation::AssocConst(item.ident.name, item.ident.span)),
+    );
+
+    debug!(
+        "object_safety_violations_for_trait(trait_def_id={:?}) = {:?}",
+        trait_def_id, violations
+    );
+
+    violations
+}
+
+fn get_sized_bounds(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span; 1]> {
+    tcx.hir()
+        .get_if_local(trait_def_id)
+        .and_then(|node| match node {
+            hir::Node::Item(hir::Item {
+                kind: hir::ItemKind::Trait(.., generics, bounds, _),
+                ..
+            }) => Some(
+                generics
+                    .where_clause
+                    .predicates
+                    .iter()
+                    .filter_map(|pred| {
+                        match pred {
+                            hir::WherePredicate::BoundPredicate(pred)
+                                if pred.bounded_ty.hir_id.owner.to_def_id() == trait_def_id =>
+                            {
+                                // Fetch spans for trait bounds that are Sized:
+                                // `trait T where Self: Pred`
+                                Some(pred.bounds.iter().filter_map(|b| match b {
+                                    hir::GenericBound::Trait(
+                                        trait_ref,
+                                        hir::TraitBoundModifier::None,
+                                    ) if trait_has_sized_self(
+                                        tcx,
+                                        trait_ref.trait_ref.trait_def_id(),
+                                    ) =>
+                                    {
+                                        Some(trait_ref.span)
+                                    }
+                                    _ => None,
+                                }))
+                            }
+                            _ => None,
+                        }
+                    })
+                    .flatten()
+                    .chain(bounds.iter().filter_map(|b| match b {
+                        hir::GenericBound::Trait(trait_ref, hir::TraitBoundModifier::None)
+                            if trait_has_sized_self(tcx, trait_ref.trait_ref.trait_def_id()) =>
+                        {
+                            // Fetch spans for supertraits that are `Sized`: `trait T: Super`
+                            Some(trait_ref.span)
+                        }
+                        _ => None,
+                    }))
+                    .collect::<SmallVec<[Span; 1]>>(),
+            ),
+            _ => None,
+        })
+        .unwrap_or_else(SmallVec::new)
+}
+
+fn predicates_reference_self(
+    tcx: TyCtxt<'_>,
+    trait_def_id: DefId,
+    supertraits_only: bool,
+) -> SmallVec<[Span; 1]> {
+    let trait_ref = ty::Binder::dummy(ty::TraitRef::identity(tcx, trait_def_id));
+    let predicates = if supertraits_only {
+        tcx.super_predicates_of(trait_def_id)
+    } else {
+        tcx.predicates_of(trait_def_id)
+    };
+    let self_ty = tcx.types.self_param;
+    let has_self_ty = |t: Ty<'_>| t.walk().any(|t| t == self_ty);
+    predicates
+        .predicates
+        .iter()
+        .map(|(predicate, sp)| (predicate.subst_supertrait(tcx, &trait_ref), sp))
+        .filter_map(|(predicate, &sp)| {
+            match predicate {
+                ty::Predicate::Trait(ref data, _) => {
+                    // In the case of a trait predicate, we can skip the "self" type.
+                    if data.skip_binder().input_types().skip(1).any(has_self_ty) {
+                        Some(sp)
+                    } else {
+                        None
+                    }
+                }
+                ty::Predicate::Projection(ref data) => {
+                    // And similarly for projections. This should be redundant with
+                    // the previous check because any projection should have a
+                    // matching `Trait` predicate with the same inputs, but we do
+                    // the check to be safe.
+                    //
+                    // Note that we *do* allow projection *outputs* to contain
+                    // `self` (i.e., `trait Foo: Bar<Output=Self::Result> { type Result; }`),
+                    // we just require the user to specify *both* outputs
+                    // in the object type (i.e., `dyn Foo<Output=(), Result=()>`).
+                    //
+                    // This is ALT2 in issue #56288, see that for discussion of the
+                    // possible alternatives.
+                    if data
+                        .skip_binder()
+                        .projection_ty
+                        .trait_ref(tcx)
+                        .input_types()
+                        .skip(1)
+                        .any(has_self_ty)
+                    {
+                        Some(sp)
+                    } else {
+                        None
+                    }
+                }
+                ty::Predicate::WellFormed(..)
+                | ty::Predicate::ObjectSafe(..)
+                | ty::Predicate::TypeOutlives(..)
+                | ty::Predicate::RegionOutlives(..)
+                | ty::Predicate::ClosureKind(..)
+                | ty::Predicate::Subtype(..)
+                | ty::Predicate::ConstEvaluatable(..) => None,
+            }
+        })
+        .collect()
+}
+
+fn trait_has_sized_self(tcx: TyCtxt<'_>, trait_def_id: DefId) -> bool {
+    generics_require_sized_self(tcx, trait_def_id)
+}
+
+fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
+    let sized_def_id = match tcx.lang_items().sized_trait() {
+        Some(def_id) => def_id,
+        None => {
+            return false; /* No Sized trait, can't require it! */
+        }
+    };
+
+    // Search for a predicate like `Self : Sized` amongst the trait bounds.
+    let predicates = tcx.predicates_of(def_id);
+    let predicates = predicates.instantiate_identity(tcx).predicates;
+    elaborate_predicates(tcx, predicates).any(|predicate| match predicate {
+        ty::Predicate::Trait(ref trait_pred, _) => {
+            trait_pred.def_id() == sized_def_id && trait_pred.skip_binder().self_ty().is_param(0)
+        }
+        ty::Predicate::Projection(..)
+        | ty::Predicate::Subtype(..)
+        | ty::Predicate::RegionOutlives(..)
+        | ty::Predicate::WellFormed(..)
+        | ty::Predicate::ObjectSafe(..)
+        | ty::Predicate::ClosureKind(..)
+        | ty::Predicate::TypeOutlives(..)
+        | ty::Predicate::ConstEvaluatable(..) => false,
+    })
+}
+
+/// Returns `Some(_)` if this method makes the containing trait not object safe.
+fn object_safety_violation_for_method(
+    tcx: TyCtxt<'_>,
+    trait_def_id: DefId,
+    method: &ty::AssocItem,
+) -> Option<(MethodViolationCode, Span)> {
+    debug!("object_safety_violation_for_method({:?}, {:?})", trait_def_id, method);
+    // Any method that has a `Self : Sized` requisite is otherwise
+    // exempt from the regulations.
+    if generics_require_sized_self(tcx, method.def_id) {
+        return None;
+    }
+
+    let violation = virtual_call_violation_for_method(tcx, trait_def_id, method);
+    // Get an accurate span depending on the violation.
+    violation.map(|v| {
+        let node = tcx.hir().get_if_local(method.def_id);
+        let span = match (v, node) {
+            (MethodViolationCode::ReferencesSelfInput(arg), Some(node)) => node
+                .fn_decl()
+                .and_then(|decl| decl.inputs.get(arg + 1))
+                .map_or(method.ident.span, |arg| arg.span),
+            (MethodViolationCode::UndispatchableReceiver, Some(node)) => node
+                .fn_decl()
+                .and_then(|decl| decl.inputs.get(0))
+                .map_or(method.ident.span, |arg| arg.span),
+            (MethodViolationCode::ReferencesSelfOutput, Some(node)) => {
+                node.fn_decl().map_or(method.ident.span, |decl| decl.output.span())
+            }
+            _ => method.ident.span,
+        };
+        (v, span)
+    })
+}
+
+/// Returns `Some(_)` if this method cannot be called on a trait
+/// object; this does not necessarily imply that the enclosing trait
+/// is not object safe, because the method might have a where clause
+/// `Self:Sized`.
+fn virtual_call_violation_for_method<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    trait_def_id: DefId,
+    method: &ty::AssocItem,
+) -> Option<MethodViolationCode> {
+    // The method's first parameter must be named `self`
+    if !method.method_has_self_argument {
+        // We'll attempt to provide a structured suggestion for `Self: Sized`.
+        let sugg =
+            tcx.hir().get_if_local(method.def_id).as_ref().and_then(|node| node.generics()).map(
+                |generics| match generics.where_clause.predicates {
+                    [] => (" where Self: Sized", generics.where_clause.span),
+                    [.., pred] => (", Self: Sized", pred.span().shrink_to_hi()),
+                },
+            );
+        return Some(MethodViolationCode::StaticMethod(sugg));
+    }
+
+    let sig = tcx.fn_sig(method.def_id);
+
+    for (i, input_ty) in sig.skip_binder().inputs()[1..].iter().enumerate() {
+        if contains_illegal_self_type_reference(tcx, trait_def_id, input_ty) {
+            return Some(MethodViolationCode::ReferencesSelfInput(i));
+        }
+    }
+    if contains_illegal_self_type_reference(tcx, trait_def_id, sig.output().skip_binder()) {
+        return Some(MethodViolationCode::ReferencesSelfOutput);
+    }
+
+    // We can't monomorphize things like `fn foo<A>(...)`.
+    let own_counts = tcx.generics_of(method.def_id).own_counts();
+    if own_counts.types + own_counts.consts != 0 {
+        return Some(MethodViolationCode::Generic);
+    }
+
+    if tcx
+        .predicates_of(method.def_id)
+        .predicates
+        .iter()
+        // A trait object can't claim to live more than the concrete type,
+        // so outlives predicates will always hold.
+        .cloned()
+        .filter(|(p, _)| p.to_opt_type_outlives().is_none())
+        .collect::<Vec<_>>()
+        // Do a shallow visit so that `contains_illegal_self_type_reference`
+        // may apply it's custom visiting.
+        .visit_tys_shallow(|t| contains_illegal_self_type_reference(tcx, trait_def_id, t))
+    {
+        return Some(MethodViolationCode::WhereClauseReferencesSelf);
+    }
+
+    let receiver_ty =
+        tcx.liberate_late_bound_regions(method.def_id, &sig.map_bound(|sig| sig.inputs()[0]));
+
+    // Until `unsized_locals` is fully implemented, `self: Self` can't be dispatched on.
+    // However, this is already considered object-safe. We allow it as a special case here.
+    // FIXME(mikeyhew) get rid of this `if` statement once `receiver_is_dispatchable` allows
+    // `Receiver: Unsize<Receiver[Self => dyn Trait]>`.
+    if receiver_ty != tcx.types.self_param {
+        if !receiver_is_dispatchable(tcx, method, receiver_ty) {
+            return Some(MethodViolationCode::UndispatchableReceiver);
+        } else {
+            // Do sanity check to make sure the receiver actually has the layout of a pointer.
+
+            use rustc::ty::layout::Abi;
+
+            let param_env = tcx.param_env(method.def_id);
+
+            let abi_of_ty = |ty: Ty<'tcx>| -> &Abi {
+                match tcx.layout_of(param_env.and(ty)) {
+                    Ok(layout) => &layout.abi,
+                    Err(err) => bug!("error: {}\n while computing layout for type {:?}", err, ty),
+                }
+            };
+
+            // e.g., `Rc<()>`
+            let unit_receiver_ty =
+                receiver_for_self_ty(tcx, receiver_ty, tcx.mk_unit(), method.def_id);
+
+            match abi_of_ty(unit_receiver_ty) {
+                &Abi::Scalar(..) => (),
+                abi => {
+                    tcx.sess.delay_span_bug(
+                        tcx.def_span(method.def_id),
+                        &format!(
+                            "receiver when `Self = ()` should have a Scalar ABI; found {:?}",
+                            abi
+                        ),
+                    );
+                }
+            }
+
+            let trait_object_ty =
+                object_ty_for_trait(tcx, trait_def_id, tcx.mk_region(ty::ReStatic));
+
+            // e.g., `Rc<dyn Trait>`
+            let trait_object_receiver =
+                receiver_for_self_ty(tcx, receiver_ty, trait_object_ty, method.def_id);
+
+            match abi_of_ty(trait_object_receiver) {
+                &Abi::ScalarPair(..) => (),
+                abi => {
+                    tcx.sess.delay_span_bug(
+                        tcx.def_span(method.def_id),
+                        &format!(
+                            "receiver when `Self = {}` should have a ScalarPair ABI; \
+                                 found {:?}",
+                            trait_object_ty, abi
+                        ),
+                    );
+                }
+            }
+        }
+    }
+
+    None
+}
+
+/// Performs a type substitution to produce the version of `receiver_ty` when `Self = self_ty`.
+/// For example, for `receiver_ty = Rc<Self>` and `self_ty = Foo`, returns `Rc<Foo>`.
+fn receiver_for_self_ty<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    receiver_ty: Ty<'tcx>,
+    self_ty: Ty<'tcx>,
+    method_def_id: DefId,
+) -> Ty<'tcx> {
+    debug!("receiver_for_self_ty({:?}, {:?}, {:?})", receiver_ty, self_ty, method_def_id);
+    let substs = InternalSubsts::for_item(tcx, method_def_id, |param, _| {
+        if param.index == 0 { self_ty.into() } else { tcx.mk_param_from_def(param) }
+    });
+
+    let result = receiver_ty.subst(tcx, substs);
+    debug!(
+        "receiver_for_self_ty({:?}, {:?}, {:?}) = {:?}",
+        receiver_ty, self_ty, method_def_id, result
+    );
+    result
+}
+
+/// Creates the object type for the current trait. For example,
+/// if the current trait is `Deref`, then this will be
+/// `dyn Deref<Target = Self::Target> + 'static`.
+fn object_ty_for_trait<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    trait_def_id: DefId,
+    lifetime: ty::Region<'tcx>,
+) -> Ty<'tcx> {
+    debug!("object_ty_for_trait: trait_def_id={:?}", trait_def_id);
+
+    let trait_ref = ty::TraitRef::identity(tcx, trait_def_id);
+
+    let trait_predicate =
+        ty::ExistentialPredicate::Trait(ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref));
+
+    let mut associated_types = traits::supertraits(tcx, ty::Binder::dummy(trait_ref))
+        .flat_map(|super_trait_ref| {
+            tcx.associated_items(super_trait_ref.def_id())
+                .in_definition_order()
+                .map(move |item| (super_trait_ref, item))
+        })
+        .filter(|(_, item)| item.kind == ty::AssocKind::Type)
+        .collect::<Vec<_>>();
+
+    // existential predicates need to be in a specific order
+    associated_types.sort_by_cached_key(|(_, item)| tcx.def_path_hash(item.def_id));
+
+    let projection_predicates = associated_types.into_iter().map(|(super_trait_ref, item)| {
+        // We *can* get bound lifetimes here in cases like
+        // `trait MyTrait: for<'s> OtherTrait<&'s T, Output=bool>`.
+        //
+        // binder moved to (*)...
+        let super_trait_ref = super_trait_ref.skip_binder();
+        ty::ExistentialPredicate::Projection(ty::ExistentialProjection {
+            ty: tcx.mk_projection(item.def_id, super_trait_ref.substs),
+            item_def_id: item.def_id,
+            substs: super_trait_ref.substs,
+        })
+    });
+
+    let existential_predicates =
+        tcx.mk_existential_predicates(iter::once(trait_predicate).chain(projection_predicates));
+
+    let object_ty = tcx.mk_dynamic(
+        // (*) ... binder re-introduced here
+        ty::Binder::bind(existential_predicates),
+        lifetime,
+    );
+
+    debug!("object_ty_for_trait: object_ty=`{}`", object_ty);
+
+    object_ty
+}
+
+/// Checks the method's receiver (the `self` argument) can be dispatched on when `Self` is a
+/// trait object. We require that `DispatchableFromDyn` be implemented for the receiver type
+/// in the following way:
+/// - let `Receiver` be the type of the `self` argument, i.e `Self`, `&Self`, `Rc<Self>`,
+/// - require the following bound:
+///
+///   ```
+///   Receiver[Self => T]: DispatchFromDyn<Receiver[Self => dyn Trait]>
+///   ```
+///
+///   where `Foo[X => Y]` means "the same type as `Foo`, but with `X` replaced with `Y`"
+///   (substitution notation).
+///
+/// Some examples of receiver types and their required obligation:
+/// - `&'a mut self` requires `&'a mut Self: DispatchFromDyn<&'a mut dyn Trait>`,
+/// - `self: Rc<Self>` requires `Rc<Self>: DispatchFromDyn<Rc<dyn Trait>>`,
+/// - `self: Pin<Box<Self>>` requires `Pin<Box<Self>>: DispatchFromDyn<Pin<Box<dyn Trait>>>`.
+///
+/// The only case where the receiver is not dispatchable, but is still a valid receiver
+/// type (just not object-safe), is when there is more than one level of pointer indirection.
+/// E.g., `self: &&Self`, `self: &Rc<Self>`, `self: Box<Box<Self>>`. In these cases, there
+/// is no way, or at least no inexpensive way, to coerce the receiver from the version where
+/// `Self = dyn Trait` to the version where `Self = T`, where `T` is the unknown erased type
+/// contained by the trait object, because the object that needs to be coerced is behind
+/// a pointer.
+///
+/// In practice, we cannot use `dyn Trait` explicitly in the obligation because it would result
+/// in a new check that `Trait` is object safe, creating a cycle (until object_safe_for_dispatch
+/// is stabilized, see tracking issue https://github.com/rust-lang/rust/issues/43561).
+/// Instead, we fudge a little by introducing a new type parameter `U` such that
+/// `Self: Unsize<U>` and `U: Trait + ?Sized`, and use `U` in place of `dyn Trait`.
+/// Written as a chalk-style query:
+///
+///     forall (U: Trait + ?Sized) {
+///         if (Self: Unsize<U>) {
+///             Receiver: DispatchFromDyn<Receiver[Self => U]>
+///         }
+///     }
+///
+/// for `self: &'a mut Self`, this means `&'a mut Self: DispatchFromDyn<&'a mut U>`
+/// for `self: Rc<Self>`, this means `Rc<Self>: DispatchFromDyn<Rc<U>>`
+/// for `self: Pin<Box<Self>>`, this means `Pin<Box<Self>>: DispatchFromDyn<Pin<Box<U>>>`
+//
+// FIXME(mikeyhew) when unsized receivers are implemented as part of unsized rvalues, add this
+// fallback query: `Receiver: Unsize<Receiver[Self => U]>` to support receivers like
+// `self: Wrapper<Self>`.
+#[allow(dead_code)]
+fn receiver_is_dispatchable<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    method: &ty::AssocItem,
+    receiver_ty: Ty<'tcx>,
+) -> bool {
+    debug!("receiver_is_dispatchable: method = {:?}, receiver_ty = {:?}", method, receiver_ty);
+
+    let traits = (tcx.lang_items().unsize_trait(), tcx.lang_items().dispatch_from_dyn_trait());
+    let (unsize_did, dispatch_from_dyn_did) = if let (Some(u), Some(cu)) = traits {
+        (u, cu)
+    } else {
+        debug!("receiver_is_dispatchable: Missing Unsize or DispatchFromDyn traits");
+        return false;
+    };
+
+    // the type `U` in the query
+    // use a bogus type parameter to mimic a forall(U) query using u32::MAX for now.
+    // FIXME(mikeyhew) this is a total hack. Once object_safe_for_dispatch is stabilized, we can
+    // replace this with `dyn Trait`
+    let unsized_self_ty: Ty<'tcx> =
+        tcx.mk_ty_param(::std::u32::MAX, Symbol::intern("RustaceansAreAwesome"));
+
+    // `Receiver[Self => U]`
+    let unsized_receiver_ty =
+        receiver_for_self_ty(tcx, receiver_ty, unsized_self_ty, method.def_id);
+
+    // create a modified param env, with `Self: Unsize<U>` and `U: Trait` added to caller bounds
+    // `U: ?Sized` is already implied here
+    let param_env = {
+        let mut param_env = tcx.param_env(method.def_id);
+
+        // Self: Unsize<U>
+        let unsize_predicate = ty::TraitRef {
+            def_id: unsize_did,
+            substs: tcx.mk_substs_trait(tcx.types.self_param, &[unsized_self_ty.into()]),
+        }
+        .without_const()
+        .to_predicate();
+
+        // U: Trait<Arg1, ..., ArgN>
+        let trait_predicate = {
+            let substs =
+                InternalSubsts::for_item(tcx, method.container.assert_trait(), |param, _| {
+                    if param.index == 0 {
+                        unsized_self_ty.into()
+                    } else {
+                        tcx.mk_param_from_def(param)
+                    }
+                });
+
+            ty::TraitRef { def_id: unsize_did, substs }.without_const().to_predicate()
+        };
+
+        let caller_bounds: Vec<Predicate<'tcx>> = param_env
+            .caller_bounds
+            .iter()
+            .cloned()
+            .chain(iter::once(unsize_predicate))
+            .chain(iter::once(trait_predicate))
+            .collect();
+
+        param_env.caller_bounds = tcx.intern_predicates(&caller_bounds);
+
+        param_env
+    };
+
+    // Receiver: DispatchFromDyn<Receiver[Self => U]>
+    let obligation = {
+        let predicate = ty::TraitRef {
+            def_id: dispatch_from_dyn_did,
+            substs: tcx.mk_substs_trait(receiver_ty, &[unsized_receiver_ty.into()]),
+        }
+        .without_const()
+        .to_predicate();
+
+        Obligation::new(ObligationCause::dummy(), param_env, predicate)
+    };
+
+    tcx.infer_ctxt().enter(|ref infcx| {
+        // the receiver is dispatchable iff the obligation holds
+        infcx.predicate_must_hold_modulo_regions(&obligation)
+    })
+}
+
+fn contains_illegal_self_type_reference<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    trait_def_id: DefId,
+    ty: Ty<'tcx>,
+) -> bool {
+    // This is somewhat subtle. In general, we want to forbid
+    // references to `Self` in the argument and return types,
+    // since the value of `Self` is erased. However, there is one
+    // exception: it is ok to reference `Self` in order to access
+    // an associated type of the current trait, since we retain
+    // the value of those associated types in the object type
+    // itself.
+    //
+    // ```rust
+    // trait SuperTrait {
+    //     type X;
+    // }
+    //
+    // trait Trait : SuperTrait {
+    //     type Y;
+    //     fn foo(&self, x: Self) // bad
+    //     fn foo(&self) -> Self // bad
+    //     fn foo(&self) -> Option<Self> // bad
+    //     fn foo(&self) -> Self::Y // OK, desugars to next example
+    //     fn foo(&self) -> <Self as Trait>::Y // OK
+    //     fn foo(&self) -> Self::X // OK, desugars to next example
+    //     fn foo(&self) -> <Self as SuperTrait>::X // OK
+    // }
+    // ```
+    //
+    // However, it is not as simple as allowing `Self` in a projected
+    // type, because there are illegal ways to use `Self` as well:
+    //
+    // ```rust
+    // trait Trait : SuperTrait {
+    //     ...
+    //     fn foo(&self) -> <Self as SomeOtherTrait>::X;
+    // }
+    // ```
+    //
+    // Here we will not have the type of `X` recorded in the
+    // object type, and we cannot resolve `Self as SomeOtherTrait`
+    // without knowing what `Self` is.
+
+    let mut supertraits: Option<Vec<ty::PolyTraitRef<'tcx>>> = None;
+    let mut error = false;
+    let self_ty = tcx.types.self_param;
+    ty.maybe_walk(|ty| {
+        match ty.kind {
+            ty::Param(_) => {
+                if ty == self_ty {
+                    error = true;
+                }
+
+                false // no contained types to walk
+            }
+
+            ty::Projection(ref data) => {
+                // This is a projected type `<Foo as SomeTrait>::X`.
+
+                // Compute supertraits of current trait lazily.
+                if supertraits.is_none() {
+                    let trait_ref = ty::Binder::bind(ty::TraitRef::identity(tcx, trait_def_id));
+                    supertraits = Some(traits::supertraits(tcx, trait_ref).collect());
+                }
+
+                // Determine whether the trait reference `Foo as
+                // SomeTrait` is in fact a supertrait of the
+                // current trait. In that case, this type is
+                // legal, because the type `X` will be specified
+                // in the object type.  Note that we can just use
+                // direct equality here because all of these types
+                // are part of the formal parameter listing, and
+                // hence there should be no inference variables.
+                let projection_trait_ref = ty::Binder::bind(data.trait_ref(tcx));
+                let is_supertrait_of_current_trait =
+                    supertraits.as_ref().unwrap().contains(&projection_trait_ref);
+
+                if is_supertrait_of_current_trait {
+                    false // do not walk contained types, do not report error, do collect $200
+                } else {
+                    true // DO walk contained types, POSSIBLY reporting an error
+                }
+            }
+
+            _ => true, // walk contained types, if any
+        }
+    });
+
+    error
+}
+
+pub fn provide(providers: &mut ty::query::Providers<'_>) {
+    *providers = ty::query::Providers { object_safety_violations, ..*providers };
+}
diff --git a/src/librustc_trait_selection/traits/on_unimplemented.rs b/src/librustc_trait_selection/traits/on_unimplemented.rs
new file mode 100644 (file)
index 0000000..1926029
--- /dev/null
@@ -0,0 +1,383 @@
+use fmt_macros::{Parser, Piece, Position};
+
+use rustc::ty::{self, GenericParamDefKind, TyCtxt};
+use rustc::util::common::ErrorReported;
+
+use rustc_ast::ast::{MetaItem, NestedMetaItem};
+use rustc_attr as attr;
+use rustc_data_structures::fx::FxHashMap;
+use rustc_errors::struct_span_err;
+use rustc_hir::def_id::DefId;
+use rustc_span::symbol::{kw, sym, Symbol};
+use rustc_span::Span;
+
+#[derive(Clone, Debug)]
+pub struct OnUnimplementedFormatString(Symbol);
+
+#[derive(Debug)]
+pub struct OnUnimplementedDirective {
+    pub condition: Option<MetaItem>,
+    pub subcommands: Vec<OnUnimplementedDirective>,
+    pub message: Option<OnUnimplementedFormatString>,
+    pub label: Option<OnUnimplementedFormatString>,
+    pub note: Option<OnUnimplementedFormatString>,
+    pub enclosing_scope: Option<OnUnimplementedFormatString>,
+}
+
+#[derive(Default)]
+pub struct OnUnimplementedNote {
+    pub message: Option<String>,
+    pub label: Option<String>,
+    pub note: Option<String>,
+    pub enclosing_scope: Option<String>,
+}
+
+fn parse_error(
+    tcx: TyCtxt<'_>,
+    span: Span,
+    message: &str,
+    label: &str,
+    note: Option<&str>,
+) -> ErrorReported {
+    let mut diag = struct_span_err!(tcx.sess, span, E0232, "{}", message);
+    diag.span_label(span, label);
+    if let Some(note) = note {
+        diag.note(note);
+    }
+    diag.emit();
+    ErrorReported
+}
+
+impl<'tcx> OnUnimplementedDirective {
+    fn parse(
+        tcx: TyCtxt<'tcx>,
+        trait_def_id: DefId,
+        items: &[NestedMetaItem],
+        span: Span,
+        is_root: bool,
+    ) -> Result<Self, ErrorReported> {
+        let mut errored = false;
+        let mut item_iter = items.iter();
+
+        let condition = if is_root {
+            None
+        } else {
+            let cond = item_iter
+                .next()
+                .ok_or_else(|| {
+                    parse_error(
+                        tcx,
+                        span,
+                        "empty `on`-clause in `#[rustc_on_unimplemented]`",
+                        "empty on-clause here",
+                        None,
+                    )
+                })?
+                .meta_item()
+                .ok_or_else(|| {
+                    parse_error(
+                        tcx,
+                        span,
+                        "invalid `on`-clause in `#[rustc_on_unimplemented]`",
+                        "invalid on-clause here",
+                        None,
+                    )
+                })?;
+            attr::eval_condition(cond, &tcx.sess.parse_sess, &mut |_| true);
+            Some(cond.clone())
+        };
+
+        let mut message = None;
+        let mut label = None;
+        let mut note = None;
+        let mut enclosing_scope = None;
+        let mut subcommands = vec![];
+
+        let parse_value = |value_str| {
+            OnUnimplementedFormatString::try_parse(tcx, trait_def_id, value_str, span).map(Some)
+        };
+
+        for item in item_iter {
+            if item.check_name(sym::message) && message.is_none() {
+                if let Some(message_) = item.value_str() {
+                    message = parse_value(message_)?;
+                    continue;
+                }
+            } else if item.check_name(sym::label) && label.is_none() {
+                if let Some(label_) = item.value_str() {
+                    label = parse_value(label_)?;
+                    continue;
+                }
+            } else if item.check_name(sym::note) && note.is_none() {
+                if let Some(note_) = item.value_str() {
+                    note = parse_value(note_)?;
+                    continue;
+                }
+            } else if item.check_name(sym::enclosing_scope) && enclosing_scope.is_none() {
+                if let Some(enclosing_scope_) = item.value_str() {
+                    enclosing_scope = parse_value(enclosing_scope_)?;
+                    continue;
+                }
+            } else if item.check_name(sym::on)
+                && is_root
+                && message.is_none()
+                && label.is_none()
+                && note.is_none()
+            {
+                if let Some(items) = item.meta_item_list() {
+                    if let Ok(subcommand) =
+                        Self::parse(tcx, trait_def_id, &items, item.span(), false)
+                    {
+                        subcommands.push(subcommand);
+                    } else {
+                        errored = true;
+                    }
+                    continue;
+                }
+            }
+
+            // nothing found
+            parse_error(
+                tcx,
+                item.span(),
+                "this attribute must have a valid value",
+                "expected value here",
+                Some(r#"eg `#[rustc_on_unimplemented(message="foo")]`"#),
+            );
+        }
+
+        if errored {
+            Err(ErrorReported)
+        } else {
+            Ok(OnUnimplementedDirective {
+                condition,
+                subcommands,
+                message,
+                label,
+                note,
+                enclosing_scope,
+            })
+        }
+    }
+
+    pub fn of_item(
+        tcx: TyCtxt<'tcx>,
+        trait_def_id: DefId,
+        impl_def_id: DefId,
+    ) -> Result<Option<Self>, ErrorReported> {
+        let attrs = tcx.get_attrs(impl_def_id);
+
+        let attr = if let Some(item) = attr::find_by_name(&attrs, sym::rustc_on_unimplemented) {
+            item
+        } else {
+            return Ok(None);
+        };
+
+        let result = if let Some(items) = attr.meta_item_list() {
+            Self::parse(tcx, trait_def_id, &items, attr.span, true).map(Some)
+        } else if let Some(value) = attr.value_str() {
+            Ok(Some(OnUnimplementedDirective {
+                condition: None,
+                message: None,
+                subcommands: vec![],
+                label: Some(OnUnimplementedFormatString::try_parse(
+                    tcx,
+                    trait_def_id,
+                    value,
+                    attr.span,
+                )?),
+                note: None,
+                enclosing_scope: None,
+            }))
+        } else {
+            return Err(ErrorReported);
+        };
+        debug!("of_item({:?}/{:?}) = {:?}", trait_def_id, impl_def_id, result);
+        result
+    }
+
+    pub fn evaluate(
+        &self,
+        tcx: TyCtxt<'tcx>,
+        trait_ref: ty::TraitRef<'tcx>,
+        options: &[(Symbol, Option<String>)],
+    ) -> OnUnimplementedNote {
+        let mut message = None;
+        let mut label = None;
+        let mut note = None;
+        let mut enclosing_scope = None;
+        info!("evaluate({:?}, trait_ref={:?}, options={:?})", self, trait_ref, options);
+
+        for command in self.subcommands.iter().chain(Some(self)).rev() {
+            if let Some(ref condition) = command.condition {
+                if !attr::eval_condition(condition, &tcx.sess.parse_sess, &mut |c| {
+                    c.ident().map_or(false, |ident| {
+                        options.contains(&(ident.name, c.value_str().map(|s| s.to_string())))
+                    })
+                }) {
+                    debug!("evaluate: skipping {:?} due to condition", command);
+                    continue;
+                }
+            }
+            debug!("evaluate: {:?} succeeded", command);
+            if let Some(ref message_) = command.message {
+                message = Some(message_.clone());
+            }
+
+            if let Some(ref label_) = command.label {
+                label = Some(label_.clone());
+            }
+
+            if let Some(ref note_) = command.note {
+                note = Some(note_.clone());
+            }
+
+            if let Some(ref enclosing_scope_) = command.enclosing_scope {
+                enclosing_scope = Some(enclosing_scope_.clone());
+            }
+        }
+
+        let options: FxHashMap<Symbol, String> =
+            options.iter().filter_map(|(k, v)| v.as_ref().map(|v| (*k, v.to_owned()))).collect();
+        OnUnimplementedNote {
+            label: label.map(|l| l.format(tcx, trait_ref, &options)),
+            message: message.map(|m| m.format(tcx, trait_ref, &options)),
+            note: note.map(|n| n.format(tcx, trait_ref, &options)),
+            enclosing_scope: enclosing_scope.map(|e_s| e_s.format(tcx, trait_ref, &options)),
+        }
+    }
+}
+
+impl<'tcx> OnUnimplementedFormatString {
+    fn try_parse(
+        tcx: TyCtxt<'tcx>,
+        trait_def_id: DefId,
+        from: Symbol,
+        err_sp: Span,
+    ) -> Result<Self, ErrorReported> {
+        let result = OnUnimplementedFormatString(from);
+        result.verify(tcx, trait_def_id, err_sp)?;
+        Ok(result)
+    }
+
+    fn verify(
+        &self,
+        tcx: TyCtxt<'tcx>,
+        trait_def_id: DefId,
+        span: Span,
+    ) -> Result<(), ErrorReported> {
+        let name = tcx.item_name(trait_def_id);
+        let generics = tcx.generics_of(trait_def_id);
+        let s = self.0.as_str();
+        let parser = Parser::new(&s, None, vec![], false);
+        let mut result = Ok(());
+        for token in parser {
+            match token {
+                Piece::String(_) => (), // Normal string, no need to check it
+                Piece::NextArgument(a) => match a.position {
+                    // `{Self}` is allowed
+                    Position::ArgumentNamed(s) if s == kw::SelfUpper => (),
+                    // `{ThisTraitsName}` is allowed
+                    Position::ArgumentNamed(s) if s == name => (),
+                    // `{from_method}` is allowed
+                    Position::ArgumentNamed(s) if s == sym::from_method => (),
+                    // `{from_desugaring}` is allowed
+                    Position::ArgumentNamed(s) if s == sym::from_desugaring => (),
+                    // `{ItemContext}` is allowed
+                    Position::ArgumentNamed(s) if s == sym::item_context => (),
+                    // So is `{A}` if A is a type parameter
+                    Position::ArgumentNamed(s) => {
+                        match generics.params.iter().find(|param| param.name == s) {
+                            Some(_) => (),
+                            None => {
+                                struct_span_err!(
+                                    tcx.sess,
+                                    span,
+                                    E0230,
+                                    "there is no parameter `{}` on trait `{}`",
+                                    s,
+                                    name
+                                )
+                                .emit();
+                                result = Err(ErrorReported);
+                            }
+                        }
+                    }
+                    // `{:1}` and `{}` are not to be used
+                    Position::ArgumentIs(_) | Position::ArgumentImplicitlyIs(_) => {
+                        struct_span_err!(
+                            tcx.sess,
+                            span,
+                            E0231,
+                            "only named substitution parameters are allowed"
+                        )
+                        .emit();
+                        result = Err(ErrorReported);
+                    }
+                },
+            }
+        }
+
+        result
+    }
+
+    pub fn format(
+        &self,
+        tcx: TyCtxt<'tcx>,
+        trait_ref: ty::TraitRef<'tcx>,
+        options: &FxHashMap<Symbol, String>,
+    ) -> String {
+        let name = tcx.item_name(trait_ref.def_id);
+        let trait_str = tcx.def_path_str(trait_ref.def_id);
+        let generics = tcx.generics_of(trait_ref.def_id);
+        let generic_map = generics
+            .params
+            .iter()
+            .filter_map(|param| {
+                let value = match param.kind {
+                    GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => {
+                        trait_ref.substs[param.index as usize].to_string()
+                    }
+                    GenericParamDefKind::Lifetime => return None,
+                };
+                let name = param.name;
+                Some((name, value))
+            })
+            .collect::<FxHashMap<Symbol, String>>();
+        let empty_string = String::new();
+
+        let s = self.0.as_str();
+        let parser = Parser::new(&s, None, vec![], false);
+        let item_context = (options.get(&sym::item_context)).unwrap_or(&empty_string);
+        parser
+            .map(|p| match p {
+                Piece::String(s) => s,
+                Piece::NextArgument(a) => match a.position {
+                    Position::ArgumentNamed(s) => match generic_map.get(&s) {
+                        Some(val) => val,
+                        None if s == name => &trait_str,
+                        None => {
+                            if let Some(val) = options.get(&s) {
+                                val
+                            } else if s == sym::from_desugaring || s == sym::from_method {
+                                // don't break messages using these two arguments incorrectly
+                                &empty_string
+                            } else if s == sym::item_context {
+                                &item_context
+                            } else {
+                                bug!(
+                                    "broken on_unimplemented {:?} for {:?}: \
+                                      no argument matching {:?}",
+                                    self.0,
+                                    trait_ref,
+                                    s
+                                )
+                            }
+                        }
+                    },
+                    _ => bug!("broken on_unimplemented {:?} - bad format arg", self.0),
+                },
+            })
+            .collect()
+    }
+}
diff --git a/src/librustc_trait_selection/traits/project.rs b/src/librustc_trait_selection/traits/project.rs
new file mode 100644 (file)
index 0000000..1ad9157
--- /dev/null
@@ -0,0 +1,1515 @@
+//! Code for projecting associated types out of trait references.
+
+use super::elaborate_predicates;
+use super::specialization_graph;
+use super::translate_substs;
+use super::util;
+use super::MismatchedProjectionTypes;
+use super::Obligation;
+use super::ObligationCause;
+use super::PredicateObligation;
+use super::Selection;
+use super::SelectionContext;
+use super::SelectionError;
+use super::{Normalized, NormalizedTy, ProjectionCacheEntry, ProjectionCacheKey};
+use super::{VtableClosureData, VtableFnPointerData, VtableGeneratorData, VtableImplData};
+
+use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use crate::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime};
+use crate::traits::error_reporting::InferCtxtExt;
+use rustc::ty::fold::{TypeFoldable, TypeFolder};
+use rustc::ty::subst::{InternalSubsts, Subst};
+use rustc::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, WithConstness};
+use rustc_ast::ast::Ident;
+use rustc_errors::ErrorReported;
+use rustc_hir::def_id::DefId;
+use rustc_span::symbol::sym;
+use rustc_span::DUMMY_SP;
+
+pub use rustc::traits::Reveal;
+
+pub type PolyProjectionObligation<'tcx> = Obligation<'tcx, ty::PolyProjectionPredicate<'tcx>>;
+
+pub type ProjectionObligation<'tcx> = Obligation<'tcx, ty::ProjectionPredicate<'tcx>>;
+
+pub type ProjectionTyObligation<'tcx> = Obligation<'tcx, ty::ProjectionTy<'tcx>>;
+
+/// When attempting to resolve `<T as TraitRef>::Name` ...
+#[derive(Debug)]
+pub enum ProjectionTyError<'tcx> {
+    /// ...we found multiple sources of information and couldn't resolve the ambiguity.
+    TooManyCandidates,
+
+    /// ...an error occurred matching `T : TraitRef`
+    TraitSelectionError(SelectionError<'tcx>),
+}
+
+#[derive(PartialEq, Eq, Debug)]
+enum ProjectionTyCandidate<'tcx> {
+    // from a where-clause in the env or object type
+    ParamEnv(ty::PolyProjectionPredicate<'tcx>),
+
+    // from the definition of `Trait` when you have something like <<A as Trait>::B as Trait2>::C
+    TraitDef(ty::PolyProjectionPredicate<'tcx>),
+
+    // from a "impl" (or a "pseudo-impl" returned by select)
+    Select(Selection<'tcx>),
+}
+
+enum ProjectionTyCandidateSet<'tcx> {
+    None,
+    Single(ProjectionTyCandidate<'tcx>),
+    Ambiguous,
+    Error(SelectionError<'tcx>),
+}
+
+impl<'tcx> ProjectionTyCandidateSet<'tcx> {
+    fn mark_ambiguous(&mut self) {
+        *self = ProjectionTyCandidateSet::Ambiguous;
+    }
+
+    fn mark_error(&mut self, err: SelectionError<'tcx>) {
+        *self = ProjectionTyCandidateSet::Error(err);
+    }
+
+    // Returns true if the push was successful, or false if the candidate
+    // was discarded -- this could be because of ambiguity, or because
+    // a higher-priority candidate is already there.
+    fn push_candidate(&mut self, candidate: ProjectionTyCandidate<'tcx>) -> bool {
+        use self::ProjectionTyCandidate::*;
+        use self::ProjectionTyCandidateSet::*;
+
+        // This wacky variable is just used to try and
+        // make code readable and avoid confusing paths.
+        // It is assigned a "value" of `()` only on those
+        // paths in which we wish to convert `*self` to
+        // ambiguous (and return false, because the candidate
+        // was not used). On other paths, it is not assigned,
+        // and hence if those paths *could* reach the code that
+        // comes after the match, this fn would not compile.
+        let convert_to_ambiguous;
+
+        match self {
+            None => {
+                *self = Single(candidate);
+                return true;
+            }
+
+            Single(current) => {
+                // Duplicates can happen inside ParamEnv. In the case, we
+                // perform a lazy deduplication.
+                if current == &candidate {
+                    return false;
+                }
+
+                // Prefer where-clauses. As in select, if there are multiple
+                // candidates, we prefer where-clause candidates over impls.  This
+                // may seem a bit surprising, since impls are the source of
+                // "truth" in some sense, but in fact some of the impls that SEEM
+                // applicable are not, because of nested obligations. Where
+                // clauses are the safer choice. See the comment on
+                // `select::SelectionCandidate` and #21974 for more details.
+                match (current, candidate) {
+                    (ParamEnv(..), ParamEnv(..)) => convert_to_ambiguous = (),
+                    (ParamEnv(..), _) => return false,
+                    (_, ParamEnv(..)) => unreachable!(),
+                    (_, _) => convert_to_ambiguous = (),
+                }
+            }
+
+            Ambiguous | Error(..) => {
+                return false;
+            }
+        }
+
+        // We only ever get here when we moved from a single candidate
+        // to ambiguous.
+        let () = convert_to_ambiguous;
+        *self = Ambiguous;
+        false
+    }
+}
+
+/// Evaluates constraints of the form:
+///
+///     for<...> <T as Trait>::U == V
+///
+/// If successful, this may result in additional obligations. Also returns
+/// the projection cache key used to track these additional obligations.
+pub fn poly_project_and_unify_type<'cx, 'tcx>(
+    selcx: &mut SelectionContext<'cx, 'tcx>,
+    obligation: &PolyProjectionObligation<'tcx>,
+) -> Result<Option<Vec<PredicateObligation<'tcx>>>, MismatchedProjectionTypes<'tcx>> {
+    debug!("poly_project_and_unify_type(obligation={:?})", obligation);
+
+    let infcx = selcx.infcx();
+    infcx.commit_if_ok(|snapshot| {
+        let (placeholder_predicate, placeholder_map) =
+            infcx.replace_bound_vars_with_placeholders(&obligation.predicate);
+
+        let placeholder_obligation = obligation.with(placeholder_predicate);
+        let result = project_and_unify_type(selcx, &placeholder_obligation)?;
+        infcx
+            .leak_check(false, &placeholder_map, snapshot)
+            .map_err(|err| MismatchedProjectionTypes { err })?;
+        Ok(result)
+    })
+}
+
+/// Evaluates constraints of the form:
+///
+///     <T as Trait>::U == V
+///
+/// If successful, this may result in additional obligations.
+fn project_and_unify_type<'cx, 'tcx>(
+    selcx: &mut SelectionContext<'cx, 'tcx>,
+    obligation: &ProjectionObligation<'tcx>,
+) -> Result<Option<Vec<PredicateObligation<'tcx>>>, MismatchedProjectionTypes<'tcx>> {
+    debug!("project_and_unify_type(obligation={:?})", obligation);
+
+    let mut obligations = vec![];
+    let normalized_ty = match opt_normalize_projection_type(
+        selcx,
+        obligation.param_env,
+        obligation.predicate.projection_ty,
+        obligation.cause.clone(),
+        obligation.recursion_depth,
+        &mut obligations,
+    ) {
+        Some(n) => n,
+        None => return Ok(None),
+    };
+
+    debug!(
+        "project_and_unify_type: normalized_ty={:?} obligations={:?}",
+        normalized_ty, obligations
+    );
+
+    let infcx = selcx.infcx();
+    match infcx
+        .at(&obligation.cause, obligation.param_env)
+        .eq(normalized_ty, obligation.predicate.ty)
+    {
+        Ok(InferOk { obligations: inferred_obligations, value: () }) => {
+            obligations.extend(inferred_obligations);
+            Ok(Some(obligations))
+        }
+        Err(err) => {
+            debug!("project_and_unify_type: equating types encountered error {:?}", err);
+            Err(MismatchedProjectionTypes { err })
+        }
+    }
+}
+
+/// Normalizes any associated type projections in `value`, replacing
+/// them with a fully resolved type where possible. The return value
+/// combines the normalized result and any additional obligations that
+/// were incurred as result.
+pub fn normalize<'a, 'b, 'tcx, T>(
+    selcx: &'a mut SelectionContext<'b, 'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    cause: ObligationCause<'tcx>,
+    value: &T,
+) -> Normalized<'tcx, T>
+where
+    T: TypeFoldable<'tcx>,
+{
+    let mut obligations = Vec::new();
+    let value = normalize_to(selcx, param_env, cause, value, &mut obligations);
+    Normalized { value, obligations }
+}
+
+pub fn normalize_to<'a, 'b, 'tcx, T>(
+    selcx: &'a mut SelectionContext<'b, 'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    cause: ObligationCause<'tcx>,
+    value: &T,
+    obligations: &mut Vec<PredicateObligation<'tcx>>,
+) -> T
+where
+    T: TypeFoldable<'tcx>,
+{
+    normalize_with_depth_to(selcx, param_env, cause, 0, value, obligations)
+}
+
+/// As `normalize`, but with a custom depth.
+pub fn normalize_with_depth<'a, 'b, 'tcx, T>(
+    selcx: &'a mut SelectionContext<'b, 'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    cause: ObligationCause<'tcx>,
+    depth: usize,
+    value: &T,
+) -> Normalized<'tcx, T>
+where
+    T: TypeFoldable<'tcx>,
+{
+    let mut obligations = Vec::new();
+    let value = normalize_with_depth_to(selcx, param_env, cause, depth, value, &mut obligations);
+    Normalized { value, obligations }
+}
+
+pub fn normalize_with_depth_to<'a, 'b, 'tcx, T>(
+    selcx: &'a mut SelectionContext<'b, 'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    cause: ObligationCause<'tcx>,
+    depth: usize,
+    value: &T,
+    obligations: &mut Vec<PredicateObligation<'tcx>>,
+) -> T
+where
+    T: TypeFoldable<'tcx>,
+{
+    debug!("normalize_with_depth(depth={}, value={:?})", depth, value);
+    let mut normalizer = AssocTypeNormalizer::new(selcx, param_env, cause, depth, obligations);
+    let result = normalizer.fold(value);
+    debug!(
+        "normalize_with_depth: depth={} result={:?} with {} obligations",
+        depth,
+        result,
+        normalizer.obligations.len()
+    );
+    debug!("normalize_with_depth: depth={} obligations={:?}", depth, normalizer.obligations);
+    result
+}
+
+struct AssocTypeNormalizer<'a, 'b, 'tcx> {
+    selcx: &'a mut SelectionContext<'b, 'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    cause: ObligationCause<'tcx>,
+    obligations: &'a mut Vec<PredicateObligation<'tcx>>,
+    depth: usize,
+}
+
+impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> {
+    fn new(
+        selcx: &'a mut SelectionContext<'b, 'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+        cause: ObligationCause<'tcx>,
+        depth: usize,
+        obligations: &'a mut Vec<PredicateObligation<'tcx>>,
+    ) -> AssocTypeNormalizer<'a, 'b, 'tcx> {
+        AssocTypeNormalizer { selcx, param_env, cause, obligations, depth }
+    }
+
+    fn fold<T: TypeFoldable<'tcx>>(&mut self, value: &T) -> T {
+        let value = self.selcx.infcx().resolve_vars_if_possible(value);
+
+        if !value.has_projections() { value } else { value.fold_with(self) }
+    }
+}
+
+impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
+    fn tcx<'c>(&'c self) -> TyCtxt<'tcx> {
+        self.selcx.tcx()
+    }
+
+    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
+        if !ty.has_projections() {
+            return ty;
+        }
+        // We don't want to normalize associated types that occur inside of region
+        // binders, because they may contain bound regions, and we can't cope with that.
+        //
+        // Example:
+        //
+        //     for<'a> fn(<T as Foo<&'a>>::A)
+        //
+        // Instead of normalizing `<T as Foo<&'a>>::A` here, we'll
+        // normalize it when we instantiate those bound regions (which
+        // should occur eventually).
+
+        let ty = ty.super_fold_with(self);
+        match ty.kind {
+            ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => {
+                // (*)
+                // Only normalize `impl Trait` after type-checking, usually in codegen.
+                match self.param_env.reveal {
+                    Reveal::UserFacing => ty,
+
+                    Reveal::All => {
+                        let recursion_limit = *self.tcx().sess.recursion_limit.get();
+                        if self.depth >= recursion_limit {
+                            let obligation = Obligation::with_depth(
+                                self.cause.clone(),
+                                recursion_limit,
+                                self.param_env,
+                                ty,
+                            );
+                            self.selcx.infcx().report_overflow_error(&obligation, true);
+                        }
+
+                        let generic_ty = self.tcx().type_of(def_id);
+                        let concrete_ty = generic_ty.subst(self.tcx(), substs);
+                        self.depth += 1;
+                        let folded_ty = self.fold_ty(concrete_ty);
+                        self.depth -= 1;
+                        folded_ty
+                    }
+                }
+            }
+
+            ty::Projection(ref data) if !data.has_escaping_bound_vars() => {
+                // (*)
+
+                // (*) This is kind of hacky -- we need to be able to
+                // handle normalization within binders because
+                // otherwise we wind up a need to normalize when doing
+                // trait matching (since you can have a trait
+                // obligation like `for<'a> T::B : Fn(&'a int)`), but
+                // we can't normalize with bound regions in scope. So
+                // far now we just ignore binders but only normalize
+                // if all bound regions are gone (and then we still
+                // have to renormalize whenever we instantiate a
+                // binder). It would be better to normalize in a
+                // binding-aware fashion.
+
+                let normalized_ty = normalize_projection_type(
+                    self.selcx,
+                    self.param_env,
+                    *data,
+                    self.cause.clone(),
+                    self.depth,
+                    &mut self.obligations,
+                );
+                debug!(
+                    "AssocTypeNormalizer: depth={} normalized {:?} to {:?}, \
+                     now with {} obligations",
+                    self.depth,
+                    ty,
+                    normalized_ty,
+                    self.obligations.len()
+                );
+                normalized_ty
+            }
+
+            _ => ty,
+        }
+    }
+
+    fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
+        constant.eval(self.selcx.tcx(), self.param_env)
+    }
+}
+
+/// The guts of `normalize`: normalize a specific projection like `<T
+/// as Trait>::Item`. The result is always a type (and possibly
+/// additional obligations). If ambiguity arises, which implies that
+/// there are unresolved type variables in the projection, we will
+/// substitute a fresh type variable `$X` and generate a new
+/// obligation `<T as Trait>::Item == $X` for later.
+pub fn normalize_projection_type<'a, 'b, 'tcx>(
+    selcx: &'a mut SelectionContext<'b, 'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    projection_ty: ty::ProjectionTy<'tcx>,
+    cause: ObligationCause<'tcx>,
+    depth: usize,
+    obligations: &mut Vec<PredicateObligation<'tcx>>,
+) -> Ty<'tcx> {
+    opt_normalize_projection_type(
+        selcx,
+        param_env,
+        projection_ty,
+        cause.clone(),
+        depth,
+        obligations,
+    )
+    .unwrap_or_else(move || {
+        // if we bottom out in ambiguity, create a type variable
+        // and a deferred predicate to resolve this when more type
+        // information is available.
+
+        let tcx = selcx.infcx().tcx;
+        let def_id = projection_ty.item_def_id;
+        let ty_var = selcx.infcx().next_ty_var(TypeVariableOrigin {
+            kind: TypeVariableOriginKind::NormalizeProjectionType,
+            span: tcx.def_span(def_id),
+        });
+        let projection = ty::Binder::dummy(ty::ProjectionPredicate { projection_ty, ty: ty_var });
+        let obligation =
+            Obligation::with_depth(cause, depth + 1, param_env, projection.to_predicate());
+        obligations.push(obligation);
+        ty_var
+    })
+}
+
+/// The guts of `normalize`: normalize a specific projection like `<T
+/// as Trait>::Item`. The result is always a type (and possibly
+/// additional obligations). Returns `None` in the case of ambiguity,
+/// which indicates that there are unbound type variables.
+///
+/// This function used to return `Option<NormalizedTy<'tcx>>`, which contains a
+/// `Ty<'tcx>` and an obligations vector. But that obligation vector was very
+/// often immediately appended to another obligations vector. So now this
+/// function takes an obligations vector and appends to it directly, which is
+/// slightly uglier but avoids the need for an extra short-lived allocation.
+fn opt_normalize_projection_type<'a, 'b, 'tcx>(
+    selcx: &'a mut SelectionContext<'b, 'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    projection_ty: ty::ProjectionTy<'tcx>,
+    cause: ObligationCause<'tcx>,
+    depth: usize,
+    obligations: &mut Vec<PredicateObligation<'tcx>>,
+) -> Option<Ty<'tcx>> {
+    let infcx = selcx.infcx();
+
+    let projection_ty = infcx.resolve_vars_if_possible(&projection_ty);
+    let cache_key = ProjectionCacheKey::new(projection_ty);
+
+    debug!(
+        "opt_normalize_projection_type(\
+         projection_ty={:?}, \
+         depth={})",
+        projection_ty, depth
+    );
+
+    // FIXME(#20304) For now, I am caching here, which is good, but it
+    // means we don't capture the type variables that are created in
+    // the case of ambiguity. Which means we may create a large stream
+    // of such variables. OTOH, if we move the caching up a level, we
+    // would not benefit from caching when proving `T: Trait<U=Foo>`
+    // bounds. It might be the case that we want two distinct caches,
+    // or else another kind of cache entry.
+
+    let cache_result = infcx.inner.borrow_mut().projection_cache.try_start(cache_key);
+    match cache_result {
+        Ok(()) => {}
+        Err(ProjectionCacheEntry::Ambiguous) => {
+            // If we found ambiguity the last time, that means we will continue
+            // to do so until some type in the key changes (and we know it
+            // hasn't, because we just fully resolved it).
+            debug!(
+                "opt_normalize_projection_type: \
+                 found cache entry: ambiguous"
+            );
+            return None;
+        }
+        Err(ProjectionCacheEntry::InProgress) => {
+            // If while normalized A::B, we are asked to normalize
+            // A::B, just return A::B itself. This is a conservative
+            // answer, in the sense that A::B *is* clearly equivalent
+            // to A::B, though there may be a better value we can
+            // find.
+
+            // Under lazy normalization, this can arise when
+            // bootstrapping.  That is, imagine an environment with a
+            // where-clause like `A::B == u32`. Now, if we are asked
+            // to normalize `A::B`, we will want to check the
+            // where-clauses in scope. So we will try to unify `A::B`
+            // with `A::B`, which can trigger a recursive
+            // normalization. In that case, I think we will want this code:
+            //
+            // ```
+            // let ty = selcx.tcx().mk_projection(projection_ty.item_def_id,
+            //                                    projection_ty.substs;
+            // return Some(NormalizedTy { value: v, obligations: vec![] });
+            // ```
+
+            debug!(
+                "opt_normalize_projection_type: \
+                 found cache entry: in-progress"
+            );
+
+            // But for now, let's classify this as an overflow:
+            let recursion_limit = *selcx.tcx().sess.recursion_limit.get();
+            let obligation =
+                Obligation::with_depth(cause, recursion_limit, param_env, projection_ty);
+            selcx.infcx().report_overflow_error(&obligation, false);
+        }
+        Err(ProjectionCacheEntry::NormalizedTy(ty)) => {
+            // This is the hottest path in this function.
+            //
+            // If we find the value in the cache, then return it along
+            // with the obligations that went along with it. Note
+            // that, when using a fulfillment context, these
+            // obligations could in principle be ignored: they have
+            // already been registered when the cache entry was
+            // created (and hence the new ones will quickly be
+            // discarded as duplicated). But when doing trait
+            // evaluation this is not the case, and dropping the trait
+            // evaluations can causes ICEs (e.g., #43132).
+            debug!(
+                "opt_normalize_projection_type: \
+                 found normalized ty `{:?}`",
+                ty
+            );
+
+            // Once we have inferred everything we need to know, we
+            // can ignore the `obligations` from that point on.
+            if infcx.unresolved_type_vars(&ty.value).is_none() {
+                infcx.inner.borrow_mut().projection_cache.complete_normalized(cache_key, &ty);
+            // No need to extend `obligations`.
+            } else {
+                obligations.extend(ty.obligations);
+            }
+
+            obligations.push(get_paranoid_cache_value_obligation(
+                infcx,
+                param_env,
+                projection_ty,
+                cause,
+                depth,
+            ));
+            return Some(ty.value);
+        }
+        Err(ProjectionCacheEntry::Error) => {
+            debug!(
+                "opt_normalize_projection_type: \
+                 found error"
+            );
+            let result = normalize_to_error(selcx, param_env, projection_ty, cause, depth);
+            obligations.extend(result.obligations);
+            return Some(result.value);
+        }
+    }
+
+    let obligation = Obligation::with_depth(cause.clone(), depth, param_env, projection_ty);
+    match project_type(selcx, &obligation) {
+        Ok(ProjectedTy::Progress(Progress {
+            ty: projected_ty,
+            obligations: mut projected_obligations,
+        })) => {
+            // if projection succeeded, then what we get out of this
+            // is also non-normalized (consider: it was derived from
+            // an impl, where-clause etc) and hence we must
+            // re-normalize it
+
+            debug!(
+                "opt_normalize_projection_type: \
+                 projected_ty={:?} \
+                 depth={} \
+                 projected_obligations={:?}",
+                projected_ty, depth, projected_obligations
+            );
+
+            let result = if projected_ty.has_projections() {
+                let mut normalizer = AssocTypeNormalizer::new(
+                    selcx,
+                    param_env,
+                    cause,
+                    depth + 1,
+                    &mut projected_obligations,
+                );
+                let normalized_ty = normalizer.fold(&projected_ty);
+
+                debug!(
+                    "opt_normalize_projection_type: \
+                     normalized_ty={:?} depth={}",
+                    normalized_ty, depth
+                );
+
+                Normalized { value: normalized_ty, obligations: projected_obligations }
+            } else {
+                Normalized { value: projected_ty, obligations: projected_obligations }
+            };
+
+            let cache_value = prune_cache_value_obligations(infcx, &result);
+            infcx.inner.borrow_mut().projection_cache.insert_ty(cache_key, cache_value);
+            obligations.extend(result.obligations);
+            Some(result.value)
+        }
+        Ok(ProjectedTy::NoProgress(projected_ty)) => {
+            debug!(
+                "opt_normalize_projection_type: \
+                 projected_ty={:?} no progress",
+                projected_ty
+            );
+            let result = Normalized { value: projected_ty, obligations: vec![] };
+            infcx.inner.borrow_mut().projection_cache.insert_ty(cache_key, result.clone());
+            // No need to extend `obligations`.
+            Some(result.value)
+        }
+        Err(ProjectionTyError::TooManyCandidates) => {
+            debug!(
+                "opt_normalize_projection_type: \
+                 too many candidates"
+            );
+            infcx.inner.borrow_mut().projection_cache.ambiguous(cache_key);
+            None
+        }
+        Err(ProjectionTyError::TraitSelectionError(_)) => {
+            debug!("opt_normalize_projection_type: ERROR");
+            // if we got an error processing the `T as Trait` part,
+            // just return `ty::err` but add the obligation `T :
+            // Trait`, which when processed will cause the error to be
+            // reported later
+
+            infcx.inner.borrow_mut().projection_cache.error(cache_key);
+            let result = normalize_to_error(selcx, param_env, projection_ty, cause, depth);
+            obligations.extend(result.obligations);
+            Some(result.value)
+        }
+    }
+}
+
+/// If there are unresolved type variables, then we need to include
+/// any subobligations that bind them, at least until those type
+/// variables are fully resolved.
+fn prune_cache_value_obligations<'a, 'tcx>(
+    infcx: &'a InferCtxt<'a, 'tcx>,
+    result: &NormalizedTy<'tcx>,
+) -> NormalizedTy<'tcx> {
+    if infcx.unresolved_type_vars(&result.value).is_none() {
+        return NormalizedTy { value: result.value, obligations: vec![] };
+    }
+
+    let mut obligations: Vec<_> = result
+        .obligations
+        .iter()
+        .filter(|obligation| match obligation.predicate {
+            // We found a `T: Foo<X = U>` predicate, let's check
+            // if `U` references any unresolved type
+            // variables. In principle, we only care if this
+            // projection can help resolve any of the type
+            // variables found in `result.value` -- but we just
+            // check for any type variables here, for fear of
+            // indirect obligations (e.g., we project to `?0`,
+            // but we have `T: Foo<X = ?1>` and `?1: Bar<X =
+            // ?0>`).
+            ty::Predicate::Projection(ref data) => infcx.unresolved_type_vars(&data.ty()).is_some(),
+
+            // We are only interested in `T: Foo<X = U>` predicates, whre
+            // `U` references one of `unresolved_type_vars`. =)
+            _ => false,
+        })
+        .cloned()
+        .collect();
+
+    obligations.shrink_to_fit();
+
+    NormalizedTy { value: result.value, obligations }
+}
+
+/// Whenever we give back a cache result for a projection like `<T as
+/// Trait>::Item ==> X`, we *always* include the obligation to prove
+/// that `T: Trait` (we may also include some other obligations). This
+/// may or may not be necessary -- in principle, all the obligations
+/// that must be proven to show that `T: Trait` were also returned
+/// when the cache was first populated. But there are some vague concerns,
+/// and so we take the precautionary measure of including `T: Trait` in
+/// the result:
+///
+/// Concern #1. The current setup is fragile. Perhaps someone could
+/// have failed to prove the concerns from when the cache was
+/// populated, but also not have used a snapshot, in which case the
+/// cache could remain populated even though `T: Trait` has not been
+/// shown. In this case, the "other code" is at fault -- when you
+/// project something, you are supposed to either have a snapshot or
+/// else prove all the resulting obligations -- but it's still easy to
+/// get wrong.
+///
+/// Concern #2. Even within the snapshot, if those original
+/// obligations are not yet proven, then we are able to do projections
+/// that may yet turn out to be wrong. This *may* lead to some sort
+/// of trouble, though we don't have a concrete example of how that
+/// can occur yet. But it seems risky at best.
+fn get_paranoid_cache_value_obligation<'a, 'tcx>(
+    infcx: &'a InferCtxt<'a, 'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    projection_ty: ty::ProjectionTy<'tcx>,
+    cause: ObligationCause<'tcx>,
+    depth: usize,
+) -> PredicateObligation<'tcx> {
+    let trait_ref = projection_ty.trait_ref(infcx.tcx).to_poly_trait_ref();
+    Obligation {
+        cause,
+        recursion_depth: depth,
+        param_env,
+        predicate: trait_ref.without_const().to_predicate(),
+    }
+}
+
+/// If we are projecting `<T as Trait>::Item`, but `T: Trait` does not
+/// hold. In various error cases, we cannot generate a valid
+/// normalized projection. Therefore, we create an inference variable
+/// return an associated obligation that, when fulfilled, will lead to
+/// an error.
+///
+/// Note that we used to return `Error` here, but that was quite
+/// dubious -- the premise was that an error would *eventually* be
+/// reported, when the obligation was processed. But in general once
+/// you see a `Error` you are supposed to be able to assume that an
+/// error *has been* reported, so that you can take whatever heuristic
+/// paths you want to take. To make things worse, it was possible for
+/// cycles to arise, where you basically had a setup like `<MyType<$0>
+/// as Trait>::Foo == $0`. Here, normalizing `<MyType<$0> as
+/// Trait>::Foo> to `[type error]` would lead to an obligation of
+/// `<MyType<[type error]> as Trait>::Foo`. We are supposed to report
+/// an error for this obligation, but we legitimately should not,
+/// because it contains `[type error]`. Yuck! (See issue #29857 for
+/// one case where this arose.)
+fn normalize_to_error<'a, 'tcx>(
+    selcx: &mut SelectionContext<'a, 'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    projection_ty: ty::ProjectionTy<'tcx>,
+    cause: ObligationCause<'tcx>,
+    depth: usize,
+) -> NormalizedTy<'tcx> {
+    let trait_ref = projection_ty.trait_ref(selcx.tcx()).to_poly_trait_ref();
+    let trait_obligation = Obligation {
+        cause,
+        recursion_depth: depth,
+        param_env,
+        predicate: trait_ref.without_const().to_predicate(),
+    };
+    let tcx = selcx.infcx().tcx;
+    let def_id = projection_ty.item_def_id;
+    let new_value = selcx.infcx().next_ty_var(TypeVariableOrigin {
+        kind: TypeVariableOriginKind::NormalizeProjectionType,
+        span: tcx.def_span(def_id),
+    });
+    Normalized { value: new_value, obligations: vec![trait_obligation] }
+}
+
+enum ProjectedTy<'tcx> {
+    Progress(Progress<'tcx>),
+    NoProgress(Ty<'tcx>),
+}
+
+struct Progress<'tcx> {
+    ty: Ty<'tcx>,
+    obligations: Vec<PredicateObligation<'tcx>>,
+}
+
+impl<'tcx> Progress<'tcx> {
+    fn error(tcx: TyCtxt<'tcx>) -> Self {
+        Progress { ty: tcx.types.err, obligations: vec![] }
+    }
+
+    fn with_addl_obligations(mut self, mut obligations: Vec<PredicateObligation<'tcx>>) -> Self {
+        debug!(
+            "with_addl_obligations: self.obligations.len={} obligations.len={}",
+            self.obligations.len(),
+            obligations.len()
+        );
+
+        debug!(
+            "with_addl_obligations: self.obligations={:?} obligations={:?}",
+            self.obligations, obligations
+        );
+
+        self.obligations.append(&mut obligations);
+        self
+    }
+}
+
+/// Computes the result of a projection type (if we can).
+///
+/// IMPORTANT:
+/// - `obligation` must be fully normalized
+fn project_type<'cx, 'tcx>(
+    selcx: &mut SelectionContext<'cx, 'tcx>,
+    obligation: &ProjectionTyObligation<'tcx>,
+) -> Result<ProjectedTy<'tcx>, ProjectionTyError<'tcx>> {
+    debug!("project(obligation={:?})", obligation);
+
+    let recursion_limit = *selcx.tcx().sess.recursion_limit.get();
+    if obligation.recursion_depth >= recursion_limit {
+        debug!("project: overflow!");
+        return Err(ProjectionTyError::TraitSelectionError(SelectionError::Overflow));
+    }
+
+    let obligation_trait_ref = &obligation.predicate.trait_ref(selcx.tcx());
+
+    debug!("project: obligation_trait_ref={:?}", obligation_trait_ref);
+
+    if obligation_trait_ref.references_error() {
+        return Ok(ProjectedTy::Progress(Progress::error(selcx.tcx())));
+    }
+
+    let mut candidates = ProjectionTyCandidateSet::None;
+
+    // Make sure that the following procedures are kept in order. ParamEnv
+    // needs to be first because it has highest priority, and Select checks
+    // the return value of push_candidate which assumes it's ran at last.
+    assemble_candidates_from_param_env(selcx, obligation, &obligation_trait_ref, &mut candidates);
+
+    assemble_candidates_from_trait_def(selcx, obligation, &obligation_trait_ref, &mut candidates);
+
+    assemble_candidates_from_impls(selcx, obligation, &obligation_trait_ref, &mut candidates);
+
+    match candidates {
+        ProjectionTyCandidateSet::Single(candidate) => Ok(ProjectedTy::Progress(
+            confirm_candidate(selcx, obligation, &obligation_trait_ref, candidate),
+        )),
+        ProjectionTyCandidateSet::None => Ok(ProjectedTy::NoProgress(
+            selcx
+                .tcx()
+                .mk_projection(obligation.predicate.item_def_id, obligation.predicate.substs),
+        )),
+        // Error occurred while trying to processing impls.
+        ProjectionTyCandidateSet::Error(e) => Err(ProjectionTyError::TraitSelectionError(e)),
+        // Inherent ambiguity that prevents us from even enumerating the
+        // candidates.
+        ProjectionTyCandidateSet::Ambiguous => Err(ProjectionTyError::TooManyCandidates),
+    }
+}
+
+/// The first thing we have to do is scan through the parameter
+/// environment to see whether there are any projection predicates
+/// there that can answer this question.
+fn assemble_candidates_from_param_env<'cx, 'tcx>(
+    selcx: &mut SelectionContext<'cx, 'tcx>,
+    obligation: &ProjectionTyObligation<'tcx>,
+    obligation_trait_ref: &ty::TraitRef<'tcx>,
+    candidate_set: &mut ProjectionTyCandidateSet<'tcx>,
+) {
+    debug!("assemble_candidates_from_param_env(..)");
+    assemble_candidates_from_predicates(
+        selcx,
+        obligation,
+        obligation_trait_ref,
+        candidate_set,
+        ProjectionTyCandidate::ParamEnv,
+        obligation.param_env.caller_bounds.iter().cloned(),
+    );
+}
+
+/// In the case of a nested projection like <<A as Foo>::FooT as Bar>::BarT, we may find
+/// that the definition of `Foo` has some clues:
+///
+/// ```
+/// trait Foo {
+///     type FooT : Bar<BarT=i32>
+/// }
+/// ```
+///
+/// Here, for example, we could conclude that the result is `i32`.
+fn assemble_candidates_from_trait_def<'cx, 'tcx>(
+    selcx: &mut SelectionContext<'cx, 'tcx>,
+    obligation: &ProjectionTyObligation<'tcx>,
+    obligation_trait_ref: &ty::TraitRef<'tcx>,
+    candidate_set: &mut ProjectionTyCandidateSet<'tcx>,
+) {
+    debug!("assemble_candidates_from_trait_def(..)");
+
+    let tcx = selcx.tcx();
+    // Check whether the self-type is itself a projection.
+    let (def_id, substs) = match obligation_trait_ref.self_ty().kind {
+        ty::Projection(ref data) => (data.trait_ref(tcx).def_id, data.substs),
+        ty::Opaque(def_id, substs) => (def_id, substs),
+        ty::Infer(ty::TyVar(_)) => {
+            // If the self-type is an inference variable, then it MAY wind up
+            // being a projected type, so induce an ambiguity.
+            candidate_set.mark_ambiguous();
+            return;
+        }
+        _ => return,
+    };
+
+    // If so, extract what we know from the trait and try to come up with a good answer.
+    let trait_predicates = tcx.predicates_of(def_id);
+    let bounds = trait_predicates.instantiate(tcx, substs);
+    let bounds = elaborate_predicates(tcx, bounds.predicates);
+    assemble_candidates_from_predicates(
+        selcx,
+        obligation,
+        obligation_trait_ref,
+        candidate_set,
+        ProjectionTyCandidate::TraitDef,
+        bounds,
+    )
+}
+
+fn assemble_candidates_from_predicates<'cx, 'tcx, I>(
+    selcx: &mut SelectionContext<'cx, 'tcx>,
+    obligation: &ProjectionTyObligation<'tcx>,
+    obligation_trait_ref: &ty::TraitRef<'tcx>,
+    candidate_set: &mut ProjectionTyCandidateSet<'tcx>,
+    ctor: fn(ty::PolyProjectionPredicate<'tcx>) -> ProjectionTyCandidate<'tcx>,
+    env_predicates: I,
+) where
+    I: IntoIterator<Item = ty::Predicate<'tcx>>,
+{
+    debug!("assemble_candidates_from_predicates(obligation={:?})", obligation);
+    let infcx = selcx.infcx();
+    for predicate in env_predicates {
+        debug!("assemble_candidates_from_predicates: predicate={:?}", predicate);
+        if let ty::Predicate::Projection(data) = predicate {
+            let same_def_id = data.projection_def_id() == obligation.predicate.item_def_id;
+
+            let is_match = same_def_id
+                && infcx.probe(|_| {
+                    let data_poly_trait_ref = data.to_poly_trait_ref(infcx.tcx);
+                    let obligation_poly_trait_ref = obligation_trait_ref.to_poly_trait_ref();
+                    infcx
+                        .at(&obligation.cause, obligation.param_env)
+                        .sup(obligation_poly_trait_ref, data_poly_trait_ref)
+                        .map(|InferOk { obligations: _, value: () }| {
+                            // FIXME(#32730) -- do we need to take obligations
+                            // into account in any way? At the moment, no.
+                        })
+                        .is_ok()
+                });
+
+            debug!(
+                "assemble_candidates_from_predicates: candidate={:?} \
+                 is_match={} same_def_id={}",
+                data, is_match, same_def_id
+            );
+
+            if is_match {
+                candidate_set.push_candidate(ctor(data));
+            }
+        }
+    }
+}
+
+fn assemble_candidates_from_impls<'cx, 'tcx>(
+    selcx: &mut SelectionContext<'cx, 'tcx>,
+    obligation: &ProjectionTyObligation<'tcx>,
+    obligation_trait_ref: &ty::TraitRef<'tcx>,
+    candidate_set: &mut ProjectionTyCandidateSet<'tcx>,
+) {
+    // If we are resolving `<T as TraitRef<...>>::Item == Type`,
+    // start out by selecting the predicate `T as TraitRef<...>`:
+    let poly_trait_ref = obligation_trait_ref.to_poly_trait_ref();
+    let trait_obligation = obligation.with(poly_trait_ref.to_poly_trait_predicate());
+    let _ = selcx.infcx().commit_if_ok(|_| {
+        let vtable = match selcx.select(&trait_obligation) {
+            Ok(Some(vtable)) => vtable,
+            Ok(None) => {
+                candidate_set.mark_ambiguous();
+                return Err(());
+            }
+            Err(e) => {
+                debug!("assemble_candidates_from_impls: selection error {:?}", e);
+                candidate_set.mark_error(e);
+                return Err(());
+            }
+        };
+
+        let eligible = match &vtable {
+            super::VtableClosure(_)
+            | super::VtableGenerator(_)
+            | super::VtableFnPointer(_)
+            | super::VtableObject(_)
+            | super::VtableTraitAlias(_) => {
+                debug!("assemble_candidates_from_impls: vtable={:?}", vtable);
+                true
+            }
+            super::VtableImpl(impl_data) => {
+                // We have to be careful when projecting out of an
+                // impl because of specialization. If we are not in
+                // codegen (i.e., projection mode is not "any"), and the
+                // impl's type is declared as default, then we disable
+                // projection (even if the trait ref is fully
+                // monomorphic). In the case where trait ref is not
+                // fully monomorphic (i.e., includes type parameters),
+                // this is because those type parameters may
+                // ultimately be bound to types from other crates that
+                // may have specialized impls we can't see. In the
+                // case where the trait ref IS fully monomorphic, this
+                // is a policy decision that we made in the RFC in
+                // order to preserve flexibility for the crate that
+                // defined the specializable impl to specialize later
+                // for existing types.
+                //
+                // In either case, we handle this by not adding a
+                // candidate for an impl if it contains a `default`
+                // type.
+                //
+                // NOTE: This should be kept in sync with the similar code in
+                // `rustc::ty::instance::resolve_associated_item()`.
+                let node_item =
+                    assoc_ty_def(selcx, impl_data.impl_def_id, obligation.predicate.item_def_id)
+                        .map_err(|ErrorReported| ())?;
+
+                let is_default = if node_item.node.is_from_trait() {
+                    // If true, the impl inherited a `type Foo = Bar`
+                    // given in the trait, which is implicitly default.
+                    // Otherwise, the impl did not specify `type` and
+                    // neither did the trait:
+                    //
+                    // ```rust
+                    // trait Foo { type T; }
+                    // impl Foo for Bar { }
+                    // ```
+                    //
+                    // This is an error, but it will be
+                    // reported in `check_impl_items_against_trait`.
+                    // We accept it here but will flag it as
+                    // an error when we confirm the candidate
+                    // (which will ultimately lead to `normalize_to_error`
+                    // being invoked).
+                    false
+                } else {
+                    // If we're looking at a trait *impl*, the item is
+                    // specializable if the impl or the item are marked
+                    // `default`.
+                    node_item.item.defaultness.is_default()
+                        || super::util::impl_is_default(selcx.tcx(), node_item.node.def_id())
+                };
+
+                match is_default {
+                    // Non-specializable items are always projectable
+                    false => true,
+
+                    // Only reveal a specializable default if we're past type-checking
+                    // and the obligation is monomorphic, otherwise passes such as
+                    // transmute checking and polymorphic MIR optimizations could
+                    // get a result which isn't correct for all monomorphizations.
+                    true if obligation.param_env.reveal == Reveal::All => {
+                        // NOTE(eddyb) inference variables can resolve to parameters, so
+                        // assume `poly_trait_ref` isn't monomorphic, if it contains any.
+                        let poly_trait_ref =
+                            selcx.infcx().resolve_vars_if_possible(&poly_trait_ref);
+                        !poly_trait_ref.needs_infer() && !poly_trait_ref.needs_subst()
+                    }
+
+                    true => {
+                        debug!(
+                            "assemble_candidates_from_impls: not eligible due to default: \
+                             assoc_ty={} predicate={}",
+                            selcx.tcx().def_path_str(node_item.item.def_id),
+                            obligation.predicate,
+                        );
+                        false
+                    }
+                }
+            }
+            super::VtableParam(..) => {
+                // This case tell us nothing about the value of an
+                // associated type. Consider:
+                //
+                // ```
+                // trait SomeTrait { type Foo; }
+                // fn foo<T:SomeTrait>(...) { }
+                // ```
+                //
+                // If the user writes `<T as SomeTrait>::Foo`, then the `T
+                // : SomeTrait` binding does not help us decide what the
+                // type `Foo` is (at least, not more specifically than
+                // what we already knew).
+                //
+                // But wait, you say! What about an example like this:
+                //
+                // ```
+                // fn bar<T:SomeTrait<Foo=usize>>(...) { ... }
+                // ```
+                //
+                // Doesn't the `T : Sometrait<Foo=usize>` predicate help
+                // resolve `T::Foo`? And of course it does, but in fact
+                // that single predicate is desugared into two predicates
+                // in the compiler: a trait predicate (`T : SomeTrait`) and a
+                // projection. And the projection where clause is handled
+                // in `assemble_candidates_from_param_env`.
+                false
+            }
+            super::VtableAutoImpl(..) | super::VtableBuiltin(..) => {
+                // These traits have no associated types.
+                span_bug!(
+                    obligation.cause.span,
+                    "Cannot project an associated type from `{:?}`",
+                    vtable
+                );
+            }
+        };
+
+        if eligible {
+            if candidate_set.push_candidate(ProjectionTyCandidate::Select(vtable)) {
+                Ok(())
+            } else {
+                Err(())
+            }
+        } else {
+            Err(())
+        }
+    });
+}
+
+fn confirm_candidate<'cx, 'tcx>(
+    selcx: &mut SelectionContext<'cx, 'tcx>,
+    obligation: &ProjectionTyObligation<'tcx>,
+    obligation_trait_ref: &ty::TraitRef<'tcx>,
+    candidate: ProjectionTyCandidate<'tcx>,
+) -> Progress<'tcx> {
+    debug!("confirm_candidate(candidate={:?}, obligation={:?})", candidate, obligation);
+
+    match candidate {
+        ProjectionTyCandidate::ParamEnv(poly_projection)
+        | ProjectionTyCandidate::TraitDef(poly_projection) => {
+            confirm_param_env_candidate(selcx, obligation, poly_projection)
+        }
+
+        ProjectionTyCandidate::Select(vtable) => {
+            confirm_select_candidate(selcx, obligation, obligation_trait_ref, vtable)
+        }
+    }
+}
+
+fn confirm_select_candidate<'cx, 'tcx>(
+    selcx: &mut SelectionContext<'cx, 'tcx>,
+    obligation: &ProjectionTyObligation<'tcx>,
+    obligation_trait_ref: &ty::TraitRef<'tcx>,
+    vtable: Selection<'tcx>,
+) -> Progress<'tcx> {
+    match vtable {
+        super::VtableImpl(data) => confirm_impl_candidate(selcx, obligation, data),
+        super::VtableGenerator(data) => confirm_generator_candidate(selcx, obligation, data),
+        super::VtableClosure(data) => confirm_closure_candidate(selcx, obligation, data),
+        super::VtableFnPointer(data) => confirm_fn_pointer_candidate(selcx, obligation, data),
+        super::VtableObject(_) => confirm_object_candidate(selcx, obligation, obligation_trait_ref),
+        super::VtableAutoImpl(..)
+        | super::VtableParam(..)
+        | super::VtableBuiltin(..)
+        | super::VtableTraitAlias(..) =>
+        // we don't create Select candidates with this kind of resolution
+        {
+            span_bug!(
+                obligation.cause.span,
+                "Cannot project an associated type from `{:?}`",
+                vtable
+            )
+        }
+    }
+}
+
+fn confirm_object_candidate<'cx, 'tcx>(
+    selcx: &mut SelectionContext<'cx, 'tcx>,
+    obligation: &ProjectionTyObligation<'tcx>,
+    obligation_trait_ref: &ty::TraitRef<'tcx>,
+) -> Progress<'tcx> {
+    let self_ty = obligation_trait_ref.self_ty();
+    let object_ty = selcx.infcx().shallow_resolve(self_ty);
+    debug!("confirm_object_candidate(object_ty={:?})", object_ty);
+    let data = match object_ty.kind {
+        ty::Dynamic(ref data, ..) => data,
+        _ => span_bug!(
+            obligation.cause.span,
+            "confirm_object_candidate called with non-object: {:?}",
+            object_ty
+        ),
+    };
+    let env_predicates = data
+        .projection_bounds()
+        .map(|p| p.with_self_ty(selcx.tcx(), object_ty).to_predicate())
+        .collect();
+    let env_predicate = {
+        let env_predicates = elaborate_predicates(selcx.tcx(), env_predicates);
+
+        // select only those projections that are actually projecting an
+        // item with the correct name
+        let env_predicates = env_predicates.filter_map(|p| match p {
+            ty::Predicate::Projection(data) => {
+                if data.projection_def_id() == obligation.predicate.item_def_id {
+                    Some(data)
+                } else {
+                    None
+                }
+            }
+            _ => None,
+        });
+
+        // select those with a relevant trait-ref
+        let mut env_predicates = env_predicates.filter(|data| {
+            let data_poly_trait_ref = data.to_poly_trait_ref(selcx.tcx());
+            let obligation_poly_trait_ref = obligation_trait_ref.to_poly_trait_ref();
+            selcx.infcx().probe(|_| {
+                selcx
+                    .infcx()
+                    .at(&obligation.cause, obligation.param_env)
+                    .sup(obligation_poly_trait_ref, data_poly_trait_ref)
+                    .is_ok()
+            })
+        });
+
+        // select the first matching one; there really ought to be one or
+        // else the object type is not WF, since an object type should
+        // include all of its projections explicitly
+        match env_predicates.next() {
+            Some(env_predicate) => env_predicate,
+            None => {
+                debug!(
+                    "confirm_object_candidate: no env-predicate \
+                     found in object type `{:?}`; ill-formed",
+                    object_ty
+                );
+                return Progress::error(selcx.tcx());
+            }
+        }
+    };
+
+    confirm_param_env_candidate(selcx, obligation, env_predicate)
+}
+
+fn confirm_generator_candidate<'cx, 'tcx>(
+    selcx: &mut SelectionContext<'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 Normalized { value: gen_sig, obligations } = normalize_with_depth(
+        selcx,
+        obligation.param_env,
+        obligation.cause.clone(),
+        obligation.recursion_depth + 1,
+        &gen_sig,
+    );
+
+    debug!(
+        "confirm_generator_candidate: obligation={:?},gen_sig={:?},obligations={:?}",
+        obligation, gen_sig, obligations
+    );
+
+    let tcx = selcx.tcx();
+
+    let gen_def_id = tcx.lang_items().gen_trait().unwrap();
+
+    let predicate = super::util::generator_trait_ref_and_outputs(
+        tcx,
+        gen_def_id,
+        obligation.predicate.self_ty(),
+        gen_sig,
+    )
+    .map_bound(|(trait_ref, yield_ty, return_ty)| {
+        let name = tcx.associated_item(obligation.predicate.item_def_id).ident.name;
+        let ty = if name == sym::Return {
+            return_ty
+        } else if name == sym::Yield {
+            yield_ty
+        } else {
+            bug!()
+        };
+
+        ty::ProjectionPredicate {
+            projection_ty: ty::ProjectionTy {
+                substs: trait_ref.substs,
+                item_def_id: obligation.predicate.item_def_id,
+            },
+            ty,
+        }
+    });
+
+    confirm_param_env_candidate(selcx, obligation, predicate)
+        .with_addl_obligations(vtable.nested)
+        .with_addl_obligations(obligations)
+}
+
+fn confirm_fn_pointer_candidate<'cx, 'tcx>(
+    selcx: &mut SelectionContext<'cx, 'tcx>,
+    obligation: &ProjectionTyObligation<'tcx>,
+    fn_pointer_vtable: VtableFnPointerData<'tcx, PredicateObligation<'tcx>>,
+) -> Progress<'tcx> {
+    let fn_type = selcx.infcx().shallow_resolve(fn_pointer_vtable.fn_ty);
+    let sig = fn_type.fn_sig(selcx.tcx());
+    let Normalized { value: sig, obligations } = normalize_with_depth(
+        selcx,
+        obligation.param_env,
+        obligation.cause.clone(),
+        obligation.recursion_depth + 1,
+        &sig,
+    );
+
+    confirm_callable_candidate(selcx, obligation, sig, util::TupleArgumentsFlag::Yes)
+        .with_addl_obligations(fn_pointer_vtable.nested)
+        .with_addl_obligations(obligations)
+}
+
+fn confirm_closure_candidate<'cx, 'tcx>(
+    selcx: &mut SelectionContext<'cx, 'tcx>,
+    obligation: &ProjectionTyObligation<'tcx>,
+    vtable: VtableClosureData<'tcx, PredicateObligation<'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 = infcx.shallow_resolve(closure_sig_ty).fn_sig(tcx);
+    let Normalized { value: closure_sig, obligations } = normalize_with_depth(
+        selcx,
+        obligation.param_env,
+        obligation.cause.clone(),
+        obligation.recursion_depth + 1,
+        &closure_sig,
+    );
+
+    debug!(
+        "confirm_closure_candidate: obligation={:?},closure_sig={:?},obligations={:?}",
+        obligation, closure_sig, obligations
+    );
+
+    confirm_callable_candidate(selcx, obligation, closure_sig, util::TupleArgumentsFlag::No)
+        .with_addl_obligations(vtable.nested)
+        .with_addl_obligations(obligations)
+}
+
+fn confirm_callable_candidate<'cx, 'tcx>(
+    selcx: &mut SelectionContext<'cx, 'tcx>,
+    obligation: &ProjectionTyObligation<'tcx>,
+    fn_sig: ty::PolyFnSig<'tcx>,
+    flag: util::TupleArgumentsFlag,
+) -> Progress<'tcx> {
+    let tcx = selcx.tcx();
+
+    debug!("confirm_callable_candidate({:?},{:?})", obligation, fn_sig);
+
+    // the `Output` associated type is declared on `FnOnce`
+    let fn_once_def_id = tcx.lang_items().fn_once_trait().unwrap();
+
+    let predicate = super::util::closure_trait_ref_and_return_type(
+        tcx,
+        fn_once_def_id,
+        obligation.predicate.self_ty(),
+        fn_sig,
+        flag,
+    )
+    .map_bound(|(trait_ref, ret_type)| ty::ProjectionPredicate {
+        projection_ty: ty::ProjectionTy::from_ref_and_name(
+            tcx,
+            trait_ref,
+            Ident::with_dummy_span(rustc_hir::FN_OUTPUT_NAME),
+        ),
+        ty: ret_type,
+    });
+
+    confirm_param_env_candidate(selcx, obligation, predicate)
+}
+
+fn confirm_param_env_candidate<'cx, 'tcx>(
+    selcx: &mut SelectionContext<'cx, 'tcx>,
+    obligation: &ProjectionTyObligation<'tcx>,
+    poly_cache_entry: ty::PolyProjectionPredicate<'tcx>,
+) -> Progress<'tcx> {
+    let infcx = selcx.infcx();
+    let cause = &obligation.cause;
+    let param_env = obligation.param_env;
+
+    let (cache_entry, _) = infcx.replace_bound_vars_with_fresh_vars(
+        cause.span,
+        LateBoundRegionConversionTime::HigherRankedType,
+        &poly_cache_entry,
+    );
+
+    let cache_trait_ref = cache_entry.projection_ty.trait_ref(infcx.tcx);
+    let obligation_trait_ref = obligation.predicate.trait_ref(infcx.tcx);
+    match infcx.at(cause, param_env).eq(cache_trait_ref, obligation_trait_ref) {
+        Ok(InferOk { value: _, obligations }) => Progress { ty: cache_entry.ty, obligations },
+        Err(e) => {
+            let msg = format!(
+                "Failed to unify obligation `{:?}` with poly_projection `{:?}`: {:?}",
+                obligation, poly_cache_entry, e,
+            );
+            debug!("confirm_param_env_candidate: {}", msg);
+            infcx.tcx.sess.delay_span_bug(obligation.cause.span, &msg);
+            Progress { ty: infcx.tcx.types.err, obligations: vec![] }
+        }
+    }
+}
+
+fn confirm_impl_candidate<'cx, 'tcx>(
+    selcx: &mut SelectionContext<'cx, 'tcx>,
+    obligation: &ProjectionTyObligation<'tcx>,
+    impl_vtable: VtableImplData<'tcx, PredicateObligation<'tcx>>,
+) -> Progress<'tcx> {
+    let tcx = selcx.tcx();
+
+    let VtableImplData { impl_def_id, substs, nested } = impl_vtable;
+    let assoc_item_id = obligation.predicate.item_def_id;
+    let trait_def_id = tcx.trait_id_of_impl(impl_def_id).unwrap();
+
+    let param_env = obligation.param_env;
+    let assoc_ty = match assoc_ty_def(selcx, impl_def_id, assoc_item_id) {
+        Ok(assoc_ty) => assoc_ty,
+        Err(ErrorReported) => return Progress { ty: tcx.types.err, obligations: nested },
+    };
+
+    if !assoc_ty.item.defaultness.has_value() {
+        // This means that the impl is missing a definition for the
+        // associated type. This error will be reported by the type
+        // checker method `check_impl_items_against_trait`, so here we
+        // just return Error.
+        debug!(
+            "confirm_impl_candidate: no associated type {:?} for {:?}",
+            assoc_ty.item.ident, obligation.predicate
+        );
+        return Progress { ty: tcx.types.err, obligations: nested };
+    }
+    let substs = obligation.predicate.substs.rebase_onto(tcx, trait_def_id, substs);
+    let substs = translate_substs(selcx.infcx(), param_env, impl_def_id, substs, assoc_ty.node);
+    let ty = if let ty::AssocKind::OpaqueTy = assoc_ty.item.kind {
+        let item_substs = InternalSubsts::identity_for_item(tcx, assoc_ty.item.def_id);
+        tcx.mk_opaque(assoc_ty.item.def_id, item_substs)
+    } else {
+        tcx.type_of(assoc_ty.item.def_id)
+    };
+    if substs.len() != tcx.generics_of(assoc_ty.item.def_id).count() {
+        tcx.sess
+            .delay_span_bug(DUMMY_SP, "impl item and trait item have different parameter counts");
+        Progress { ty: tcx.types.err, obligations: nested }
+    } else {
+        Progress { ty: ty.subst(tcx, substs), obligations: nested }
+    }
+}
+
+/// Locate the definition of an associated type in the specialization hierarchy,
+/// starting from the given impl.
+///
+/// Based on the "projection mode", this lookup may in fact only examine the
+/// topmost impl. See the comments for `Reveal` for more details.
+fn assoc_ty_def(
+    selcx: &SelectionContext<'_, '_>,
+    impl_def_id: DefId,
+    assoc_ty_def_id: DefId,
+) -> Result<specialization_graph::NodeItem<ty::AssocItem>, ErrorReported> {
+    let tcx = selcx.tcx();
+    let assoc_ty_name = tcx.associated_item(assoc_ty_def_id).ident;
+    let trait_def_id = tcx.impl_trait_ref(impl_def_id).unwrap().def_id;
+    let trait_def = tcx.trait_def(trait_def_id);
+
+    // This function may be called while we are still building the
+    // specialization graph that is queried below (via TraitDef::ancestors()),
+    // so, in order to avoid unnecessary infinite recursion, we manually look
+    // for the associated item at the given impl.
+    // If there is no such item in that impl, this function will fail with a
+    // cycle error if the specialization graph is currently being built.
+    let impl_node = specialization_graph::Node::Impl(impl_def_id);
+    for item in impl_node.items(tcx) {
+        if matches!(item.kind, ty::AssocKind::Type | ty::AssocKind::OpaqueTy)
+            && tcx.hygienic_eq(item.ident, assoc_ty_name, trait_def_id)
+        {
+            return Ok(specialization_graph::NodeItem {
+                node: specialization_graph::Node::Impl(impl_def_id),
+                item: *item,
+            });
+        }
+    }
+
+    let ancestors = trait_def.ancestors(tcx, impl_def_id)?;
+    if let Some(assoc_item) = ancestors.leaf_def(tcx, assoc_ty_name, ty::AssocKind::Type) {
+        Ok(assoc_item)
+    } else {
+        // This is saying that neither the trait nor
+        // the impl contain a definition for this
+        // associated type.  Normally this situation
+        // could only arise through a compiler bug --
+        // if the user wrote a bad item name, it
+        // should have failed in astconv.
+        bug!("No associated type `{}` for {}", assoc_ty_name, tcx.def_path_str(impl_def_id))
+    }
+}
+
+crate trait ProjectionCacheKeyExt<'tcx>: Sized {
+    fn from_poly_projection_predicate(
+        selcx: &mut SelectionContext<'cx, 'tcx>,
+        predicate: &ty::PolyProjectionPredicate<'tcx>,
+    ) -> Option<Self>;
+}
+
+impl<'tcx> ProjectionCacheKeyExt<'tcx> for ProjectionCacheKey<'tcx> {
+    fn from_poly_projection_predicate(
+        selcx: &mut SelectionContext<'cx, 'tcx>,
+        predicate: &ty::PolyProjectionPredicate<'tcx>,
+    ) -> Option<Self> {
+        let infcx = selcx.infcx();
+        // We don't do cross-snapshot caching of obligations with escaping regions,
+        // so there's no cache key to use
+        predicate.no_bound_vars().map(|predicate| {
+            ProjectionCacheKey::new(
+                // We don't attempt to match up with a specific type-variable state
+                // from a specific call to `opt_normalize_projection_type` - if
+                // there's no precise match, the original cache entry is "stranded"
+                // anyway.
+                infcx.resolve_vars_if_possible(&predicate.projection_ty),
+            )
+        })
+    }
+}
diff --git a/src/librustc_trait_selection/traits/query/dropck_outlives.rs b/src/librustc_trait_selection/traits/query/dropck_outlives.rs
new file mode 100644 (file)
index 0000000..40a21b5
--- /dev/null
@@ -0,0 +1,141 @@
+use crate::infer::at::At;
+use crate::infer::canonical::OriginalQueryValues;
+use crate::infer::InferOk;
+
+use rustc::ty::subst::GenericArg;
+use rustc::ty::{self, Ty, TyCtxt};
+
+pub use rustc::traits::query::{DropckOutlivesResult, DtorckConstraint};
+
+pub trait AtExt<'tcx> {
+    fn dropck_outlives(&self, ty: Ty<'tcx>) -> InferOk<'tcx, Vec<GenericArg<'tcx>>>;
+}
+
+impl<'cx, 'tcx> AtExt<'tcx> for At<'cx, 'tcx> {
+    /// Given a type `ty` of some value being dropped, computes a set
+    /// of "kinds" (types, regions) that must be outlive the execution
+    /// of the destructor. These basically correspond to data that the
+    /// destructor might access. This is used during regionck to
+    /// impose "outlives" constraints on any lifetimes referenced
+    /// within.
+    ///
+    /// The rules here are given by the "dropck" RFCs, notably [#1238]
+    /// and [#1327]. This is a fixed-point computation, where we
+    /// explore all the data that will be dropped (transitively) when
+    /// a value of type `ty` is dropped. For each type T that will be
+    /// dropped and which has a destructor, we must assume that all
+    /// the types/regions of T are live during the destructor, unless
+    /// they are marked with a special attribute (`#[may_dangle]`).
+    ///
+    /// [#1238]: https://github.com/rust-lang/rfcs/blob/master/text/1238-nonparametric-dropck.md
+    /// [#1327]: https://github.com/rust-lang/rfcs/blob/master/text/1327-dropck-param-eyepatch.md
+    fn dropck_outlives(&self, ty: Ty<'tcx>) -> InferOk<'tcx, Vec<GenericArg<'tcx>>> {
+        debug!("dropck_outlives(ty={:?}, param_env={:?})", ty, self.param_env,);
+
+        // Quick check: there are a number of cases that we know do not require
+        // any destructor.
+        let tcx = self.infcx.tcx;
+        if trivial_dropck_outlives(tcx, ty) {
+            return InferOk { value: vec![], obligations: vec![] };
+        }
+
+        let mut orig_values = OriginalQueryValues::default();
+        let c_ty = self.infcx.canonicalize_query(&self.param_env.and(ty), &mut orig_values);
+        let span = self.cause.span;
+        debug!("c_ty = {:?}", c_ty);
+        if let Ok(result) = &tcx.dropck_outlives(c_ty) {
+            if result.is_proven() {
+                if let Ok(InferOk { value, obligations }) =
+                    self.infcx.instantiate_query_response_and_region_obligations(
+                        self.cause,
+                        self.param_env,
+                        &orig_values,
+                        result,
+                    )
+                {
+                    let ty = self.infcx.resolve_vars_if_possible(&ty);
+                    let kinds = value.into_kinds_reporting_overflows(tcx, span, ty);
+                    return InferOk { value: kinds, obligations };
+                }
+            }
+        }
+
+        // Errors and ambiuity in dropck occur in two cases:
+        // - unresolved inference variables at the end of typeck
+        // - non well-formed types where projections cannot be resolved
+        // Either of these should have created an error before.
+        tcx.sess.delay_span_bug(span, "dtorck encountered internal error");
+
+        InferOk { value: vec![], obligations: vec![] }
+    }
+}
+
+/// This returns true if the type `ty` is "trivial" for
+/// dropck-outlives -- that is, if it doesn't require any types to
+/// outlive. This is similar but not *quite* the same as the
+/// `needs_drop` test in the compiler already -- that is, for every
+/// type T for which this function return true, needs-drop would
+/// return `false`. But the reverse does not hold: in particular,
+/// `needs_drop` returns false for `PhantomData`, but it is not
+/// trivial for dropck-outlives.
+///
+/// Note also that `needs_drop` requires a "global" type (i.e., one
+/// with erased regions), but this function does not.
+pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
+    match ty.kind {
+        // None of these types have a destructor and hence they do not
+        // require anything in particular to outlive the dtor's
+        // execution.
+        ty::Infer(ty::FreshIntTy(_))
+        | ty::Infer(ty::FreshFloatTy(_))
+        | ty::Bool
+        | ty::Int(_)
+        | ty::Uint(_)
+        | ty::Float(_)
+        | ty::Never
+        | ty::FnDef(..)
+        | ty::FnPtr(_)
+        | ty::Char
+        | ty::GeneratorWitness(..)
+        | ty::RawPtr(_)
+        | ty::Ref(..)
+        | ty::Str
+        | ty::Foreign(..)
+        | ty::Error => true,
+
+        // [T; N] and [T] have same properties as T.
+        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| trivial_dropck_outlives(tcx, t.expect_ty())),
+        ty::Closure(def_id, ref substs) => {
+            substs.as_closure().upvar_tys(def_id, tcx).all(|t| trivial_dropck_outlives(tcx, t))
+        }
+
+        ty::Adt(def, _) => {
+            if Some(def.did) == tcx.lang_items().manually_drop() {
+                // `ManuallyDrop` never has a dtor.
+                true
+            } else {
+                // Other types might. Moreover, PhantomData doesn't
+                // have a dtor, but it is considered to own its
+                // content, so it is non-trivial. Unions can have `impl Drop`,
+                // and hence are non-trivial as well.
+                false
+            }
+        }
+
+        // The following *might* require a destructor: needs deeper inspection.
+        ty::Dynamic(..)
+        | ty::Projection(..)
+        | ty::Param(_)
+        | ty::Opaque(..)
+        | ty::Placeholder(..)
+        | ty::Infer(_)
+        | ty::Bound(..)
+        | ty::Generator(..) => false,
+
+        ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
+    }
+}
diff --git a/src/librustc_trait_selection/traits/query/evaluate_obligation.rs b/src/librustc_trait_selection/traits/query/evaluate_obligation.rs
new file mode 100644 (file)
index 0000000..0569f62
--- /dev/null
@@ -0,0 +1,97 @@
+use crate::infer::canonical::OriginalQueryValues;
+use crate::infer::InferCtxt;
+use crate::traits::{
+    EvaluationResult, OverflowError, PredicateObligation, SelectionContext, TraitQueryMode,
+};
+
+pub trait InferCtxtExt<'tcx> {
+    fn predicate_may_hold(&self, obligation: &PredicateObligation<'tcx>) -> bool;
+
+    fn predicate_must_hold_considering_regions(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+    ) -> bool;
+
+    fn predicate_must_hold_modulo_regions(&self, obligation: &PredicateObligation<'tcx>) -> bool;
+
+    fn evaluate_obligation(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+    ) -> Result<EvaluationResult, OverflowError>;
+
+    // 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(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+    ) -> EvaluationResult;
+}
+
+impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> {
+    /// Evaluates whether the predicate can be satisfied (by any means)
+    /// in the given `ParamEnv`.
+    fn predicate_may_hold(&self, obligation: &PredicateObligation<'tcx>) -> bool {
+        self.evaluate_obligation_no_overflow(obligation).may_apply()
+    }
+
+    /// Evaluates whether the predicate can be satisfied in the given
+    /// `ParamEnv`, and returns `false` if not certain. However, this is
+    /// not entirely accurate if inference variables are involved.
+    ///
+    /// This version may conservatively fail when outlives obligations
+    /// are required.
+    fn predicate_must_hold_considering_regions(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+    ) -> bool {
+        self.evaluate_obligation_no_overflow(obligation).must_apply_considering_regions()
+    }
+
+    /// Evaluates whether the predicate can be satisfied in the given
+    /// `ParamEnv`, and returns `false` if not certain. However, this is
+    /// not entirely accurate if inference variables are involved.
+    ///
+    /// This version ignores all outlives constraints.
+    fn predicate_must_hold_modulo_regions(&self, obligation: &PredicateObligation<'tcx>) -> bool {
+        self.evaluate_obligation_no_overflow(obligation).must_apply_modulo_regions()
+    }
+
+    /// Evaluate a given predicate, capturing overflow and propagating it back.
+    fn evaluate_obligation(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+    ) -> Result<EvaluationResult, OverflowError> {
+        let mut _orig_values = OriginalQueryValues::default();
+        let c_pred = self
+            .canonicalize_query(&obligation.param_env.and(obligation.predicate), &mut _orig_values);
+        // Run canonical query. If overflow occurs, rerun from scratch but this time
+        // in standard trait query mode so that overflow is handled appropriately
+        // within `SelectionContext`.
+        self.tcx.evaluate_obligation(c_pred)
+    }
+
+    // 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.
+    fn evaluate_obligation_no_overflow(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+    ) -> EvaluationResult {
+        match self.evaluate_obligation(obligation) {
+            Ok(result) => result,
+            Err(OverflowError) => {
+                let mut selcx = SelectionContext::with_query_mode(&self, TraitQueryMode::Standard);
+                selcx.evaluate_root_obligation(obligation).unwrap_or_else(|r| {
+                    span_bug!(
+                        obligation.cause.span,
+                        "Overflow should be caught earlier in standard query mode: {:?}, {:?}",
+                        obligation,
+                        r,
+                    )
+                })
+            }
+        }
+    }
+}
diff --git a/src/librustc_trait_selection/traits/query/method_autoderef.rs b/src/librustc_trait_selection/traits/query/method_autoderef.rs
new file mode 100644 (file)
index 0000000..80748c5
--- /dev/null
@@ -0,0 +1 @@
+pub use rustc::traits::query::{CandidateStep, MethodAutoderefBadTy, MethodAutoderefStepsResult};
diff --git a/src/librustc_trait_selection/traits/query/mod.rs b/src/librustc_trait_selection/traits/query/mod.rs
new file mode 100644 (file)
index 0000000..77b5ec6
--- /dev/null
@@ -0,0 +1,15 @@
+//! Experimental types for the trait query interface. The methods
+//! defined in this module are all based on **canonicalization**,
+//! which makes a canonical query by replacing unbound inference
+//! variables and regions, so that results can be reused more broadly.
+//! The providers for the queries defined here can be found in
+//! `librustc_traits`.
+
+pub mod dropck_outlives;
+pub mod evaluate_obligation;
+pub mod method_autoderef;
+pub mod normalize;
+pub mod outlives_bounds;
+pub mod type_op;
+
+pub use rustc::traits::query::*;
diff --git a/src/librustc_trait_selection/traits/query/normalize.rs b/src/librustc_trait_selection/traits/query/normalize.rs
new file mode 100644 (file)
index 0000000..adec2dd
--- /dev/null
@@ -0,0 +1,196 @@
+//! Code for the 'normalization' query. This consists of a wrapper
+//! which folds deeply, invoking the underlying
+//! `normalize_projection_ty` query when it encounters projections.
+
+use crate::infer::at::At;
+use crate::infer::canonical::OriginalQueryValues;
+use crate::infer::{InferCtxt, InferOk};
+use crate::traits::error_reporting::InferCtxtExt;
+use crate::traits::{Obligation, ObligationCause, PredicateObligation, Reveal};
+use rustc::ty::fold::{TypeFoldable, TypeFolder};
+use rustc::ty::subst::Subst;
+use rustc::ty::{self, Ty, TyCtxt};
+use rustc_infer::traits::Normalized;
+
+use super::NoSolution;
+
+pub use rustc::traits::query::NormalizationResult;
+
+pub trait AtExt<'tcx> {
+    fn normalize<T>(&self, value: &T) -> Result<Normalized<'tcx, T>, NoSolution>
+    where
+        T: TypeFoldable<'tcx>;
+}
+
+impl<'cx, 'tcx> AtExt<'tcx> for At<'cx, 'tcx> {
+    /// Normalize `value` in the context of the inference context,
+    /// yielding a resulting type, or an error if `value` cannot be
+    /// normalized. If you don't care about regions, you should prefer
+    /// `normalize_erasing_regions`, which is more efficient.
+    ///
+    /// If the normalization succeeds and is unambiguous, returns back
+    /// the normalized value along with various outlives relations (in
+    /// the form of obligations that must be discharged).
+    ///
+    /// N.B., this will *eventually* be the main means of
+    /// normalizing, but for now should be used only when we actually
+    /// know that normalization will succeed, since error reporting
+    /// and other details are still "under development".
+    fn normalize<T>(&self, value: &T) -> Result<Normalized<'tcx, T>, NoSolution>
+    where
+        T: TypeFoldable<'tcx>,
+    {
+        debug!(
+            "normalize::<{}>(value={:?}, param_env={:?})",
+            ::std::any::type_name::<T>(),
+            value,
+            self.param_env,
+        );
+        if !value.has_projections() {
+            return Ok(Normalized { value: value.clone(), obligations: vec![] });
+        }
+
+        let mut normalizer = QueryNormalizer {
+            infcx: self.infcx,
+            cause: self.cause,
+            param_env: self.param_env,
+            obligations: vec![],
+            error: false,
+            anon_depth: 0,
+        };
+
+        let value1 = value.fold_with(&mut normalizer);
+        if normalizer.error {
+            Err(NoSolution)
+        } else {
+            Ok(Normalized { value: value1, obligations: normalizer.obligations })
+        }
+    }
+}
+
+struct QueryNormalizer<'cx, 'tcx> {
+    infcx: &'cx InferCtxt<'cx, 'tcx>,
+    cause: &'cx ObligationCause<'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    obligations: Vec<PredicateObligation<'tcx>>,
+    error: bool,
+    anon_depth: usize,
+}
+
+impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
+    fn tcx<'c>(&'c self) -> TyCtxt<'tcx> {
+        self.infcx.tcx
+    }
+
+    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
+        if !ty.has_projections() {
+            return ty;
+        }
+
+        let ty = ty.super_fold_with(self);
+        match ty.kind {
+            ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => {
+                // (*)
+                // Only normalize `impl Trait` after type-checking, usually in codegen.
+                match self.param_env.reveal {
+                    Reveal::UserFacing => ty,
+
+                    Reveal::All => {
+                        let recursion_limit = *self.tcx().sess.recursion_limit.get();
+                        if self.anon_depth >= recursion_limit {
+                            let obligation = Obligation::with_depth(
+                                self.cause.clone(),
+                                recursion_limit,
+                                self.param_env,
+                                ty,
+                            );
+                            self.infcx.report_overflow_error(&obligation, true);
+                        }
+
+                        let generic_ty = self.tcx().type_of(def_id);
+                        let concrete_ty = generic_ty.subst(self.tcx(), substs);
+                        self.anon_depth += 1;
+                        if concrete_ty == ty {
+                            bug!(
+                                "infinite recursion generic_ty: {:#?}, substs: {:#?}, \
+                                 concrete_ty: {:#?}, ty: {:#?}",
+                                generic_ty,
+                                substs,
+                                concrete_ty,
+                                ty
+                            );
+                        }
+                        let folded_ty = self.fold_ty(concrete_ty);
+                        self.anon_depth -= 1;
+                        folded_ty
+                    }
+                }
+            }
+
+            ty::Projection(ref data) if !data.has_escaping_bound_vars() => {
+                // (*)
+                // (*) This is kind of hacky -- we need to be able to
+                // handle normalization within binders because
+                // otherwise we wind up a need to normalize when doing
+                // trait matching (since you can have a trait
+                // obligation like `for<'a> T::B : Fn(&'a int)`), but
+                // we can't normalize with bound regions in scope. So
+                // far now we just ignore binders but only normalize
+                // if all bound regions are gone (and then we still
+                // have to renormalize whenever we instantiate a
+                // binder). It would be better to normalize in a
+                // binding-aware fashion.
+
+                let tcx = self.infcx.tcx;
+
+                let mut orig_values = OriginalQueryValues::default();
+                // HACK(matthewjasper) `'static` is special-cased in selection,
+                // so we cannot canonicalize it.
+                let c_data = self
+                    .infcx
+                    .canonicalize_hr_query_hack(&self.param_env.and(*data), &mut orig_values);
+                debug!("QueryNormalizer: c_data = {:#?}", c_data);
+                debug!("QueryNormalizer: orig_values = {:#?}", orig_values);
+                match tcx.normalize_projection_ty(c_data) {
+                    Ok(result) => {
+                        // We don't expect ambiguity.
+                        if result.is_ambiguous() {
+                            self.error = true;
+                            return ty;
+                        }
+
+                        match self.infcx.instantiate_query_response_and_region_obligations(
+                            self.cause,
+                            self.param_env,
+                            &orig_values,
+                            &result,
+                        ) {
+                            Ok(InferOk { value: result, obligations }) => {
+                                debug!("QueryNormalizer: result = {:#?}", result);
+                                debug!("QueryNormalizer: obligations = {:#?}", obligations);
+                                self.obligations.extend(obligations);
+                                return result.normalized_ty;
+                            }
+
+                            Err(_) => {
+                                self.error = true;
+                                return ty;
+                            }
+                        }
+                    }
+
+                    Err(NoSolution) => {
+                        self.error = true;
+                        ty
+                    }
+                }
+            }
+
+            _ => ty,
+        }
+    }
+
+    fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
+        constant.eval(self.infcx.tcx, self.param_env)
+    }
+}
diff --git a/src/librustc_trait_selection/traits/query/outlives_bounds.rs b/src/librustc_trait_selection/traits/query/outlives_bounds.rs
new file mode 100644 (file)
index 0000000..05c96dd
--- /dev/null
@@ -0,0 +1,95 @@
+use crate::infer::canonical::OriginalQueryValues;
+use crate::infer::InferCtxt;
+use crate::traits::query::NoSolution;
+use crate::traits::{FulfillmentContext, ObligationCause, TraitEngine};
+use rustc::ty::{self, Ty};
+use rustc_hir as hir;
+use rustc_infer::traits::TraitEngineExt as _;
+use rustc_span::source_map::Span;
+
+pub use rustc::traits::query::OutlivesBound;
+
+pub trait InferCtxtExt<'tcx> {
+    fn implied_outlives_bounds(
+        &self,
+        param_env: ty::ParamEnv<'tcx>,
+        body_id: hir::HirId,
+        ty: Ty<'tcx>,
+        span: Span,
+    ) -> Vec<OutlivesBound<'tcx>>;
+}
+
+impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> {
+    /// Implied bounds are region relationships that we deduce
+    /// automatically. The idea is that (e.g.) a caller must check that a
+    /// function's argument types are well-formed immediately before
+    /// calling that fn, and hence the *callee* can assume that its
+    /// argument types are well-formed. This may imply certain relationships
+    /// between generic parameters. For example:
+    ///
+    ///     fn foo<'a,T>(x: &'a T)
+    ///
+    /// can only be called with a `'a` and `T` such that `&'a T` is WF.
+    /// For `&'a T` to be WF, `T: 'a` must hold. So we can assume `T: 'a`.
+    ///
+    /// # Parameters
+    ///
+    /// - `param_env`, the where-clauses in scope
+    /// - `body_id`, the body-id to use when normalizing assoc types.
+    ///   Note that this may cause outlives obligations to be injected
+    ///   into the inference context with this body-id.
+    /// - `ty`, the type that we are supposed to assume is WF.
+    /// - `span`, a span to use when normalizing, hopefully not important,
+    ///   might be useful if a `bug!` occurs.
+    fn implied_outlives_bounds(
+        &self,
+        param_env: ty::ParamEnv<'tcx>,
+        body_id: hir::HirId,
+        ty: Ty<'tcx>,
+        span: Span,
+    ) -> Vec<OutlivesBound<'tcx>> {
+        debug!("implied_outlives_bounds(ty = {:?})", ty);
+
+        let mut orig_values = OriginalQueryValues::default();
+        let key = self.canonicalize_query(&param_env.and(ty), &mut orig_values);
+        let result = match self.tcx.implied_outlives_bounds(key) {
+            Ok(r) => r,
+            Err(NoSolution) => {
+                self.tcx.sess.delay_span_bug(
+                    span,
+                    "implied_outlives_bounds failed to solve all obligations",
+                );
+                return vec![];
+            }
+        };
+        assert!(result.value.is_proven());
+
+        let result = self.instantiate_query_response_and_region_obligations(
+            &ObligationCause::misc(span, body_id),
+            param_env,
+            &orig_values,
+            &result,
+        );
+        debug!("implied_outlives_bounds for {:?}: {:#?}", ty, result);
+        let result = match result {
+            Ok(v) => v,
+            Err(_) => {
+                self.tcx.sess.delay_span_bug(span, "implied_outlives_bounds failed to instantiate");
+                return vec![];
+            }
+        };
+
+        // Instantiation may have produced new inference variables and constraints on those
+        // variables. Process these constraints.
+        let mut fulfill_cx = FulfillmentContext::new();
+        fulfill_cx.register_predicate_obligations(self, result.obligations);
+        if fulfill_cx.select_all_or_error(self).is_err() {
+            self.tcx.sess.delay_span_bug(
+                span,
+                "implied_outlives_bounds failed to solve obligations from instantiation",
+            );
+        }
+
+        result.value
+    }
+}
diff --git a/src/librustc_trait_selection/traits/query/type_op/ascribe_user_type.rs b/src/librustc_trait_selection/traits/query/type_op/ascribe_user_type.rs
new file mode 100644 (file)
index 0000000..b14b79f
--- /dev/null
@@ -0,0 +1,23 @@
+use crate::infer::canonical::{Canonicalized, CanonicalizedQueryResponse};
+use crate::traits::query::Fallible;
+use rustc::ty::{ParamEnvAnd, TyCtxt};
+
+pub use rustc::traits::query::type_op::AscribeUserType;
+
+impl<'tcx> super::QueryTypeOp<'tcx> for AscribeUserType<'tcx> {
+    type QueryResponse = ();
+
+    fn try_fast_path(
+        _tcx: TyCtxt<'tcx>,
+        _key: &ParamEnvAnd<'tcx, Self>,
+    ) -> Option<Self::QueryResponse> {
+        None
+    }
+
+    fn perform_query(
+        tcx: TyCtxt<'tcx>,
+        canonicalized: Canonicalized<'tcx, ParamEnvAnd<'tcx, Self>>,
+    ) -> Fallible<CanonicalizedQueryResponse<'tcx, ()>> {
+        tcx.type_op_ascribe_user_type(canonicalized)
+    }
+}
diff --git a/src/librustc_trait_selection/traits/query/type_op/custom.rs b/src/librustc_trait_selection/traits/query/type_op/custom.rs
new file mode 100644 (file)
index 0000000..915e8ae
--- /dev/null
@@ -0,0 +1,108 @@
+use crate::infer::{InferCtxt, InferOk};
+use crate::traits::query::Fallible;
+use std::fmt;
+
+use crate::infer::canonical::query_response;
+use crate::infer::canonical::QueryRegionConstraints;
+use crate::traits::engine::TraitEngineExt as _;
+use crate::traits::{ObligationCause, TraitEngine};
+use rustc_infer::traits::TraitEngineExt as _;
+use rustc_span::source_map::DUMMY_SP;
+use std::rc::Rc;
+
+pub struct CustomTypeOp<F, G> {
+    closure: F,
+    description: G,
+}
+
+impl<F, G> CustomTypeOp<F, G> {
+    pub fn new<'tcx, R>(closure: F, description: G) -> Self
+    where
+        F: FnOnce(&InferCtxt<'_, 'tcx>) -> Fallible<InferOk<'tcx, R>>,
+        G: Fn() -> String,
+    {
+        CustomTypeOp { closure, description }
+    }
+}
+
+impl<'tcx, F, R, G> super::TypeOp<'tcx> for CustomTypeOp<F, G>
+where
+    F: for<'a, 'cx> FnOnce(&'a InferCtxt<'cx, 'tcx>) -> Fallible<InferOk<'tcx, R>>,
+    G: Fn() -> String,
+{
+    type Output = R;
+
+    /// Processes the operation and all resulting obligations,
+    /// returning the final result along with any region constraints
+    /// (they will be given over to the NLL region solver).
+    fn fully_perform(
+        self,
+        infcx: &InferCtxt<'_, 'tcx>,
+    ) -> Fallible<(Self::Output, Option<Rc<QueryRegionConstraints<'tcx>>>)> {
+        if cfg!(debug_assertions) {
+            info!("fully_perform({:?})", self);
+        }
+
+        scrape_region_constraints(infcx, || Ok((self.closure)(infcx)?))
+    }
+}
+
+impl<F, G> fmt::Debug for CustomTypeOp<F, G>
+where
+    G: Fn() -> String,
+{
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{}", (self.description)())
+    }
+}
+
+/// Executes `op` and then scrapes out all the "old style" region
+/// constraints that result, creating query-region-constraints.
+fn scrape_region_constraints<'tcx, R>(
+    infcx: &InferCtxt<'_, 'tcx>,
+    op: impl FnOnce() -> Fallible<InferOk<'tcx, R>>,
+) -> Fallible<(R, Option<Rc<QueryRegionConstraints<'tcx>>>)> {
+    let mut fulfill_cx = TraitEngine::new(infcx.tcx);
+    let dummy_body_id = ObligationCause::dummy().body_id;
+
+    // During NLL, we expect that nobody will register region
+    // obligations **except** as part of a custom type op (and, at the
+    // end of each custom type op, we scrape out the region
+    // obligations that resulted). So this vector should be empty on
+    // entry.
+    let pre_obligations = infcx.take_registered_region_obligations();
+    assert!(
+        pre_obligations.is_empty(),
+        "scrape_region_constraints: incoming region obligations = {:#?}",
+        pre_obligations,
+    );
+
+    let InferOk { value, obligations } = infcx.commit_if_ok(|_| op())?;
+    debug_assert!(obligations.iter().all(|o| o.cause.body_id == dummy_body_id));
+    fulfill_cx.register_predicate_obligations(infcx, obligations);
+    if let Err(e) = fulfill_cx.select_all_or_error(infcx) {
+        infcx.tcx.sess.diagnostic().delay_span_bug(
+            DUMMY_SP,
+            &format!("errors selecting obligation during MIR typeck: {:?}", e),
+        );
+    }
+
+    let region_obligations = infcx.take_registered_region_obligations();
+
+    let region_constraint_data = infcx.take_and_reset_region_constraints();
+
+    let region_constraints = query_response::make_query_region_constraints(
+        infcx.tcx,
+        region_obligations
+            .iter()
+            .map(|(_, r_o)| (r_o.sup_type, r_o.sub_region))
+            .map(|(ty, r)| (infcx.resolve_vars_if_possible(&ty), r)),
+        &region_constraint_data,
+    );
+
+    if region_constraints.is_empty() {
+        Ok((value, None))
+    } else {
+        Ok((value, Some(Rc::new(region_constraints))))
+    }
+}
diff --git a/src/librustc_trait_selection/traits/query/type_op/eq.rs b/src/librustc_trait_selection/traits/query/type_op/eq.rs
new file mode 100644 (file)
index 0000000..3b6fbc7
--- /dev/null
@@ -0,0 +1,23 @@
+use crate::infer::canonical::{Canonicalized, CanonicalizedQueryResponse};
+use crate::traits::query::Fallible;
+use rustc::ty::{ParamEnvAnd, TyCtxt};
+
+pub use rustc::traits::query::type_op::Eq;
+
+impl<'tcx> super::QueryTypeOp<'tcx> for Eq<'tcx> {
+    type QueryResponse = ();
+
+    fn try_fast_path(
+        _tcx: TyCtxt<'tcx>,
+        key: &ParamEnvAnd<'tcx, Eq<'tcx>>,
+    ) -> Option<Self::QueryResponse> {
+        if key.value.a == key.value.b { Some(()) } else { None }
+    }
+
+    fn perform_query(
+        tcx: TyCtxt<'tcx>,
+        canonicalized: Canonicalized<'tcx, ParamEnvAnd<'tcx, Self>>,
+    ) -> Fallible<CanonicalizedQueryResponse<'tcx, ()>> {
+        tcx.type_op_eq(canonicalized)
+    }
+}
diff --git a/src/librustc_trait_selection/traits/query/type_op/implied_outlives_bounds.rs b/src/librustc_trait_selection/traits/query/type_op/implied_outlives_bounds.rs
new file mode 100644 (file)
index 0000000..3dad546
--- /dev/null
@@ -0,0 +1,41 @@
+use crate::infer::canonical::{Canonicalized, CanonicalizedQueryResponse};
+use crate::traits::query::outlives_bounds::OutlivesBound;
+use crate::traits::query::Fallible;
+use rustc::ty::{ParamEnvAnd, Ty, TyCtxt};
+
+#[derive(Clone, Debug, HashStable, TypeFoldable, Lift)]
+pub struct ImpliedOutlivesBounds<'tcx> {
+    pub ty: Ty<'tcx>,
+}
+
+impl<'tcx> ImpliedOutlivesBounds<'tcx> {
+    pub fn new(ty: Ty<'tcx>) -> Self {
+        ImpliedOutlivesBounds { ty }
+    }
+}
+
+impl<'tcx> super::QueryTypeOp<'tcx> for ImpliedOutlivesBounds<'tcx> {
+    type QueryResponse = Vec<OutlivesBound<'tcx>>;
+
+    fn try_fast_path(
+        _tcx: TyCtxt<'tcx>,
+        _key: &ParamEnvAnd<'tcx, Self>,
+    ) -> Option<Self::QueryResponse> {
+        None
+    }
+
+    fn perform_query(
+        tcx: TyCtxt<'tcx>,
+        canonicalized: Canonicalized<'tcx, ParamEnvAnd<'tcx, Self>>,
+    ) -> Fallible<CanonicalizedQueryResponse<'tcx, Self::QueryResponse>> {
+        // FIXME this `unchecked_map` is only necessary because the
+        // query is defined as taking a `ParamEnvAnd<Ty>`; it should
+        // take a `ImpliedOutlivesBounds` instead
+        let canonicalized = canonicalized.unchecked_map(|ParamEnvAnd { param_env, value }| {
+            let ImpliedOutlivesBounds { ty } = value;
+            param_env.and(ty)
+        });
+
+        tcx.implied_outlives_bounds(canonicalized)
+    }
+}
diff --git a/src/librustc_trait_selection/traits/query/type_op/mod.rs b/src/librustc_trait_selection/traits/query/type_op/mod.rs
new file mode 100644 (file)
index 0000000..1644746
--- /dev/null
@@ -0,0 +1,136 @@
+use crate::infer::canonical::{
+    Canonicalized, CanonicalizedQueryResponse, OriginalQueryValues, QueryRegionConstraints,
+};
+use crate::infer::{InferCtxt, InferOk};
+use crate::traits::query::Fallible;
+use crate::traits::ObligationCause;
+use rustc::ty::fold::TypeFoldable;
+use rustc::ty::{ParamEnvAnd, TyCtxt};
+use std::fmt;
+use std::rc::Rc;
+
+pub mod ascribe_user_type;
+pub mod custom;
+pub mod eq;
+pub mod implied_outlives_bounds;
+pub mod normalize;
+pub mod outlives;
+pub mod prove_predicate;
+use self::prove_predicate::ProvePredicate;
+pub mod subtype;
+
+pub use rustc::traits::query::type_op::*;
+
+/// "Type ops" are used in NLL to perform some particular action and
+/// extract out the resulting region constraints (or an error if it
+/// cannot be completed).
+pub trait TypeOp<'tcx>: Sized + fmt::Debug {
+    type Output;
+
+    /// Processes the operation and all resulting obligations,
+    /// returning the final result along with any region constraints
+    /// (they will be given over to the NLL region solver).
+    fn fully_perform(
+        self,
+        infcx: &InferCtxt<'_, 'tcx>,
+    ) -> Fallible<(Self::Output, Option<Rc<QueryRegionConstraints<'tcx>>>)>;
+}
+
+/// "Query type ops" are type ops that are implemented using a
+/// [canonical query][c]. The `Self` type here contains the kernel of
+/// information needed to do the operation -- `TypeOp` is actually
+/// implemented for `ParamEnvAnd<Self>`, since we always need to bring
+/// along a parameter environment as well. For query type-ops, we will
+/// first canonicalize the key and then invoke the query on the tcx,
+/// which produces the resulting query region constraints.
+///
+/// [c]: https://rustc-dev-guide.rust-lang.org/traits/canonicalization.html
+pub trait QueryTypeOp<'tcx>: fmt::Debug + Sized + TypeFoldable<'tcx> + 'tcx {
+    type QueryResponse: TypeFoldable<'tcx>;
+
+    /// Give query the option for a simple fast path that never
+    /// actually hits the tcx cache lookup etc. Return `Some(r)` with
+    /// a final result or `None` to do the full path.
+    fn try_fast_path(
+        tcx: TyCtxt<'tcx>,
+        key: &ParamEnvAnd<'tcx, Self>,
+    ) -> Option<Self::QueryResponse>;
+
+    /// Performs the actual query with the canonicalized key -- the
+    /// real work happens here. This method is not given an `infcx`
+    /// because it shouldn't need one -- and if it had access to one,
+    /// it might do things like invoke `sub_regions`, which would be
+    /// bad, because it would create subregion relationships that are
+    /// not captured in the return value.
+    fn perform_query(
+        tcx: TyCtxt<'tcx>,
+        canonicalized: Canonicalized<'tcx, ParamEnvAnd<'tcx, Self>>,
+    ) -> Fallible<CanonicalizedQueryResponse<'tcx, Self::QueryResponse>>;
+
+    fn fully_perform_into(
+        query_key: ParamEnvAnd<'tcx, Self>,
+        infcx: &InferCtxt<'_, 'tcx>,
+        output_query_region_constraints: &mut QueryRegionConstraints<'tcx>,
+    ) -> Fallible<Self::QueryResponse> {
+        if let Some(result) = QueryTypeOp::try_fast_path(infcx.tcx, &query_key) {
+            return Ok(result);
+        }
+
+        // FIXME(#33684) -- We need to use
+        // `canonicalize_hr_query_hack` here because of things
+        // like the subtype query, which go awry around
+        // `'static` otherwise.
+        let mut canonical_var_values = OriginalQueryValues::default();
+        let canonical_self =
+            infcx.canonicalize_hr_query_hack(&query_key, &mut canonical_var_values);
+        let canonical_result = Self::perform_query(infcx.tcx, canonical_self)?;
+
+        let param_env = query_key.param_env;
+
+        let InferOk { value, obligations } = infcx
+            .instantiate_nll_query_response_and_region_obligations(
+                &ObligationCause::dummy(),
+                param_env,
+                &canonical_var_values,
+                canonical_result,
+                output_query_region_constraints,
+            )?;
+
+        // Typically, instantiating NLL query results does not
+        // create obligations. However, in some cases there
+        // are unresolved type variables, and unify them *can*
+        // create obligations. In that case, we have to go
+        // fulfill them. We do this via a (recursive) query.
+        for obligation in obligations {
+            let () = ProvePredicate::fully_perform_into(
+                obligation.param_env.and(ProvePredicate::new(obligation.predicate)),
+                infcx,
+                output_query_region_constraints,
+            )?;
+        }
+
+        Ok(value)
+    }
+}
+
+impl<'tcx, Q> TypeOp<'tcx> for ParamEnvAnd<'tcx, Q>
+where
+    Q: QueryTypeOp<'tcx>,
+{
+    type Output = Q::QueryResponse;
+
+    fn fully_perform(
+        self,
+        infcx: &InferCtxt<'_, 'tcx>,
+    ) -> Fallible<(Self::Output, Option<Rc<QueryRegionConstraints<'tcx>>>)> {
+        let mut region_constraints = QueryRegionConstraints::default();
+        let r = Q::fully_perform_into(self, infcx, &mut region_constraints)?;
+
+        // Promote the final query-region-constraints into a
+        // (optional) ref-counted vector:
+        let opt_qrc =
+            if region_constraints.is_empty() { None } else { Some(Rc::new(region_constraints)) };
+
+        Ok((r, opt_qrc))
+    }
+}
diff --git a/src/librustc_trait_selection/traits/query/type_op/normalize.rs b/src/librustc_trait_selection/traits/query/type_op/normalize.rs
new file mode 100644 (file)
index 0000000..d2eec53
--- /dev/null
@@ -0,0 +1,68 @@
+use crate::infer::canonical::{Canonicalized, CanonicalizedQueryResponse};
+use crate::traits::query::Fallible;
+use rustc::ty::fold::TypeFoldable;
+use rustc::ty::{self, Lift, ParamEnvAnd, Ty, TyCtxt};
+use std::fmt;
+
+pub use rustc::traits::query::type_op::Normalize;
+
+impl<'tcx, T> super::QueryTypeOp<'tcx> for Normalize<T>
+where
+    T: Normalizable<'tcx> + 'tcx,
+{
+    type QueryResponse = T;
+
+    fn try_fast_path(_tcx: TyCtxt<'tcx>, key: &ParamEnvAnd<'tcx, Self>) -> Option<T> {
+        if !key.value.value.has_projections() { Some(key.value.value) } else { None }
+    }
+
+    fn perform_query(
+        tcx: TyCtxt<'tcx>,
+        canonicalized: Canonicalized<'tcx, ParamEnvAnd<'tcx, Self>>,
+    ) -> Fallible<CanonicalizedQueryResponse<'tcx, Self::QueryResponse>> {
+        T::type_op_method(tcx, canonicalized)
+    }
+}
+
+pub trait Normalizable<'tcx>: fmt::Debug + TypeFoldable<'tcx> + Lift<'tcx> + Copy {
+    fn type_op_method(
+        tcx: TyCtxt<'tcx>,
+        canonicalized: Canonicalized<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
+    ) -> Fallible<CanonicalizedQueryResponse<'tcx, Self>>;
+}
+
+impl Normalizable<'tcx> for Ty<'tcx> {
+    fn type_op_method(
+        tcx: TyCtxt<'tcx>,
+        canonicalized: Canonicalized<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
+    ) -> Fallible<CanonicalizedQueryResponse<'tcx, Self>> {
+        tcx.type_op_normalize_ty(canonicalized)
+    }
+}
+
+impl Normalizable<'tcx> for ty::Predicate<'tcx> {
+    fn type_op_method(
+        tcx: TyCtxt<'tcx>,
+        canonicalized: Canonicalized<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
+    ) -> Fallible<CanonicalizedQueryResponse<'tcx, Self>> {
+        tcx.type_op_normalize_predicate(canonicalized)
+    }
+}
+
+impl Normalizable<'tcx> for ty::PolyFnSig<'tcx> {
+    fn type_op_method(
+        tcx: TyCtxt<'tcx>,
+        canonicalized: Canonicalized<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
+    ) -> Fallible<CanonicalizedQueryResponse<'tcx, Self>> {
+        tcx.type_op_normalize_poly_fn_sig(canonicalized)
+    }
+}
+
+impl Normalizable<'tcx> for ty::FnSig<'tcx> {
+    fn type_op_method(
+        tcx: TyCtxt<'tcx>,
+        canonicalized: Canonicalized<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
+    ) -> Fallible<CanonicalizedQueryResponse<'tcx, Self>> {
+        tcx.type_op_normalize_fn_sig(canonicalized)
+    }
+}
diff --git a/src/librustc_trait_selection/traits/query/type_op/outlives.rs b/src/librustc_trait_selection/traits/query/type_op/outlives.rs
new file mode 100644 (file)
index 0000000..b94948c
--- /dev/null
@@ -0,0 +1,55 @@
+use crate::infer::canonical::{Canonicalized, CanonicalizedQueryResponse};
+use crate::traits::query::dropck_outlives::{trivial_dropck_outlives, DropckOutlivesResult};
+use crate::traits::query::Fallible;
+use rustc::ty::{ParamEnvAnd, Ty, TyCtxt};
+
+#[derive(Copy, Clone, Debug, HashStable, TypeFoldable, Lift)]
+pub struct DropckOutlives<'tcx> {
+    dropped_ty: Ty<'tcx>,
+}
+
+impl<'tcx> DropckOutlives<'tcx> {
+    pub fn new(dropped_ty: Ty<'tcx>) -> Self {
+        DropckOutlives { dropped_ty }
+    }
+}
+
+impl super::QueryTypeOp<'tcx> for DropckOutlives<'tcx> {
+    type QueryResponse = DropckOutlivesResult<'tcx>;
+
+    fn try_fast_path(
+        tcx: TyCtxt<'tcx>,
+        key: &ParamEnvAnd<'tcx, Self>,
+    ) -> Option<Self::QueryResponse> {
+        if trivial_dropck_outlives(tcx, key.value.dropped_ty) {
+            Some(DropckOutlivesResult::default())
+        } else {
+            None
+        }
+    }
+
+    fn perform_query(
+        tcx: TyCtxt<'tcx>,
+        canonicalized: Canonicalized<'tcx, ParamEnvAnd<'tcx, Self>>,
+    ) -> Fallible<CanonicalizedQueryResponse<'tcx, Self::QueryResponse>> {
+        // Subtle: note that we are not invoking
+        // `infcx.at(...).dropck_outlives(...)` here, but rather the
+        // underlying `dropck_outlives` query. This same underlying
+        // query is also used by the
+        // `infcx.at(...).dropck_outlives(...)` fn. Avoiding the
+        // wrapper means we don't need an infcx in this code, which is
+        // good because the interface doesn't give us one (so that we
+        // know we are not registering any subregion relations or
+        // other things).
+
+        // FIXME convert to the type expected by the `dropck_outlives`
+        // query. This should eventually be fixed by changing the
+        // *underlying query*.
+        let canonicalized = canonicalized.unchecked_map(|ParamEnvAnd { param_env, value }| {
+            let DropckOutlives { dropped_ty } = value;
+            param_env.and(dropped_ty)
+        });
+
+        tcx.dropck_outlives(canonicalized)
+    }
+}
diff --git a/src/librustc_trait_selection/traits/query/type_op/prove_predicate.rs b/src/librustc_trait_selection/traits/query/type_op/prove_predicate.rs
new file mode 100644 (file)
index 0000000..8c68f7d
--- /dev/null
@@ -0,0 +1,37 @@
+use crate::infer::canonical::{Canonicalized, CanonicalizedQueryResponse};
+use crate::traits::query::Fallible;
+use rustc::ty::{ParamEnvAnd, Predicate, TyCtxt};
+
+pub use rustc::traits::query::type_op::ProvePredicate;
+
+impl<'tcx> super::QueryTypeOp<'tcx> for ProvePredicate<'tcx> {
+    type QueryResponse = ();
+
+    fn try_fast_path(
+        tcx: TyCtxt<'tcx>,
+        key: &ParamEnvAnd<'tcx, Self>,
+    ) -> Option<Self::QueryResponse> {
+        // Proving Sized, very often on "obviously sized" types like
+        // `&T`, accounts for about 60% percentage of the predicates
+        // we have to prove. No need to canonicalize and all that for
+        // such cases.
+        if let Predicate::Trait(trait_ref, _) = key.value.predicate {
+            if let Some(sized_def_id) = tcx.lang_items().sized_trait() {
+                if trait_ref.def_id() == sized_def_id {
+                    if trait_ref.skip_binder().self_ty().is_trivially_sized(tcx) {
+                        return Some(());
+                    }
+                }
+            }
+        }
+
+        None
+    }
+
+    fn perform_query(
+        tcx: TyCtxt<'tcx>,
+        canonicalized: Canonicalized<'tcx, ParamEnvAnd<'tcx, Self>>,
+    ) -> Fallible<CanonicalizedQueryResponse<'tcx, ()>> {
+        tcx.type_op_prove_predicate(canonicalized)
+    }
+}
diff --git a/src/librustc_trait_selection/traits/query/type_op/subtype.rs b/src/librustc_trait_selection/traits/query/type_op/subtype.rs
new file mode 100644 (file)
index 0000000..053411b
--- /dev/null
@@ -0,0 +1,20 @@
+use crate::infer::canonical::{Canonicalized, CanonicalizedQueryResponse};
+use crate::traits::query::Fallible;
+use rustc::ty::{ParamEnvAnd, TyCtxt};
+
+pub use rustc::traits::query::type_op::Subtype;
+
+impl<'tcx> super::QueryTypeOp<'tcx> for Subtype<'tcx> {
+    type QueryResponse = ();
+
+    fn try_fast_path(_tcx: TyCtxt<'tcx>, key: &ParamEnvAnd<'tcx, Self>) -> Option<()> {
+        if key.value.sub == key.value.sup { Some(()) } else { None }
+    }
+
+    fn perform_query(
+        tcx: TyCtxt<'tcx>,
+        canonicalized: Canonicalized<'tcx, ParamEnvAnd<'tcx, Self>>,
+    ) -> Fallible<CanonicalizedQueryResponse<'tcx, ()>> {
+        tcx.type_op_subtype(canonicalized)
+    }
+}
diff --git a/src/librustc_trait_selection/traits/select.rs b/src/librustc_trait_selection/traits/select.rs
new file mode 100644 (file)
index 0000000..ab3214d
--- /dev/null
@@ -0,0 +1,3790 @@
+// ignore-tidy-filelength
+
+//! Candidate selection. See the [rustc dev guide] for more information on how this works.
+//!
+//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/resolution.html#selection
+
+use self::EvaluationResult::*;
+use self::SelectionCandidate::*;
+
+use super::coherence::{self, Conflict};
+use super::project;
+use super::project::{normalize_with_depth, normalize_with_depth_to};
+use super::util;
+use super::util::{closure_trait_ref_and_return_type, predicate_for_trait_def};
+use super::wf;
+use super::DerivedObligationCause;
+use super::Selection;
+use super::SelectionResult;
+use super::TraitNotObjectSafe;
+use super::TraitQueryMode;
+use super::{BuiltinDerivedObligation, ImplDerivedObligation, ObligationCauseCode};
+use super::{Normalized, ProjectionCacheKey};
+use super::{ObjectCastObligation, Obligation};
+use super::{ObligationCause, PredicateObligation, TraitObligation};
+use super::{OutputTypeParameterMismatch, Overflow, SelectionError, Unimplemented};
+use super::{
+    VtableAutoImpl, VtableBuiltin, VtableClosure, VtableFnPointer, VtableGenerator, VtableImpl,
+    VtableObject, VtableParam, VtableTraitAlias,
+};
+use super::{
+    VtableAutoImplData, VtableBuiltinData, VtableClosureData, VtableFnPointerData,
+    VtableGeneratorData, VtableImplData, VtableObjectData, VtableTraitAliasData,
+};
+
+use crate::infer::{CombinedSnapshot, InferCtxt, InferOk, PlaceholderMap, TypeFreshener};
+use crate::traits::error_reporting::InferCtxtExt;
+use crate::traits::project::ProjectionCacheKeyExt;
+use rustc::dep_graph::{DepKind, DepNodeIndex};
+use rustc::middle::lang_items;
+use rustc::ty::fast_reject;
+use rustc::ty::relate::TypeRelation;
+use rustc::ty::subst::{Subst, SubstsRef};
+use rustc::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
+use rustc_ast::attr;
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
+use rustc_index::bit_set::GrowableBitSet;
+use rustc_span::symbol::sym;
+use rustc_target::spec::abi::Abi;
+
+use std::cell::{Cell, RefCell};
+use std::cmp;
+use std::fmt::{self, Display};
+use std::iter;
+use std::rc::Rc;
+
+pub use rustc::traits::select::*;
+
+pub struct SelectionContext<'cx, 'tcx> {
+    infcx: &'cx InferCtxt<'cx, 'tcx>,
+
+    /// Freshener used specifically for entries on the obligation
+    /// stack. This ensures that all entries on the stack at one time
+    /// will have the same set of placeholder entries, which is
+    /// important for checking for trait bounds that recursively
+    /// require themselves.
+    freshener: TypeFreshener<'cx, 'tcx>,
+
+    /// If `true`, indicates that the evaluation should be conservative
+    /// and consider the possibility of types outside this crate.
+    /// This comes up primarily when resolving ambiguity. Imagine
+    /// there is some trait reference `$0: Bar` where `$0` is an
+    /// inference variable. If `intercrate` is true, then we can never
+    /// say for sure that this reference is not implemented, even if
+    /// there are *no impls at all for `Bar`*, because `$0` could be
+    /// bound to some type that in a downstream crate that implements
+    /// `Bar`. This is the suitable mode for coherence. Elsewhere,
+    /// though, we set this to false, because we are only interested
+    /// in types that the user could actually have written --- in
+    /// other words, we consider `$0: Bar` to be unimplemented if
+    /// there is no type that the user could *actually name* that
+    /// would satisfy it. This avoids crippling inference, basically.
+    intercrate: bool,
+
+    intercrate_ambiguity_causes: Option<Vec<IntercrateAmbiguityCause>>,
+
+    /// Controls whether or not to filter out negative impls when selecting.
+    /// This is used in librustdoc to distinguish between the lack of an impl
+    /// and a negative impl
+    allow_negative_impls: bool,
+
+    /// The mode that trait queries run in, which informs our error handling
+    /// policy. In essence, canonicalized queries need their errors propagated
+    /// rather than immediately reported because we do not have accurate spans.
+    query_mode: TraitQueryMode,
+}
+
+// A stack that walks back up the stack frame.
+struct TraitObligationStack<'prev, 'tcx> {
+    obligation: &'prev TraitObligation<'tcx>,
+
+    /// The trait ref from `obligation` but "freshened" with the
+    /// selection-context's freshener. Used to check for recursion.
+    fresh_trait_ref: ty::PolyTraitRef<'tcx>,
+
+    /// Starts out equal to `depth` -- if, during evaluation, we
+    /// encounter a cycle, then we will set this flag to the minimum
+    /// depth of that cycle for all participants in the cycle. These
+    /// participants will then forego caching their results. This is
+    /// not the most efficient solution, but it addresses #60010. The
+    /// problem we are trying to prevent:
+    ///
+    /// - If you have `A: AutoTrait` requires `B: AutoTrait` and `C: NonAutoTrait`
+    /// - `B: AutoTrait` requires `A: AutoTrait` (coinductive cycle, ok)
+    /// - `C: NonAutoTrait` requires `A: AutoTrait` (non-coinductive cycle, not ok)
+    ///
+    /// you don't want to cache that `B: AutoTrait` or `A: AutoTrait`
+    /// is `EvaluatedToOk`; this is because they were only considered
+    /// ok on the premise that if `A: AutoTrait` held, but we indeed
+    /// encountered a problem (later on) with `A: AutoTrait. So we
+    /// currently set a flag on the stack node for `B: AutoTrait` (as
+    /// well as the second instance of `A: AutoTrait`) to suppress
+    /// caching.
+    ///
+    /// This is a simple, targeted fix. A more-performant fix requires
+    /// deeper changes, but would permit more caching: we could
+    /// basically defer caching until we have fully evaluated the
+    /// tree, and then cache the entire tree at once. In any case, the
+    /// performance impact here shouldn't be so horrible: every time
+    /// this is hit, we do cache at least one trait, so we only
+    /// evaluate each member of a cycle up to N times, where N is the
+    /// length of the cycle. This means the performance impact is
+    /// bounded and we shouldn't have any terrible worst-cases.
+    reached_depth: Cell<usize>,
+
+    previous: TraitObligationStackList<'prev, 'tcx>,
+
+    /// The number of parent frames plus one (thus, the topmost frame has depth 1).
+    depth: usize,
+
+    /// The depth-first number of this node in the search graph -- a
+    /// pre-order index. Basically, a freshly incremented counter.
+    dfn: usize,
+}
+
+struct SelectionCandidateSet<'tcx> {
+    // A list of candidates that definitely apply to the current
+    // obligation (meaning: types unify).
+    vec: Vec<SelectionCandidate<'tcx>>,
+
+    // If `true`, then there were candidates that might or might
+    // not have applied, but we couldn't tell. This occurs when some
+    // of the input types are type variables, in which case there are
+    // various "builtin" rules that might or might not trigger.
+    ambiguous: bool,
+}
+
+#[derive(PartialEq, Eq, Debug, Clone)]
+struct EvaluatedCandidate<'tcx> {
+    candidate: SelectionCandidate<'tcx>,
+    evaluation: EvaluationResult,
+}
+
+/// When does the builtin impl for `T: Trait` apply?
+enum BuiltinImplConditions<'tcx> {
+    /// The impl is conditional on `T1, T2, ...: Trait`.
+    Where(ty::Binder<Vec<Ty<'tcx>>>),
+    /// There is no built-in impl. There may be some other
+    /// candidate (a where-clause or user-defined impl).
+    None,
+    /// It is unknown whether there is an impl.
+    Ambiguous,
+}
+
+impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
+    pub fn new(infcx: &'cx InferCtxt<'cx, 'tcx>) -> SelectionContext<'cx, 'tcx> {
+        SelectionContext {
+            infcx,
+            freshener: infcx.freshener(),
+            intercrate: false,
+            intercrate_ambiguity_causes: None,
+            allow_negative_impls: false,
+            query_mode: TraitQueryMode::Standard,
+        }
+    }
+
+    pub fn intercrate(infcx: &'cx InferCtxt<'cx, 'tcx>) -> SelectionContext<'cx, 'tcx> {
+        SelectionContext {
+            infcx,
+            freshener: infcx.freshener(),
+            intercrate: true,
+            intercrate_ambiguity_causes: None,
+            allow_negative_impls: false,
+            query_mode: TraitQueryMode::Standard,
+        }
+    }
+
+    pub fn with_negative(
+        infcx: &'cx InferCtxt<'cx, 'tcx>,
+        allow_negative_impls: bool,
+    ) -> SelectionContext<'cx, 'tcx> {
+        debug!("with_negative({:?})", allow_negative_impls);
+        SelectionContext {
+            infcx,
+            freshener: infcx.freshener(),
+            intercrate: false,
+            intercrate_ambiguity_causes: None,
+            allow_negative_impls,
+            query_mode: TraitQueryMode::Standard,
+        }
+    }
+
+    pub fn with_query_mode(
+        infcx: &'cx InferCtxt<'cx, 'tcx>,
+        query_mode: TraitQueryMode,
+    ) -> SelectionContext<'cx, 'tcx> {
+        debug!("with_query_mode({:?})", query_mode);
+        SelectionContext {
+            infcx,
+            freshener: infcx.freshener(),
+            intercrate: false,
+            intercrate_ambiguity_causes: None,
+            allow_negative_impls: false,
+            query_mode,
+        }
+    }
+
+    /// Enables tracking of intercrate ambiguity causes. These are
+    /// used in coherence to give improved diagnostics. We don't do
+    /// this until we detect a coherence error because it can lead to
+    /// false overflow results (#47139) and because it costs
+    /// computation time.
+    pub fn enable_tracking_intercrate_ambiguity_causes(&mut self) {
+        assert!(self.intercrate);
+        assert!(self.intercrate_ambiguity_causes.is_none());
+        self.intercrate_ambiguity_causes = Some(vec![]);
+        debug!("selcx: enable_tracking_intercrate_ambiguity_causes");
+    }
+
+    /// Gets the intercrate ambiguity causes collected since tracking
+    /// was enabled and disables tracking at the same time. If
+    /// tracking is not enabled, just returns an empty vector.
+    pub fn take_intercrate_ambiguity_causes(&mut self) -> Vec<IntercrateAmbiguityCause> {
+        assert!(self.intercrate);
+        self.intercrate_ambiguity_causes.take().unwrap_or(vec![])
+    }
+
+    pub fn infcx(&self) -> &'cx InferCtxt<'cx, 'tcx> {
+        self.infcx
+    }
+
+    pub fn tcx(&self) -> TyCtxt<'tcx> {
+        self.infcx.tcx
+    }
+
+    pub fn closure_typer(&self) -> &'cx InferCtxt<'cx, 'tcx> {
+        self.infcx
+    }
+
+    ///////////////////////////////////////////////////////////////////////////
+    // Selection
+    //
+    // The selection phase tries to identify *how* an obligation will
+    // be resolved. For example, it will identify which impl or
+    // parameter bound is to be used. The process can be inconclusive
+    // if the self type in the obligation is not fully inferred. Selection
+    // can result in an error in one of two ways:
+    //
+    // 1. If no applicable impl or parameter bound can be found.
+    // 2. If the output type parameters in the obligation do not match
+    //    those specified by the impl/bound. For example, if the obligation
+    //    is `Vec<Foo>: Iterable<Bar>`, but the impl specifies
+    //    `impl<T> Iterable<T> for Vec<T>`, than an error would result.
+
+    /// Attempts to satisfy the obligation. If successful, this will affect the surrounding
+    /// type environment by performing unification.
+    pub fn select(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+    ) -> SelectionResult<'tcx, Selection<'tcx>> {
+        debug!("select({:?})", obligation);
+        debug_assert!(!obligation.predicate.has_escaping_bound_vars());
+
+        let pec = &ProvisionalEvaluationCache::default();
+        let stack = self.push_stack(TraitObligationStackList::empty(pec), obligation);
+
+        let candidate = match self.candidate_from_obligation(&stack) {
+            Err(SelectionError::Overflow) => {
+                // In standard mode, overflow must have been caught and reported
+                // earlier.
+                assert!(self.query_mode == TraitQueryMode::Canonical);
+                return Err(SelectionError::Overflow);
+            }
+            Err(e) => {
+                return Err(e);
+            }
+            Ok(None) => {
+                return Ok(None);
+            }
+            Ok(Some(candidate)) => candidate,
+        };
+
+        match self.confirm_candidate(obligation, candidate) {
+            Err(SelectionError::Overflow) => {
+                assert!(self.query_mode == TraitQueryMode::Canonical);
+                Err(SelectionError::Overflow)
+            }
+            Err(e) => Err(e),
+            Ok(candidate) => Ok(Some(candidate)),
+        }
+    }
+
+    ///////////////////////////////////////////////////////////////////////////
+    // EVALUATION
+    //
+    // Tests whether an obligation can be selected or whether an impl
+    // can be applied to particular types. It skips the "confirmation"
+    // step and hence completely ignores output type parameters.
+    //
+    // The result is "true" if the obligation *may* hold and "false" if
+    // we can be sure it does not.
+
+    /// Evaluates whether the obligation `obligation` can be satisfied (by any means).
+    pub fn predicate_may_hold_fatal(&mut self, obligation: &PredicateObligation<'tcx>) -> bool {
+        debug!("predicate_may_hold_fatal({:?})", obligation);
+
+        // This fatal query is a stopgap that should only be used in standard mode,
+        // where we do not expect overflow to be propagated.
+        assert!(self.query_mode == TraitQueryMode::Standard);
+
+        self.evaluate_root_obligation(obligation)
+            .expect("Overflow should be caught earlier in standard query mode")
+            .may_apply()
+    }
+
+    /// Evaluates whether the obligation `obligation` can be satisfied
+    /// and returns an `EvaluationResult`. This is meant for the
+    /// *initial* call.
+    pub fn evaluate_root_obligation(
+        &mut self,
+        obligation: &PredicateObligation<'tcx>,
+    ) -> Result<EvaluationResult, OverflowError> {
+        self.evaluation_probe(|this| {
+            this.evaluate_predicate_recursively(
+                TraitObligationStackList::empty(&ProvisionalEvaluationCache::default()),
+                obligation.clone(),
+            )
+        })
+    }
+
+    fn evaluation_probe(
+        &mut self,
+        op: impl FnOnce(&mut Self) -> Result<EvaluationResult, OverflowError>,
+    ) -> Result<EvaluationResult, OverflowError> {
+        self.infcx.probe(|snapshot| -> Result<EvaluationResult, OverflowError> {
+            let result = op(self)?;
+            match self.infcx.region_constraints_added_in_snapshot(snapshot) {
+                None => Ok(result),
+                Some(_) => Ok(result.max(EvaluatedToOkModuloRegions)),
+            }
+        })
+    }
+
+    /// Evaluates the predicates in `predicates` recursively. Note that
+    /// this applies projections in the predicates, and therefore
+    /// is run within an inference probe.
+    fn evaluate_predicates_recursively<'o, I>(
+        &mut self,
+        stack: TraitObligationStackList<'o, 'tcx>,
+        predicates: I,
+    ) -> Result<EvaluationResult, OverflowError>
+    where
+        I: IntoIterator<Item = PredicateObligation<'tcx>>,
+    {
+        let mut result = EvaluatedToOk;
+        for obligation in predicates {
+            let eval = self.evaluate_predicate_recursively(stack, obligation.clone())?;
+            debug!("evaluate_predicate_recursively({:?}) = {:?}", obligation, eval);
+            if let EvaluatedToErr = eval {
+                // fast-path - EvaluatedToErr is the top of the lattice,
+                // so we don't need to look on the other predicates.
+                return Ok(EvaluatedToErr);
+            } else {
+                result = cmp::max(result, eval);
+            }
+        }
+        Ok(result)
+    }
+
+    fn evaluate_predicate_recursively<'o>(
+        &mut self,
+        previous_stack: TraitObligationStackList<'o, 'tcx>,
+        obligation: PredicateObligation<'tcx>,
+    ) -> Result<EvaluationResult, OverflowError> {
+        debug!(
+            "evaluate_predicate_recursively(previous_stack={:?}, obligation={:?})",
+            previous_stack.head(),
+            obligation
+        );
+
+        // `previous_stack` stores a `TraitObligatiom`, while `obligation` is
+        // a `PredicateObligation`. These are distinct types, so we can't
+        // use any `Option` combinator method that would force them to be
+        // the same.
+        match previous_stack.head() {
+            Some(h) => self.check_recursion_limit(&obligation, h.obligation)?,
+            None => self.check_recursion_limit(&obligation, &obligation)?,
+        }
+
+        match obligation.predicate {
+            ty::Predicate::Trait(ref t, _) => {
+                debug_assert!(!t.has_escaping_bound_vars());
+                let obligation = obligation.with(t.clone());
+                self.evaluate_trait_predicate_recursively(previous_stack, obligation)
+            }
+
+            ty::Predicate::Subtype(ref p) => {
+                // Does this code ever run?
+                match self.infcx.subtype_predicate(&obligation.cause, obligation.param_env, p) {
+                    Some(Ok(InferOk { mut obligations, .. })) => {
+                        self.add_depth(obligations.iter_mut(), obligation.recursion_depth);
+                        self.evaluate_predicates_recursively(
+                            previous_stack,
+                            obligations.into_iter(),
+                        )
+                    }
+                    Some(Err(_)) => Ok(EvaluatedToErr),
+                    None => Ok(EvaluatedToAmbig),
+                }
+            }
+
+            ty::Predicate::WellFormed(ty) => match wf::obligations(
+                self.infcx,
+                obligation.param_env,
+                obligation.cause.body_id,
+                ty,
+                obligation.cause.span,
+            ) {
+                Some(mut obligations) => {
+                    self.add_depth(obligations.iter_mut(), obligation.recursion_depth);
+                    self.evaluate_predicates_recursively(previous_stack, obligations.into_iter())
+                }
+                None => Ok(EvaluatedToAmbig),
+            },
+
+            ty::Predicate::TypeOutlives(..) | ty::Predicate::RegionOutlives(..) => {
+                // We do not consider region relationships when evaluating trait matches.
+                Ok(EvaluatedToOkModuloRegions)
+            }
+
+            ty::Predicate::ObjectSafe(trait_def_id) => {
+                if self.tcx().is_object_safe(trait_def_id) {
+                    Ok(EvaluatedToOk)
+                } else {
+                    Ok(EvaluatedToErr)
+                }
+            }
+
+            ty::Predicate::Projection(ref data) => {
+                let project_obligation = obligation.with(data.clone());
+                match project::poly_project_and_unify_type(self, &project_obligation) {
+                    Ok(Some(mut subobligations)) => {
+                        self.add_depth(subobligations.iter_mut(), obligation.recursion_depth);
+                        let result = self.evaluate_predicates_recursively(
+                            previous_stack,
+                            subobligations.into_iter(),
+                        );
+                        if let Some(key) =
+                            ProjectionCacheKey::from_poly_projection_predicate(self, data)
+                        {
+                            self.infcx.inner.borrow_mut().projection_cache.complete(key);
+                        }
+                        result
+                    }
+                    Ok(None) => Ok(EvaluatedToAmbig),
+                    Err(_) => Ok(EvaluatedToErr),
+                }
+            }
+
+            ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => {
+                match self.infcx.closure_kind(closure_def_id, closure_substs) {
+                    Some(closure_kind) => {
+                        if closure_kind.extends(kind) {
+                            Ok(EvaluatedToOk)
+                        } else {
+                            Ok(EvaluatedToErr)
+                        }
+                    }
+                    None => Ok(EvaluatedToAmbig),
+                }
+            }
+
+            ty::Predicate::ConstEvaluatable(def_id, substs) => {
+                match self.tcx().const_eval_resolve(
+                    obligation.param_env,
+                    def_id,
+                    substs,
+                    None,
+                    None,
+                ) {
+                    Ok(_) => Ok(EvaluatedToOk),
+                    Err(_) => Ok(EvaluatedToErr),
+                }
+            }
+        }
+    }
+
+    fn evaluate_trait_predicate_recursively<'o>(
+        &mut self,
+        previous_stack: TraitObligationStackList<'o, 'tcx>,
+        mut obligation: TraitObligation<'tcx>,
+    ) -> Result<EvaluationResult, OverflowError> {
+        debug!("evaluate_trait_predicate_recursively({:?})", obligation);
+
+        if !self.intercrate
+            && obligation.is_global()
+            && obligation.param_env.caller_bounds.iter().all(|bound| bound.needs_subst())
+        {
+            // If a param env has no global bounds, global obligations do not
+            // depend on its particular value in order to work, so we can clear
+            // out the param env and get better caching.
+            debug!("evaluate_trait_predicate_recursively({:?}) - in global", obligation);
+            obligation.param_env = obligation.param_env.without_caller_bounds();
+        }
+
+        let stack = self.push_stack(previous_stack, &obligation);
+        let fresh_trait_ref = stack.fresh_trait_ref;
+        if let Some(result) = self.check_evaluation_cache(obligation.param_env, fresh_trait_ref) {
+            debug!("CACHE HIT: EVAL({:?})={:?}", fresh_trait_ref, result);
+            return Ok(result);
+        }
+
+        if let Some(result) = stack.cache().get_provisional(fresh_trait_ref) {
+            debug!("PROVISIONAL CACHE HIT: EVAL({:?})={:?}", fresh_trait_ref, result);
+            stack.update_reached_depth(stack.cache().current_reached_depth());
+            return Ok(result);
+        }
+
+        // Check if this is a match for something already on the
+        // stack. If so, we don't want to insert the result into the
+        // main cache (it is cycle dependent) nor the provisional
+        // cache (which is meant for things that have completed but
+        // for a "backedge" -- this result *is* the backedge).
+        if let Some(cycle_result) = self.check_evaluation_cycle(&stack) {
+            return Ok(cycle_result);
+        }
+
+        let (result, dep_node) = self.in_task(|this| this.evaluate_stack(&stack));
+        let result = result?;
+
+        if !result.must_apply_modulo_regions() {
+            stack.cache().on_failure(stack.dfn);
+        }
+
+        let reached_depth = stack.reached_depth.get();
+        if reached_depth >= stack.depth {
+            debug!("CACHE MISS: EVAL({:?})={:?}", fresh_trait_ref, result);
+            self.insert_evaluation_cache(obligation.param_env, fresh_trait_ref, dep_node, result);
+
+            stack.cache().on_completion(stack.depth, |fresh_trait_ref, provisional_result| {
+                self.insert_evaluation_cache(
+                    obligation.param_env,
+                    fresh_trait_ref,
+                    dep_node,
+                    provisional_result.max(result),
+                );
+            });
+        } else {
+            debug!("PROVISIONAL: {:?}={:?}", fresh_trait_ref, result);
+            debug!(
+                "evaluate_trait_predicate_recursively: caching provisionally because {:?} \
+                 is a cycle participant (at depth {}, reached depth {})",
+                fresh_trait_ref, stack.depth, reached_depth,
+            );
+
+            stack.cache().insert_provisional(stack.dfn, reached_depth, fresh_trait_ref, result);
+        }
+
+        Ok(result)
+    }
+
+    /// If there is any previous entry on the stack that precisely
+    /// matches this obligation, then we can assume that the
+    /// obligation is satisfied for now (still all other conditions
+    /// must be met of course). One obvious case this comes up is
+    /// marker traits like `Send`. Think of a linked list:
+    ///
+    ///    struct List<T> { data: T, next: Option<Box<List<T>>> }
+    ///
+    /// `Box<List<T>>` will be `Send` if `T` is `Send` and
+    /// `Option<Box<List<T>>>` is `Send`, and in turn
+    /// `Option<Box<List<T>>>` is `Send` if `Box<List<T>>` is
+    /// `Send`.
+    ///
+    /// Note that we do this comparison using the `fresh_trait_ref`
+    /// fields. Because these have all been freshened using
+    /// `self.freshener`, we can be sure that (a) this will not
+    /// affect the inferencer state and (b) that if we see two
+    /// fresh regions with the same index, they refer to the same
+    /// unbound type variable.
+    fn check_evaluation_cycle(
+        &mut self,
+        stack: &TraitObligationStack<'_, 'tcx>,
+    ) -> Option<EvaluationResult> {
+        if let Some(cycle_depth) = stack
+            .iter()
+            .skip(1) // Skip top-most frame.
+            .find(|prev| {
+                stack.obligation.param_env == prev.obligation.param_env
+                    && stack.fresh_trait_ref == prev.fresh_trait_ref
+            })
+            .map(|stack| stack.depth)
+        {
+            debug!(
+                "evaluate_stack({:?}) --> recursive at depth {}",
+                stack.fresh_trait_ref, cycle_depth,
+            );
+
+            // If we have a stack like `A B C D E A`, where the top of
+            // the stack is the final `A`, then this will iterate over
+            // `A, E, D, C, B` -- i.e., all the participants apart
+            // from the cycle head. We mark them as participating in a
+            // cycle. This suppresses caching for those nodes. See
+            // `in_cycle` field for more details.
+            stack.update_reached_depth(cycle_depth);
+
+            // Subtle: when checking for a coinductive cycle, we do
+            // not compare using the "freshened trait refs" (which
+            // have erased regions) but rather the fully explicit
+            // trait refs. This is important because it's only a cycle
+            // if the regions match exactly.
+            let cycle = stack.iter().skip(1).take_while(|s| s.depth >= cycle_depth);
+            let cycle = cycle.map(|stack| {
+                ty::Predicate::Trait(stack.obligation.predicate, hir::Constness::NotConst)
+            });
+            if self.coinductive_match(cycle) {
+                debug!("evaluate_stack({:?}) --> recursive, coinductive", stack.fresh_trait_ref);
+                Some(EvaluatedToOk)
+            } else {
+                debug!("evaluate_stack({:?}) --> recursive, inductive", stack.fresh_trait_ref);
+                Some(EvaluatedToRecur)
+            }
+        } else {
+            None
+        }
+    }
+
+    fn evaluate_stack<'o>(
+        &mut self,
+        stack: &TraitObligationStack<'o, 'tcx>,
+    ) -> Result<EvaluationResult, OverflowError> {
+        // In intercrate mode, whenever any of the types are unbound,
+        // there can always be an impl. Even if there are no impls in
+        // this crate, perhaps the type would be unified with
+        // something from another crate that does provide an impl.
+        //
+        // In intra mode, we must still be conservative. The reason is
+        // that we want to avoid cycles. Imagine an impl like:
+        //
+        //     impl<T:Eq> Eq for Vec<T>
+        //
+        // and a trait reference like `$0 : Eq` where `$0` is an
+        // unbound variable. When we evaluate this trait-reference, we
+        // will unify `$0` with `Vec<$1>` (for some fresh variable
+        // `$1`), on the condition that `$1 : Eq`. We will then wind
+        // up with many candidates (since that are other `Eq` impls
+        // that apply) and try to winnow things down. This results in
+        // a recursive evaluation that `$1 : Eq` -- as you can
+        // imagine, this is just where we started. To avoid that, we
+        // check for unbound variables and return an ambiguous (hence possible)
+        // match if we've seen this trait before.
+        //
+        // This suffices to allow chains like `FnMut` implemented in
+        // terms of `Fn` etc, but we could probably make this more
+        // precise still.
+        let unbound_input_types =
+            stack.fresh_trait_ref.skip_binder().input_types().any(|ty| ty.is_fresh());
+        // This check was an imperfect workaround for a bug in the old
+        // intercrate mode; it should be removed when that goes away.
+        if unbound_input_types && self.intercrate {
+            debug!(
+                "evaluate_stack({:?}) --> unbound argument, intercrate -->  ambiguous",
+                stack.fresh_trait_ref
+            );
+            // Heuristics: show the diagnostics when there are no candidates in crate.
+            if self.intercrate_ambiguity_causes.is_some() {
+                debug!("evaluate_stack: intercrate_ambiguity_causes is some");
+                if let Ok(candidate_set) = self.assemble_candidates(stack) {
+                    if !candidate_set.ambiguous && candidate_set.vec.is_empty() {
+                        let trait_ref = stack.obligation.predicate.skip_binder().trait_ref;
+                        let self_ty = trait_ref.self_ty();
+                        let cause = IntercrateAmbiguityCause::DownstreamCrate {
+                            trait_desc: trait_ref.print_only_trait_path().to_string(),
+                            self_desc: if self_ty.has_concrete_skeleton() {
+                                Some(self_ty.to_string())
+                            } else {
+                                None
+                            },
+                        };
+                        debug!("evaluate_stack: pushing cause = {:?}", cause);
+                        self.intercrate_ambiguity_causes.as_mut().unwrap().push(cause);
+                    }
+                }
+            }
+            return Ok(EvaluatedToAmbig);
+        }
+        if unbound_input_types
+            && stack.iter().skip(1).any(|prev| {
+                stack.obligation.param_env == prev.obligation.param_env
+                    && self.match_fresh_trait_refs(
+                        &stack.fresh_trait_ref,
+                        &prev.fresh_trait_ref,
+                        prev.obligation.param_env,
+                    )
+            })
+        {
+            debug!(
+                "evaluate_stack({:?}) --> unbound argument, recursive --> giving up",
+                stack.fresh_trait_ref
+            );
+            return Ok(EvaluatedToUnknown);
+        }
+
+        match self.candidate_from_obligation(stack) {
+            Ok(Some(c)) => self.evaluate_candidate(stack, &c),
+            Ok(None) => Ok(EvaluatedToAmbig),
+            Err(Overflow) => Err(OverflowError),
+            Err(..) => Ok(EvaluatedToErr),
+        }
+    }
+
+    /// For defaulted traits, we use a co-inductive strategy to solve, so
+    /// that recursion is ok. This routine returns `true` if the top of the
+    /// stack (`cycle[0]`):
+    ///
+    /// - is a defaulted trait,
+    /// - it also appears in the backtrace at some position `X`,
+    /// - all the predicates at positions `X..` between `X` and the top are
+    ///   also defaulted traits.
+    pub fn coinductive_match<I>(&mut self, cycle: I) -> bool
+    where
+        I: Iterator<Item = ty::Predicate<'tcx>>,
+    {
+        let mut cycle = cycle;
+        cycle.all(|predicate| self.coinductive_predicate(predicate))
+    }
+
+    fn coinductive_predicate(&self, predicate: ty::Predicate<'tcx>) -> bool {
+        let result = match predicate {
+            ty::Predicate::Trait(ref data, _) => self.tcx().trait_is_auto(data.def_id()),
+            _ => false,
+        };
+        debug!("coinductive_predicate({:?}) = {:?}", predicate, result);
+        result
+    }
+
+    /// Further evaluates `candidate` to decide whether all type parameters match and whether nested
+    /// obligations are met. Returns whether `candidate` remains viable after this further
+    /// scrutiny.
+    fn evaluate_candidate<'o>(
+        &mut self,
+        stack: &TraitObligationStack<'o, 'tcx>,
+        candidate: &SelectionCandidate<'tcx>,
+    ) -> Result<EvaluationResult, OverflowError> {
+        debug!(
+            "evaluate_candidate: depth={} candidate={:?}",
+            stack.obligation.recursion_depth, candidate
+        );
+        let result = self.evaluation_probe(|this| {
+            let candidate = (*candidate).clone();
+            match this.confirm_candidate(stack.obligation, candidate) {
+                Ok(selection) => this.evaluate_predicates_recursively(
+                    stack.list(),
+                    selection.nested_obligations().into_iter(),
+                ),
+                Err(..) => Ok(EvaluatedToErr),
+            }
+        })?;
+        debug!(
+            "evaluate_candidate: depth={} result={:?}",
+            stack.obligation.recursion_depth, result
+        );
+        Ok(result)
+    }
+
+    fn check_evaluation_cache(
+        &self,
+        param_env: ty::ParamEnv<'tcx>,
+        trait_ref: ty::PolyTraitRef<'tcx>,
+    ) -> Option<EvaluationResult> {
+        let tcx = self.tcx();
+        if self.can_use_global_caches(param_env) {
+            let cache = tcx.evaluation_cache.hashmap.borrow();
+            if let Some(cached) = cache.get(&param_env.and(trait_ref)) {
+                return Some(cached.get(tcx));
+            }
+        }
+        self.infcx
+            .evaluation_cache
+            .hashmap
+            .borrow()
+            .get(&param_env.and(trait_ref))
+            .map(|v| v.get(tcx))
+    }
+
+    fn insert_evaluation_cache(
+        &mut self,
+        param_env: ty::ParamEnv<'tcx>,
+        trait_ref: ty::PolyTraitRef<'tcx>,
+        dep_node: DepNodeIndex,
+        result: EvaluationResult,
+    ) {
+        // Avoid caching results that depend on more than just the trait-ref
+        // - the stack can create recursion.
+        if result.is_stack_dependent() {
+            return;
+        }
+
+        if self.can_use_global_caches(param_env) {
+            if !trait_ref.has_local_value() {
+                debug!(
+                    "insert_evaluation_cache(trait_ref={:?}, candidate={:?}) global",
+                    trait_ref, result,
+                );
+                // This may overwrite the cache with the same value
+                // FIXME: Due to #50507 this overwrites the different values
+                // This should be changed to use HashMapExt::insert_same
+                // when that is fixed
+                self.tcx()
+                    .evaluation_cache
+                    .hashmap
+                    .borrow_mut()
+                    .insert(param_env.and(trait_ref), WithDepNode::new(dep_node, result));
+                return;
+            }
+        }
+
+        debug!("insert_evaluation_cache(trait_ref={:?}, candidate={:?})", trait_ref, result,);
+        self.infcx
+            .evaluation_cache
+            .hashmap
+            .borrow_mut()
+            .insert(param_env.and(trait_ref), WithDepNode::new(dep_node, result));
+    }
+
+    /// For various reasons, it's possible for a subobligation
+    /// to have a *lower* recursion_depth than the obligation used to create it.
+    /// Projection sub-obligations may be returned from the projection cache,
+    /// which results in obligations with an 'old' `recursion_depth`.
+    /// Additionally, methods like `wf::obligations` and
+    /// `InferCtxt.subtype_predicate` produce subobligations without
+    /// taking in a 'parent' depth, causing the generated subobligations
+    /// to have a `recursion_depth` of `0`.
+    ///
+    /// To ensure that obligation_depth never decreasees, we force all subobligations
+    /// to have at least the depth of the original obligation.
+    fn add_depth<T: 'cx, I: Iterator<Item = &'cx mut Obligation<'tcx, T>>>(
+        &self,
+        it: I,
+        min_depth: usize,
+    ) {
+        it.for_each(|o| o.recursion_depth = cmp::max(min_depth, o.recursion_depth) + 1);
+    }
+
+    /// Checks that the recursion limit has not been exceeded.
+    ///
+    /// The weird return type of this function allows it to be used with the `try` (`?`)
+    /// operator within certain functions.
+    fn check_recursion_limit<T: Display + TypeFoldable<'tcx>, V: Display + TypeFoldable<'tcx>>(
+        &self,
+        obligation: &Obligation<'tcx, T>,
+        error_obligation: &Obligation<'tcx, V>,
+    ) -> Result<(), OverflowError> {
+        let recursion_limit = *self.infcx.tcx.sess.recursion_limit.get();
+        if obligation.recursion_depth >= recursion_limit {
+            match self.query_mode {
+                TraitQueryMode::Standard => {
+                    self.infcx().report_overflow_error(error_obligation, true);
+                }
+                TraitQueryMode::Canonical => {
+                    return Err(OverflowError);
+                }
+            }
+        }
+        Ok(())
+    }
+
+    ///////////////////////////////////////////////////////////////////////////
+    // CANDIDATE ASSEMBLY
+    //
+    // The selection process begins by examining all in-scope impls,
+    // caller obligations, and so forth and assembling a list of
+    // candidates. See the [rustc dev guide] for more details.
+    //
+    // [rustc dev guide]:
+    // https://rustc-dev-guide.rust-lang.org/traits/resolution.html#candidate-assembly
+
+    fn candidate_from_obligation<'o>(
+        &mut self,
+        stack: &TraitObligationStack<'o, 'tcx>,
+    ) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
+        // Watch out for overflow. This intentionally bypasses (and does
+        // not update) the cache.
+        self.check_recursion_limit(&stack.obligation, &stack.obligation)?;
+
+        // Check the cache. Note that we freshen the trait-ref
+        // separately rather than using `stack.fresh_trait_ref` --
+        // this is because we want the unbound variables to be
+        // replaced with fresh types starting from index 0.
+        let cache_fresh_trait_pred = self.infcx.freshen(stack.obligation.predicate.clone());
+        debug!(
+            "candidate_from_obligation(cache_fresh_trait_pred={:?}, obligation={:?})",
+            cache_fresh_trait_pred, stack
+        );
+        debug_assert!(!stack.obligation.predicate.has_escaping_bound_vars());
+
+        if let Some(c) =
+            self.check_candidate_cache(stack.obligation.param_env, &cache_fresh_trait_pred)
+        {
+            debug!("CACHE HIT: SELECT({:?})={:?}", cache_fresh_trait_pred, c);
+            return c;
+        }
+
+        // If no match, compute result and insert into cache.
+        //
+        // FIXME(nikomatsakis) -- this cache is not taking into
+        // account cycles that may have occurred in forming the
+        // candidate. I don't know of any specific problems that
+        // result but it seems awfully suspicious.
+        let (candidate, dep_node) =
+            self.in_task(|this| this.candidate_from_obligation_no_cache(stack));
+
+        debug!("CACHE MISS: SELECT({:?})={:?}", cache_fresh_trait_pred, candidate);
+        self.insert_candidate_cache(
+            stack.obligation.param_env,
+            cache_fresh_trait_pred,
+            dep_node,
+            candidate.clone(),
+        );
+        candidate
+    }
+
+    fn in_task<OP, R>(&mut self, op: OP) -> (R, DepNodeIndex)
+    where
+        OP: FnOnce(&mut Self) -> R,
+    {
+        let (result, dep_node) =
+            self.tcx().dep_graph.with_anon_task(DepKind::TraitSelect, || op(self));
+        self.tcx().dep_graph.read_index(dep_node);
+        (result, dep_node)
+    }
+
+    // Treat negative impls as unimplemented, and reservation impls as ambiguity.
+    fn filter_negative_and_reservation_impls(
+        &mut self,
+        candidate: SelectionCandidate<'tcx>,
+    ) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
+        if let ImplCandidate(def_id) = candidate {
+            let tcx = self.tcx();
+            match tcx.impl_polarity(def_id) {
+                ty::ImplPolarity::Negative if !self.allow_negative_impls => {
+                    return Err(Unimplemented);
+                }
+                ty::ImplPolarity::Reservation => {
+                    if let Some(intercrate_ambiguity_clauses) =
+                        &mut self.intercrate_ambiguity_causes
+                    {
+                        let attrs = tcx.get_attrs(def_id);
+                        let attr = attr::find_by_name(&attrs, sym::rustc_reservation_impl);
+                        let value = attr.and_then(|a| a.value_str());
+                        if let Some(value) = value {
+                            debug!(
+                                "filter_negative_and_reservation_impls: \
+                                 reservation impl ambiguity on {:?}",
+                                def_id
+                            );
+                            intercrate_ambiguity_clauses.push(
+                                IntercrateAmbiguityCause::ReservationImpl {
+                                    message: value.to_string(),
+                                },
+                            );
+                        }
+                    }
+                    return Ok(None);
+                }
+                _ => {}
+            };
+        }
+        Ok(Some(candidate))
+    }
+
+    fn candidate_from_obligation_no_cache<'o>(
+        &mut self,
+        stack: &TraitObligationStack<'o, 'tcx>,
+    ) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
+        if stack.obligation.predicate.references_error() {
+            // If we encounter a `Error`, we generally prefer the
+            // most "optimistic" result in response -- that is, the
+            // one least likely to report downstream errors. But
+            // because this routine is shared by coherence and by
+            // trait selection, there isn't an obvious "right" choice
+            // here in that respect, so we opt to just return
+            // ambiguity and let the upstream clients sort it out.
+            return Ok(None);
+        }
+
+        if let Some(conflict) = self.is_knowable(stack) {
+            debug!("coherence stage: not knowable");
+            if self.intercrate_ambiguity_causes.is_some() {
+                debug!("evaluate_stack: intercrate_ambiguity_causes is some");
+                // Heuristics: show the diagnostics when there are no candidates in crate.
+                if let Ok(candidate_set) = self.assemble_candidates(stack) {
+                    let mut no_candidates_apply = true;
+                    {
+                        let evaluated_candidates =
+                            candidate_set.vec.iter().map(|c| self.evaluate_candidate(stack, &c));
+
+                        for ec in evaluated_candidates {
+                            match ec {
+                                Ok(c) => {
+                                    if c.may_apply() {
+                                        no_candidates_apply = false;
+                                        break;
+                                    }
+                                }
+                                Err(e) => return Err(e.into()),
+                            }
+                        }
+                    }
+
+                    if !candidate_set.ambiguous && no_candidates_apply {
+                        let trait_ref = stack.obligation.predicate.skip_binder().trait_ref;
+                        let self_ty = trait_ref.self_ty();
+                        let trait_desc = trait_ref.print_only_trait_path().to_string();
+                        let self_desc = if self_ty.has_concrete_skeleton() {
+                            Some(self_ty.to_string())
+                        } else {
+                            None
+                        };
+                        let cause = if let Conflict::Upstream = conflict {
+                            IntercrateAmbiguityCause::UpstreamCrateUpdate { trait_desc, self_desc }
+                        } else {
+                            IntercrateAmbiguityCause::DownstreamCrate { trait_desc, self_desc }
+                        };
+                        debug!("evaluate_stack: pushing cause = {:?}", cause);
+                        self.intercrate_ambiguity_causes.as_mut().unwrap().push(cause);
+                    }
+                }
+            }
+            return Ok(None);
+        }
+
+        let candidate_set = self.assemble_candidates(stack)?;
+
+        if candidate_set.ambiguous {
+            debug!("candidate set contains ambig");
+            return Ok(None);
+        }
+
+        let mut candidates = candidate_set.vec;
+
+        debug!("assembled {} candidates for {:?}: {:?}", candidates.len(), stack, candidates);
+
+        // At this point, we know that each of the entries in the
+        // candidate set is *individually* applicable. Now we have to
+        // figure out if they contain mutual incompatibilities. This
+        // frequently arises if we have an unconstrained input type --
+        // for example, we are looking for `$0: Eq` where `$0` is some
+        // unconstrained type variable. In that case, we'll get a
+        // candidate which assumes $0 == int, one that assumes `$0 ==
+        // usize`, etc. This spells an ambiguity.
+
+        // If there is more than one candidate, first winnow them down
+        // by considering extra conditions (nested obligations and so
+        // forth). We don't winnow if there is exactly one
+        // candidate. This is a relatively minor distinction but it
+        // can lead to better inference and error-reporting. An
+        // example would be if there was an impl:
+        //
+        //     impl<T:Clone> Vec<T> { fn push_clone(...) { ... } }
+        //
+        // and we were to see some code `foo.push_clone()` where `boo`
+        // is a `Vec<Bar>` and `Bar` does not implement `Clone`.  If
+        // we were to winnow, we'd wind up with zero candidates.
+        // Instead, we select the right impl now but report "`Bar` does
+        // not implement `Clone`".
+        if candidates.len() == 1 {
+            return self.filter_negative_and_reservation_impls(candidates.pop().unwrap());
+        }
+
+        // Winnow, but record the exact outcome of evaluation, which
+        // is needed for specialization. Propagate overflow if it occurs.
+        let mut candidates = candidates
+            .into_iter()
+            .map(|c| match self.evaluate_candidate(stack, &c) {
+                Ok(eval) if eval.may_apply() => {
+                    Ok(Some(EvaluatedCandidate { candidate: c, evaluation: eval }))
+                }
+                Ok(_) => Ok(None),
+                Err(OverflowError) => Err(Overflow),
+            })
+            .flat_map(Result::transpose)
+            .collect::<Result<Vec<_>, _>>()?;
+
+        debug!("winnowed to {} candidates for {:?}: {:?}", candidates.len(), stack, candidates);
+
+        let needs_infer = stack.obligation.predicate.needs_infer();
+
+        // If there are STILL multiple candidates, we can further
+        // reduce the list by dropping duplicates -- including
+        // resolving specializations.
+        if candidates.len() > 1 {
+            let mut i = 0;
+            while i < candidates.len() {
+                let is_dup = (0..candidates.len()).filter(|&j| i != j).any(|j| {
+                    self.candidate_should_be_dropped_in_favor_of(
+                        &candidates[i],
+                        &candidates[j],
+                        needs_infer,
+                    )
+                });
+                if is_dup {
+                    debug!("Dropping candidate #{}/{}: {:?}", i, candidates.len(), candidates[i]);
+                    candidates.swap_remove(i);
+                } else {
+                    debug!("Retaining candidate #{}/{}: {:?}", i, candidates.len(), candidates[i]);
+                    i += 1;
+
+                    // If there are *STILL* multiple candidates, give up
+                    // and report ambiguity.
+                    if i > 1 {
+                        debug!("multiple matches, ambig");
+                        return Ok(None);
+                    }
+                }
+            }
+        }
+
+        // If there are *NO* candidates, then there are no impls --
+        // that we know of, anyway. Note that in the case where there
+        // are unbound type variables within the obligation, it might
+        // be the case that you could still satisfy the obligation
+        // from another crate by instantiating the type variables with
+        // a type from another crate that does have an impl. This case
+        // is checked for in `evaluate_stack` (and hence users
+        // who might care about this case, like coherence, should use
+        // that function).
+        if candidates.is_empty() {
+            return Err(Unimplemented);
+        }
+
+        // Just one candidate left.
+        self.filter_negative_and_reservation_impls(candidates.pop().unwrap().candidate)
+    }
+
+    fn is_knowable<'o>(&mut self, stack: &TraitObligationStack<'o, 'tcx>) -> Option<Conflict> {
+        debug!("is_knowable(intercrate={:?})", self.intercrate);
+
+        if !self.intercrate {
+            return None;
+        }
+
+        let obligation = &stack.obligation;
+        let predicate = self.infcx().resolve_vars_if_possible(&obligation.predicate);
+
+        // Okay to skip binder because of the nature of the
+        // trait-ref-is-knowable check, which does not care about
+        // bound regions.
+        let trait_ref = predicate.skip_binder().trait_ref;
+
+        coherence::trait_ref_is_knowable(self.tcx(), trait_ref)
+    }
+
+    /// Returns `true` if the global caches can be used.
+    /// Do note that if the type itself is not in the
+    /// global tcx, the local caches will be used.
+    fn can_use_global_caches(&self, param_env: ty::ParamEnv<'tcx>) -> bool {
+        // If there are any e.g. inference variables in the `ParamEnv`, then we
+        // always use a cache local to this particular scope. Otherwise, we
+        // switch to a global cache.
+        if param_env.has_local_value() {
+            return false;
+        }
+
+        // Avoid using the master cache during coherence and just rely
+        // on the local cache. This effectively disables caching
+        // during coherence. It is really just a simplification to
+        // avoid us having to fear that coherence results "pollute"
+        // the master cache. Since coherence executes pretty quickly,
+        // it's not worth going to more trouble to increase the
+        // hit-rate, I don't think.
+        if self.intercrate {
+            return false;
+        }
+
+        // Otherwise, we can use the global cache.
+        true
+    }
+
+    fn check_candidate_cache(
+        &mut self,
+        param_env: ty::ParamEnv<'tcx>,
+        cache_fresh_trait_pred: &ty::PolyTraitPredicate<'tcx>,
+    ) -> Option<SelectionResult<'tcx, SelectionCandidate<'tcx>>> {
+        let tcx = self.tcx();
+        let trait_ref = &cache_fresh_trait_pred.skip_binder().trait_ref;
+        if self.can_use_global_caches(param_env) {
+            let cache = tcx.selection_cache.hashmap.borrow();
+            if let Some(cached) = cache.get(&param_env.and(*trait_ref)) {
+                return Some(cached.get(tcx));
+            }
+        }
+        self.infcx
+            .selection_cache
+            .hashmap
+            .borrow()
+            .get(&param_env.and(*trait_ref))
+            .map(|v| v.get(tcx))
+    }
+
+    /// Determines whether can we safely cache the result
+    /// of selecting an obligation. This is almost always `true`,
+    /// except when dealing with certain `ParamCandidate`s.
+    ///
+    /// Ordinarily, a `ParamCandidate` will contain no inference variables,
+    /// since it was usually produced directly from a `DefId`. However,
+    /// certain cases (currently only librustdoc's blanket impl finder),
+    /// a `ParamEnv` may be explicitly constructed with inference types.
+    /// When this is the case, we do *not* want to cache the resulting selection
+    /// candidate. This is due to the fact that it might not always be possible
+    /// to equate the obligation's trait ref and the candidate's trait ref,
+    /// if more constraints end up getting added to an inference variable.
+    ///
+    /// Because of this, we always want to re-run the full selection
+    /// process for our obligation the next time we see it, since
+    /// we might end up picking a different `SelectionCandidate` (or none at all).
+    fn can_cache_candidate(
+        &self,
+        result: &SelectionResult<'tcx, SelectionCandidate<'tcx>>,
+    ) -> bool {
+        match result {
+            Ok(Some(SelectionCandidate::ParamCandidate(trait_ref))) => {
+                !trait_ref.skip_binder().input_types().any(|t| t.walk().any(|t_| t_.is_ty_infer()))
+            }
+            _ => true,
+        }
+    }
+
+    fn insert_candidate_cache(
+        &mut self,
+        param_env: ty::ParamEnv<'tcx>,
+        cache_fresh_trait_pred: ty::PolyTraitPredicate<'tcx>,
+        dep_node: DepNodeIndex,
+        candidate: SelectionResult<'tcx, SelectionCandidate<'tcx>>,
+    ) {
+        let tcx = self.tcx();
+        let trait_ref = cache_fresh_trait_pred.skip_binder().trait_ref;
+
+        if !self.can_cache_candidate(&candidate) {
+            debug!(
+                "insert_candidate_cache(trait_ref={:?}, candidate={:?} -\
+                 candidate is not cacheable",
+                trait_ref, candidate
+            );
+            return;
+        }
+
+        if self.can_use_global_caches(param_env) {
+            if let Err(Overflow) = candidate {
+                // Don't cache overflow globally; we only produce this in certain modes.
+            } else if !trait_ref.has_local_value() {
+                if !candidate.has_local_value() {
+                    debug!(
+                        "insert_candidate_cache(trait_ref={:?}, candidate={:?}) global",
+                        trait_ref, candidate,
+                    );
+                    // This may overwrite the cache with the same value.
+                    tcx.selection_cache
+                        .hashmap
+                        .borrow_mut()
+                        .insert(param_env.and(trait_ref), WithDepNode::new(dep_node, candidate));
+                    return;
+                }
+            }
+        }
+
+        debug!(
+            "insert_candidate_cache(trait_ref={:?}, candidate={:?}) local",
+            trait_ref, candidate,
+        );
+        self.infcx
+            .selection_cache
+            .hashmap
+            .borrow_mut()
+            .insert(param_env.and(trait_ref), WithDepNode::new(dep_node, candidate));
+    }
+
+    fn assemble_candidates<'o>(
+        &mut self,
+        stack: &TraitObligationStack<'o, 'tcx>,
+    ) -> Result<SelectionCandidateSet<'tcx>, SelectionError<'tcx>> {
+        let TraitObligationStack { obligation, .. } = *stack;
+        let obligation = &Obligation {
+            param_env: obligation.param_env,
+            cause: obligation.cause.clone(),
+            recursion_depth: obligation.recursion_depth,
+            predicate: self.infcx().resolve_vars_if_possible(&obligation.predicate),
+        };
+
+        if obligation.predicate.skip_binder().self_ty().is_ty_var() {
+            // Self is a type variable (e.g., `_: AsRef<str>`).
+            //
+            // This is somewhat problematic, as the current scheme can't really
+            // handle it turning to be a projection. This does end up as truly
+            // ambiguous in most cases anyway.
+            //
+            // Take the fast path out - this also improves
+            // performance by preventing assemble_candidates_from_impls from
+            // matching every impl for this trait.
+            return Ok(SelectionCandidateSet { vec: vec![], ambiguous: true });
+        }
+
+        let mut candidates = SelectionCandidateSet { vec: Vec::new(), ambiguous: false };
+
+        self.assemble_candidates_for_trait_alias(obligation, &mut candidates)?;
+
+        // Other bounds. Consider both in-scope bounds from fn decl
+        // and applicable impls. There is a certain set of precedence rules here.
+        let def_id = obligation.predicate.def_id();
+        let lang_items = self.tcx().lang_items();
+
+        if lang_items.copy_trait() == Some(def_id) {
+            debug!("obligation self ty is {:?}", obligation.predicate.skip_binder().self_ty());
+
+            // User-defined copy impls are permitted, but only for
+            // structs and enums.
+            self.assemble_candidates_from_impls(obligation, &mut candidates)?;
+
+            // For other types, we'll use the builtin rules.
+            let copy_conditions = self.copy_clone_conditions(obligation);
+            self.assemble_builtin_bound_candidates(copy_conditions, &mut candidates)?;
+        } else if lang_items.sized_trait() == Some(def_id) {
+            // Sized is never implementable by end-users, it is
+            // always automatically computed.
+            let sized_conditions = self.sized_conditions(obligation);
+            self.assemble_builtin_bound_candidates(sized_conditions, &mut candidates)?;
+        } else if lang_items.unsize_trait() == Some(def_id) {
+            self.assemble_candidates_for_unsizing(obligation, &mut candidates);
+        } else {
+            if lang_items.clone_trait() == Some(def_id) {
+                // Same builtin conditions as `Copy`, i.e., every type which has builtin support
+                // for `Copy` also has builtin support for `Clone`, and tuples/arrays of `Clone`
+                // types have builtin support for `Clone`.
+                let clone_conditions = self.copy_clone_conditions(obligation);
+                self.assemble_builtin_bound_candidates(clone_conditions, &mut candidates)?;
+            }
+
+            self.assemble_generator_candidates(obligation, &mut candidates)?;
+            self.assemble_closure_candidates(obligation, &mut candidates)?;
+            self.assemble_fn_pointer_candidates(obligation, &mut candidates)?;
+            self.assemble_candidates_from_impls(obligation, &mut candidates)?;
+            self.assemble_candidates_from_object_ty(obligation, &mut candidates);
+        }
+
+        self.assemble_candidates_from_projected_tys(obligation, &mut candidates);
+        self.assemble_candidates_from_caller_bounds(stack, &mut candidates)?;
+        // Auto implementations have lower priority, so we only
+        // consider triggering a default if there is no other impl that can apply.
+        if candidates.vec.is_empty() {
+            self.assemble_candidates_from_auto_impls(obligation, &mut candidates)?;
+        }
+        debug!("candidate list size: {}", candidates.vec.len());
+        Ok(candidates)
+    }
+
+    fn assemble_candidates_from_projected_tys(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+        candidates: &mut SelectionCandidateSet<'tcx>,
+    ) {
+        debug!("assemble_candidates_for_projected_tys({:?})", obligation);
+
+        // Before we go into the whole placeholder thing, just
+        // quickly check if the self-type is a projection at all.
+        match obligation.predicate.skip_binder().trait_ref.self_ty().kind {
+            ty::Projection(_) | ty::Opaque(..) => {}
+            ty::Infer(ty::TyVar(_)) => {
+                span_bug!(
+                    obligation.cause.span,
+                    "Self=_ should have been handled by assemble_candidates"
+                );
+            }
+            _ => return,
+        }
+
+        let result = self.infcx.probe(|snapshot| {
+            self.match_projection_obligation_against_definition_bounds(obligation, snapshot)
+        });
+
+        if result {
+            candidates.vec.push(ProjectionCandidate);
+        }
+    }
+
+    fn match_projection_obligation_against_definition_bounds(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+        snapshot: &CombinedSnapshot<'_, 'tcx>,
+    ) -> bool {
+        let poly_trait_predicate = self.infcx().resolve_vars_if_possible(&obligation.predicate);
+        let (placeholder_trait_predicate, placeholder_map) =
+            self.infcx().replace_bound_vars_with_placeholders(&poly_trait_predicate);
+        debug!(
+            "match_projection_obligation_against_definition_bounds: \
+             placeholder_trait_predicate={:?}",
+            placeholder_trait_predicate,
+        );
+
+        let (def_id, substs) = match placeholder_trait_predicate.trait_ref.self_ty().kind {
+            ty::Projection(ref data) => (data.trait_ref(self.tcx()).def_id, data.substs),
+            ty::Opaque(def_id, substs) => (def_id, substs),
+            _ => {
+                span_bug!(
+                    obligation.cause.span,
+                    "match_projection_obligation_against_definition_bounds() called \
+                     but self-ty is not a projection: {:?}",
+                    placeholder_trait_predicate.trait_ref.self_ty()
+                );
+            }
+        };
+        debug!(
+            "match_projection_obligation_against_definition_bounds: \
+             def_id={:?}, substs={:?}",
+            def_id, substs
+        );
+
+        let predicates_of = self.tcx().predicates_of(def_id);
+        let bounds = predicates_of.instantiate(self.tcx(), substs);
+        debug!(
+            "match_projection_obligation_against_definition_bounds: \
+             bounds={:?}",
+            bounds
+        );
+
+        let elaborated_predicates = util::elaborate_predicates(self.tcx(), bounds.predicates);
+        let matching_bound = elaborated_predicates.filter_to_traits().find(|bound| {
+            self.infcx.probe(|_| {
+                self.match_projection(
+                    obligation,
+                    bound.clone(),
+                    placeholder_trait_predicate.trait_ref.clone(),
+                    &placeholder_map,
+                    snapshot,
+                )
+            })
+        });
+
+        debug!(
+            "match_projection_obligation_against_definition_bounds: \
+             matching_bound={:?}",
+            matching_bound
+        );
+        match matching_bound {
+            None => false,
+            Some(bound) => {
+                // Repeat the successful match, if any, this time outside of a probe.
+                let result = self.match_projection(
+                    obligation,
+                    bound,
+                    placeholder_trait_predicate.trait_ref.clone(),
+                    &placeholder_map,
+                    snapshot,
+                );
+
+                assert!(result);
+                true
+            }
+        }
+    }
+
+    fn match_projection(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+        trait_bound: ty::PolyTraitRef<'tcx>,
+        placeholder_trait_ref: ty::TraitRef<'tcx>,
+        placeholder_map: &PlaceholderMap<'tcx>,
+        snapshot: &CombinedSnapshot<'_, 'tcx>,
+    ) -> bool {
+        debug_assert!(!placeholder_trait_ref.has_escaping_bound_vars());
+        self.infcx
+            .at(&obligation.cause, obligation.param_env)
+            .sup(ty::Binder::dummy(placeholder_trait_ref), trait_bound)
+            .is_ok()
+            && self.infcx.leak_check(false, placeholder_map, snapshot).is_ok()
+    }
+
+    /// Given an obligation like `<SomeTrait for T>`, searches the obligations that the caller
+    /// supplied to find out whether it is listed among them.
+    ///
+    /// Never affects the inference environment.
+    fn assemble_candidates_from_caller_bounds<'o>(
+        &mut self,
+        stack: &TraitObligationStack<'o, 'tcx>,
+        candidates: &mut SelectionCandidateSet<'tcx>,
+    ) -> Result<(), SelectionError<'tcx>> {
+        debug!("assemble_candidates_from_caller_bounds({:?})", stack.obligation);
+
+        let all_bounds = stack
+            .obligation
+            .param_env
+            .caller_bounds
+            .iter()
+            .filter_map(|o| o.to_opt_poly_trait_ref());
+
+        // Micro-optimization: filter out predicates relating to different traits.
+        let matching_bounds =
+            all_bounds.filter(|p| p.def_id() == stack.obligation.predicate.def_id());
+
+        // Keep only those bounds which may apply, and propagate overflow if it occurs.
+        let mut param_candidates = vec![];
+        for bound in matching_bounds {
+            let wc = self.evaluate_where_clause(stack, bound.clone())?;
+            if wc.may_apply() {
+                param_candidates.push(ParamCandidate(bound));
+            }
+        }
+
+        candidates.vec.extend(param_candidates);
+
+        Ok(())
+    }
+
+    fn evaluate_where_clause<'o>(
+        &mut self,
+        stack: &TraitObligationStack<'o, 'tcx>,
+        where_clause_trait_ref: ty::PolyTraitRef<'tcx>,
+    ) -> Result<EvaluationResult, OverflowError> {
+        self.evaluation_probe(|this| {
+            match this.match_where_clause_trait_ref(stack.obligation, where_clause_trait_ref) {
+                Ok(obligations) => {
+                    this.evaluate_predicates_recursively(stack.list(), obligations.into_iter())
+                }
+                Err(()) => Ok(EvaluatedToErr),
+            }
+        })
+    }
+
+    fn assemble_generator_candidates(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+        candidates: &mut SelectionCandidateSet<'tcx>,
+    ) -> Result<(), SelectionError<'tcx>> {
+        if self.tcx().lang_items().gen_trait() != Some(obligation.predicate.def_id()) {
+            return Ok(());
+        }
+
+        // Okay to skip binder because the substs on generator types never
+        // touch bound regions, they just capture the in-scope
+        // type/region parameters.
+        let self_ty = *obligation.self_ty().skip_binder();
+        match self_ty.kind {
+            ty::Generator(..) => {
+                debug!(
+                    "assemble_generator_candidates: self_ty={:?} obligation={:?}",
+                    self_ty, obligation
+                );
+
+                candidates.vec.push(GeneratorCandidate);
+            }
+            ty::Infer(ty::TyVar(_)) => {
+                debug!("assemble_generator_candidates: ambiguous self-type");
+                candidates.ambiguous = true;
+            }
+            _ => {}
+        }
+
+        Ok(())
+    }
+
+    /// Checks for the artificial impl that the compiler will create for an obligation like `X :
+    /// FnMut<..>` where `X` is a closure type.
+    ///
+    /// Note: the type parameters on a closure candidate are modeled as *output* type
+    /// parameters and hence do not affect whether this trait is a match or not. They will be
+    /// unified during the confirmation step.
+    fn assemble_closure_candidates(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+        candidates: &mut SelectionCandidateSet<'tcx>,
+    ) -> Result<(), SelectionError<'tcx>> {
+        let kind = match self.tcx().fn_trait_kind_from_lang_item(obligation.predicate.def_id()) {
+            Some(k) => k,
+            None => {
+                return Ok(());
+            }
+        };
+
+        // Okay to skip binder because the substs on closure types never
+        // touch bound regions, they just capture the in-scope
+        // type/region parameters
+        match obligation.self_ty().skip_binder().kind {
+            ty::Closure(closure_def_id, closure_substs) => {
+                debug!("assemble_unboxed_candidates: kind={:?} obligation={:?}", kind, obligation);
+                match self.infcx.closure_kind(closure_def_id, closure_substs) {
+                    Some(closure_kind) => {
+                        debug!("assemble_unboxed_candidates: closure_kind = {:?}", closure_kind);
+                        if closure_kind.extends(kind) {
+                            candidates.vec.push(ClosureCandidate);
+                        }
+                    }
+                    None => {
+                        debug!("assemble_unboxed_candidates: closure_kind not yet known");
+                        candidates.vec.push(ClosureCandidate);
+                    }
+                }
+            }
+            ty::Infer(ty::TyVar(_)) => {
+                debug!("assemble_unboxed_closure_candidates: ambiguous self-type");
+                candidates.ambiguous = true;
+            }
+            _ => {}
+        }
+
+        Ok(())
+    }
+
+    /// Implements one of the `Fn()` family for a fn pointer.
+    fn assemble_fn_pointer_candidates(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+        candidates: &mut SelectionCandidateSet<'tcx>,
+    ) -> Result<(), SelectionError<'tcx>> {
+        // We provide impl of all fn traits for fn pointers.
+        if self.tcx().fn_trait_kind_from_lang_item(obligation.predicate.def_id()).is_none() {
+            return Ok(());
+        }
+
+        // Okay to skip binder because what we are inspecting doesn't involve bound regions.
+        let self_ty = *obligation.self_ty().skip_binder();
+        match self_ty.kind {
+            ty::Infer(ty::TyVar(_)) => {
+                debug!("assemble_fn_pointer_candidates: ambiguous self-type");
+                candidates.ambiguous = true; // Could wind up being a fn() type.
+            }
+            // Provide an impl, but only for suitable `fn` pointers.
+            ty::FnDef(..) | ty::FnPtr(_) => {
+                if let ty::FnSig {
+                    unsafety: hir::Unsafety::Normal,
+                    abi: Abi::Rust,
+                    c_variadic: false,
+                    ..
+                } = self_ty.fn_sig(self.tcx()).skip_binder()
+                {
+                    candidates.vec.push(FnPointerCandidate);
+                }
+            }
+            _ => {}
+        }
+
+        Ok(())
+    }
+
+    /// Searches for impls that might apply to `obligation`.
+    fn assemble_candidates_from_impls(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+        candidates: &mut SelectionCandidateSet<'tcx>,
+    ) -> Result<(), SelectionError<'tcx>> {
+        debug!("assemble_candidates_from_impls(obligation={:?})", obligation);
+
+        self.tcx().for_each_relevant_impl(
+            obligation.predicate.def_id(),
+            obligation.predicate.skip_binder().trait_ref.self_ty(),
+            |impl_def_id| {
+                self.infcx.probe(|snapshot| {
+                    if let Ok(_substs) = self.match_impl(impl_def_id, obligation, snapshot) {
+                        candidates.vec.push(ImplCandidate(impl_def_id));
+                    }
+                });
+            },
+        );
+
+        Ok(())
+    }
+
+    fn assemble_candidates_from_auto_impls(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+        candidates: &mut SelectionCandidateSet<'tcx>,
+    ) -> Result<(), SelectionError<'tcx>> {
+        // Okay to skip binder here because the tests we do below do not involve bound regions.
+        let self_ty = *obligation.self_ty().skip_binder();
+        debug!("assemble_candidates_from_auto_impls(self_ty={:?})", self_ty);
+
+        let def_id = obligation.predicate.def_id();
+
+        if self.tcx().trait_is_auto(def_id) {
+            match self_ty.kind {
+                ty::Dynamic(..) => {
+                    // For object types, we don't know what the closed
+                    // over types are. This means we conservatively
+                    // say nothing; a candidate may be added by
+                    // `assemble_candidates_from_object_ty`.
+                }
+                ty::Foreign(..) => {
+                    // Since the contents of foreign types is unknown,
+                    // we don't add any `..` impl. Default traits could
+                    // still be provided by a manual implementation for
+                    // this trait and type.
+                }
+                ty::Param(..) | ty::Projection(..) => {
+                    // In these cases, we don't know what the actual
+                    // type is.  Therefore, we cannot break it down
+                    // into its constituent types. So we don't
+                    // consider the `..` impl but instead just add no
+                    // candidates: this means that typeck will only
+                    // succeed if there is another reason to believe
+                    // that this obligation holds. That could be a
+                    // where-clause or, in the case of an object type,
+                    // it could be that the object type lists the
+                    // trait (e.g., `Foo+Send : Send`). See
+                    // `compile-fail/typeck-default-trait-impl-send-param.rs`
+                    // for an example of a test case that exercises
+                    // this path.
+                }
+                ty::Infer(ty::TyVar(_)) => {
+                    // The auto impl might apply; we don't know.
+                    candidates.ambiguous = true;
+                }
+                ty::Generator(_, _, movability)
+                    if self.tcx().lang_items().unpin_trait() == Some(def_id) =>
+                {
+                    match movability {
+                        hir::Movability::Static => {
+                            // Immovable generators are never `Unpin`, so
+                            // suppress the normal auto-impl candidate for it.
+                        }
+                        hir::Movability::Movable => {
+                            // Movable generators are always `Unpin`, so add an
+                            // unconditional builtin candidate.
+                            candidates.vec.push(BuiltinCandidate { has_nested: false });
+                        }
+                    }
+                }
+
+                _ => candidates.vec.push(AutoImplCandidate(def_id)),
+            }
+        }
+
+        Ok(())
+    }
+
+    /// Searches for impls that might apply to `obligation`.
+    fn assemble_candidates_from_object_ty(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+        candidates: &mut SelectionCandidateSet<'tcx>,
+    ) {
+        debug!(
+            "assemble_candidates_from_object_ty(self_ty={:?})",
+            obligation.self_ty().skip_binder()
+        );
+
+        self.infcx.probe(|_snapshot| {
+            // The code below doesn't care about regions, and the
+            // self-ty here doesn't escape this probe, so just erase
+            // any LBR.
+            let self_ty = self.tcx().erase_late_bound_regions(&obligation.self_ty());
+            let poly_trait_ref = match self_ty.kind {
+                ty::Dynamic(ref data, ..) => {
+                    if data.auto_traits().any(|did| did == obligation.predicate.def_id()) {
+                        debug!(
+                            "assemble_candidates_from_object_ty: matched builtin bound, \
+                             pushing candidate"
+                        );
+                        candidates.vec.push(BuiltinObjectCandidate);
+                        return;
+                    }
+
+                    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;
+                        }
+                    } else {
+                        // Only auto trait bounds exist.
+                        return;
+                    }
+                }
+                ty::Infer(ty::TyVar(_)) => {
+                    debug!("assemble_candidates_from_object_ty: ambiguous");
+                    candidates.ambiguous = true; // could wind up being an object type
+                    return;
+                }
+                _ => return,
+            };
+
+            debug!("assemble_candidates_from_object_ty: poly_trait_ref={:?}", poly_trait_ref);
+
+            // Count only those upcast versions that match the trait-ref
+            // we are looking for. Specifically, do not only check for the
+            // correct trait, but also the correct type parameters.
+            // For example, we may be trying to upcast `Foo` to `Bar<i32>`,
+            // but `Foo` is declared as `trait Foo: Bar<u32>`.
+            let upcast_trait_refs = util::supertraits(self.tcx(), poly_trait_ref)
+                .filter(|upcast_trait_ref| {
+                    self.infcx
+                        .probe(|_| self.match_poly_trait_ref(obligation, *upcast_trait_ref).is_ok())
+                })
+                .count();
+
+            if upcast_trait_refs > 1 {
+                // Can be upcast in many ways; need more type information.
+                candidates.ambiguous = true;
+            } else if upcast_trait_refs == 1 {
+                candidates.vec.push(ObjectCandidate);
+            }
+        })
+    }
+
+    /// Searches for unsizing that might apply to `obligation`.
+    fn assemble_candidates_for_unsizing(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+        candidates: &mut SelectionCandidateSet<'tcx>,
+    ) {
+        // We currently never consider higher-ranked obligations e.g.
+        // `for<'a> &'a T: Unsize<Trait+'a>` to be implemented. This is not
+        // because they are a priori invalid, and we could potentially add support
+        // for them later, it's just that there isn't really a strong need for it.
+        // A `T: Unsize<U>` obligation is always used as part of a `T: CoerceUnsize<U>`
+        // impl, and those are generally applied to concrete types.
+        //
+        // That said, one might try to write a fn with a where clause like
+        //     for<'a> Foo<'a, T>: Unsize<Foo<'a, Trait>>
+        // where the `'a` is kind of orthogonal to the relevant part of the `Unsize`.
+        // Still, you'd be more likely to write that where clause as
+        //     T: Trait
+        // so it seems ok if we (conservatively) fail to accept that `Unsize`
+        // obligation above. Should be possible to extend this in the future.
+        let source = match obligation.self_ty().no_bound_vars() {
+            Some(t) => t,
+            None => {
+                // Don't add any candidates if there are bound regions.
+                return;
+            }
+        };
+        let target = obligation.predicate.skip_binder().trait_ref.substs.type_at(1);
+
+        debug!("assemble_candidates_for_unsizing(source={:?}, target={:?})", source, target);
+
+        let may_apply = match (&source.kind, &target.kind) {
+            // Trait+Kx+'a -> Trait+Ky+'b (upcasts).
+            (&ty::Dynamic(ref data_a, ..), &ty::Dynamic(ref data_b, ..)) => {
+                // Upcasts permit two things:
+                //
+                // 1. Dropping auto traits, e.g., `Foo + Send` to `Foo`
+                // 2. Tightening the region bound, e.g., `Foo + 'a` to `Foo + 'b` if `'a: 'b`
+                //
+                // Note that neither of these changes requires any
+                // change at runtime. Eventually this will be
+                // generalized.
+                //
+                // We always upcast when we can because of reason
+                // #2 (region bounds).
+                data_a.principal_def_id() == data_b.principal_def_id()
+                    && data_b
+                        .auto_traits()
+                        // All of a's auto traits need to be in b's auto traits.
+                        .all(|b| data_a.auto_traits().any(|a| a == b))
+            }
+
+            // `T` -> `Trait`
+            (_, &ty::Dynamic(..)) => true,
+
+            // Ambiguous handling is below `T` -> `Trait`, because inference
+            // variables can still implement `Unsize<Trait>` and nested
+            // obligations will have the final say (likely deferred).
+            (&ty::Infer(ty::TyVar(_)), _) | (_, &ty::Infer(ty::TyVar(_))) => {
+                debug!("assemble_candidates_for_unsizing: ambiguous");
+                candidates.ambiguous = true;
+                false
+            }
+
+            // `[T; n]` -> `[T]`
+            (&ty::Array(..), &ty::Slice(_)) => true,
+
+            // `Struct<T>` -> `Struct<U>`
+            (&ty::Adt(def_id_a, _), &ty::Adt(def_id_b, _)) if def_id_a.is_struct() => {
+                def_id_a == def_id_b
+            }
+
+            // `(.., T)` -> `(.., U)`
+            (&ty::Tuple(tys_a), &ty::Tuple(tys_b)) => tys_a.len() == tys_b.len(),
+
+            _ => false,
+        };
+
+        if may_apply {
+            candidates.vec.push(BuiltinUnsizeCandidate);
+        }
+    }
+
+    fn assemble_candidates_for_trait_alias(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+        candidates: &mut SelectionCandidateSet<'tcx>,
+    ) -> Result<(), SelectionError<'tcx>> {
+        // Okay to skip binder here because the tests we do below do not involve bound regions.
+        let self_ty = *obligation.self_ty().skip_binder();
+        debug!("assemble_candidates_for_trait_alias(self_ty={:?})", self_ty);
+
+        let def_id = obligation.predicate.def_id();
+
+        if self.tcx().is_trait_alias(def_id) {
+            candidates.vec.push(TraitAliasCandidate(def_id));
+        }
+
+        Ok(())
+    }
+
+    ///////////////////////////////////////////////////////////////////////////
+    // WINNOW
+    //
+    // Winnowing is the process of attempting to resolve ambiguity by
+    // probing further. During the winnowing process, we unify all
+    // type variables and then we also attempt to evaluate recursive
+    // bounds to see if they are satisfied.
+
+    /// Returns `true` if `victim` should be dropped in favor of
+    /// `other`. Generally speaking we will drop duplicate
+    /// candidates and prefer where-clause candidates.
+    ///
+    /// See the comment for "SelectionCandidate" for more details.
+    fn candidate_should_be_dropped_in_favor_of(
+        &mut self,
+        victim: &EvaluatedCandidate<'tcx>,
+        other: &EvaluatedCandidate<'tcx>,
+        needs_infer: bool,
+    ) -> bool {
+        if victim.candidate == other.candidate {
+            return true;
+        }
+
+        // Check if a bound would previously have been removed when normalizing
+        // the param_env so that it can be given the lowest priority. See
+        // #50825 for the motivation for this.
+        let is_global =
+            |cand: &ty::PolyTraitRef<'_>| cand.is_global() && !cand.has_late_bound_regions();
+
+        match other.candidate {
+            // Prefer `BuiltinCandidate { has_nested: false }` to anything else.
+            // This is a fix for #53123 and prevents winnowing from accidentally extending the
+            // lifetime of a variable.
+            BuiltinCandidate { has_nested: false } => true,
+            ParamCandidate(ref cand) => match victim.candidate {
+                AutoImplCandidate(..) => {
+                    bug!(
+                        "default implementations shouldn't be recorded \
+                         when there are other valid candidates"
+                    );
+                }
+                // Prefer `BuiltinCandidate { has_nested: false }` to anything else.
+                // This is a fix for #53123 and prevents winnowing from accidentally extending the
+                // lifetime of a variable.
+                BuiltinCandidate { has_nested: false } => false,
+                ImplCandidate(..)
+                | ClosureCandidate
+                | GeneratorCandidate
+                | FnPointerCandidate
+                | BuiltinObjectCandidate
+                | BuiltinUnsizeCandidate
+                | BuiltinCandidate { .. }
+                | TraitAliasCandidate(..) => {
+                    // Global bounds from the where clause should be ignored
+                    // here (see issue #50825). Otherwise, we have a where
+                    // clause so don't go around looking for impls.
+                    !is_global(cand)
+                }
+                ObjectCandidate | ProjectionCandidate => {
+                    // Arbitrarily give param candidates priority
+                    // over projection and object candidates.
+                    !is_global(cand)
+                }
+                ParamCandidate(..) => false,
+            },
+            ObjectCandidate | ProjectionCandidate => match victim.candidate {
+                AutoImplCandidate(..) => {
+                    bug!(
+                        "default implementations shouldn't be recorded \
+                         when there are other valid candidates"
+                    );
+                }
+                // Prefer `BuiltinCandidate { has_nested: false }` to anything else.
+                // This is a fix for #53123 and prevents winnowing from accidentally extending the
+                // lifetime of a variable.
+                BuiltinCandidate { has_nested: false } => false,
+                ImplCandidate(..)
+                | ClosureCandidate
+                | GeneratorCandidate
+                | FnPointerCandidate
+                | BuiltinObjectCandidate
+                | BuiltinUnsizeCandidate
+                | BuiltinCandidate { .. }
+                | TraitAliasCandidate(..) => true,
+                ObjectCandidate | ProjectionCandidate => {
+                    // Arbitrarily give param candidates priority
+                    // over projection and object candidates.
+                    true
+                }
+                ParamCandidate(ref cand) => is_global(cand),
+            },
+            ImplCandidate(other_def) => {
+                // See if we can toss out `victim` based on specialization.
+                // This requires us to know *for sure* that the `other` impl applies
+                // i.e., `EvaluatedToOk`.
+                if other.evaluation.must_apply_modulo_regions() {
+                    match victim.candidate {
+                        ImplCandidate(victim_def) => {
+                            let tcx = self.tcx();
+                            if tcx.specializes((other_def, victim_def)) {
+                                return true;
+                            }
+                            return match tcx.impls_are_allowed_to_overlap(other_def, victim_def) {
+                                Some(ty::ImplOverlapKind::Permitted { marker: true }) => {
+                                    // Subtle: If the predicate we are evaluating has inference
+                                    // variables, do *not* allow discarding candidates due to
+                                    // marker trait impls.
+                                    //
+                                    // Without this restriction, we could end up accidentally
+                                    // constrainting inference variables based on an arbitrarily
+                                    // chosen trait impl.
+                                    //
+                                    // Imagine we have the following code:
+                                    //
+                                    // ```rust
+                                    // #[marker] trait MyTrait {}
+                                    // impl MyTrait for u8 {}
+                                    // impl MyTrait for bool {}
+                                    // ```
+                                    //
+                                    // And we are evaluating the predicate `<_#0t as MyTrait>`.
+                                    //
+                                    // During selection, we will end up with one candidate for each
+                                    // impl of `MyTrait`. If we were to discard one impl in favor
+                                    // of the other, we would be left with one candidate, causing
+                                    // us to "successfully" select the predicate, unifying
+                                    // _#0t with (for example) `u8`.
+                                    //
+                                    // However, we have no reason to believe that this unification
+                                    // is correct - we've essentially just picked an arbitrary
+                                    // *possibility* for _#0t, and required that this be the *only*
+                                    // possibility.
+                                    //
+                                    // Eventually, we will either:
+                                    // 1) Unify all inference variables in the predicate through
+                                    // some other means (e.g. type-checking of a function). We will
+                                    // then be in a position to drop marker trait candidates
+                                    // without constraining inference variables (since there are
+                                    // none left to constrin)
+                                    // 2) Be left with some unconstrained inference variables. We
+                                    // will then correctly report an inference error, since the
+                                    // existence of multiple marker trait impls tells us nothing
+                                    // about which one should actually apply.
+                                    !needs_infer
+                                }
+                                Some(_) => true,
+                                None => false,
+                            };
+                        }
+                        ParamCandidate(ref cand) => {
+                            // Prefer the impl to a global where clause candidate.
+                            return is_global(cand);
+                        }
+                        _ => (),
+                    }
+                }
+
+                false
+            }
+            ClosureCandidate
+            | GeneratorCandidate
+            | FnPointerCandidate
+            | BuiltinObjectCandidate
+            | BuiltinUnsizeCandidate
+            | BuiltinCandidate { has_nested: true } => {
+                match victim.candidate {
+                    ParamCandidate(ref cand) => {
+                        // Prefer these to a global where-clause bound
+                        // (see issue #50825).
+                        is_global(cand) && other.evaluation.must_apply_modulo_regions()
+                    }
+                    _ => false,
+                }
+            }
+            _ => false,
+        }
+    }
+
+    ///////////////////////////////////////////////////////////////////////////
+    // BUILTIN BOUNDS
+    //
+    // These cover the traits that are built-in to the language
+    // itself: `Copy`, `Clone` and `Sized`.
+
+    fn assemble_builtin_bound_candidates(
+        &mut self,
+        conditions: BuiltinImplConditions<'tcx>,
+        candidates: &mut SelectionCandidateSet<'tcx>,
+    ) -> Result<(), SelectionError<'tcx>> {
+        match conditions {
+            BuiltinImplConditions::Where(nested) => {
+                debug!("builtin_bound: nested={:?}", nested);
+                candidates
+                    .vec
+                    .push(BuiltinCandidate { has_nested: !nested.skip_binder().is_empty() });
+            }
+            BuiltinImplConditions::None => {}
+            BuiltinImplConditions::Ambiguous => {
+                debug!("assemble_builtin_bound_candidates: ambiguous builtin");
+                candidates.ambiguous = true;
+            }
+        }
+
+        Ok(())
+    }
+
+    fn sized_conditions(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+    ) -> BuiltinImplConditions<'tcx> {
+        use self::BuiltinImplConditions::{Ambiguous, None, Where};
+
+        // NOTE: binder moved to (*)
+        let self_ty = self.infcx.shallow_resolve(obligation.predicate.skip_binder().self_ty());
+
+        match self_ty.kind {
+            ty::Infer(ty::IntVar(_))
+            | ty::Infer(ty::FloatVar(_))
+            | ty::Uint(_)
+            | ty::Int(_)
+            | ty::Bool
+            | ty::Float(_)
+            | ty::FnDef(..)
+            | ty::FnPtr(_)
+            | ty::RawPtr(..)
+            | ty::Char
+            | ty::Ref(..)
+            | ty::Generator(..)
+            | ty::GeneratorWitness(..)
+            | ty::Array(..)
+            | ty::Closure(..)
+            | ty::Never
+            | ty::Error => {
+                // safe for everything
+                Where(ty::Binder::dummy(Vec::new()))
+            }
+
+            ty::Str | ty::Slice(_) | ty::Dynamic(..) | ty::Foreign(..) => None,
+
+            ty::Tuple(tys) => {
+                Where(ty::Binder::bind(tys.last().into_iter().map(|k| k.expect_ty()).collect()))
+            }
+
+            ty::Adt(def, substs) => {
+                let sized_crit = def.sized_constraint(self.tcx());
+                // (*) binder moved here
+                Where(ty::Binder::bind(
+                    sized_crit.iter().map(|ty| ty.subst(self.tcx(), substs)).collect(),
+                ))
+            }
+
+            ty::Projection(_) | ty::Param(_) | ty::Opaque(..) => None,
+            ty::Infer(ty::TyVar(_)) => Ambiguous,
+
+            ty::UnnormalizedProjection(..)
+            | ty::Placeholder(..)
+            | ty::Bound(..)
+            | ty::Infer(ty::FreshTy(_))
+            | ty::Infer(ty::FreshIntTy(_))
+            | ty::Infer(ty::FreshFloatTy(_)) => {
+                bug!("asked to assemble builtin bounds of unexpected type: {:?}", self_ty);
+            }
+        }
+    }
+
+    fn copy_clone_conditions(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+    ) -> BuiltinImplConditions<'tcx> {
+        // NOTE: binder moved to (*)
+        let self_ty = self.infcx.shallow_resolve(obligation.predicate.skip_binder().self_ty());
+
+        use self::BuiltinImplConditions::{Ambiguous, None, Where};
+
+        match self_ty.kind {
+            ty::Infer(ty::IntVar(_))
+            | ty::Infer(ty::FloatVar(_))
+            | ty::FnDef(..)
+            | ty::FnPtr(_)
+            | ty::Error => Where(ty::Binder::dummy(Vec::new())),
+
+            ty::Uint(_)
+            | ty::Int(_)
+            | ty::Bool
+            | ty::Float(_)
+            | ty::Char
+            | ty::RawPtr(..)
+            | ty::Never
+            | ty::Ref(_, _, hir::Mutability::Not) => {
+                // Implementations provided in libcore
+                None
+            }
+
+            ty::Dynamic(..)
+            | ty::Str
+            | ty::Slice(..)
+            | ty::Generator(..)
+            | ty::GeneratorWitness(..)
+            | ty::Foreign(..)
+            | ty::Ref(_, _, hir::Mutability::Mut) => None,
+
+            ty::Array(element_ty, _) => {
+                // (*) binder moved here
+                Where(ty::Binder::bind(vec![element_ty]))
+            }
+
+            ty::Tuple(tys) => {
+                // (*) binder moved here
+                Where(ty::Binder::bind(tys.iter().map(|k| k.expect_ty()).collect()))
+            }
+
+            ty::Closure(def_id, substs) => {
+                // (*) binder moved here
+                Where(ty::Binder::bind(substs.as_closure().upvar_tys(def_id, self.tcx()).collect()))
+            }
+
+            ty::Adt(..) | ty::Projection(..) | ty::Param(..) | ty::Opaque(..) => {
+                // Fallback to whatever user-defined impls exist in this case.
+                None
+            }
+
+            ty::Infer(ty::TyVar(_)) => {
+                // Unbound type variable. Might or might not have
+                // applicable impls and so forth, depending on what
+                // those type variables wind up being bound to.
+                Ambiguous
+            }
+
+            ty::UnnormalizedProjection(..)
+            | ty::Placeholder(..)
+            | ty::Bound(..)
+            | ty::Infer(ty::FreshTy(_))
+            | ty::Infer(ty::FreshIntTy(_))
+            | ty::Infer(ty::FreshFloatTy(_)) => {
+                bug!("asked to assemble builtin bounds of unexpected type: {:?}", self_ty);
+            }
+        }
+    }
+
+    /// For default impls, we need to break apart a type into its
+    /// "constituent types" -- meaning, the types that it contains.
+    ///
+    /// Here are some (simple) examples:
+    ///
+    /// ```
+    /// (i32, u32) -> [i32, u32]
+    /// Foo where struct Foo { x: i32, y: u32 } -> [i32, u32]
+    /// Bar<i32> where struct Bar<T> { x: T, y: u32 } -> [i32, u32]
+    /// Zed<i32> where enum Zed { A(T), B(u32) } -> [i32, u32]
+    /// ```
+    fn constituent_types_for_ty(&self, t: Ty<'tcx>) -> Vec<Ty<'tcx>> {
+        match t.kind {
+            ty::Uint(_)
+            | ty::Int(_)
+            | ty::Bool
+            | ty::Float(_)
+            | ty::FnDef(..)
+            | ty::FnPtr(_)
+            | ty::Str
+            | ty::Error
+            | ty::Infer(ty::IntVar(_))
+            | ty::Infer(ty::FloatVar(_))
+            | ty::Never
+            | ty::Char => Vec::new(),
+
+            ty::UnnormalizedProjection(..)
+            | ty::Placeholder(..)
+            | ty::Dynamic(..)
+            | ty::Param(..)
+            | ty::Foreign(..)
+            | ty::Projection(..)
+            | ty::Bound(..)
+            | ty::Infer(ty::TyVar(_))
+            | ty::Infer(ty::FreshTy(_))
+            | ty::Infer(ty::FreshIntTy(_))
+            | ty::Infer(ty::FreshFloatTy(_)) => {
+                bug!("asked to assemble constituent types of unexpected type: {:?}", t);
+            }
+
+            ty::RawPtr(ty::TypeAndMut { ty: element_ty, .. }) | ty::Ref(_, element_ty, _) => {
+                vec![element_ty]
+            }
+
+            ty::Array(element_ty, _) | ty::Slice(element_ty) => vec![element_ty],
+
+            ty::Tuple(ref tys) => {
+                // (T1, ..., Tn) -- meets any bound that all of T1...Tn meet
+                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::Generator(def_id, ref substs, _) => {
+                let witness = substs.as_generator().witness(def_id, self.tcx());
+                substs
+                    .as_generator()
+                    .upvar_tys(def_id, self.tcx())
+                    .chain(iter::once(witness))
+                    .collect()
+            }
+
+            ty::GeneratorWitness(types) => {
+                // This is sound because no regions in the witness can refer to
+                // the binder outside the witness. So we'll effectivly reuse
+                // the implicit binder around the witness.
+                types.skip_binder().to_vec()
+            }
+
+            // For `PhantomData<T>`, we pass `T`.
+            ty::Adt(def, substs) if def.is_phantom_data() => substs.types().collect(),
+
+            ty::Adt(def, substs) => def.all_fields().map(|f| f.ty(self.tcx(), substs)).collect(),
+
+            ty::Opaque(def_id, substs) => {
+                // We can resolve the `impl Trait` to its concrete type,
+                // which enforces a DAG between the functions requiring
+                // the auto trait bounds in question.
+                vec![self.tcx().type_of(def_id).subst(self.tcx(), substs)]
+            }
+        }
+    }
+
+    fn collect_predicates_for_types(
+        &mut self,
+        param_env: ty::ParamEnv<'tcx>,
+        cause: ObligationCause<'tcx>,
+        recursion_depth: usize,
+        trait_def_id: DefId,
+        types: ty::Binder<Vec<Ty<'tcx>>>,
+    ) -> Vec<PredicateObligation<'tcx>> {
+        // Because the types were potentially derived from
+        // higher-ranked obligations they may reference late-bound
+        // regions. For example, `for<'a> Foo<&'a int> : Copy` would
+        // yield a type like `for<'a> &'a int`. In general, we
+        // maintain the invariant that we never manipulate bound
+        // regions, so we have to process these bound regions somehow.
+        //
+        // The strategy is to:
+        //
+        // 1. Instantiate those regions to placeholder regions (e.g.,
+        //    `for<'a> &'a int` becomes `&0 int`.
+        // 2. Produce something like `&'0 int : Copy`
+        // 3. Re-bind the regions back to `for<'a> &'a int : Copy`
+
+        types
+            .skip_binder()
+            .iter()
+            .flat_map(|ty| {
+                // binder moved -\
+                let ty: ty::Binder<Ty<'tcx>> = ty::Binder::bind(ty); // <----/
+
+                self.infcx.commit_unconditionally(|_| {
+                    let (skol_ty, _) = self.infcx.replace_bound_vars_with_placeholders(&ty);
+                    let Normalized { value: normalized_ty, mut obligations } =
+                        project::normalize_with_depth(
+                            self,
+                            param_env,
+                            cause.clone(),
+                            recursion_depth,
+                            &skol_ty,
+                        );
+                    let skol_obligation = predicate_for_trait_def(
+                        self.tcx(),
+                        param_env,
+                        cause.clone(),
+                        trait_def_id,
+                        recursion_depth,
+                        normalized_ty,
+                        &[],
+                    );
+                    obligations.push(skol_obligation);
+                    obligations
+                })
+            })
+            .collect()
+    }
+
+    ///////////////////////////////////////////////////////////////////////////
+    // CONFIRMATION
+    //
+    // Confirmation unifies the output type parameters of the trait
+    // with the values found in the obligation, possibly yielding a
+    // type error.  See the [rustc dev guide] for more details.
+    //
+    // [rustc dev guide]:
+    // https://rustc-dev-guide.rust-lang.org/traits/resolution.html#confirmation
+
+    fn confirm_candidate(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+        candidate: SelectionCandidate<'tcx>,
+    ) -> Result<Selection<'tcx>, SelectionError<'tcx>> {
+        debug!("confirm_candidate({:?}, {:?})", obligation, candidate);
+
+        match candidate {
+            BuiltinCandidate { has_nested } => {
+                let data = self.confirm_builtin_candidate(obligation, has_nested);
+                Ok(VtableBuiltin(data))
+            }
+
+            ParamCandidate(param) => {
+                let obligations = self.confirm_param_candidate(obligation, param);
+                Ok(VtableParam(obligations))
+            }
+
+            ImplCandidate(impl_def_id) => {
+                Ok(VtableImpl(self.confirm_impl_candidate(obligation, impl_def_id)))
+            }
+
+            AutoImplCandidate(trait_def_id) => {
+                let data = self.confirm_auto_impl_candidate(obligation, trait_def_id);
+                Ok(VtableAutoImpl(data))
+            }
+
+            ProjectionCandidate => {
+                self.confirm_projection_candidate(obligation);
+                Ok(VtableParam(Vec::new()))
+            }
+
+            ClosureCandidate => {
+                let vtable_closure = self.confirm_closure_candidate(obligation)?;
+                Ok(VtableClosure(vtable_closure))
+            }
+
+            GeneratorCandidate => {
+                let vtable_generator = self.confirm_generator_candidate(obligation)?;
+                Ok(VtableGenerator(vtable_generator))
+            }
+
+            FnPointerCandidate => {
+                let data = self.confirm_fn_pointer_candidate(obligation)?;
+                Ok(VtableFnPointer(data))
+            }
+
+            TraitAliasCandidate(alias_def_id) => {
+                let data = self.confirm_trait_alias_candidate(obligation, alias_def_id);
+                Ok(VtableTraitAlias(data))
+            }
+
+            ObjectCandidate => {
+                let data = self.confirm_object_candidate(obligation);
+                Ok(VtableObject(data))
+            }
+
+            BuiltinObjectCandidate => {
+                // This indicates something like `Trait + Send: Send`. In this case, we know that
+                // this holds because that's what the object type is telling us, and there's really
+                // no additional obligations to prove and no types in particular to unify, etc.
+                Ok(VtableParam(Vec::new()))
+            }
+
+            BuiltinUnsizeCandidate => {
+                let data = self.confirm_builtin_unsize_candidate(obligation)?;
+                Ok(VtableBuiltin(data))
+            }
+        }
+    }
+
+    fn confirm_projection_candidate(&mut self, obligation: &TraitObligation<'tcx>) {
+        self.infcx.commit_unconditionally(|snapshot| {
+            let result =
+                self.match_projection_obligation_against_definition_bounds(obligation, snapshot);
+            assert!(result);
+        })
+    }
+
+    fn confirm_param_candidate(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+        param: ty::PolyTraitRef<'tcx>,
+    ) -> Vec<PredicateObligation<'tcx>> {
+        debug!("confirm_param_candidate({:?},{:?})", obligation, param);
+
+        // During evaluation, we already checked that this
+        // where-clause trait-ref could be unified with the obligation
+        // trait-ref. Repeat that unification now without any
+        // transactional boundary; it should not fail.
+        match self.match_where_clause_trait_ref(obligation, param.clone()) {
+            Ok(obligations) => obligations,
+            Err(()) => {
+                bug!(
+                    "Where clause `{:?}` was applicable to `{:?}` but now is not",
+                    param,
+                    obligation
+                );
+            }
+        }
+    }
+
+    fn confirm_builtin_candidate(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+        has_nested: bool,
+    ) -> VtableBuiltinData<PredicateObligation<'tcx>> {
+        debug!("confirm_builtin_candidate({:?}, {:?})", obligation, has_nested);
+
+        let lang_items = self.tcx().lang_items();
+        let obligations = if has_nested {
+            let trait_def = obligation.predicate.def_id();
+            let conditions = if Some(trait_def) == lang_items.sized_trait() {
+                self.sized_conditions(obligation)
+            } else if Some(trait_def) == lang_items.copy_trait() {
+                self.copy_clone_conditions(obligation)
+            } else if Some(trait_def) == lang_items.clone_trait() {
+                self.copy_clone_conditions(obligation)
+            } else {
+                bug!("unexpected builtin trait {:?}", trait_def)
+            };
+            let nested = match conditions {
+                BuiltinImplConditions::Where(nested) => nested,
+                _ => bug!("obligation {:?} had matched a builtin impl but now doesn't", obligation),
+            };
+
+            let cause = obligation.derived_cause(BuiltinDerivedObligation);
+            self.collect_predicates_for_types(
+                obligation.param_env,
+                cause,
+                obligation.recursion_depth + 1,
+                trait_def,
+                nested,
+            )
+        } else {
+            vec![]
+        };
+
+        debug!("confirm_builtin_candidate: obligations={:?}", obligations);
+
+        VtableBuiltinData { nested: obligations }
+    }
+
+    /// This handles the case where a `auto trait Foo` impl is being used.
+    /// The idea is that the impl applies to `X : Foo` if the following conditions are met:
+    ///
+    /// 1. For each constituent type `Y` in `X`, `Y : Foo` holds
+    /// 2. For each where-clause `C` declared on `Foo`, `[Self => X] C` holds.
+    fn confirm_auto_impl_candidate(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+        trait_def_id: DefId,
+    ) -> VtableAutoImplData<PredicateObligation<'tcx>> {
+        debug!("confirm_auto_impl_candidate({:?}, {:?})", obligation, trait_def_id);
+
+        let types = obligation.predicate.map_bound(|inner| {
+            let self_ty = self.infcx.shallow_resolve(inner.self_ty());
+            self.constituent_types_for_ty(self_ty)
+        });
+        self.vtable_auto_impl(obligation, trait_def_id, types)
+    }
+
+    /// See `confirm_auto_impl_candidate`.
+    fn vtable_auto_impl(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+        trait_def_id: DefId,
+        nested: ty::Binder<Vec<Ty<'tcx>>>,
+    ) -> VtableAutoImplData<PredicateObligation<'tcx>> {
+        debug!("vtable_auto_impl: nested={:?}", nested);
+
+        let cause = obligation.derived_cause(BuiltinDerivedObligation);
+        let mut obligations = self.collect_predicates_for_types(
+            obligation.param_env,
+            cause,
+            obligation.recursion_depth + 1,
+            trait_def_id,
+            nested,
+        );
+
+        let trait_obligations: Vec<PredicateObligation<'_>> =
+            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,
+                )
+            });
+
+        // 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.
+        obligations.extend(trait_obligations);
+
+        debug!("vtable_auto_impl: obligations={:?}", obligations);
+
+        VtableAutoImplData { trait_def_id, nested: obligations }
+    }
+
+    fn confirm_impl_candidate(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+        impl_def_id: DefId,
+    ) -> VtableImplData<'tcx, PredicateObligation<'tcx>> {
+        debug!("confirm_impl_candidate({:?},{:?})", obligation, impl_def_id);
+
+        // First, create the substitutions by matching the impl again,
+        // this time not in a probe.
+        self.infcx.commit_unconditionally(|snapshot| {
+            let substs = self.rematch_impl(impl_def_id, obligation, snapshot);
+            debug!("confirm_impl_candidate: substs={:?}", substs);
+            let cause = obligation.derived_cause(ImplDerivedObligation);
+            self.vtable_impl(
+                impl_def_id,
+                substs,
+                cause,
+                obligation.recursion_depth + 1,
+                obligation.param_env,
+            )
+        })
+    }
+
+    fn vtable_impl(
+        &mut self,
+        impl_def_id: DefId,
+        mut substs: Normalized<'tcx, SubstsRef<'tcx>>,
+        cause: ObligationCause<'tcx>,
+        recursion_depth: usize,
+        param_env: ty::ParamEnv<'tcx>,
+    ) -> VtableImplData<'tcx, PredicateObligation<'tcx>> {
+        debug!(
+            "vtable_impl(impl_def_id={:?}, substs={:?}, recursion_depth={})",
+            impl_def_id, substs, recursion_depth,
+        );
+
+        let mut impl_obligations = self.impl_or_trait_obligations(
+            cause,
+            recursion_depth,
+            param_env,
+            impl_def_id,
+            &substs.value,
+        );
+
+        debug!(
+            "vtable_impl: impl_def_id={:?} impl_obligations={:?}",
+            impl_def_id, impl_obligations
+        );
+
+        // Because of RFC447, the impl-trait-ref and obligations
+        // are sufficient to determine the impl substs, without
+        // relying on projections in the impl-trait-ref.
+        //
+        // e.g., `impl<U: Tr, V: Iterator<Item=U>> Foo<<U as Tr>::T> for V`
+        impl_obligations.append(&mut substs.obligations);
+
+        VtableImplData { impl_def_id, substs: substs.value, nested: impl_obligations }
+    }
+
+    fn confirm_object_candidate(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+    ) -> VtableObjectData<'tcx, PredicateObligation<'tcx>> {
+        debug!("confirm_object_candidate({:?})", obligation);
+
+        // FIXME(nmatsakis) skipping binder here seems wrong -- we should
+        // probably flatten the binder from the obligation and the binder
+        // from the object. Have to try to make a broken test case that
+        // results.
+        let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder());
+        let poly_trait_ref = match self_ty.kind {
+            ty::Dynamic(ref data, ..) => data
+                .principal()
+                .unwrap_or_else(|| {
+                    span_bug!(obligation.cause.span, "object candidate with no principal")
+                })
+                .with_self_ty(self.tcx(), self_ty),
+            _ => span_bug!(obligation.cause.span, "object candidate with non-object"),
+        };
+
+        let mut upcast_trait_ref = None;
+        let mut nested = vec![];
+        let vtable_base;
+
+        {
+            let tcx = self.tcx();
+
+            // We want to find the first supertrait in the list of
+            // supertraits that we can unify with, and do that
+            // unification. We know that there is exactly one in the list
+            // where we can unify, because otherwise select would have
+            // reported an ambiguity. (When we do find a match, also
+            // record it for later.)
+            let nonmatching = util::supertraits(tcx, poly_trait_ref).take_while(|&t| {
+                match self.infcx.commit_if_ok(|_| self.match_poly_trait_ref(obligation, t)) {
+                    Ok(obligations) => {
+                        upcast_trait_ref = Some(t);
+                        nested.extend(obligations);
+                        false
+                    }
+                    Err(_) => true,
+                }
+            });
+
+            // Additionally, for each of the non-matching predicates that
+            // we pass over, we sum up the set of number of vtable
+            // entries, so that we can compute the offset for the selected
+            // trait.
+            vtable_base = nonmatching.map(|t| super::util::count_own_vtable_entries(tcx, t)).sum();
+        }
+
+        VtableObjectData { upcast_trait_ref: upcast_trait_ref.unwrap(), vtable_base, nested }
+    }
+
+    fn confirm_fn_pointer_candidate(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+    ) -> Result<VtableFnPointerData<'tcx, PredicateObligation<'tcx>>, SelectionError<'tcx>> {
+        debug!("confirm_fn_pointer_candidate({:?})", obligation);
+
+        // Okay to skip binder; it is reintroduced below.
+        let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder());
+        let sig = self_ty.fn_sig(self.tcx());
+        let trait_ref = closure_trait_ref_and_return_type(
+            self.tcx(),
+            obligation.predicate.def_id(),
+            self_ty,
+            sig,
+            util::TupleArgumentsFlag::Yes,
+        )
+        .map_bound(|(trait_ref, _)| trait_ref);
+
+        let Normalized { value: trait_ref, obligations } = project::normalize_with_depth(
+            self,
+            obligation.param_env,
+            obligation.cause.clone(),
+            obligation.recursion_depth + 1,
+            &trait_ref,
+        );
+
+        self.confirm_poly_trait_refs(
+            obligation.cause.clone(),
+            obligation.param_env,
+            obligation.predicate.to_poly_trait_ref(),
+            trait_ref,
+        )?;
+        Ok(VtableFnPointerData { fn_ty: self_ty, nested: obligations })
+    }
+
+    fn confirm_trait_alias_candidate(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+        alias_def_id: DefId,
+    ) -> VtableTraitAliasData<'tcx, PredicateObligation<'tcx>> {
+        debug!("confirm_trait_alias_candidate({:?}, {:?})", obligation, alias_def_id);
+
+        self.infcx.commit_unconditionally(|_| {
+            let (predicate, _) =
+                self.infcx().replace_bound_vars_with_placeholders(&obligation.predicate);
+            let trait_ref = predicate.trait_ref;
+            let trait_def_id = trait_ref.def_id;
+            let substs = trait_ref.substs;
+
+            let trait_obligations = self.impl_or_trait_obligations(
+                obligation.cause.clone(),
+                obligation.recursion_depth,
+                obligation.param_env,
+                trait_def_id,
+                &substs,
+            );
+
+            debug!(
+                "confirm_trait_alias_candidate: trait_def_id={:?} trait_obligations={:?}",
+                trait_def_id, trait_obligations
+            );
+
+            VtableTraitAliasData { alias_def_id, substs: substs, nested: trait_obligations }
+        })
+    }
+
+    fn confirm_generator_candidate(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+    ) -> Result<VtableGeneratorData<'tcx, PredicateObligation<'tcx>>, SelectionError<'tcx>> {
+        // Okay to skip binder because the substs on generator types never
+        // touch bound regions, they just capture the in-scope
+        // type/region parameters.
+        let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder());
+        let (generator_def_id, substs) = match self_ty.kind {
+            ty::Generator(id, substs, _) => (id, substs),
+            _ => bug!("closure candidate for non-closure {:?}", obligation),
+        };
+
+        debug!("confirm_generator_candidate({:?},{:?},{:?})", obligation, generator_def_id, substs);
+
+        let trait_ref = self.generator_trait_ref_unnormalized(obligation, generator_def_id, substs);
+        let Normalized { value: trait_ref, mut obligations } = normalize_with_depth(
+            self,
+            obligation.param_env,
+            obligation.cause.clone(),
+            obligation.recursion_depth + 1,
+            &trait_ref,
+        );
+
+        debug!(
+            "confirm_generator_candidate(generator_def_id={:?}, \
+             trait_ref={:?}, obligations={:?})",
+            generator_def_id, trait_ref, obligations
+        );
+
+        obligations.extend(self.confirm_poly_trait_refs(
+            obligation.cause.clone(),
+            obligation.param_env,
+            obligation.predicate.to_poly_trait_ref(),
+            trait_ref,
+        )?);
+
+        Ok(VtableGeneratorData { generator_def_id, substs, nested: obligations })
+    }
+
+    fn confirm_closure_candidate(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+    ) -> Result<VtableClosureData<'tcx, PredicateObligation<'tcx>>, SelectionError<'tcx>> {
+        debug!("confirm_closure_candidate({:?})", obligation);
+
+        let kind = self
+            .tcx()
+            .fn_trait_kind_from_lang_item(obligation.predicate.def_id())
+            .unwrap_or_else(|| bug!("closure candidate for non-fn trait {:?}", obligation));
+
+        // Okay to skip binder because the substs on closure types never
+        // touch bound regions, they just capture the in-scope
+        // type/region parameters.
+        let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder());
+        let (closure_def_id, substs) = match self_ty.kind {
+            ty::Closure(id, substs) => (id, substs),
+            _ => bug!("closure candidate for non-closure {:?}", obligation),
+        };
+
+        let trait_ref = self.closure_trait_ref_unnormalized(obligation, closure_def_id, substs);
+        let Normalized { value: trait_ref, mut obligations } = normalize_with_depth(
+            self,
+            obligation.param_env,
+            obligation.cause.clone(),
+            obligation.recursion_depth + 1,
+            &trait_ref,
+        );
+
+        debug!(
+            "confirm_closure_candidate(closure_def_id={:?}, trait_ref={:?}, obligations={:?})",
+            closure_def_id, trait_ref, obligations
+        );
+
+        obligations.extend(self.confirm_poly_trait_refs(
+            obligation.cause.clone(),
+            obligation.param_env,
+            obligation.predicate.to_poly_trait_ref(),
+            trait_ref,
+        )?);
+
+        obligations.push(Obligation::new(
+            obligation.cause.clone(),
+            obligation.param_env,
+            ty::Predicate::ClosureKind(closure_def_id, substs, kind),
+        ));
+
+        Ok(VtableClosureData { closure_def_id, substs, nested: obligations })
+    }
+
+    /// In the case of closure types and fn pointers,
+    /// we currently treat the input type parameters on the trait as
+    /// outputs. This means that when we have a match we have only
+    /// considered the self type, so we have to go back and make sure
+    /// to relate the argument types too. This is kind of wrong, but
+    /// since we control the full set of impls, also not that wrong,
+    /// and it DOES yield better error messages (since we don't report
+    /// errors as if there is no applicable impl, but rather report
+    /// errors are about mismatched argument types.
+    ///
+    /// Here is an example. Imagine we have a closure expression
+    /// and we desugared it so that the type of the expression is
+    /// `Closure`, and `Closure` expects an int as argument. Then it
+    /// is "as if" the compiler generated this impl:
+    ///
+    ///     impl Fn(int) for Closure { ... }
+    ///
+    /// Now imagine our obligation is `Fn(usize) for Closure`. So far
+    /// we have matched the self type `Closure`. At this point we'll
+    /// compare the `int` to `usize` and generate an error.
+    ///
+    /// Note that this checking occurs *after* the impl has selected,
+    /// because these output type parameters should not affect the
+    /// selection of the impl. Therefore, if there is a mismatch, we
+    /// report an error to the user.
+    fn confirm_poly_trait_refs(
+        &mut self,
+        obligation_cause: ObligationCause<'tcx>,
+        obligation_param_env: ty::ParamEnv<'tcx>,
+        obligation_trait_ref: ty::PolyTraitRef<'tcx>,
+        expected_trait_ref: ty::PolyTraitRef<'tcx>,
+    ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
+        self.infcx
+            .at(&obligation_cause, obligation_param_env)
+            .sup(obligation_trait_ref, expected_trait_ref)
+            .map(|InferOk { obligations, .. }| obligations)
+            .map_err(|e| OutputTypeParameterMismatch(expected_trait_ref, obligation_trait_ref, e))
+    }
+
+    fn confirm_builtin_unsize_candidate(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+    ) -> Result<VtableBuiltinData<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
+        let tcx = self.tcx();
+
+        // `assemble_candidates_for_unsizing` should ensure there are no late-bound
+        // regions here. See the comment there for more details.
+        let source = self.infcx.shallow_resolve(obligation.self_ty().no_bound_vars().unwrap());
+        let target = obligation.predicate.skip_binder().trait_ref.substs.type_at(1);
+        let target = self.infcx.shallow_resolve(target);
+
+        debug!("confirm_builtin_unsize_candidate(source={:?}, target={:?})", source, target);
+
+        let mut nested = vec![];
+        match (&source.kind, &target.kind) {
+            // Trait+Kx+'a -> Trait+Ky+'b (upcasts).
+            (&ty::Dynamic(ref data_a, r_a), &ty::Dynamic(ref data_b, r_b)) => {
+                // See `assemble_candidates_for_unsizing` for more info.
+                let existential_predicates = data_a.map_bound(|data_a| {
+                    let iter = data_a
+                        .principal()
+                        .map(|x| ty::ExistentialPredicate::Trait(x))
+                        .into_iter()
+                        .chain(
+                            data_a
+                                .projection_bounds()
+                                .map(|x| ty::ExistentialPredicate::Projection(x)),
+                        )
+                        .chain(data_b.auto_traits().map(ty::ExistentialPredicate::AutoTrait));
+                    tcx.mk_existential_predicates(iter)
+                });
+                let source_trait = tcx.mk_dynamic(existential_predicates, r_b);
+
+                // Require that the traits involved in this upcast are **equal**;
+                // only the **lifetime bound** is changed.
+                //
+                // FIXME: This condition is arguably too strong -- it would
+                // suffice for the source trait to be a *subtype* of the target
+                // trait. In particular, changing from something like
+                // `for<'a, 'b> Foo<'a, 'b>` to `for<'a> Foo<'a, 'a>` should be
+                // permitted. And, indeed, in the in commit
+                // 904a0bde93f0348f69914ee90b1f8b6e4e0d7cbc, this
+                // condition was loosened. However, when the leak check was
+                // added back, using subtype here actually guides the coercion
+                // code in such a way that it accepts `old-lub-glb-object.rs`.
+                // This is probably a good thing, but I've modified this to `.eq`
+                // because I want to continue rejecting that test (as we have
+                // done for quite some time) before we are firmly comfortable
+                // with what our behavior should be there. -nikomatsakis
+                let InferOk { obligations, .. } = self
+                    .infcx
+                    .at(&obligation.cause, obligation.param_env)
+                    .eq(target, source_trait) // FIXME -- see below
+                    .map_err(|_| Unimplemented)?;
+                nested.extend(obligations);
+
+                // Register one obligation for 'a: 'b.
+                let cause = ObligationCause::new(
+                    obligation.cause.span,
+                    obligation.cause.body_id,
+                    ObjectCastObligation(target),
+                );
+                let outlives = ty::OutlivesPredicate(r_a, r_b);
+                nested.push(Obligation::with_depth(
+                    cause,
+                    obligation.recursion_depth + 1,
+                    obligation.param_env,
+                    ty::Binder::bind(outlives).to_predicate(),
+                ));
+            }
+
+            // `T` -> `Trait`
+            (_, &ty::Dynamic(ref data, r)) => {
+                let mut object_dids = data.auto_traits().chain(data.principal_def_id());
+                if let Some(did) = object_dids.find(|did| !tcx.is_object_safe(*did)) {
+                    return Err(TraitNotObjectSafe(did));
+                }
+
+                let cause = ObligationCause::new(
+                    obligation.cause.span,
+                    obligation.cause.body_id,
+                    ObjectCastObligation(target),
+                );
+
+                let predicate_to_obligation = |predicate| {
+                    Obligation::with_depth(
+                        cause.clone(),
+                        obligation.recursion_depth + 1,
+                        obligation.param_env,
+                        predicate,
+                    )
+                };
+
+                // Create obligations:
+                //  - Casting `T` to `Trait`
+                //  - For all the various builtin bounds attached to the object cast. (In other
+                //  words, if the object type is `Foo + Send`, this would create an obligation for
+                //  the `Send` check.)
+                //  - Projection predicates
+                nested.extend(
+                    data.iter().map(|predicate| {
+                        predicate_to_obligation(predicate.with_self_ty(tcx, source))
+                    }),
+                );
+
+                // We can only make objects from sized types.
+                let tr = ty::TraitRef::new(
+                    tcx.require_lang_item(lang_items::SizedTraitLangItem, None),
+                    tcx.mk_substs_trait(source, &[]),
+                );
+                nested.push(predicate_to_obligation(tr.without_const().to_predicate()));
+
+                // If the type is `Foo + 'a`, ensure that the type
+                // being cast to `Foo + 'a` outlives `'a`:
+                let outlives = ty::OutlivesPredicate(source, r);
+                nested.push(predicate_to_obligation(ty::Binder::dummy(outlives).to_predicate()));
+            }
+
+            // `[T; n]` -> `[T]`
+            (&ty::Array(a, _), &ty::Slice(b)) => {
+                let InferOk { obligations, .. } = self
+                    .infcx
+                    .at(&obligation.cause, obligation.param_env)
+                    .eq(b, a)
+                    .map_err(|_| Unimplemented)?;
+                nested.extend(obligations);
+            }
+
+            // `Struct<T>` -> `Struct<U>`
+            (&ty::Adt(def, substs_a), &ty::Adt(_, substs_b)) => {
+                let fields =
+                    def.all_fields().map(|field| tcx.type_of(field.did)).collect::<Vec<_>>();
+
+                // The last field of the structure has to exist and contain type parameters.
+                let field = if let Some(&field) = fields.last() {
+                    field
+                } else {
+                    return Err(Unimplemented);
+                };
+                let mut ty_params = GrowableBitSet::new_empty();
+                let mut found = false;
+                for ty in field.walk() {
+                    if let ty::Param(p) = ty.kind {
+                        ty_params.insert(p.index as usize);
+                        found = true;
+                    }
+                }
+                if !found {
+                    return Err(Unimplemented);
+                }
+
+                // Replace type parameters used in unsizing with
+                // Error and ensure they do not affect any other fields.
+                // This could be checked after type collection for any struct
+                // with a potentially unsized trailing field.
+                let params = substs_a
+                    .iter()
+                    .enumerate()
+                    .map(|(i, &k)| if ty_params.contains(i) { tcx.types.err.into() } else { k });
+                let substs = tcx.mk_substs(params);
+                for &ty in fields.split_last().unwrap().1 {
+                    if ty.subst(tcx, substs).references_error() {
+                        return Err(Unimplemented);
+                    }
+                }
+
+                // Extract `Field<T>` and `Field<U>` from `Struct<T>` and `Struct<U>`.
+                let inner_source = field.subst(tcx, substs_a);
+                let inner_target = field.subst(tcx, substs_b);
+
+                // Check that the source struct with the target's
+                // unsized parameters is equal to the target.
+                let params = substs_a.iter().enumerate().map(|(i, &k)| {
+                    if ty_params.contains(i) { substs_b.type_at(i).into() } else { k }
+                });
+                let new_struct = tcx.mk_adt(def, tcx.mk_substs(params));
+                let InferOk { obligations, .. } = self
+                    .infcx
+                    .at(&obligation.cause, obligation.param_env)
+                    .eq(target, new_struct)
+                    .map_err(|_| Unimplemented)?;
+                nested.extend(obligations);
+
+                // Construct the nested `Field<T>: Unsize<Field<U>>` predicate.
+                nested.push(predicate_for_trait_def(
+                    tcx,
+                    obligation.param_env,
+                    obligation.cause.clone(),
+                    obligation.predicate.def_id(),
+                    obligation.recursion_depth + 1,
+                    inner_source,
+                    &[inner_target.into()],
+                ));
+            }
+
+            // `(.., T)` -> `(.., U)`
+            (&ty::Tuple(tys_a), &ty::Tuple(tys_b)) => {
+                assert_eq!(tys_a.len(), tys_b.len());
+
+                // The last field of the tuple has to exist.
+                let (&a_last, a_mid) = if let Some(x) = tys_a.split_last() {
+                    x
+                } else {
+                    return Err(Unimplemented);
+                };
+                let &b_last = tys_b.last().unwrap();
+
+                // Check that the source tuple with the target's
+                // last element is equal to the target.
+                let new_tuple = tcx.mk_tup(
+                    a_mid.iter().map(|k| k.expect_ty()).chain(iter::once(b_last.expect_ty())),
+                );
+                let InferOk { obligations, .. } = self
+                    .infcx
+                    .at(&obligation.cause, obligation.param_env)
+                    .eq(target, new_tuple)
+                    .map_err(|_| Unimplemented)?;
+                nested.extend(obligations);
+
+                // Construct the nested `T: Unsize<U>` predicate.
+                nested.push(predicate_for_trait_def(
+                    tcx,
+                    obligation.param_env,
+                    obligation.cause.clone(),
+                    obligation.predicate.def_id(),
+                    obligation.recursion_depth + 1,
+                    a_last.expect_ty(),
+                    &[b_last],
+                ));
+            }
+
+            _ => bug!(),
+        };
+
+        Ok(VtableBuiltinData { nested })
+    }
+
+    ///////////////////////////////////////////////////////////////////////////
+    // Matching
+    //
+    // Matching is a common path used for both evaluation and
+    // confirmation.  It basically unifies types that appear in impls
+    // and traits. This does affect the surrounding environment;
+    // therefore, when used during evaluation, match routines must be
+    // run inside of a `probe()` so that their side-effects are
+    // contained.
+
+    fn rematch_impl(
+        &mut self,
+        impl_def_id: DefId,
+        obligation: &TraitObligation<'tcx>,
+        snapshot: &CombinedSnapshot<'_, 'tcx>,
+    ) -> Normalized<'tcx, SubstsRef<'tcx>> {
+        match self.match_impl(impl_def_id, obligation, snapshot) {
+            Ok(substs) => substs,
+            Err(()) => {
+                bug!(
+                    "Impl {:?} was matchable against {:?} but now is not",
+                    impl_def_id,
+                    obligation
+                );
+            }
+        }
+    }
+
+    fn match_impl(
+        &mut self,
+        impl_def_id: DefId,
+        obligation: &TraitObligation<'tcx>,
+        snapshot: &CombinedSnapshot<'_, 'tcx>,
+    ) -> Result<Normalized<'tcx, SubstsRef<'tcx>>, ()> {
+        let impl_trait_ref = self.tcx().impl_trait_ref(impl_def_id).unwrap();
+
+        // Before we create the substitutions and everything, first
+        // consider a "quick reject". This avoids creating more types
+        // and so forth that we need to.
+        if self.fast_reject_trait_refs(obligation, &impl_trait_ref) {
+            return Err(());
+        }
+
+        let (skol_obligation, placeholder_map) =
+            self.infcx().replace_bound_vars_with_placeholders(&obligation.predicate);
+        let skol_obligation_trait_ref = skol_obligation.trait_ref;
+
+        let impl_substs = self.infcx.fresh_substs_for_item(obligation.cause.span, impl_def_id);
+
+        let impl_trait_ref = impl_trait_ref.subst(self.tcx(), impl_substs);
+
+        let Normalized { value: impl_trait_ref, obligations: mut nested_obligations } =
+            project::normalize_with_depth(
+                self,
+                obligation.param_env,
+                obligation.cause.clone(),
+                obligation.recursion_depth + 1,
+                &impl_trait_ref,
+            );
+
+        debug!(
+            "match_impl(impl_def_id={:?}, obligation={:?}, \
+             impl_trait_ref={:?}, skol_obligation_trait_ref={:?})",
+            impl_def_id, obligation, impl_trait_ref, skol_obligation_trait_ref
+        );
+
+        let InferOk { obligations, .. } = self
+            .infcx
+            .at(&obligation.cause, obligation.param_env)
+            .eq(skol_obligation_trait_ref, impl_trait_ref)
+            .map_err(|e| debug!("match_impl: failed eq_trait_refs due to `{}`", e))?;
+        nested_obligations.extend(obligations);
+
+        if let Err(e) = self.infcx.leak_check(false, &placeholder_map, snapshot) {
+            debug!("match_impl: failed leak check due to `{}`", e);
+            return Err(());
+        }
+
+        if !self.intercrate
+            && self.tcx().impl_polarity(impl_def_id) == ty::ImplPolarity::Reservation
+        {
+            debug!("match_impl: reservation impls only apply in intercrate mode");
+            return Err(());
+        }
+
+        debug!("match_impl: success impl_substs={:?}", impl_substs);
+        Ok(Normalized { value: impl_substs, obligations: nested_obligations })
+    }
+
+    fn fast_reject_trait_refs(
+        &mut self,
+        obligation: &TraitObligation<'_>,
+        impl_trait_ref: &ty::TraitRef<'_>,
+    ) -> bool {
+        // We can avoid creating type variables and doing the full
+        // substitution if we find that any of the input types, when
+        // simplified, do not match.
+
+        obligation.predicate.skip_binder().input_types().zip(impl_trait_ref.input_types()).any(
+            |(obligation_ty, impl_ty)| {
+                let simplified_obligation_ty =
+                    fast_reject::simplify_type(self.tcx(), obligation_ty, true);
+                let simplified_impl_ty = fast_reject::simplify_type(self.tcx(), impl_ty, false);
+
+                simplified_obligation_ty.is_some()
+                    && simplified_impl_ty.is_some()
+                    && simplified_obligation_ty != simplified_impl_ty
+            },
+        )
+    }
+
+    /// Normalize `where_clause_trait_ref` and try to match it against
+    /// `obligation`. If successful, return any predicates that
+    /// result from the normalization. Normalization is necessary
+    /// because where-clauses are stored in the parameter environment
+    /// unnormalized.
+    fn match_where_clause_trait_ref(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+        where_clause_trait_ref: ty::PolyTraitRef<'tcx>,
+    ) -> Result<Vec<PredicateObligation<'tcx>>, ()> {
+        self.match_poly_trait_ref(obligation, where_clause_trait_ref)
+    }
+
+    /// Returns `Ok` if `poly_trait_ref` being true implies that the
+    /// obligation is satisfied.
+    fn match_poly_trait_ref(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+        poly_trait_ref: ty::PolyTraitRef<'tcx>,
+    ) -> Result<Vec<PredicateObligation<'tcx>>, ()> {
+        debug!(
+            "match_poly_trait_ref: obligation={:?} poly_trait_ref={:?}",
+            obligation, poly_trait_ref
+        );
+
+        self.infcx
+            .at(&obligation.cause, obligation.param_env)
+            .sup(obligation.predicate.to_poly_trait_ref(), poly_trait_ref)
+            .map(|InferOk { obligations, .. }| obligations)
+            .map_err(|_| ())
+    }
+
+    ///////////////////////////////////////////////////////////////////////////
+    // Miscellany
+
+    fn match_fresh_trait_refs(
+        &self,
+        previous: &ty::PolyTraitRef<'tcx>,
+        current: &ty::PolyTraitRef<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+    ) -> bool {
+        let mut matcher = ty::_match::Match::new(self.tcx(), param_env);
+        matcher.relate(previous, current).is_ok()
+    }
+
+    fn push_stack<'o>(
+        &mut self,
+        previous_stack: TraitObligationStackList<'o, 'tcx>,
+        obligation: &'o TraitObligation<'tcx>,
+    ) -> TraitObligationStack<'o, 'tcx> {
+        let fresh_trait_ref =
+            obligation.predicate.to_poly_trait_ref().fold_with(&mut self.freshener);
+
+        let dfn = previous_stack.cache.next_dfn();
+        let depth = previous_stack.depth() + 1;
+        TraitObligationStack {
+            obligation,
+            fresh_trait_ref,
+            reached_depth: Cell::new(depth),
+            previous: previous_stack,
+            dfn,
+            depth,
+        }
+    }
+
+    fn closure_trait_ref_unnormalized(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+        closure_def_id: DefId,
+        substs: SubstsRef<'tcx>,
+    ) -> ty::PolyTraitRef<'tcx> {
+        debug!(
+            "closure_trait_ref_unnormalized(obligation={:?}, closure_def_id={:?}, substs={:?})",
+            obligation, closure_def_id, substs,
+        );
+        let closure_type = self.infcx.closure_sig(closure_def_id, substs);
+
+        debug!("closure_trait_ref_unnormalized: closure_type = {:?}", closure_type);
+
+        // (1) Feels icky to skip the binder here, but OTOH we know
+        // that the self-type is an unboxed closure type and hence is
+        // in fact unparameterized (or at least does not reference any
+        // regions bound in the obligation). Still probably some
+        // refactoring could make this nicer.
+        closure_trait_ref_and_return_type(
+            self.tcx(),
+            obligation.predicate.def_id(),
+            obligation.predicate.skip_binder().self_ty(), // (1)
+            closure_type,
+            util::TupleArgumentsFlag::No,
+        )
+        .map_bound(|(trait_ref, _)| trait_ref)
+    }
+
+    fn generator_trait_ref_unnormalized(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+        closure_def_id: DefId,
+        substs: SubstsRef<'tcx>,
+    ) -> ty::PolyTraitRef<'tcx> {
+        let gen_sig = substs.as_generator().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
+        // in fact unparameterized (or at least does not reference any
+        // regions bound in the obligation). Still probably some
+        // refactoring could make this nicer.
+
+        super::util::generator_trait_ref_and_outputs(
+            self.tcx(),
+            obligation.predicate.def_id(),
+            obligation.predicate.skip_binder().self_ty(), // (1)
+            gen_sig,
+        )
+        .map_bound(|(trait_ref, ..)| trait_ref)
+    }
+
+    /// Returns the obligations that are implied by instantiating an
+    /// impl or trait. The obligations are substituted and fully
+    /// normalized. This is used when confirming an impl or default
+    /// impl.
+    fn impl_or_trait_obligations(
+        &mut self,
+        cause: ObligationCause<'tcx>,
+        recursion_depth: usize,
+        param_env: ty::ParamEnv<'tcx>,
+        def_id: DefId,           // of impl or trait
+        substs: SubstsRef<'tcx>, // for impl or trait
+    ) -> Vec<PredicateObligation<'tcx>> {
+        debug!("impl_or_trait_obligations(def_id={:?})", def_id);
+        let tcx = self.tcx();
+
+        // To allow for one-pass evaluation of the nested obligation,
+        // each predicate must be preceded by the obligations required
+        // to normalize it.
+        // for example, if we have:
+        //    impl<U: Iterator<Item: Copy>, V: Iterator<Item = U>> Foo for V
+        // the impl will have the following predicates:
+        //    <V as Iterator>::Item = U,
+        //    U: Iterator, U: Sized,
+        //    V: Iterator, V: Sized,
+        //    <U as Iterator>::Item: Copy
+        // When we substitute, say, `V => IntoIter<u32>, U => $0`, the last
+        // obligation will normalize to `<$0 as Iterator>::Item = $1` and
+        // `$1: Copy`, so we must ensure the obligations are emitted in
+        // that order.
+        let predicates = tcx.predicates_of(def_id);
+        assert_eq!(predicates.parent, None);
+        let mut obligations = Vec::with_capacity(predicates.predicates.len());
+        for (predicate, _) in predicates.predicates {
+            let predicate = normalize_with_depth_to(
+                self,
+                param_env,
+                cause.clone(),
+                recursion_depth,
+                &predicate.subst(tcx, substs),
+                &mut obligations,
+            );
+            obligations.push(Obligation {
+                cause: cause.clone(),
+                recursion_depth,
+                param_env,
+                predicate,
+            });
+        }
+
+        // We are performing deduplication here to avoid exponential blowups
+        // (#38528) from happening, but the real cause of the duplication is
+        // unknown. What we know is that the deduplication avoids exponential
+        // amount of predicates being propagated when processing deeply nested
+        // types.
+        //
+        // This code is hot enough that it's worth avoiding the allocation
+        // required for the FxHashSet when possible. Special-casing lengths 0,
+        // 1 and 2 covers roughly 75-80% of the cases.
+        if obligations.len() <= 1 {
+            // No possibility of duplicates.
+        } else if obligations.len() == 2 {
+            // Only two elements. Drop the second if they are equal.
+            if obligations[0] == obligations[1] {
+                obligations.truncate(1);
+            }
+        } else {
+            // Three or more elements. Use a general deduplication process.
+            let mut seen = FxHashSet::default();
+            obligations.retain(|i| seen.insert(i.clone()));
+        }
+
+        obligations
+    }
+}
+
+trait TraitObligationExt<'tcx> {
+    fn derived_cause(
+        &self,
+        variant: fn(DerivedObligationCause<'tcx>) -> ObligationCauseCode<'tcx>,
+    ) -> ObligationCause<'tcx>;
+}
+
+impl<'tcx> TraitObligationExt<'tcx> for TraitObligation<'tcx> {
+    #[allow(unused_comparisons)]
+    fn derived_cause(
+        &self,
+        variant: fn(DerivedObligationCause<'tcx>) -> ObligationCauseCode<'tcx>,
+    ) -> ObligationCause<'tcx> {
+        /*!
+         * Creates a cause for obligations that are derived from
+         * `obligation` by a recursive search (e.g., for a builtin
+         * bound, or eventually a `auto trait Foo`). If `obligation`
+         * is itself a derived obligation, this is just a clone, but
+         * otherwise we create a "derived obligation" cause so as to
+         * keep track of the original root obligation for error
+         * reporting.
+         */
+
+        let obligation = self;
+
+        // NOTE(flaper87): As of now, it keeps track of the whole error
+        // chain. Ideally, we should have a way to configure this either
+        // by using -Z verbose or just a CLI argument.
+        let derived_cause = DerivedObligationCause {
+            parent_trait_ref: obligation.predicate.to_poly_trait_ref(),
+            parent_code: Rc::new(obligation.cause.code.clone()),
+        };
+        let derived_code = variant(derived_cause);
+        ObligationCause::new(obligation.cause.span, obligation.cause.body_id, derived_code)
+    }
+}
+
+impl<'o, 'tcx> TraitObligationStack<'o, 'tcx> {
+    fn list(&'o self) -> TraitObligationStackList<'o, 'tcx> {
+        TraitObligationStackList::with(self)
+    }
+
+    fn cache(&self) -> &'o ProvisionalEvaluationCache<'tcx> {
+        self.previous.cache
+    }
+
+    fn iter(&'o self) -> TraitObligationStackList<'o, 'tcx> {
+        self.list()
+    }
+
+    /// Indicates that attempting to evaluate this stack entry
+    /// required accessing something from the stack at depth `reached_depth`.
+    fn update_reached_depth(&self, reached_depth: usize) {
+        assert!(
+            self.depth > reached_depth,
+            "invoked `update_reached_depth` with something under this stack: \
+             self.depth={} reached_depth={}",
+            self.depth,
+            reached_depth,
+        );
+        debug!("update_reached_depth(reached_depth={})", reached_depth);
+        let mut p = self;
+        while reached_depth < p.depth {
+            debug!("update_reached_depth: marking {:?} as cycle participant", p.fresh_trait_ref);
+            p.reached_depth.set(p.reached_depth.get().min(reached_depth));
+            p = p.previous.head.unwrap();
+        }
+    }
+}
+
+/// The "provisional evaluation cache" is used to store intermediate cache results
+/// when solving auto traits. Auto traits are unusual in that they can support
+/// cycles. So, for example, a "proof tree" like this would be ok:
+///
+/// - `Foo<T>: Send` :-
+///   - `Bar<T>: Send` :-
+///     - `Foo<T>: Send` -- cycle, but ok
+///   - `Baz<T>: Send`
+///
+/// Here, to prove `Foo<T>: Send`, we have to prove `Bar<T>: Send` and
+/// `Baz<T>: Send`. Proving `Bar<T>: Send` in turn required `Foo<T>: Send`.
+/// For non-auto traits, this cycle would be an error, but for auto traits (because
+/// they are coinductive) it is considered ok.
+///
+/// However, there is a complication: at the point where we have
+/// "proven" `Bar<T>: Send`, we have in fact only proven it
+/// *provisionally*. In particular, we proved that `Bar<T>: Send`
+/// *under the assumption* that `Foo<T>: Send`. But what if we later
+/// find out this assumption is wrong?  Specifically, we could
+/// encounter some kind of error proving `Baz<T>: Send`. In that case,
+/// `Bar<T>: Send` didn't turn out to be true.
+///
+/// In Issue #60010, we found a bug in rustc where it would cache
+/// these intermediate results. This was fixed in #60444 by disabling
+/// *all* caching for things involved in a cycle -- in our example,
+/// that would mean we don't cache that `Bar<T>: Send`.  But this led
+/// to large slowdowns.
+///
+/// Specifically, imagine this scenario, where proving `Baz<T>: Send`
+/// first requires proving `Bar<T>: Send` (which is true:
+///
+/// - `Foo<T>: Send` :-
+///   - `Bar<T>: Send` :-
+///     - `Foo<T>: Send` -- cycle, but ok
+///   - `Baz<T>: Send`
+///     - `Bar<T>: Send` -- would be nice for this to be a cache hit!
+///     - `*const T: Send` -- but what if we later encounter an error?
+///
+/// The *provisional evaluation cache* resolves this issue. It stores
+/// cache results that we've proven but which were involved in a cycle
+/// in some way. We track the minimal stack depth (i.e., the
+/// farthest from the top of the stack) that we are dependent on.
+/// The idea is that the cache results within are all valid -- so long as
+/// none of the nodes in between the current node and the node at that minimum
+/// depth result in an error (in which case the cached results are just thrown away).
+///
+/// During evaluation, we consult this provisional cache and rely on
+/// it. Accessing a cached value is considered equivalent to accessing
+/// a result at `reached_depth`, so it marks the *current* solution as
+/// provisional as well. If an error is encountered, we toss out any
+/// provisional results added from the subtree that encountered the
+/// error.  When we pop the node at `reached_depth` from the stack, we
+/// can commit all the things that remain in the provisional cache.
+struct ProvisionalEvaluationCache<'tcx> {
+    /// next "depth first number" to issue -- just a counter
+    dfn: Cell<usize>,
+
+    /// Stores the "coldest" depth (bottom of stack) reached by any of
+    /// the evaluation entries. The idea here is that all things in the provisional
+    /// cache are always dependent on *something* that is colder in the stack:
+    /// therefore, if we add a new entry that is dependent on something *colder still*,
+    /// we have to modify the depth for all entries at once.
+    ///
+    /// Example:
+    ///
+    /// Imagine we have a stack `A B C D E` (with `E` being the top of
+    /// the stack).  We cache something with depth 2, which means that
+    /// it was dependent on C.  Then we pop E but go on and process a
+    /// new node F: A B C D F.  Now F adds something to the cache with
+    /// depth 1, meaning it is dependent on B.  Our original cache
+    /// entry is also dependent on B, because there is a path from E
+    /// to C and then from C to F and from F to B.
+    reached_depth: Cell<usize>,
+
+    /// Map from cache key to the provisionally evaluated thing.
+    /// The cache entries contain the result but also the DFN in which they
+    /// were added. The DFN is used to clear out values on failure.
+    ///
+    /// Imagine we have a stack like:
+    ///
+    /// - `A B C` and we add a cache for the result of C (DFN 2)
+    /// - Then we have a stack `A B D` where `D` has DFN 3
+    /// - We try to solve D by evaluating E: `A B D E` (DFN 4)
+    /// - `E` generates various cache entries which have cyclic dependices on `B`
+    ///   - `A B D E F` and so forth
+    ///   - the DFN of `F` for example would be 5
+    /// - then we determine that `E` is in error -- we will then clear
+    ///   all cache values whose DFN is >= 4 -- in this case, that
+    ///   means the cached value for `F`.
+    map: RefCell<FxHashMap<ty::PolyTraitRef<'tcx>, ProvisionalEvaluation>>,
+}
+
+/// A cache value for the provisional cache: contains the depth-first
+/// number (DFN) and result.
+#[derive(Copy, Clone, Debug)]
+struct ProvisionalEvaluation {
+    from_dfn: usize,
+    result: EvaluationResult,
+}
+
+impl<'tcx> Default for ProvisionalEvaluationCache<'tcx> {
+    fn default() -> Self {
+        Self {
+            dfn: Cell::new(0),
+            reached_depth: Cell::new(std::usize::MAX),
+            map: Default::default(),
+        }
+    }
+}
+
+impl<'tcx> ProvisionalEvaluationCache<'tcx> {
+    /// Get the next DFN in sequence (basically a counter).
+    fn next_dfn(&self) -> usize {
+        let result = self.dfn.get();
+        self.dfn.set(result + 1);
+        result
+    }
+
+    /// Check the provisional cache for any result for
+    /// `fresh_trait_ref`. If there is a hit, then you must consider
+    /// it an access to the stack slots at depth
+    /// `self.current_reached_depth()` and above.
+    fn get_provisional(&self, fresh_trait_ref: ty::PolyTraitRef<'tcx>) -> Option<EvaluationResult> {
+        debug!(
+            "get_provisional(fresh_trait_ref={:?}) = {:#?} with reached-depth {}",
+            fresh_trait_ref,
+            self.map.borrow().get(&fresh_trait_ref),
+            self.reached_depth.get(),
+        );
+        Some(self.map.borrow().get(&fresh_trait_ref)?.result)
+    }
+
+    /// Current value of the `reached_depth` counter -- all the
+    /// provisional cache entries are dependent on the item at this
+    /// depth.
+    fn current_reached_depth(&self) -> usize {
+        self.reached_depth.get()
+    }
+
+    /// Insert a provisional result into the cache. The result came
+    /// from the node with the given DFN. It accessed a minimum depth
+    /// of `reached_depth` to compute. It evaluated `fresh_trait_ref`
+    /// and resulted in `result`.
+    fn insert_provisional(
+        &self,
+        from_dfn: usize,
+        reached_depth: usize,
+        fresh_trait_ref: ty::PolyTraitRef<'tcx>,
+        result: EvaluationResult,
+    ) {
+        debug!(
+            "insert_provisional(from_dfn={}, reached_depth={}, fresh_trait_ref={:?}, result={:?})",
+            from_dfn, reached_depth, fresh_trait_ref, result,
+        );
+        let r_d = self.reached_depth.get();
+        self.reached_depth.set(r_d.min(reached_depth));
+
+        debug!("insert_provisional: reached_depth={:?}", self.reached_depth.get());
+
+        self.map.borrow_mut().insert(fresh_trait_ref, ProvisionalEvaluation { from_dfn, result });
+    }
+
+    /// Invoked when the node with dfn `dfn` does not get a successful
+    /// result.  This will clear out any provisional cache entries
+    /// that were added since `dfn` was created. This is because the
+    /// provisional entries are things which must assume that the
+    /// things on the stack at the time of their creation succeeded --
+    /// since the failing node is presently at the top of the stack,
+    /// these provisional entries must either depend on it or some
+    /// ancestor of it.
+    fn on_failure(&self, dfn: usize) {
+        debug!("on_failure(dfn={:?})", dfn,);
+        self.map.borrow_mut().retain(|key, eval| {
+            if !eval.from_dfn >= dfn {
+                debug!("on_failure: removing {:?}", key);
+                false
+            } else {
+                true
+            }
+        });
+    }
+
+    /// Invoked when the node at depth `depth` completed without
+    /// depending on anything higher in the stack (if that completion
+    /// was a failure, then `on_failure` should have been invoked
+    /// already). The callback `op` will be invoked for each
+    /// provisional entry that we can now confirm.
+    fn on_completion(
+        &self,
+        depth: usize,
+        mut op: impl FnMut(ty::PolyTraitRef<'tcx>, EvaluationResult),
+    ) {
+        debug!("on_completion(depth={}, reached_depth={})", depth, self.reached_depth.get(),);
+
+        if self.reached_depth.get() < depth {
+            debug!("on_completion: did not yet reach depth to complete");
+            return;
+        }
+
+        for (fresh_trait_ref, eval) in self.map.borrow_mut().drain() {
+            debug!("on_completion: fresh_trait_ref={:?} eval={:?}", fresh_trait_ref, eval,);
+
+            op(fresh_trait_ref, eval.result);
+        }
+
+        self.reached_depth.set(std::usize::MAX);
+    }
+}
+
+#[derive(Copy, Clone)]
+struct TraitObligationStackList<'o, 'tcx> {
+    cache: &'o ProvisionalEvaluationCache<'tcx>,
+    head: Option<&'o TraitObligationStack<'o, 'tcx>>,
+}
+
+impl<'o, 'tcx> TraitObligationStackList<'o, 'tcx> {
+    fn empty(cache: &'o ProvisionalEvaluationCache<'tcx>) -> TraitObligationStackList<'o, 'tcx> {
+        TraitObligationStackList { cache, head: None }
+    }
+
+    fn with(r: &'o TraitObligationStack<'o, 'tcx>) -> TraitObligationStackList<'o, 'tcx> {
+        TraitObligationStackList { cache: r.cache(), head: Some(r) }
+    }
+
+    fn head(&self) -> Option<&'o TraitObligationStack<'o, 'tcx>> {
+        self.head
+    }
+
+    fn depth(&self) -> usize {
+        if let Some(head) = self.head { head.depth } else { 0 }
+    }
+}
+
+impl<'o, 'tcx> Iterator for TraitObligationStackList<'o, 'tcx> {
+    type Item = &'o TraitObligationStack<'o, 'tcx>;
+
+    fn next(&mut self) -> Option<&'o TraitObligationStack<'o, 'tcx>> {
+        match self.head {
+            Some(o) => {
+                *self = o.previous;
+                Some(o)
+            }
+            None => None,
+        }
+    }
+}
+
+impl<'o, 'tcx> fmt::Debug for TraitObligationStack<'o, 'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "TraitObligationStack({:?})", self.obligation)
+    }
+}
diff --git a/src/librustc_trait_selection/traits/specialize/mod.rs b/src/librustc_trait_selection/traits/specialize/mod.rs
new file mode 100644 (file)
index 0000000..b763851
--- /dev/null
@@ -0,0 +1,473 @@
+//! Logic and data structures related to impl specialization, explained in
+//! greater detail below.
+//!
+//! At the moment, this implementation support only the simple "chain" rule:
+//! If any two impls overlap, one must be a strict subset of the other.
+//!
+//! See the [rustc dev guide] for a bit more detail on how specialization
+//! fits together with the rest of the trait machinery.
+//!
+//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/specialization.html
+
+pub mod specialization_graph;
+use specialization_graph::GraphExt;
+
+use crate::infer::{InferCtxt, InferOk, TyCtxtInferExt};
+use crate::traits::select::IntercrateAmbiguityCause;
+use crate::traits::{self, coherence, FutureCompatOverlapErrorKind, ObligationCause, TraitEngine};
+use rustc::lint::LintDiagnosticBuilder;
+use rustc::ty::subst::{InternalSubsts, Subst, SubstsRef};
+use rustc::ty::{self, TyCtxt, TypeFoldable};
+use rustc_data_structures::fx::FxHashSet;
+use rustc_errors::struct_span_err;
+use rustc_hir::def_id::DefId;
+use rustc_session::lint::builtin::COHERENCE_LEAK_CHECK;
+use rustc_session::lint::builtin::ORDER_DEPENDENT_TRAIT_OBJECTS;
+use rustc_span::DUMMY_SP;
+
+use super::util::impl_trait_ref_and_oblig;
+use super::{FulfillmentContext, SelectionContext};
+
+/// Information pertinent to an overlapping impl error.
+#[derive(Debug)]
+pub struct OverlapError {
+    pub with_impl: DefId,
+    pub trait_desc: String,
+    pub self_desc: Option<String>,
+    pub intercrate_ambiguity_causes: Vec<IntercrateAmbiguityCause>,
+    pub involves_placeholder: bool,
+}
+
+/// Given a subst for the requested impl, translate it to a subst
+/// appropriate for the actual item definition (whether it be in that impl,
+/// a parent impl, or the trait).
+///
+/// When we have selected one impl, but are actually using item definitions from
+/// a parent impl providing a default, we need a way to translate between the
+/// type parameters of the two impls. Here the `source_impl` is the one we've
+/// selected, and `source_substs` is a substitution of its generics.
+/// And `target_node` is the impl/trait we're actually going to get the
+/// definition from. The resulting substitution will map from `target_node`'s
+/// generics to `source_impl`'s generics as instantiated by `source_subst`.
+///
+/// For example, consider the following scenario:
+///
+/// ```rust
+/// trait Foo { ... }
+/// impl<T, U> Foo for (T, U) { ... }  // target impl
+/// impl<V> Foo for (V, V) { ... }     // source impl
+/// ```
+///
+/// Suppose we have selected "source impl" with `V` instantiated with `u32`.
+/// This function will produce a substitution with `T` and `U` both mapping to `u32`.
+///
+/// where-clauses add some trickiness here, because they can be used to "define"
+/// an argument indirectly:
+///
+/// ```rust
+/// impl<'a, I, T: 'a> Iterator for Cloned<I>
+///    where I: Iterator<Item = &'a T>, T: Clone
+/// ```
+///
+/// In a case like this, the substitution for `T` is determined indirectly,
+/// through associated type projection. We deal with such cases by using
+/// *fulfillment* to relate the two impls, requiring that all projections are
+/// resolved.
+pub fn translate_substs<'a, 'tcx>(
+    infcx: &InferCtxt<'a, 'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    source_impl: DefId,
+    source_substs: SubstsRef<'tcx>,
+    target_node: specialization_graph::Node,
+) -> SubstsRef<'tcx> {
+    debug!(
+        "translate_substs({:?}, {:?}, {:?}, {:?})",
+        param_env, source_impl, source_substs, target_node
+    );
+    let source_trait_ref =
+        infcx.tcx.impl_trait_ref(source_impl).unwrap().subst(infcx.tcx, &source_substs);
+
+    // translate the Self and Param parts of the substitution, since those
+    // vary across impls
+    let target_substs = match target_node {
+        specialization_graph::Node::Impl(target_impl) => {
+            // no need to translate if we're targeting the impl we started with
+            if source_impl == target_impl {
+                return source_substs;
+            }
+
+            fulfill_implication(infcx, param_env, source_trait_ref, target_impl).unwrap_or_else(
+                |_| {
+                    bug!(
+                        "When translating substitutions for specialization, the expected \
+                         specialization failed to hold"
+                    )
+                },
+            )
+        }
+        specialization_graph::Node::Trait(..) => source_trait_ref.substs,
+    };
+
+    // directly inherent the method generics, since those do not vary across impls
+    source_substs.rebase_onto(infcx.tcx, source_impl, target_substs)
+}
+
+/// Given a selected impl described by `impl_data`, returns the
+/// definition and substitutions for the method with the name `name`
+/// the kind `kind`, and trait method substitutions `substs`, in
+/// that impl, a less specialized impl, or the trait default,
+/// whichever applies.
+pub fn find_associated_item<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    item: &ty::AssocItem,
+    substs: SubstsRef<'tcx>,
+    impl_data: &super::VtableImplData<'tcx, ()>,
+) -> (DefId, SubstsRef<'tcx>) {
+    debug!("find_associated_item({:?}, {:?}, {:?}, {:?})", param_env, item, substs, impl_data);
+    assert!(!substs.needs_infer());
+
+    let trait_def_id = tcx.trait_id_of_impl(impl_data.impl_def_id).unwrap();
+    let trait_def = tcx.trait_def(trait_def_id);
+
+    if let Ok(ancestors) = trait_def.ancestors(tcx, impl_data.impl_def_id) {
+        match ancestors.leaf_def(tcx, item.ident, item.kind) {
+            Some(node_item) => {
+                let substs = tcx.infer_ctxt().enter(|infcx| {
+                    let param_env = param_env.with_reveal_all();
+                    let substs = substs.rebase_onto(tcx, trait_def_id, impl_data.substs);
+                    let substs = translate_substs(
+                        &infcx,
+                        param_env,
+                        impl_data.impl_def_id,
+                        substs,
+                        node_item.node,
+                    );
+                    infcx.tcx.erase_regions(&substs)
+                });
+                (node_item.item.def_id, substs)
+            }
+            None => bug!("{:?} not found in {:?}", item, impl_data.impl_def_id),
+        }
+    } else {
+        (item.def_id, substs)
+    }
+}
+
+/// Is `impl1` a specialization of `impl2`?
+///
+/// Specialization is determined by the sets of types to which the impls apply;
+/// `impl1` specializes `impl2` if it applies to a subset of the types `impl2` applies
+/// to.
+pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId, DefId)) -> bool {
+    debug!("specializes({:?}, {:?})", impl1_def_id, impl2_def_id);
+
+    // The feature gate should prevent introducing new specializations, but not
+    // taking advantage of upstream ones.
+    let features = tcx.features();
+    let specialization_enabled = features.specialization || features.min_specialization;
+    if !specialization_enabled && (impl1_def_id.is_local() || impl2_def_id.is_local()) {
+        return false;
+    }
+
+    // We determine whether there's a subset relationship by:
+    //
+    // - skolemizing impl1,
+    // - assuming the where clauses for impl1,
+    // - instantiating impl2 with fresh inference variables,
+    // - unifying,
+    // - attempting to prove the where clauses for impl2
+    //
+    // The last three steps are encapsulated in `fulfill_implication`.
+    //
+    // See RFC 1210 for more details and justification.
+
+    // Currently we do not allow e.g., a negative impl to specialize a positive one
+    if tcx.impl_polarity(impl1_def_id) != tcx.impl_polarity(impl2_def_id) {
+        return false;
+    }
+
+    // create a parameter environment corresponding to a (placeholder) instantiation of impl1
+    let penv = tcx.param_env(impl1_def_id);
+    let impl1_trait_ref = tcx.impl_trait_ref(impl1_def_id).unwrap();
+
+    // Create a infcx, taking the predicates of impl1 as assumptions:
+    tcx.infer_ctxt().enter(|infcx| {
+        // Normalize the trait reference. The WF rules ought to ensure
+        // that this always succeeds.
+        let impl1_trait_ref = match traits::fully_normalize(
+            &infcx,
+            FulfillmentContext::new(),
+            ObligationCause::dummy(),
+            penv,
+            &impl1_trait_ref,
+        ) {
+            Ok(impl1_trait_ref) => impl1_trait_ref,
+            Err(err) => {
+                bug!("failed to fully normalize {:?}: {:?}", impl1_trait_ref, err);
+            }
+        };
+
+        // Attempt to prove that impl2 applies, given all of the above.
+        fulfill_implication(&infcx, penv, impl1_trait_ref, impl2_def_id).is_ok()
+    })
+}
+
+/// Attempt to fulfill all obligations of `target_impl` after unification with
+/// `source_trait_ref`. If successful, returns a substitution for *all* the
+/// generics of `target_impl`, including both those needed to unify with
+/// `source_trait_ref` and those whose identity is determined via a where
+/// clause in the impl.
+fn fulfill_implication<'a, 'tcx>(
+    infcx: &InferCtxt<'a, 'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    source_trait_ref: ty::TraitRef<'tcx>,
+    target_impl: DefId,
+) -> Result<SubstsRef<'tcx>, ()> {
+    debug!(
+        "fulfill_implication({:?}, trait_ref={:?} |- {:?} applies)",
+        param_env, source_trait_ref, target_impl
+    );
+
+    let selcx = &mut SelectionContext::new(&infcx);
+    let target_substs = infcx.fresh_substs_for_item(DUMMY_SP, target_impl);
+    let (target_trait_ref, mut obligations) =
+        impl_trait_ref_and_oblig(selcx, param_env, target_impl, target_substs);
+    debug!(
+        "fulfill_implication: target_trait_ref={:?}, obligations={:?}",
+        target_trait_ref, obligations
+    );
+
+    // do the impls unify? If not, no specialization.
+    match infcx.at(&ObligationCause::dummy(), param_env).eq(source_trait_ref, target_trait_ref) {
+        Ok(InferOk { obligations: o, .. }) => {
+            obligations.extend(o);
+        }
+        Err(_) => {
+            debug!(
+                "fulfill_implication: {:?} does not unify with {:?}",
+                source_trait_ref, target_trait_ref
+            );
+            return Err(());
+        }
+    }
+
+    // attempt to prove all of the predicates for impl2 given those for impl1
+    // (which are packed up in penv)
+
+    infcx.save_and_restore_in_snapshot_flag(|infcx| {
+        // If we came from `translate_substs`, we already know that the
+        // predicates for our impl hold (after all, we know that a more
+        // specialized impl holds, so our impl must hold too), and
+        // we only want to process the projections to determine the
+        // the types in our substs using RFC 447, so we can safely
+        // ignore region obligations, which allows us to avoid threading
+        // a node-id to assign them with.
+        //
+        // If we came from specialization graph construction, then
+        // we already make a mockery out of the region system, so
+        // why not ignore them a bit earlier?
+        let mut fulfill_cx = FulfillmentContext::new_ignoring_regions();
+        for oblig in obligations.into_iter() {
+            fulfill_cx.register_predicate_obligation(&infcx, oblig);
+        }
+        match fulfill_cx.select_all_or_error(infcx) {
+            Err(errors) => {
+                // no dice!
+                debug!(
+                    "fulfill_implication: for impls on {:?} and {:?}, \
+                     could not fulfill: {:?} given {:?}",
+                    source_trait_ref, target_trait_ref, errors, param_env.caller_bounds
+                );
+                Err(())
+            }
+
+            Ok(()) => {
+                debug!(
+                    "fulfill_implication: an impl for {:?} specializes {:?}",
+                    source_trait_ref, target_trait_ref
+                );
+
+                // Now resolve the *substitution* we built for the target earlier, replacing
+                // the inference variables inside with whatever we got from fulfillment.
+                Ok(infcx.resolve_vars_if_possible(&target_substs))
+            }
+        }
+    })
+}
+
+// Query provider for `specialization_graph_of`.
+pub(super) fn specialization_graph_provider(
+    tcx: TyCtxt<'_>,
+    trait_id: DefId,
+) -> &specialization_graph::Graph {
+    let mut sg = specialization_graph::Graph::new();
+
+    let mut trait_impls = tcx.all_impls(trait_id);
+
+    // The coherence checking implementation seems to rely on impls being
+    // iterated over (roughly) in definition order, so we are sorting by
+    // negated `CrateNum` (so remote definitions are visited first) and then
+    // by a flattened version of the `DefIndex`.
+    trait_impls
+        .sort_unstable_by_key(|def_id| (-(def_id.krate.as_u32() as i64), def_id.index.index()));
+
+    for impl_def_id in trait_impls {
+        if impl_def_id.is_local() {
+            // This is where impl overlap checking happens:
+            let insert_result = sg.insert(tcx, impl_def_id);
+            // Report error if there was one.
+            let (overlap, used_to_be_allowed) = match insert_result {
+                Err(overlap) => (Some(overlap), None),
+                Ok(Some(overlap)) => (Some(overlap.error), Some(overlap.kind)),
+                Ok(None) => (None, None),
+            };
+
+            if let Some(overlap) = overlap {
+                let impl_span =
+                    tcx.sess.source_map().def_span(tcx.span_of_impl(impl_def_id).unwrap());
+
+                // Work to be done after we've built the DiagnosticBuilder. We have to define it
+                // now because the struct_lint methods don't return back the DiagnosticBuilder
+                // that's passed in.
+                let decorate = |err: LintDiagnosticBuilder<'_>| {
+                    let msg = format!(
+                        "conflicting implementations of trait `{}`{}:{}",
+                        overlap.trait_desc,
+                        overlap
+                            .self_desc
+                            .clone()
+                            .map_or(String::new(), |ty| { format!(" for type `{}`", ty) }),
+                        match used_to_be_allowed {
+                            Some(FutureCompatOverlapErrorKind::Issue33140) => " (E0119)",
+                            _ => "",
+                        }
+                    );
+                    let mut err = err.build(&msg);
+                    match tcx.span_of_impl(overlap.with_impl) {
+                        Ok(span) => {
+                            err.span_label(
+                                tcx.sess.source_map().def_span(span),
+                                "first implementation here".to_string(),
+                            );
+
+                            err.span_label(
+                                impl_span,
+                                format!(
+                                    "conflicting implementation{}",
+                                    overlap
+                                        .self_desc
+                                        .map_or(String::new(), |ty| format!(" for `{}`", ty))
+                                ),
+                            );
+                        }
+                        Err(cname) => {
+                            let msg = match to_pretty_impl_header(tcx, overlap.with_impl) {
+                                Some(s) => format!(
+                                    "conflicting implementation in crate `{}`:\n- {}",
+                                    cname, s
+                                ),
+                                None => format!("conflicting implementation in crate `{}`", cname),
+                            };
+                            err.note(&msg);
+                        }
+                    }
+
+                    for cause in &overlap.intercrate_ambiguity_causes {
+                        cause.add_intercrate_ambiguity_hint(&mut err);
+                    }
+
+                    if overlap.involves_placeholder {
+                        coherence::add_placeholder_note(&mut err);
+                    }
+                    err.emit()
+                };
+
+                match used_to_be_allowed {
+                    None => {
+                        sg.has_errored = true;
+                        let err = struct_span_err!(tcx.sess, impl_span, E0119, "");
+                        decorate(LintDiagnosticBuilder::new(err));
+                    }
+                    Some(kind) => {
+                        let lint = match kind {
+                            FutureCompatOverlapErrorKind::Issue33140 => {
+                                ORDER_DEPENDENT_TRAIT_OBJECTS
+                            }
+                            FutureCompatOverlapErrorKind::LeakCheck => COHERENCE_LEAK_CHECK,
+                        };
+                        tcx.struct_span_lint_hir(
+                            lint,
+                            tcx.hir().as_local_hir_id(impl_def_id).unwrap(),
+                            impl_span,
+                            decorate,
+                        )
+                    }
+                };
+            }
+        } else {
+            let parent = tcx.impl_parent(impl_def_id).unwrap_or(trait_id);
+            sg.record_impl_from_cstore(tcx, parent, impl_def_id)
+        }
+    }
+
+    tcx.arena.alloc(sg)
+}
+
+/// Recovers the "impl X for Y" signature from `impl_def_id` and returns it as a
+/// string.
+fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Option<String> {
+    use std::fmt::Write;
+
+    let trait_ref = tcx.impl_trait_ref(impl_def_id)?;
+    let mut w = "impl".to_owned();
+
+    let substs = InternalSubsts::identity_for_item(tcx, impl_def_id);
+
+    // FIXME: Currently only handles ?Sized.
+    //        Needs to support ?Move and ?DynSized when they are implemented.
+    let mut types_without_default_bounds = FxHashSet::default();
+    let sized_trait = tcx.lang_items().sized_trait();
+
+    if !substs.is_noop() {
+        types_without_default_bounds.extend(substs.types());
+        w.push('<');
+        w.push_str(
+            &substs
+                .iter()
+                .map(|k| k.to_string())
+                .filter(|k| k != "'_")
+                .collect::<Vec<_>>()
+                .join(", "),
+        );
+        w.push('>');
+    }
+
+    write!(w, " {} for {}", trait_ref.print_only_trait_path(), tcx.type_of(impl_def_id)).unwrap();
+
+    // 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 mut pretty_predicates =
+        Vec::with_capacity(predicates.len() + types_without_default_bounds.len());
+
+    for (p, _) in predicates {
+        if let Some(poly_trait_ref) = p.to_opt_poly_trait_ref() {
+            if Some(poly_trait_ref.def_id()) == sized_trait {
+                types_without_default_bounds.remove(poly_trait_ref.self_ty());
+                continue;
+            }
+        }
+        pretty_predicates.push(p.to_string());
+    }
+
+    pretty_predicates
+        .extend(types_without_default_bounds.iter().map(|ty| format!("{}: ?Sized", ty)));
+
+    if !pretty_predicates.is_empty() {
+        write!(w, "\n  where {}", pretty_predicates.join(", ")).unwrap();
+    }
+
+    w.push(';');
+    Some(w)
+}
diff --git a/src/librustc_trait_selection/traits/specialize/specialization_graph.rs b/src/librustc_trait_selection/traits/specialize/specialization_graph.rs
new file mode 100644 (file)
index 0000000..17d4a22
--- /dev/null
@@ -0,0 +1,379 @@
+use super::OverlapError;
+
+use crate::traits;
+use rustc::ty::fast_reject::{self, SimplifiedType};
+use rustc::ty::{self, TyCtxt, TypeFoldable};
+use rustc_hir::def_id::DefId;
+
+pub use rustc::traits::specialization_graph::*;
+
+#[derive(Copy, Clone, Debug)]
+pub enum FutureCompatOverlapErrorKind {
+    Issue33140,
+    LeakCheck,
+}
+
+#[derive(Debug)]
+pub struct FutureCompatOverlapError {
+    pub error: OverlapError,
+    pub kind: FutureCompatOverlapErrorKind,
+}
+
+/// The result of attempting to insert an impl into a group of children.
+enum Inserted {
+    /// The impl was inserted as a new child in this group of children.
+    BecameNewSibling(Option<FutureCompatOverlapError>),
+
+    /// The impl should replace existing impls [X1, ..], because the impl specializes X1, X2, etc.
+    ReplaceChildren(Vec<DefId>),
+
+    /// The impl is a specialization of an existing child.
+    ShouldRecurseOn(DefId),
+}
+
+trait ChildrenExt {
+    fn insert_blindly(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId);
+    fn remove_existing(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId);
+
+    fn insert(
+        &mut self,
+        tcx: TyCtxt<'tcx>,
+        impl_def_id: DefId,
+        simplified_self: Option<SimplifiedType>,
+    ) -> Result<Inserted, OverlapError>;
+}
+
+impl ChildrenExt for Children {
+    /// Insert an impl into this set of children without comparing to any existing impls.
+    fn insert_blindly(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) {
+        let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
+        if let Some(st) = fast_reject::simplify_type(tcx, trait_ref.self_ty(), false) {
+            debug!("insert_blindly: impl_def_id={:?} st={:?}", impl_def_id, st);
+            self.nonblanket_impls.entry(st).or_default().push(impl_def_id)
+        } else {
+            debug!("insert_blindly: impl_def_id={:?} st=None", impl_def_id);
+            self.blanket_impls.push(impl_def_id)
+        }
+    }
+
+    /// Removes an impl from this set of children. Used when replacing
+    /// an impl with a parent. The impl must be present in the list of
+    /// children already.
+    fn remove_existing(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) {
+        let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
+        let vec: &mut Vec<DefId>;
+        if let Some(st) = fast_reject::simplify_type(tcx, trait_ref.self_ty(), false) {
+            debug!("remove_existing: impl_def_id={:?} st={:?}", impl_def_id, st);
+            vec = self.nonblanket_impls.get_mut(&st).unwrap();
+        } else {
+            debug!("remove_existing: impl_def_id={:?} st=None", impl_def_id);
+            vec = &mut self.blanket_impls;
+        }
+
+        let index = vec.iter().position(|d| *d == impl_def_id).unwrap();
+        vec.remove(index);
+    }
+
+    /// Attempt to insert an impl into this set of children, while comparing for
+    /// specialization relationships.
+    fn insert(
+        &mut self,
+        tcx: TyCtxt<'tcx>,
+        impl_def_id: DefId,
+        simplified_self: Option<SimplifiedType>,
+    ) -> Result<Inserted, OverlapError> {
+        let mut last_lint = None;
+        let mut replace_children = Vec::new();
+
+        debug!("insert(impl_def_id={:?}, simplified_self={:?})", impl_def_id, simplified_self,);
+
+        let possible_siblings = match simplified_self {
+            Some(st) => PotentialSiblings::Filtered(filtered_children(self, st)),
+            None => PotentialSiblings::Unfiltered(iter_children(self)),
+        };
+
+        for possible_sibling in possible_siblings {
+            debug!(
+                "insert: impl_def_id={:?}, simplified_self={:?}, possible_sibling={:?}",
+                impl_def_id, simplified_self, possible_sibling,
+            );
+
+            let create_overlap_error = |overlap: traits::coherence::OverlapResult<'_>| {
+                let trait_ref = overlap.impl_header.trait_ref.unwrap();
+                let self_ty = trait_ref.self_ty();
+
+                OverlapError {
+                    with_impl: possible_sibling,
+                    trait_desc: trait_ref.print_only_trait_path().to_string(),
+                    // Only report the `Self` type if it has at least
+                    // some outer concrete shell; otherwise, it's
+                    // not adding much information.
+                    self_desc: if self_ty.has_concrete_skeleton() {
+                        Some(self_ty.to_string())
+                    } else {
+                        None
+                    },
+                    intercrate_ambiguity_causes: overlap.intercrate_ambiguity_causes,
+                    involves_placeholder: overlap.involves_placeholder,
+                }
+            };
+
+            let report_overlap_error = |overlap: traits::coherence::OverlapResult<'_>,
+                                        last_lint: &mut _| {
+                // Found overlap, but no specialization; error out or report future-compat warning.
+
+                // Do we *still* get overlap if we disable the future-incompatible modes?
+                let should_err = traits::overlapping_impls(
+                    tcx,
+                    possible_sibling,
+                    impl_def_id,
+                    traits::SkipLeakCheck::default(),
+                    |_| true,
+                    || false,
+                );
+
+                let error = create_overlap_error(overlap);
+
+                if should_err {
+                    Err(error)
+                } else {
+                    *last_lint = Some(FutureCompatOverlapError {
+                        error,
+                        kind: FutureCompatOverlapErrorKind::LeakCheck,
+                    });
+
+                    Ok((false, false))
+                }
+            };
+
+            let last_lint_mut = &mut last_lint;
+            let (le, ge) = traits::overlapping_impls(
+                tcx,
+                possible_sibling,
+                impl_def_id,
+                traits::SkipLeakCheck::Yes,
+                |overlap| {
+                    if let Some(overlap_kind) =
+                        tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling)
+                    {
+                        match overlap_kind {
+                            ty::ImplOverlapKind::Permitted { marker: _ } => {}
+                            ty::ImplOverlapKind::Issue33140 => {
+                                *last_lint_mut = Some(FutureCompatOverlapError {
+                                    error: create_overlap_error(overlap),
+                                    kind: FutureCompatOverlapErrorKind::Issue33140,
+                                });
+                            }
+                        }
+
+                        return Ok((false, false));
+                    }
+
+                    let le = tcx.specializes((impl_def_id, possible_sibling));
+                    let ge = tcx.specializes((possible_sibling, impl_def_id));
+
+                    if le == ge {
+                        report_overlap_error(overlap, last_lint_mut)
+                    } else {
+                        Ok((le, ge))
+                    }
+                },
+                || Ok((false, false)),
+            )?;
+
+            if le && !ge {
+                debug!(
+                    "descending as child of TraitRef {:?}",
+                    tcx.impl_trait_ref(possible_sibling).unwrap()
+                );
+
+                // The impl specializes `possible_sibling`.
+                return Ok(Inserted::ShouldRecurseOn(possible_sibling));
+            } else if ge && !le {
+                debug!(
+                    "placing as parent of TraitRef {:?}",
+                    tcx.impl_trait_ref(possible_sibling).unwrap()
+                );
+
+                replace_children.push(possible_sibling);
+            } else {
+                // Either there's no overlap, or the overlap was already reported by
+                // `overlap_error`.
+            }
+        }
+
+        if !replace_children.is_empty() {
+            return Ok(Inserted::ReplaceChildren(replace_children));
+        }
+
+        // No overlap with any potential siblings, so add as a new sibling.
+        debug!("placing as new sibling");
+        self.insert_blindly(tcx, impl_def_id);
+        Ok(Inserted::BecameNewSibling(last_lint))
+    }
+}
+
+fn iter_children(children: &mut Children) -> impl Iterator<Item = DefId> + '_ {
+    let nonblanket = children.nonblanket_impls.iter_mut().flat_map(|(_, v)| v.iter());
+    children.blanket_impls.iter().chain(nonblanket).cloned()
+}
+
+fn filtered_children(
+    children: &mut Children,
+    st: SimplifiedType,
+) -> impl Iterator<Item = DefId> + '_ {
+    let nonblanket = children.nonblanket_impls.entry(st).or_default().iter();
+    children.blanket_impls.iter().chain(nonblanket).cloned()
+}
+
+// A custom iterator used by Children::insert
+enum PotentialSiblings<I, J>
+where
+    I: Iterator<Item = DefId>,
+    J: Iterator<Item = DefId>,
+{
+    Unfiltered(I),
+    Filtered(J),
+}
+
+impl<I, J> Iterator for PotentialSiblings<I, J>
+where
+    I: Iterator<Item = DefId>,
+    J: Iterator<Item = DefId>,
+{
+    type Item = DefId;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        match *self {
+            PotentialSiblings::Unfiltered(ref mut iter) => iter.next(),
+            PotentialSiblings::Filtered(ref mut iter) => iter.next(),
+        }
+    }
+}
+
+pub trait GraphExt {
+    /// Insert a local impl into the specialization graph. If an existing impl
+    /// conflicts with it (has overlap, but neither specializes the other),
+    /// information about the area of overlap is returned in the `Err`.
+    fn insert(
+        &mut self,
+        tcx: TyCtxt<'tcx>,
+        impl_def_id: DefId,
+    ) -> Result<Option<FutureCompatOverlapError>, OverlapError>;
+
+    /// Insert cached metadata mapping from a child impl back to its parent.
+    fn record_impl_from_cstore(&mut self, tcx: TyCtxt<'tcx>, parent: DefId, child: DefId);
+}
+
+impl GraphExt for Graph {
+    /// Insert a local impl into the specialization graph. If an existing impl
+    /// conflicts with it (has overlap, but neither specializes the other),
+    /// information about the area of overlap is returned in the `Err`.
+    fn insert(
+        &mut self,
+        tcx: TyCtxt<'tcx>,
+        impl_def_id: DefId,
+    ) -> Result<Option<FutureCompatOverlapError>, OverlapError> {
+        assert!(impl_def_id.is_local());
+
+        let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
+        let trait_def_id = trait_ref.def_id;
+
+        debug!(
+            "insert({:?}): inserting TraitRef {:?} into specialization graph",
+            impl_def_id, trait_ref
+        );
+
+        // If the reference itself contains an earlier error (e.g., due to a
+        // resolution failure), then we just insert the impl at the top level of
+        // the graph and claim that there's no overlap (in order to suppress
+        // bogus errors).
+        if trait_ref.references_error() {
+            debug!(
+                "insert: inserting dummy node for erroneous TraitRef {:?}, \
+                 impl_def_id={:?}, trait_def_id={:?}",
+                trait_ref, impl_def_id, trait_def_id
+            );
+
+            self.parent.insert(impl_def_id, trait_def_id);
+            self.children.entry(trait_def_id).or_default().insert_blindly(tcx, impl_def_id);
+            return Ok(None);
+        }
+
+        let mut parent = trait_def_id;
+        let mut last_lint = None;
+        let simplified = fast_reject::simplify_type(tcx, trait_ref.self_ty(), false);
+
+        // Descend the specialization tree, where `parent` is the current parent node.
+        loop {
+            use self::Inserted::*;
+
+            let insert_result =
+                self.children.entry(parent).or_default().insert(tcx, impl_def_id, simplified)?;
+
+            match insert_result {
+                BecameNewSibling(opt_lint) => {
+                    last_lint = opt_lint;
+                    break;
+                }
+                ReplaceChildren(grand_children_to_be) => {
+                    // We currently have
+                    //
+                    //     P
+                    //     |
+                    //     G
+                    //
+                    // and we are inserting the impl N. We want to make it:
+                    //
+                    //     P
+                    //     |
+                    //     N
+                    //     |
+                    //     G
+
+                    // Adjust P's list of children: remove G and then add N.
+                    {
+                        let siblings = self.children.get_mut(&parent).unwrap();
+                        for &grand_child_to_be in &grand_children_to_be {
+                            siblings.remove_existing(tcx, grand_child_to_be);
+                        }
+                        siblings.insert_blindly(tcx, impl_def_id);
+                    }
+
+                    // Set G's parent to N and N's parent to P.
+                    for &grand_child_to_be in &grand_children_to_be {
+                        self.parent.insert(grand_child_to_be, impl_def_id);
+                    }
+                    self.parent.insert(impl_def_id, parent);
+
+                    // Add G as N's child.
+                    for &grand_child_to_be in &grand_children_to_be {
+                        self.children
+                            .entry(impl_def_id)
+                            .or_default()
+                            .insert_blindly(tcx, grand_child_to_be);
+                    }
+                    break;
+                }
+                ShouldRecurseOn(new_parent) => {
+                    parent = new_parent;
+                }
+            }
+        }
+
+        self.parent.insert(impl_def_id, parent);
+        Ok(last_lint)
+    }
+
+    /// Insert cached metadata mapping from a child impl back to its parent.
+    fn record_impl_from_cstore(&mut self, tcx: TyCtxt<'tcx>, parent: DefId, child: DefId) {
+        if self.parent.insert(child, parent).is_some() {
+            bug!(
+                "When recording an impl from the crate store, information about its parent \
+                 was already present."
+            );
+        }
+
+        self.children.entry(parent).or_default().insert_blindly(tcx, child);
+    }
+}
diff --git a/src/librustc_trait_selection/traits/structural_match.rs b/src/librustc_trait_selection/traits/structural_match.rs
new file mode 100644 (file)
index 0000000..60682f5
--- /dev/null
@@ -0,0 +1,216 @@
+use crate::infer::{InferCtxt, TyCtxtInferExt};
+use crate::traits::ObligationCause;
+use crate::traits::{self, ConstPatternStructural, TraitEngine};
+
+use rustc::ty::{self, AdtDef, Ty, TyCtxt, TypeFoldable, TypeVisitor};
+use rustc_data_structures::fx::FxHashSet;
+use rustc_hir as hir;
+use rustc_span::Span;
+
+#[derive(Debug)]
+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<T>`.
+///
+/// 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>(
+    id: hir::HirId,
+    span: Span,
+    tcx: TyCtxt<'tcx>,
+    ty: Ty<'tcx>,
+) -> Option<NonStructuralMatchTy<'tcx>> {
+    // FIXME: we should instead pass in an `infcx` from the outside.
+    tcx.infer_ctxt().enter(|infcx| {
+        let mut search = Search { id, span, infcx, found: None, seen: FxHashSet::default() };
+        ty.visit_with(&mut search);
+        search.found
+    })
+}
+
+/// This method returns true if and only if `adt_ty` itself has been marked as
+/// eligible for structural-match: namely, if it implements both
+/// `StructuralPartialEq` and `StructuralEq` (which are respectively injected by
+/// `#[derive(PartialEq)]` and `#[derive(Eq)]`).
+///
+/// Note that this does *not* recursively check if the substructure of `adt_ty`
+/// implements the traits.
+pub fn type_marked_structural(
+    id: hir::HirId,
+    span: Span,
+    infcx: &InferCtxt<'_, 'tcx>,
+    adt_ty: Ty<'tcx>,
+) -> bool {
+    let mut fulfillment_cx = traits::FulfillmentContext::new();
+    let cause = ObligationCause::new(span, id, ConstPatternStructural);
+    // require `#[derive(PartialEq)]`
+    let structural_peq_def_id = infcx.tcx.lang_items().structural_peq_trait().unwrap();
+    fulfillment_cx.register_bound(
+        infcx,
+        ty::ParamEnv::empty(),
+        adt_ty,
+        structural_peq_def_id,
+        cause,
+    );
+    // for now, require `#[derive(Eq)]`. (Doing so is a hack to work around
+    // the type `for<'a> fn(&'a ())` failing to implement `Eq` itself.)
+    let cause = ObligationCause::new(span, id, ConstPatternStructural);
+    let structural_teq_def_id = infcx.tcx.lang_items().structural_teq_trait().unwrap();
+    fulfillment_cx.register_bound(
+        infcx,
+        ty::ParamEnv::empty(),
+        adt_ty,
+        structural_teq_def_id,
+        cause,
+    );
+
+    // We deliberately skip *reporting* fulfillment errors (via
+    // `report_fulfillment_errors`), for two reasons:
+    //
+    // 1. The error messages would mention `std::marker::StructuralPartialEq`
+    //    (a trait which is solely meant as an implementation detail
+    //    for now), and
+    //
+    // 2. We are sometimes doing future-incompatibility lints for
+    //    now, so we do not want unconditional errors here.
+    fulfillment_cx.select_all_or_error(infcx).is_ok()
+}
+
+/// This implements the traversal over the structure of a given type to try to
+/// find instances of ADTs (specifically structs or enums) that do not implement
+/// the structural-match traits (`StructuralPartialEq` and `StructuralEq`).
+struct Search<'a, 'tcx> {
+    id: hir::HirId,
+    span: Span,
+
+    infcx: InferCtxt<'a, 'tcx>,
+
+    /// Records first ADT that does not implement a structural-match trait.
+    found: Option<NonStructuralMatchTy<'tcx>>,
+
+    /// Tracks ADTs previously encountered during search, so that
+    /// we will not recur on them again.
+    seen: FxHashSet<hir::def_id::DefId>,
+}
+
+impl Search<'a, 'tcx> {
+    fn tcx(&self) -> TyCtxt<'tcx> {
+        self.infcx.tcx
+    }
+
+    fn type_marked_structural(&self, adt_ty: Ty<'tcx>) -> bool {
+        type_marked_structural(self.id, self.span, &self.infcx, adt_ty)
+    }
+}
+
+impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, '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`.
+                //
+                // For example, if you have:
+                // ```
+                // struct NonStructural;
+                // #[derive(PartialEq, Eq)]
+                // struct T(*const NonStructural);
+                // const C: T = T(std::ptr::null());
+                // ```
+                //
+                // Even though `NonStructural` does not implement `PartialEq`,
+                // structural equality on `T` does not recur into the raw
+                // pointer. Therefore, one can still use `C` in a pattern.
+
+                // (But still tell caller to continue search.)
+                return false;
+            }
+            ty::FnDef(..) | ty::FnPtr(..) => {
+                // types of formals and return in `fn(_) -> _` are also irrelevant;
+                // so we do not recur into them via `super_visit_with`
+                //
+                // (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.seen.insert(adt_def.did) {
+            debug!("Search already seen adt_def: {:?}", adt_def);
+            // let caller continue its search
+            return false;
+        }
+
+        if !self.type_marked_structural(ty) {
+            debug!("Search found ty: {:?}", ty);
+            self.found = Some(NonStructuralMatchTy::Adt(&adt_def));
+            return true; // Halt visiting!
+        }
+
+        // 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<T>` 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
+    }
+}
diff --git a/src/librustc_trait_selection/traits/util.rs b/src/librustc_trait_selection/traits/util.rs
new file mode 100644 (file)
index 0000000..cd4595e
--- /dev/null
@@ -0,0 +1,675 @@
+use rustc_errors::DiagnosticBuilder;
+use rustc_span::Span;
+use smallvec::smallvec;
+use smallvec::SmallVec;
+
+use rustc::ty::outlives::Component;
+use rustc::ty::subst::{GenericArg, Subst, SubstsRef};
+use rustc::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, WithConstness};
+use rustc_data_structures::fx::FxHashSet;
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
+
+use super::{Normalized, Obligation, ObligationCause, PredicateObligation, SelectionContext};
+
+fn anonymize_predicate<'tcx>(tcx: TyCtxt<'tcx>, pred: &ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
+    match *pred {
+        ty::Predicate::Trait(ref data, constness) => {
+            ty::Predicate::Trait(tcx.anonymize_late_bound_regions(data), constness)
+        }
+
+        ty::Predicate::RegionOutlives(ref data) => {
+            ty::Predicate::RegionOutlives(tcx.anonymize_late_bound_regions(data))
+        }
+
+        ty::Predicate::TypeOutlives(ref data) => {
+            ty::Predicate::TypeOutlives(tcx.anonymize_late_bound_regions(data))
+        }
+
+        ty::Predicate::Projection(ref data) => {
+            ty::Predicate::Projection(tcx.anonymize_late_bound_regions(data))
+        }
+
+        ty::Predicate::WellFormed(data) => ty::Predicate::WellFormed(data),
+
+        ty::Predicate::ObjectSafe(data) => ty::Predicate::ObjectSafe(data),
+
+        ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => {
+            ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind)
+        }
+
+        ty::Predicate::Subtype(ref data) => {
+            ty::Predicate::Subtype(tcx.anonymize_late_bound_regions(data))
+        }
+
+        ty::Predicate::ConstEvaluatable(def_id, substs) => {
+            ty::Predicate::ConstEvaluatable(def_id, substs)
+        }
+    }
+}
+
+struct PredicateSet<'tcx> {
+    tcx: TyCtxt<'tcx>,
+    set: FxHashSet<ty::Predicate<'tcx>>,
+}
+
+impl PredicateSet<'tcx> {
+    fn new(tcx: TyCtxt<'tcx>) -> Self {
+        Self { tcx, set: Default::default() }
+    }
+
+    fn insert(&mut self, pred: &ty::Predicate<'tcx>) -> bool {
+        // We have to be careful here because we want
+        //
+        //    for<'a> Foo<&'a int>
+        //
+        // and
+        //
+        //    for<'b> Foo<&'b int>
+        //
+        // to be considered equivalent. So normalize all late-bound
+        // regions before we throw things into the underlying set.
+        self.set.insert(anonymize_predicate(self.tcx, pred))
+    }
+}
+
+impl<T: AsRef<ty::Predicate<'tcx>>> Extend<T> for PredicateSet<'tcx> {
+    fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
+        for pred in iter {
+            self.insert(pred.as_ref());
+        }
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////
+// `Elaboration` iterator
+///////////////////////////////////////////////////////////////////////////
+
+/// "Elaboration" is the process of identifying all the predicates that
+/// are implied by a source predicate. Currently, this basically means
+/// walking the "supertraits" and other similar assumptions. For example,
+/// if we know that `T: Ord`, the elaborator would deduce that `T: PartialOrd`
+/// holds as well. Similarly, if we have `trait Foo: 'static`, and we know that
+/// `T: Foo`, then we know that `T: 'static`.
+pub struct Elaborator<'tcx> {
+    stack: Vec<ty::Predicate<'tcx>>,
+    visited: PredicateSet<'tcx>,
+}
+
+pub fn elaborate_trait_ref<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    trait_ref: ty::PolyTraitRef<'tcx>,
+) -> Elaborator<'tcx> {
+    elaborate_predicates(tcx, vec![trait_ref.without_const().to_predicate()])
+}
+
+pub fn elaborate_trait_refs<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    trait_refs: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
+) -> Elaborator<'tcx> {
+    let predicates = trait_refs.map(|trait_ref| trait_ref.without_const().to_predicate()).collect();
+    elaborate_predicates(tcx, predicates)
+}
+
+pub fn elaborate_predicates<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    mut predicates: Vec<ty::Predicate<'tcx>>,
+) -> Elaborator<'tcx> {
+    let mut visited = PredicateSet::new(tcx);
+    predicates.retain(|pred| visited.insert(pred));
+    Elaborator { stack: predicates, visited }
+}
+
+impl Elaborator<'tcx> {
+    pub fn filter_to_traits(self) -> FilterToTraits<Self> {
+        FilterToTraits::new(self)
+    }
+
+    fn elaborate(&mut self, predicate: &ty::Predicate<'tcx>) {
+        let tcx = self.visited.tcx;
+        match *predicate {
+            ty::Predicate::Trait(ref data, _) => {
+                // Get predicates declared on the trait.
+                let predicates = tcx.super_predicates_of(data.def_id());
+
+                let predicates = predicates
+                    .predicates
+                    .iter()
+                    .map(|(pred, _)| pred.subst_supertrait(tcx, &data.to_poly_trait_ref()));
+                debug!("super_predicates: data={:?} predicates={:?}", data, predicates.clone());
+
+                // Only keep those bounds that we haven't already seen.
+                // This is necessary to prevent infinite recursion in some
+                // cases. One common case is when people define
+                // `trait Sized: Sized { }` rather than `trait Sized { }`.
+                let visited = &mut self.visited;
+                let predicates = predicates.filter(|pred| visited.insert(pred));
+
+                self.stack.extend(predicates);
+            }
+            ty::Predicate::WellFormed(..) => {
+                // Currently, we do not elaborate WF predicates,
+                // although we easily could.
+            }
+            ty::Predicate::ObjectSafe(..) => {
+                // Currently, we do not elaborate object-safe
+                // predicates.
+            }
+            ty::Predicate::Subtype(..) => {
+                // Currently, we do not "elaborate" predicates like `X <: Y`,
+                // though conceivably we might.
+            }
+            ty::Predicate::Projection(..) => {
+                // Nothing to elaborate in a projection predicate.
+            }
+            ty::Predicate::ClosureKind(..) => {
+                // Nothing to elaborate when waiting for a closure's kind to be inferred.
+            }
+            ty::Predicate::ConstEvaluatable(..) => {
+                // Currently, we do not elaborate const-evaluatable
+                // predicates.
+            }
+            ty::Predicate::RegionOutlives(..) => {
+                // Nothing to elaborate from `'a: 'b`.
+            }
+            ty::Predicate::TypeOutlives(ref data) => {
+                // We know that `T: 'a` for some type `T`. We can
+                // often elaborate this. For example, if we know that
+                // `[U]: 'a`, that implies that `U: 'a`. Similarly, if
+                // we know `&'a U: 'b`, then we know that `'a: 'b` and
+                // `U: 'b`.
+                //
+                // We can basically ignore bound regions here. So for
+                // example `for<'c> Foo<'a,'c>: 'b` can be elaborated to
+                // `'a: 'b`.
+
+                // Ignore `for<'a> T: 'a` -- we might in the future
+                // consider this as evidence that `T: 'static`, but
+                // I'm a bit wary of such constructions and so for now
+                // I want to be conservative. --nmatsakis
+                let ty_max = data.skip_binder().0;
+                let r_min = data.skip_binder().1;
+                if r_min.is_late_bound() {
+                    return;
+                }
+
+                let visited = &mut self.visited;
+                let mut components = smallvec![];
+                tcx.push_outlives_components(ty_max, &mut components);
+                self.stack.extend(
+                    components
+                        .into_iter()
+                        .filter_map(|component| match component {
+                            Component::Region(r) => {
+                                if r.is_late_bound() {
+                                    None
+                                } else {
+                                    Some(ty::Predicate::RegionOutlives(ty::Binder::dummy(
+                                        ty::OutlivesPredicate(r, r_min),
+                                    )))
+                                }
+                            }
+
+                            Component::Param(p) => {
+                                let ty = tcx.mk_ty_param(p.index, p.name);
+                                Some(ty::Predicate::TypeOutlives(ty::Binder::dummy(
+                                    ty::OutlivesPredicate(ty, r_min),
+                                )))
+                            }
+
+                            Component::UnresolvedInferenceVariable(_) => None,
+
+                            Component::Projection(_) | Component::EscapingProjection(_) => {
+                                // We can probably do more here. This
+                                // corresponds to a case like `<T as
+                                // Foo<'a>>::U: 'b`.
+                                None
+                            }
+                        })
+                        .filter(|p| visited.insert(p)),
+                );
+            }
+        }
+    }
+}
+
+impl Iterator for Elaborator<'tcx> {
+    type Item = ty::Predicate<'tcx>;
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        (self.stack.len(), None)
+    }
+
+    fn next(&mut self) -> Option<ty::Predicate<'tcx>> {
+        // Extract next item from top-most stack frame, if any.
+        if let Some(pred) = self.stack.pop() {
+            self.elaborate(&pred);
+            Some(pred)
+        } else {
+            None
+        }
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////
+// Supertrait iterator
+///////////////////////////////////////////////////////////////////////////
+
+pub type Supertraits<'tcx> = FilterToTraits<Elaborator<'tcx>>;
+
+pub fn supertraits<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    trait_ref: ty::PolyTraitRef<'tcx>,
+) -> Supertraits<'tcx> {
+    elaborate_trait_ref(tcx, trait_ref).filter_to_traits()
+}
+
+pub fn transitive_bounds<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    bounds: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
+) -> Supertraits<'tcx> {
+    elaborate_trait_refs(tcx, bounds).filter_to_traits()
+}
+
+///////////////////////////////////////////////////////////////////////////
+// `TraitAliasExpander` iterator
+///////////////////////////////////////////////////////////////////////////
+
+/// "Trait alias expansion" is the process of expanding a sequence of trait
+/// references into another sequence by transitively following all trait
+/// aliases. e.g. If you have bounds like `Foo + Send`, a trait alias
+/// `trait Foo = Bar + Sync;`, and another trait alias
+/// `trait Bar = Read + Write`, then the bounds would expand to
+/// `Read + Write + Sync + Send`.
+/// Expansion is done via a DFS (depth-first search), and the `visited` field
+/// is used to avoid cycles.
+pub struct TraitAliasExpander<'tcx> {
+    tcx: TyCtxt<'tcx>,
+    stack: Vec<TraitAliasExpansionInfo<'tcx>>,
+}
+
+/// Stores information about the expansion of a trait via a path of zero or more trait aliases.
+#[derive(Debug, Clone)]
+pub struct TraitAliasExpansionInfo<'tcx> {
+    pub path: SmallVec<[(ty::PolyTraitRef<'tcx>, Span); 4]>,
+}
+
+impl<'tcx> TraitAliasExpansionInfo<'tcx> {
+    fn new(trait_ref: ty::PolyTraitRef<'tcx>, span: Span) -> Self {
+        Self { path: smallvec![(trait_ref, span)] }
+    }
+
+    /// Adds diagnostic labels to `diag` for the expansion path of a trait through all intermediate
+    /// trait aliases.
+    pub fn label_with_exp_info(
+        &self,
+        diag: &mut DiagnosticBuilder<'_>,
+        top_label: &str,
+        use_desc: &str,
+    ) {
+        diag.span_label(self.top().1, top_label);
+        if self.path.len() > 1 {
+            for (_, sp) in self.path.iter().rev().skip(1).take(self.path.len() - 2) {
+                diag.span_label(*sp, format!("referenced here ({})", use_desc));
+            }
+        }
+        diag.span_label(
+            self.bottom().1,
+            format!("trait alias used in trait object type ({})", use_desc),
+        );
+    }
+
+    pub fn trait_ref(&self) -> &ty::PolyTraitRef<'tcx> {
+        &self.top().0
+    }
+
+    pub fn top(&self) -> &(ty::PolyTraitRef<'tcx>, Span) {
+        self.path.last().unwrap()
+    }
+
+    pub fn bottom(&self) -> &(ty::PolyTraitRef<'tcx>, Span) {
+        self.path.first().unwrap()
+    }
+
+    fn clone_and_push(&self, trait_ref: ty::PolyTraitRef<'tcx>, span: Span) -> Self {
+        let mut path = self.path.clone();
+        path.push((trait_ref, span));
+
+        Self { path }
+    }
+}
+
+pub fn expand_trait_aliases<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    trait_refs: impl IntoIterator<Item = (ty::PolyTraitRef<'tcx>, Span)>,
+) -> TraitAliasExpander<'tcx> {
+    let items: Vec<_> = trait_refs
+        .into_iter()
+        .map(|(trait_ref, span)| TraitAliasExpansionInfo::new(trait_ref, span))
+        .collect();
+    TraitAliasExpander { tcx, stack: items }
+}
+
+impl<'tcx> TraitAliasExpander<'tcx> {
+    /// If `item` is a trait alias and its predicate has not yet been visited, then expands `item`
+    /// to the definition, pushes the resulting expansion onto `self.stack`, and returns `false`.
+    /// Otherwise, immediately returns `true` if `item` is a regular trait, or `false` if it is a
+    /// trait alias.
+    /// The return value indicates whether `item` should be yielded to the user.
+    fn expand(&mut self, item: &TraitAliasExpansionInfo<'tcx>) -> bool {
+        let tcx = self.tcx;
+        let trait_ref = item.trait_ref();
+        let pred = trait_ref.without_const().to_predicate();
+
+        debug!("expand_trait_aliases: trait_ref={:?}", trait_ref);
+
+        // Don't recurse if this bound is not a trait alias.
+        let is_alias = tcx.is_trait_alias(trait_ref.def_id());
+        if !is_alias {
+            return true;
+        }
+
+        // Don't recurse if this trait alias is already on the stack for the DFS search.
+        let anon_pred = anonymize_predicate(tcx, &pred);
+        if item.path.iter().rev().skip(1).any(|(tr, _)| {
+            anonymize_predicate(tcx, &tr.without_const().to_predicate()) == anon_pred
+        }) {
+            return false;
+        }
+
+        // Get components of trait alias.
+        let predicates = tcx.super_predicates_of(trait_ref.def_id());
+
+        let items = predicates.predicates.iter().rev().filter_map(|(pred, span)| {
+            pred.subst_supertrait(tcx, &trait_ref)
+                .to_opt_poly_trait_ref()
+                .map(|trait_ref| item.clone_and_push(trait_ref, *span))
+        });
+        debug!("expand_trait_aliases: items={:?}", items.clone());
+
+        self.stack.extend(items);
+
+        false
+    }
+}
+
+impl<'tcx> Iterator for TraitAliasExpander<'tcx> {
+    type Item = TraitAliasExpansionInfo<'tcx>;
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        (self.stack.len(), None)
+    }
+
+    fn next(&mut self) -> Option<TraitAliasExpansionInfo<'tcx>> {
+        while let Some(item) = self.stack.pop() {
+            if self.expand(&item) {
+                return Some(item);
+            }
+        }
+        None
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////
+// Iterator over def-IDs of supertraits
+///////////////////////////////////////////////////////////////////////////
+
+pub struct SupertraitDefIds<'tcx> {
+    tcx: TyCtxt<'tcx>,
+    stack: Vec<DefId>,
+    visited: FxHashSet<DefId>,
+}
+
+pub fn supertrait_def_ids(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SupertraitDefIds<'_> {
+    SupertraitDefIds {
+        tcx,
+        stack: vec![trait_def_id],
+        visited: Some(trait_def_id).into_iter().collect(),
+    }
+}
+
+impl Iterator for SupertraitDefIds<'tcx> {
+    type Item = DefId;
+
+    fn next(&mut self) -> Option<DefId> {
+        let def_id = self.stack.pop()?;
+        let predicates = self.tcx.super_predicates_of(def_id);
+        let visited = &mut self.visited;
+        self.stack.extend(
+            predicates
+                .predicates
+                .iter()
+                .filter_map(|(pred, _)| pred.to_opt_poly_trait_ref())
+                .map(|trait_ref| trait_ref.def_id())
+                .filter(|&super_def_id| visited.insert(super_def_id)),
+        );
+        Some(def_id)
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////
+// Other
+///////////////////////////////////////////////////////////////////////////
+
+/// A filter around an iterator of predicates that makes it yield up
+/// just trait references.
+pub struct FilterToTraits<I> {
+    base_iterator: I,
+}
+
+impl<I> FilterToTraits<I> {
+    fn new(base: I) -> FilterToTraits<I> {
+        FilterToTraits { base_iterator: base }
+    }
+}
+
+impl<'tcx, I: Iterator<Item = ty::Predicate<'tcx>>> Iterator for FilterToTraits<I> {
+    type Item = ty::PolyTraitRef<'tcx>;
+
+    fn next(&mut self) -> Option<ty::PolyTraitRef<'tcx>> {
+        while let Some(pred) = self.base_iterator.next() {
+            if let ty::Predicate::Trait(data, _) = pred {
+                return Some(data.to_poly_trait_ref());
+            }
+        }
+        None
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        let (_, upper) = self.base_iterator.size_hint();
+        (0, upper)
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////
+// Other
+///////////////////////////////////////////////////////////////////////////
+
+/// Instantiate all bound parameters of the impl with the given substs,
+/// returning the resulting trait ref and all obligations that arise.
+/// The obligations are closed under normalization.
+pub fn impl_trait_ref_and_oblig<'a, 'tcx>(
+    selcx: &mut SelectionContext<'a, 'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    impl_def_id: DefId,
+    impl_substs: SubstsRef<'tcx>,
+) -> (ty::TraitRef<'tcx>, Vec<PredicateObligation<'tcx>>) {
+    let impl_trait_ref = selcx.tcx().impl_trait_ref(impl_def_id).unwrap();
+    let impl_trait_ref = impl_trait_ref.subst(selcx.tcx(), impl_substs);
+    let Normalized { value: impl_trait_ref, obligations: normalization_obligations1 } =
+        super::normalize(selcx, param_env, ObligationCause::dummy(), &impl_trait_ref);
+
+    let predicates = selcx.tcx().predicates_of(impl_def_id);
+    let predicates = predicates.instantiate(selcx.tcx(), impl_substs);
+    let Normalized { value: predicates, obligations: normalization_obligations2 } =
+        super::normalize(selcx, param_env, ObligationCause::dummy(), &predicates);
+    let impl_obligations =
+        predicates_for_generics(ObligationCause::dummy(), 0, param_env, &predicates);
+
+    let impl_obligations: Vec<_> = impl_obligations
+        .into_iter()
+        .chain(normalization_obligations1)
+        .chain(normalization_obligations2)
+        .collect();
+
+    (impl_trait_ref, impl_obligations)
+}
+
+/// See [`super::obligations_for_generics`].
+pub fn predicates_for_generics<'tcx>(
+    cause: ObligationCause<'tcx>,
+    recursion_depth: usize,
+    param_env: ty::ParamEnv<'tcx>,
+    generic_bounds: &ty::InstantiatedPredicates<'tcx>,
+) -> Vec<PredicateObligation<'tcx>> {
+    debug!("predicates_for_generics(generic_bounds={:?})", generic_bounds);
+
+    generic_bounds
+        .predicates
+        .iter()
+        .map(|&predicate| Obligation {
+            cause: cause.clone(),
+            recursion_depth,
+            param_env,
+            predicate,
+        })
+        .collect()
+}
+
+pub fn predicate_for_trait_ref<'tcx>(
+    cause: ObligationCause<'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    trait_ref: ty::TraitRef<'tcx>,
+    recursion_depth: usize,
+) -> PredicateObligation<'tcx> {
+    Obligation {
+        cause,
+        param_env,
+        recursion_depth,
+        predicate: trait_ref.without_const().to_predicate(),
+    }
+}
+
+pub fn predicate_for_trait_def(
+    tcx: TyCtxt<'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    cause: ObligationCause<'tcx>,
+    trait_def_id: DefId,
+    recursion_depth: usize,
+    self_ty: Ty<'tcx>,
+    params: &[GenericArg<'tcx>],
+) -> PredicateObligation<'tcx> {
+    let trait_ref =
+        ty::TraitRef { def_id: trait_def_id, substs: tcx.mk_substs_trait(self_ty, params) };
+    predicate_for_trait_ref(cause, param_env, trait_ref, recursion_depth)
+}
+
+/// Casts a trait reference into a reference to one of its super
+/// traits; returns `None` if `target_trait_def_id` is not a
+/// supertrait.
+pub fn upcast_choices(
+    tcx: TyCtxt<'tcx>,
+    source_trait_ref: ty::PolyTraitRef<'tcx>,
+    target_trait_def_id: DefId,
+) -> Vec<ty::PolyTraitRef<'tcx>> {
+    if source_trait_ref.def_id() == target_trait_def_id {
+        return vec![source_trait_ref]; // Shortcut the most common case.
+    }
+
+    supertraits(tcx, source_trait_ref).filter(|r| r.def_id() == target_trait_def_id).collect()
+}
+
+/// Given a trait `trait_ref`, returns the number of vtable entries
+/// that come from `trait_ref`, excluding its supertraits. Used in
+/// computing the vtable base for an upcast trait of a trait object.
+pub fn count_own_vtable_entries(tcx: TyCtxt<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>) -> usize {
+    let mut entries = 0;
+    // Count number of methods and add them to the total offset.
+    // Skip over associated types and constants.
+    for trait_item in tcx.associated_items(trait_ref.def_id()).in_definition_order() {
+        if trait_item.kind == ty::AssocKind::Method {
+            entries += 1;
+        }
+    }
+    entries
+}
+
+/// Given an upcast trait object described by `object`, returns the
+/// index of the method `method_def_id` (which should be part of
+/// `object.upcast_trait_ref`) within the vtable for `object`.
+pub fn get_vtable_index_of_object_method<N>(
+    tcx: TyCtxt<'tcx>,
+    object: &super::VtableObjectData<'tcx, N>,
+    method_def_id: DefId,
+) -> usize {
+    // Count number of methods preceding the one we are selecting and
+    // add them to the total offset.
+    // Skip over associated types and constants.
+    let mut entries = object.vtable_base;
+    for trait_item in tcx.associated_items(object.upcast_trait_ref.def_id()).in_definition_order() {
+        if trait_item.def_id == method_def_id {
+            // The item with the ID we were given really ought to be a method.
+            assert_eq!(trait_item.kind, ty::AssocKind::Method);
+            return entries;
+        }
+        if trait_item.kind == ty::AssocKind::Method {
+            entries += 1;
+        }
+    }
+
+    bug!("get_vtable_index_of_object_method: {:?} was not found", method_def_id);
+}
+
+pub fn closure_trait_ref_and_return_type(
+    tcx: TyCtxt<'tcx>,
+    fn_trait_def_id: DefId,
+    self_ty: Ty<'tcx>,
+    sig: ty::PolyFnSig<'tcx>,
+    tuple_arguments: TupleArgumentsFlag,
+) -> ty::Binder<(ty::TraitRef<'tcx>, Ty<'tcx>)> {
+    let arguments_tuple = match tuple_arguments {
+        TupleArgumentsFlag::No => sig.skip_binder().inputs()[0],
+        TupleArgumentsFlag::Yes => tcx.intern_tup(sig.skip_binder().inputs()),
+    };
+    let trait_ref = ty::TraitRef {
+        def_id: fn_trait_def_id,
+        substs: tcx.mk_substs_trait(self_ty, &[arguments_tuple.into()]),
+    };
+    ty::Binder::bind((trait_ref, sig.skip_binder().output()))
+}
+
+pub fn generator_trait_ref_and_outputs(
+    tcx: TyCtxt<'tcx>,
+    fn_trait_def_id: DefId,
+    self_ty: Ty<'tcx>,
+    sig: ty::PolyGenSig<'tcx>,
+) -> ty::Binder<(ty::TraitRef<'tcx>, Ty<'tcx>, Ty<'tcx>)> {
+    let trait_ref = ty::TraitRef {
+        def_id: fn_trait_def_id,
+        substs: tcx.mk_substs_trait(self_ty, &[sig.skip_binder().resume_ty.into()]),
+    };
+    ty::Binder::bind((trait_ref, sig.skip_binder().yield_ty, sig.skip_binder().return_ty))
+}
+
+pub fn impl_is_default(tcx: TyCtxt<'_>, node_item_def_id: DefId) -> bool {
+    match tcx.hir().as_local_hir_id(node_item_def_id) {
+        Some(hir_id) => {
+            let item = tcx.hir().expect_item(hir_id);
+            if let hir::ItemKind::Impl { defaultness, .. } = item.kind {
+                defaultness.is_default()
+            } else {
+                false
+            }
+        }
+        None => tcx.impl_defaultness(node_item_def_id).is_default(),
+    }
+}
+
+pub fn impl_item_is_final(tcx: TyCtxt<'_>, assoc_item: &ty::AssocItem) -> bool {
+    assoc_item.defaultness.is_final() && !impl_is_default(tcx, assoc_item.container.id())
+}
+
+pub enum TupleArgumentsFlag {
+    Yes,
+    No,
+}
diff --git a/src/librustc_trait_selection/traits/wf.rs b/src/librustc_trait_selection/traits/wf.rs
new file mode 100644 (file)
index 0000000..b69c5bd
--- /dev/null
@@ -0,0 +1,753 @@
+use crate::infer::InferCtxt;
+use crate::opaque_types::required_region_bounds;
+use crate::traits::{self, AssocTypeBoundData};
+use rustc::middle::lang_items;
+use rustc::ty::subst::SubstsRef;
+use rustc::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
+use rustc_span::symbol::{kw, Ident};
+use rustc_span::Span;
+
+/// Returns the set of obligations needed to make `ty` well-formed.
+/// If `ty` contains unresolved inference variables, this may include
+/// further WF obligations. However, if `ty` IS an unresolved
+/// inference variable, returns `None`, because we are not able to
+/// make any progress at all. This is to prevent "livelock" where we
+/// say "$0 is WF if $0 is WF".
+pub fn obligations<'a, 'tcx>(
+    infcx: &InferCtxt<'a, 'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    body_id: hir::HirId,
+    ty: Ty<'tcx>,
+    span: Span,
+) -> Option<Vec<traits::PredicateObligation<'tcx>>> {
+    let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![], item: None };
+    if wf.compute(ty) {
+        debug!("wf::obligations({:?}, body_id={:?}) = {:?}", ty, body_id, wf.out);
+
+        let result = wf.normalize();
+        debug!("wf::obligations({:?}, body_id={:?}) ~~> {:?}", ty, body_id, result);
+        Some(result)
+    } else {
+        None // no progress made, return None
+    }
+}
+
+/// Returns the obligations that make this trait reference
+/// well-formed.  For example, if there is a trait `Set` defined like
+/// `trait Set<K:Eq>`, then the trait reference `Foo: Set<Bar>` is WF
+/// if `Bar: Eq`.
+pub fn trait_obligations<'a, 'tcx>(
+    infcx: &InferCtxt<'a, 'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    body_id: hir::HirId,
+    trait_ref: &ty::TraitRef<'tcx>,
+    span: Span,
+    item: Option<&'tcx hir::Item<'tcx>>,
+) -> Vec<traits::PredicateObligation<'tcx>> {
+    let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![], item };
+    wf.compute_trait_ref(trait_ref, Elaborate::All);
+    wf.normalize()
+}
+
+pub fn predicate_obligations<'a, 'tcx>(
+    infcx: &InferCtxt<'a, 'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    body_id: hir::HirId,
+    predicate: &ty::Predicate<'tcx>,
+    span: Span,
+) -> Vec<traits::PredicateObligation<'tcx>> {
+    let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![], item: None };
+
+    // (*) ok to skip binders, because wf code is prepared for it
+    match *predicate {
+        ty::Predicate::Trait(ref t, _) => {
+            wf.compute_trait_ref(&t.skip_binder().trait_ref, Elaborate::None); // (*)
+        }
+        ty::Predicate::RegionOutlives(..) => {}
+        ty::Predicate::TypeOutlives(ref t) => {
+            wf.compute(t.skip_binder().0);
+        }
+        ty::Predicate::Projection(ref t) => {
+            let t = t.skip_binder(); // (*)
+            wf.compute_projection(t.projection_ty);
+            wf.compute(t.ty);
+        }
+        ty::Predicate::WellFormed(t) => {
+            wf.compute(t);
+        }
+        ty::Predicate::ObjectSafe(_) => {}
+        ty::Predicate::ClosureKind(..) => {}
+        ty::Predicate::Subtype(ref data) => {
+            wf.compute(data.skip_binder().a); // (*)
+            wf.compute(data.skip_binder().b); // (*)
+        }
+        ty::Predicate::ConstEvaluatable(def_id, substs) => {
+            let obligations = wf.nominal_obligations(def_id, substs);
+            wf.out.extend(obligations);
+
+            for ty in substs.types() {
+                wf.compute(ty);
+            }
+        }
+    }
+
+    wf.normalize()
+}
+
+struct WfPredicates<'a, 'tcx> {
+    infcx: &'a InferCtxt<'a, 'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    body_id: hir::HirId,
+    span: Span,
+    out: Vec<traits::PredicateObligation<'tcx>>,
+    item: Option<&'tcx hir::Item<'tcx>>,
+}
+
+/// Controls whether we "elaborate" supertraits and so forth on the WF
+/// predicates. This is a kind of hack to address #43784. The
+/// underlying problem in that issue was a trait structure like:
+///
+/// ```
+/// trait Foo: Copy { }
+/// trait Bar: Foo { }
+/// impl<T: Bar> Foo for T { }
+/// impl<T> Bar for T { }
+/// ```
+///
+/// Here, in the `Foo` impl, we will check that `T: Copy` holds -- but
+/// we decide that this is true because `T: Bar` is in the
+/// where-clauses (and we can elaborate that to include `T:
+/// Copy`). This wouldn't be a problem, except that when we check the
+/// `Bar` impl, we decide that `T: Foo` must hold because of the `Foo`
+/// impl. And so nowhere did we check that `T: Copy` holds!
+///
+/// To resolve this, we elaborate the WF requirements that must be
+/// proven when checking impls. This means that (e.g.) the `impl Bar
+/// for T` will be forced to prove not only that `T: Foo` but also `T:
+/// Copy` (which it won't be able to do, because there is no `Copy`
+/// impl for `T`).
+#[derive(Debug, PartialEq, Eq, Copy, Clone)]
+enum Elaborate {
+    All,
+    None,
+}
+
+impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
+    fn cause(&mut self, code: traits::ObligationCauseCode<'tcx>) -> traits::ObligationCause<'tcx> {
+        traits::ObligationCause::new(self.span, self.body_id, code)
+    }
+
+    fn normalize(&mut self) -> Vec<traits::PredicateObligation<'tcx>> {
+        let cause = self.cause(traits::MiscObligation);
+        let infcx = &mut self.infcx;
+        let param_env = self.param_env;
+        let mut obligations = Vec::with_capacity(self.out.len());
+        for pred in &self.out {
+            assert!(!pred.has_escaping_bound_vars());
+            let mut selcx = traits::SelectionContext::new(infcx);
+            let i = obligations.len();
+            let value =
+                traits::normalize_to(&mut selcx, param_env, cause.clone(), pred, &mut obligations);
+            obligations.insert(i, value);
+        }
+        obligations
+    }
+
+    /// Pushes the obligations required for `trait_ref` to be WF into `self.out`.
+    fn compute_trait_ref(&mut self, trait_ref: &ty::TraitRef<'tcx>, elaborate: Elaborate) {
+        let tcx = self.infcx.tcx;
+        let obligations = self.nominal_obligations(trait_ref.def_id, trait_ref.substs);
+
+        let cause = self.cause(traits::MiscObligation);
+        let param_env = self.param_env;
+
+        let item = &self.item;
+        let extend_cause_with_original_assoc_item_obligation =
+            |cause: &mut traits::ObligationCause<'_>,
+             pred: &ty::Predicate<'_>,
+             trait_assoc_items: &[ty::AssocItem]| {
+                let trait_item = tcx
+                    .hir()
+                    .as_local_hir_id(trait_ref.def_id)
+                    .and_then(|trait_id| tcx.hir().find(trait_id));
+                let (trait_name, trait_generics) = match trait_item {
+                    Some(hir::Node::Item(hir::Item {
+                        ident,
+                        kind: hir::ItemKind::Trait(.., generics, _, _),
+                        ..
+                    }))
+                    | Some(hir::Node::Item(hir::Item {
+                        ident,
+                        kind: hir::ItemKind::TraitAlias(generics, _),
+                        ..
+                    })) => (Some(ident), Some(generics)),
+                    _ => (None, None),
+                };
+
+                let item_span = item.map(|i| tcx.sess.source_map().def_span(i.span));
+                match pred {
+                    ty::Predicate::Projection(proj) => {
+                        // The obligation comes not from the current `impl` nor the `trait` being
+                        // implemented, but rather from a "second order" obligation, like in
+                        // `src/test/ui/associated-types/point-at-type-on-obligation-failure.rs`:
+                        //
+                        //   error[E0271]: type mismatch resolving `<Foo2 as Bar2>::Ok == ()`
+                        //     --> $DIR/point-at-type-on-obligation-failure.rs:13:5
+                        //      |
+                        //   LL |     type Ok;
+                        //      |          -- associated type defined here
+                        //   ...
+                        //   LL | impl Bar for Foo {
+                        //      | ---------------- in this `impl` item
+                        //   LL |     type Ok = ();
+                        //      |     ^^^^^^^^^^^^^ expected `u32`, found `()`
+                        //      |
+                        //      = note: expected type `u32`
+                        //                 found type `()`
+                        //
+                        // FIXME: we would want to point a span to all places that contributed to this
+                        // obligation. In the case above, it should be closer to:
+                        //
+                        //   error[E0271]: type mismatch resolving `<Foo2 as Bar2>::Ok == ()`
+                        //     --> $DIR/point-at-type-on-obligation-failure.rs:13:5
+                        //      |
+                        //   LL |     type Ok;
+                        //      |          -- associated type defined here
+                        //   LL |     type Sibling: Bar2<Ok=Self::Ok>;
+                        //      |     -------------------------------- obligation set here
+                        //   ...
+                        //   LL | impl Bar for Foo {
+                        //      | ---------------- in this `impl` item
+                        //   LL |     type Ok = ();
+                        //      |     ^^^^^^^^^^^^^ expected `u32`, found `()`
+                        //   ...
+                        //   LL | impl Bar2 for Foo2 {
+                        //      | ---------------- in this `impl` item
+                        //   LL |     type Ok = u32;
+                        //      |     -------------- obligation set here
+                        //      |
+                        //      = note: expected type `u32`
+                        //                 found type `()`
+                        if let Some(hir::ItemKind::Impl { items, .. }) = item.map(|i| &i.kind) {
+                            let trait_assoc_item = tcx.associated_item(proj.projection_def_id());
+                            if let Some(impl_item) =
+                                items.iter().find(|item| item.ident == trait_assoc_item.ident)
+                            {
+                                cause.span = impl_item.span;
+                                cause.code = traits::AssocTypeBound(Box::new(AssocTypeBoundData {
+                                    impl_span: item_span,
+                                    original: trait_assoc_item.ident.span,
+                                    bounds: vec![],
+                                }));
+                            }
+                        }
+                    }
+                    ty::Predicate::Trait(proj, _) => {
+                        // An associated item obligation born out of the `trait` failed to be met.
+                        // Point at the `impl` that failed the obligation, the associated item that
+                        // needed to meet the obligation, and the definition of that associated item,
+                        // which should hold the obligation in most cases. An example can be seen in
+                        // `src/test/ui/associated-types/point-at-type-on-obligation-failure-2.rs`:
+                        //
+                        //   error[E0277]: the trait bound `bool: Bar` is not satisfied
+                        //     --> $DIR/point-at-type-on-obligation-failure-2.rs:8:5
+                        //      |
+                        //   LL |     type Assoc: Bar;
+                        //      |          ----- associated type defined here
+                        //   ...
+                        //   LL | impl Foo for () {
+                        //      | --------------- in this `impl` item
+                        //   LL |     type Assoc = bool;
+                        //      |     ^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `bool`
+                        //
+                        // If the obligation comes from the where clause in the `trait`, we point at it:
+                        //
+                        //   error[E0277]: the trait bound `bool: Bar` is not satisfied
+                        //     --> $DIR/point-at-type-on-obligation-failure-2.rs:8:5
+                        //      |
+                        //      | trait Foo where <Self as Foo>>::Assoc: Bar {
+                        //      |                 -------------------------- restricted in this bound
+                        //   LL |     type Assoc;
+                        //      |          ----- associated type defined here
+                        //   ...
+                        //   LL | impl Foo for () {
+                        //      | --------------- in this `impl` item
+                        //   LL |     type Assoc = bool;
+                        //      |     ^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `bool`
+                        if let (
+                            ty::Projection(ty::ProjectionTy { item_def_id, .. }),
+                            Some(hir::ItemKind::Impl { items, .. }),
+                        ) = (&proj.skip_binder().self_ty().kind, item.map(|i| &i.kind))
+                        {
+                            if let Some((impl_item, trait_assoc_item)) = trait_assoc_items
+                                .iter()
+                                .find(|i| i.def_id == *item_def_id)
+                                .and_then(|trait_assoc_item| {
+                                    items
+                                        .iter()
+                                        .find(|i| i.ident == trait_assoc_item.ident)
+                                        .map(|impl_item| (impl_item, trait_assoc_item))
+                                })
+                            {
+                                let bounds = trait_generics
+                                    .map(|generics| {
+                                        get_generic_bound_spans(
+                                            &generics,
+                                            trait_name,
+                                            trait_assoc_item.ident,
+                                        )
+                                    })
+                                    .unwrap_or_else(Vec::new);
+                                cause.span = impl_item.span;
+                                cause.code = traits::AssocTypeBound(Box::new(AssocTypeBoundData {
+                                    impl_span: item_span,
+                                    original: trait_assoc_item.ident.span,
+                                    bounds,
+                                }));
+                            }
+                        }
+                    }
+                    _ => {}
+                }
+            };
+
+        if let Elaborate::All = elaborate {
+            // FIXME: Make `extend_cause_with_original_assoc_item_obligation` take an iterator
+            // instead of a slice.
+            let trait_assoc_items: Vec<_> =
+                tcx.associated_items(trait_ref.def_id).in_definition_order().copied().collect();
+
+            let predicates = obligations.iter().map(|obligation| obligation.predicate).collect();
+            let implied_obligations = traits::elaborate_predicates(tcx, predicates);
+            let implied_obligations = implied_obligations.map(|pred| {
+                let mut cause = cause.clone();
+                extend_cause_with_original_assoc_item_obligation(
+                    &mut cause,
+                    &pred,
+                    &*trait_assoc_items,
+                );
+                traits::Obligation::new(cause, param_env, pred)
+            });
+            self.out.extend(implied_obligations);
+        }
+
+        self.out.extend(obligations);
+
+        self.out.extend(trait_ref.substs.types().filter(|ty| !ty.has_escaping_bound_vars()).map(
+            |ty| traits::Obligation::new(cause.clone(), param_env, ty::Predicate::WellFormed(ty)),
+        ));
+    }
+
+    /// Pushes the obligations required for `trait_ref::Item` to be WF
+    /// into `self.out`.
+    fn compute_projection(&mut self, data: ty::ProjectionTy<'tcx>) {
+        // A projection is well-formed if (a) the trait ref itself is
+        // WF and (b) the trait-ref holds.  (It may also be
+        // normalizable and be WF that way.)
+        let trait_ref = data.trait_ref(self.infcx.tcx);
+        self.compute_trait_ref(&trait_ref, Elaborate::None);
+
+        if !data.has_escaping_bound_vars() {
+            let predicate = trait_ref.without_const().to_predicate();
+            let cause = self.cause(traits::ProjectionWf(data));
+            self.out.push(traits::Obligation::new(cause, self.param_env, predicate));
+        }
+    }
+
+    /// Pushes the obligations required for an array length to be WF
+    /// into `self.out`.
+    fn compute_array_len(&mut self, constant: ty::Const<'tcx>) {
+        if let ty::ConstKind::Unevaluated(def_id, substs, promoted) = constant.val {
+            assert!(promoted.is_none());
+
+            let obligations = self.nominal_obligations(def_id, substs);
+            self.out.extend(obligations);
+
+            let predicate = ty::Predicate::ConstEvaluatable(def_id, substs);
+            let cause = self.cause(traits::MiscObligation);
+            self.out.push(traits::Obligation::new(cause, self.param_env, predicate));
+        }
+    }
+
+    fn require_sized(&mut self, subty: Ty<'tcx>, cause: traits::ObligationCauseCode<'tcx>) {
+        if !subty.has_escaping_bound_vars() {
+            let cause = self.cause(cause);
+            let trait_ref = ty::TraitRef {
+                def_id: self.infcx.tcx.require_lang_item(lang_items::SizedTraitLangItem, None),
+                substs: self.infcx.tcx.mk_substs_trait(subty, &[]),
+            };
+            self.out.push(traits::Obligation::new(
+                cause,
+                self.param_env,
+                trait_ref.without_const().to_predicate(),
+            ));
+        }
+    }
+
+    /// Pushes new obligations into `out`. Returns `true` if it was able
+    /// to generate all the predicates needed to validate that `ty0`
+    /// is WF. Returns false if `ty0` is an unresolved type variable,
+    /// in which case we are not able to simplify at all.
+    fn compute(&mut self, ty0: Ty<'tcx>) -> bool {
+        let mut subtys = ty0.walk();
+        let param_env = self.param_env;
+        while let Some(ty) = subtys.next() {
+            match ty.kind {
+                ty::Bool
+                | ty::Char
+                | ty::Int(..)
+                | ty::Uint(..)
+                | ty::Float(..)
+                | ty::Error
+                | ty::Str
+                | ty::GeneratorWitness(..)
+                | ty::Never
+                | ty::Param(_)
+                | ty::Bound(..)
+                | ty::Placeholder(..)
+                | ty::Foreign(..) => {
+                    // WfScalar, WfParameter, etc
+                }
+
+                ty::Slice(subty) => {
+                    self.require_sized(subty, traits::SliceOrArrayElem);
+                }
+
+                ty::Array(subty, len) => {
+                    self.require_sized(subty, traits::SliceOrArrayElem);
+                    self.compute_array_len(*len);
+                }
+
+                ty::Tuple(ref tys) => {
+                    if let Some((_last, rest)) = tys.split_last() {
+                        for elem in rest {
+                            self.require_sized(elem.expect_ty(), traits::TupleElem);
+                        }
+                    }
+                }
+
+                ty::RawPtr(_) => {
+                    // simple cases that are WF if their type args are WF
+                }
+
+                ty::Projection(data) => {
+                    subtys.skip_current_subtree(); // subtree handled by compute_projection
+                    self.compute_projection(data);
+                }
+
+                ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
+
+                ty::Adt(def, substs) => {
+                    // WfNominalType
+                    let obligations = self.nominal_obligations(def.did, substs);
+                    self.out.extend(obligations);
+                }
+
+                ty::FnDef(did, substs) => {
+                    let obligations = self.nominal_obligations(did, substs);
+                    self.out.extend(obligations);
+                }
+
+                ty::Ref(r, rty, _) => {
+                    // WfReference
+                    if !r.has_escaping_bound_vars() && !rty.has_escaping_bound_vars() {
+                        let cause = self.cause(traits::ReferenceOutlivesReferent(ty));
+                        self.out.push(traits::Obligation::new(
+                            cause,
+                            param_env,
+                            ty::Predicate::TypeOutlives(ty::Binder::dummy(ty::OutlivesPredicate(
+                                rty, r,
+                            ))),
+                        ));
+                    }
+                }
+
+                ty::Generator(..) => {
+                    // Walk ALL the types in the generator: this will
+                    // include the upvar types as well as the yield
+                    // type. Note that this is mildly distinct from
+                    // the closure case, where we have to be careful
+                    // about the signature of the closure. We don't
+                    // have the problem of implied bounds here since
+                    // generators don't take arguments.
+                }
+
+                ty::Closure(def_id, substs) => {
+                    // Only check the upvar types for WF, not the rest
+                    // of the types within. This is needed because we
+                    // capture the signature and it may not be WF
+                    // without the implied bounds. Consider a closure
+                    // like `|x: &'a T|` -- it may be that `T: 'a` is
+                    // not known to hold in the creator's context (and
+                    // indeed the closure may not be invoked by its
+                    // creator, but rather turned to someone who *can*
+                    // verify that).
+                    //
+                    // The special treatment of closures here really
+                    // ought not to be necessary either; the problem
+                    // is related to #25860 -- there is no way for us
+                    // to express a fn type complete with the implied
+                    // bounds that it is assuming. I think in reality
+                    // the WF rules around fn are a bit messed up, and
+                    // that is the rot problem: `fn(&'a T)` should
+                    // probably always be WF, because it should be
+                    // shorthand for something like `where(T: 'a) {
+                    // fn(&'a T) }`, as discussed in #25860.
+                    //
+                    // Note that we are also skipping the generic
+                    // types. This is consistent with the `outlives`
+                    // code, but anyway doesn't matter: within the fn
+                    // body where they are created, the generics will
+                    // always be WF, and outside of that fn body we
+                    // are not directly inspecting closure types
+                    // 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) {
+                        self.compute(upvar_ty);
+                    }
+                }
+
+                ty::FnPtr(_) => {
+                    // let the loop iterate into the argument/return
+                    // types appearing in the fn signature
+                }
+
+                ty::Opaque(did, substs) => {
+                    // all of the requirements on type parameters
+                    // should've been checked by the instantiation
+                    // of whatever returned this exact `impl Trait`.
+
+                    // for named opaque `impl Trait` types we still need to check them
+                    if ty::is_impl_trait_defn(self.infcx.tcx, did).is_none() {
+                        let obligations = self.nominal_obligations(did, substs);
+                        self.out.extend(obligations);
+                    }
+                }
+
+                ty::Dynamic(data, r) => {
+                    // WfObject
+                    //
+                    // Here, we defer WF checking due to higher-ranked
+                    // regions. This is perhaps not ideal.
+                    self.from_object_ty(ty, data, r);
+
+                    // FIXME(#27579) RFC also considers adding trait
+                    // 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),
+                            )
+                        }));
+                    }
+                }
+
+                // Inference variables are the complicated case, since we don't
+                // know what type they are. We do two things:
+                //
+                // 1. Check if they have been resolved, and if so proceed with
+                //    THAT type.
+                // 2. If not, check whether this is the type that we
+                //    started with (ty0). In that case, we've made no
+                //    progress at all, so return false. Otherwise,
+                //    we've at least simplified things (i.e., we went
+                //    from `Vec<$0>: WF` to `$0: WF`, so we can
+                //    register a pending obligation and keep
+                //    moving. (Goal is that an "inductive hypothesis"
+                //    is satisfied to ensure termination.)
+                ty::Infer(_) => {
+                    let ty = self.infcx.shallow_resolve(ty);
+                    if let ty::Infer(_) = ty.kind {
+                        // not yet resolved...
+                        if ty == ty0 {
+                            // ...this is the type we started from! no progress.
+                            return false;
+                        }
+
+                        let cause = self.cause(traits::MiscObligation);
+                        self.out.push(
+                            // ...not the type we started from, so we made progress.
+                            traits::Obligation::new(
+                                cause,
+                                self.param_env,
+                                ty::Predicate::WellFormed(ty),
+                            ),
+                        );
+                    } else {
+                        // Yes, resolved, proceed with the
+                        // result. Should never return false because
+                        // `ty` is not a Infer.
+                        assert!(self.compute(ty));
+                    }
+                }
+            }
+        }
+
+        // if we made it through that loop above, we made progress!
+        return true;
+    }
+
+    fn nominal_obligations(
+        &mut self,
+        def_id: DefId,
+        substs: SubstsRef<'tcx>,
+    ) -> Vec<traits::PredicateObligation<'tcx>> {
+        let predicates = self.infcx.tcx.predicates_of(def_id).instantiate(self.infcx.tcx, substs);
+        let cause = self.cause(traits::ItemObligation(def_id));
+        predicates
+            .predicates
+            .into_iter()
+            .map(|pred| traits::Obligation::new(cause.clone(), self.param_env, pred))
+            .filter(|pred| !pred.has_escaping_bound_vars())
+            .collect()
+    }
+
+    fn from_object_ty(
+        &mut self,
+        ty: Ty<'tcx>,
+        data: ty::Binder<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>,
+        region: ty::Region<'tcx>,
+    ) {
+        // Imagine a type like this:
+        //
+        //     trait Foo { }
+        //     trait Bar<'c> : 'c { }
+        //
+        //     &'b (Foo+'c+Bar<'d>)
+        //         ^
+        //
+        // In this case, the following relationships must hold:
+        //
+        //     'b <= 'c
+        //     'd <= 'c
+        //
+        // The first conditions is due to the normal region pointer
+        // rules, which say that a reference cannot outlive its
+        // referent.
+        //
+        // The final condition may be a bit surprising. In particular,
+        // you may expect that it would have been `'c <= 'd`, since
+        // usually lifetimes of outer things are conservative
+        // approximations for inner things. However, it works somewhat
+        // differently with trait objects: here the idea is that if the
+        // user specifies a region bound (`'c`, in this case) it is the
+        // "master bound" that *implies* that bounds from other traits are
+        // all met. (Remember that *all bounds* in a type like
+        // `Foo+Bar+Zed` must be met, not just one, hence if we write
+        // `Foo<'x>+Bar<'y>`, we know that the type outlives *both* 'x and
+        // 'y.)
+        //
+        // Note: in fact we only permit builtin traits, not `Bar<'d>`, I
+        // am looking forward to the future here.
+        if !data.has_escaping_bound_vars() && !region.has_escaping_bound_vars() {
+            let implicit_bounds = object_region_bounds(self.infcx.tcx, data);
+
+            let explicit_bound = region;
+
+            self.out.reserve(implicit_bounds.len());
+            for implicit_bound in implicit_bounds {
+                let cause = self.cause(traits::ObjectTypeBound(ty, explicit_bound));
+                let outlives =
+                    ty::Binder::dummy(ty::OutlivesPredicate(explicit_bound, implicit_bound));
+                self.out.push(traits::Obligation::new(
+                    cause,
+                    self.param_env,
+                    outlives.to_predicate(),
+                ));
+            }
+        }
+    }
+}
+
+/// Given an object type like `SomeTrait + Send`, computes the lifetime
+/// bounds that must hold on the elided self type. These are derived
+/// from the declarations of `SomeTrait`, `Send`, and friends -- if
+/// they declare `trait SomeTrait : 'static`, for example, then
+/// `'static` would appear in the list. The hard work is done by
+/// `infer::required_region_bounds`, see that for more information.
+pub fn object_region_bounds<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    existential_predicates: ty::Binder<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>,
+) -> Vec<ty::Region<'tcx>> {
+    // Since we don't actually *know* the self type for an object,
+    // this "open(err)" serves as a kind of dummy standin -- basically
+    // a placeholder type.
+    let open_ty = tcx.mk_ty_infer(ty::FreshTy(0));
+
+    let predicates = existential_predicates
+        .iter()
+        .filter_map(|predicate| {
+            if let ty::ExistentialPredicate::Projection(_) = *predicate.skip_binder() {
+                None
+            } else {
+                Some(predicate.with_self_ty(tcx, open_ty))
+            }
+        })
+        .collect();
+
+    required_region_bounds(tcx, open_ty, predicates)
+}
+
+/// Find the span of a generic bound affecting an associated type.
+fn get_generic_bound_spans(
+    generics: &hir::Generics<'_>,
+    trait_name: Option<&Ident>,
+    assoc_item_name: Ident,
+) -> Vec<Span> {
+    let mut bounds = vec![];
+    for clause in generics.where_clause.predicates.iter() {
+        if let hir::WherePredicate::BoundPredicate(pred) = clause {
+            match &pred.bounded_ty.kind {
+                hir::TyKind::Path(hir::QPath::Resolved(Some(ty), path)) => {
+                    let mut s = path.segments.iter();
+                    if let (a, Some(b), None) = (s.next(), s.next(), s.next()) {
+                        if a.map(|s| &s.ident) == trait_name
+                            && b.ident == assoc_item_name
+                            && is_self_path(&ty.kind)
+                        {
+                            // `<Self as Foo>::Bar`
+                            bounds.push(pred.span);
+                        }
+                    }
+                }
+                hir::TyKind::Path(hir::QPath::TypeRelative(ty, segment)) => {
+                    if segment.ident == assoc_item_name {
+                        if is_self_path(&ty.kind) {
+                            // `Self::Bar`
+                            bounds.push(pred.span);
+                        }
+                    }
+                }
+                _ => {}
+            }
+        }
+    }
+    bounds
+}
+
+fn is_self_path(kind: &hir::TyKind<'_>) -> bool {
+    match kind {
+        hir::TyKind::Path(hir::QPath::Resolved(None, path)) => {
+            let mut s = path.segments.iter();
+            if let (Some(segment), None) = (s.next(), s.next()) {
+                if segment.ident.name == kw::SelfUpper {
+                    // `type(Self)`
+                    return true;
+                }
+            }
+        }
+        _ => {}
+    }
+    false
+}
index 3fdbb4e68057d1eee1ec897ff3da5e848c6380d7..5e33efb1cf9b56a9cf234ee2082cc1de8c385dbe 100644 (file)
@@ -17,6 +17,6 @@ rustc_macros = { path = "../librustc_macros" }
 rustc_target = { path = "../librustc_target" }
 rustc_ast = { path = "../librustc_ast" }
 rustc_span = { path = "../librustc_span" }
-chalk-engine = { version = "0.9.0", default-features=false }
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
 rustc_infer = { path = "../librustc_infer" }
+rustc_trait_selection = { path = "../librustc_trait_selection" }
diff --git a/src/librustc_traits/chalk_context/mod.rs b/src/librustc_traits/chalk_context/mod.rs
deleted file mode 100644 (file)
index 240a93f..0000000
+++ /dev/null
@@ -1,638 +0,0 @@
-mod program_clauses;
-mod resolvent_ops;
-mod unify;
-
-use chalk_engine::fallible::Fallible;
-use chalk_engine::forest::Forest;
-use chalk_engine::{context, hh::HhGoal, DelayedLiteral, ExClause, Literal};
-use rustc::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
-use rustc::ty::query::Providers;
-use rustc::ty::subst::{GenericArg, GenericArgKind};
-use rustc::ty::{self, TyCtxt};
-use rustc_infer::infer::canonical::{
-    Canonical, CanonicalVarValues, Certainty, OriginalQueryValues, QueryRegionConstraints,
-    QueryResponse,
-};
-use rustc_infer::infer::{InferCtxt, LateBoundRegionConversionTime, TyCtxtInferExt};
-use rustc_infer::traits::{
-    self, ChalkCanonicalGoal, ChalkContextLift, Clause, DomainGoal, Environment, ExClauseFold,
-    Goal, GoalKind, InEnvironment, QuantifierKind,
-};
-use rustc_macros::{Lift, TypeFoldable};
-use rustc_span::DUMMY_SP;
-
-use std::fmt::{self, Debug};
-use std::marker::PhantomData;
-
-use self::unify::*;
-
-#[derive(Copy, Clone, Debug)]
-crate struct ChalkArenas<'tcx> {
-    _phantom: PhantomData<&'tcx ()>,
-}
-
-#[derive(Copy, Clone)]
-crate struct ChalkContext<'tcx> {
-    _arenas: ChalkArenas<'tcx>,
-    tcx: TyCtxt<'tcx>,
-}
-
-#[derive(Copy, Clone)]
-crate struct ChalkInferenceContext<'cx, 'tcx> {
-    infcx: &'cx InferCtxt<'cx, 'tcx>,
-}
-
-#[derive(Copy, Clone, Debug)]
-crate struct UniverseMap;
-
-crate type RegionConstraint<'tcx> = ty::OutlivesPredicate<GenericArg<'tcx>, ty::Region<'tcx>>;
-
-#[derive(Clone, Debug, PartialEq, Eq, Hash, TypeFoldable, Lift)]
-crate struct ConstrainedSubst<'tcx> {
-    subst: CanonicalVarValues<'tcx>,
-    constraints: Vec<RegionConstraint<'tcx>>,
-}
-
-impl context::Context for ChalkArenas<'tcx> {
-    type CanonicalExClause = Canonical<'tcx, ChalkExClause<'tcx>>;
-
-    type CanonicalGoalInEnvironment = Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>>;
-
-    // u-canonicalization not yet implemented
-    type UCanonicalGoalInEnvironment = Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>>;
-
-    type CanonicalConstrainedSubst = Canonical<'tcx, ConstrainedSubst<'tcx>>;
-
-    // u-canonicalization not yet implemented
-    type UniverseMap = UniverseMap;
-
-    type Solution = Canonical<'tcx, QueryResponse<'tcx, ()>>;
-
-    type InferenceNormalizedSubst = CanonicalVarValues<'tcx>;
-
-    type GoalInEnvironment = InEnvironment<'tcx, Goal<'tcx>>;
-
-    type RegionConstraint = RegionConstraint<'tcx>;
-
-    type Substitution = CanonicalVarValues<'tcx>;
-
-    type Environment = Environment<'tcx>;
-
-    type Goal = Goal<'tcx>;
-
-    type DomainGoal = DomainGoal<'tcx>;
-
-    type BindersGoal = ty::Binder<Goal<'tcx>>;
-
-    type Parameter = GenericArg<'tcx>;
-
-    type ProgramClause = Clause<'tcx>;
-
-    type ProgramClauses = Vec<Clause<'tcx>>;
-
-    type UnificationResult = UnificationResult<'tcx>;
-
-    type Variance = ty::Variance;
-
-    fn goal_in_environment(
-        env: &Environment<'tcx>,
-        goal: Goal<'tcx>,
-    ) -> InEnvironment<'tcx, Goal<'tcx>> {
-        env.with(goal)
-    }
-}
-
-impl context::AggregateOps<ChalkArenas<'tcx>> for ChalkContext<'tcx> {
-    fn make_solution(
-        &self,
-        root_goal: &Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>>,
-        mut simplified_answers: impl context::AnswerStream<ChalkArenas<'tcx>>,
-    ) -> Option<Canonical<'tcx, QueryResponse<'tcx, ()>>> {
-        use chalk_engine::SimplifiedAnswer;
-
-        debug!("make_solution(root_goal = {:?})", root_goal);
-
-        if simplified_answers.peek_answer().is_none() {
-            return None;
-        }
-
-        let SimplifiedAnswer { subst: constrained_subst, ambiguous } =
-            simplified_answers.next_answer().unwrap();
-
-        debug!("make_solution: ambiguous flag = {}", ambiguous);
-
-        let ambiguous = simplified_answers.peek_answer().is_some() || ambiguous;
-
-        let solution = constrained_subst.unchecked_map(|cs| match ambiguous {
-            true => QueryResponse {
-                var_values: cs.subst.make_identity(self.tcx),
-                region_constraints: QueryRegionConstraints::default(),
-                certainty: Certainty::Ambiguous,
-                value: (),
-            },
-
-            false => QueryResponse {
-                var_values: cs.subst,
-                region_constraints: QueryRegionConstraints::default(),
-
-                // FIXME: restore this later once we get better at handling regions
-                // region_constraints: cs.constraints
-                //     .into_iter()
-                //     .map(|c| ty::Binder::bind(c))
-                //     .collect(),
-                certainty: Certainty::Proven,
-                value: (),
-            },
-        });
-
-        debug!("make_solution: solution = {:?}", solution);
-
-        Some(solution)
-    }
-}
-
-impl context::ContextOps<ChalkArenas<'tcx>> for ChalkContext<'tcx> {
-    /// Returns `true` if this is a coinductive goal: basically proving that an auto trait
-    /// is implemented or proving that a trait reference is well-formed.
-    fn is_coinductive(&self, goal: &Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>>) -> bool {
-        use rustc::traits::{WellFormed, WhereClause};
-
-        let mut goal = goal.value.goal;
-        loop {
-            match goal {
-                GoalKind::DomainGoal(domain_goal) => match domain_goal {
-                    DomainGoal::WellFormed(WellFormed::Trait(..)) => return true,
-                    DomainGoal::Holds(WhereClause::Implemented(trait_predicate)) => {
-                        return self.tcx.trait_is_auto(trait_predicate.def_id());
-                    }
-                    _ => return false,
-                },
-
-                GoalKind::Quantified(_, bound_goal) => goal = *bound_goal.skip_binder(),
-                _ => return false,
-            }
-        }
-    }
-
-    /// Creates an inference table for processing a new goal and instantiate that goal
-    /// in that context, returning "all the pieces".
-    ///
-    /// More specifically: given a u-canonical goal `arg`, creates a
-    /// new inference table `T` and populates it with the universes
-    /// found in `arg`. Then, creates a substitution `S` that maps
-    /// each bound variable in `arg` to a fresh inference variable
-    /// from T. Returns:
-    ///
-    /// - the table `T`,
-    /// - the substitution `S`,
-    /// - the environment and goal found by substitution `S` into `arg`.
-    fn instantiate_ucanonical_goal<R>(
-        &self,
-        arg: &Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>>,
-        op: impl context::WithInstantiatedUCanonicalGoal<ChalkArenas<'tcx>, Output = R>,
-    ) -> R {
-        self.tcx.infer_ctxt().enter_with_canonical(DUMMY_SP, arg, |ref infcx, arg, subst| {
-            let chalk_infcx = &mut ChalkInferenceContext { infcx };
-            op.with(chalk_infcx, subst, arg.environment, arg.goal)
-        })
-    }
-
-    fn instantiate_ex_clause<R>(
-        &self,
-        _num_universes: usize,
-        arg: &Canonical<'tcx, ChalkExClause<'tcx>>,
-        op: impl context::WithInstantiatedExClause<ChalkArenas<'tcx>, Output = R>,
-    ) -> R {
-        self.tcx.infer_ctxt().enter_with_canonical(DUMMY_SP, &arg.upcast(), |ref infcx, arg, _| {
-            let chalk_infcx = &mut ChalkInferenceContext { infcx };
-            op.with(chalk_infcx, arg)
-        })
-    }
-
-    /// Returns `true` if this solution has no region constraints.
-    fn empty_constraints(ccs: &Canonical<'tcx, ConstrainedSubst<'tcx>>) -> bool {
-        ccs.value.constraints.is_empty()
-    }
-
-    fn inference_normalized_subst_from_ex_clause(
-        canon_ex_clause: &'a Canonical<'tcx, ChalkExClause<'tcx>>,
-    ) -> &'a CanonicalVarValues<'tcx> {
-        &canon_ex_clause.value.subst
-    }
-
-    fn inference_normalized_subst_from_subst(
-        canon_subst: &'a Canonical<'tcx, ConstrainedSubst<'tcx>>,
-    ) -> &'a CanonicalVarValues<'tcx> {
-        &canon_subst.value.subst
-    }
-
-    fn canonical(
-        u_canon: &'a Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>>,
-    ) -> &'a Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>> {
-        u_canon
-    }
-
-    fn is_trivial_substitution(
-        u_canon: &Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>>,
-        canonical_subst: &Canonical<'tcx, ConstrainedSubst<'tcx>>,
-    ) -> bool {
-        let subst = &canonical_subst.value.subst;
-        assert_eq!(u_canon.variables.len(), subst.var_values.len());
-        subst.var_values.iter_enumerated().all(|(cvar, kind)| match kind.unpack() {
-            GenericArgKind::Lifetime(r) => match r {
-                &ty::ReLateBound(debruijn, br) => {
-                    debug_assert_eq!(debruijn, ty::INNERMOST);
-                    cvar == br.assert_bound_var()
-                }
-                _ => false,
-            },
-            GenericArgKind::Type(ty) => match ty.kind {
-                ty::Bound(debruijn, bound_ty) => {
-                    debug_assert_eq!(debruijn, ty::INNERMOST);
-                    cvar == bound_ty.var
-                }
-                _ => false,
-            },
-            GenericArgKind::Const(ct) => match ct.val {
-                ty::ConstKind::Bound(debruijn, bound_ct) => {
-                    debug_assert_eq!(debruijn, ty::INNERMOST);
-                    cvar == bound_ct
-                }
-                _ => false,
-            },
-        })
-    }
-
-    fn num_universes(canon: &Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>>) -> usize {
-        canon.max_universe.index() + 1
-    }
-
-    /// Convert a goal G *from* the canonical universes *into* our
-    /// local universes. This will yield a goal G' that is the same
-    /// but for the universes of universally quantified names.
-    fn map_goal_from_canonical(
-        _map: &UniverseMap,
-        value: &Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>>,
-    ) -> Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>> {
-        *value // FIXME universe maps not implemented yet
-    }
-
-    fn map_subst_from_canonical(
-        _map: &UniverseMap,
-        value: &Canonical<'tcx, ConstrainedSubst<'tcx>>,
-    ) -> Canonical<'tcx, ConstrainedSubst<'tcx>> {
-        value.clone() // FIXME universe maps not implemented yet
-    }
-}
-
-impl context::InferenceTable<ChalkArenas<'tcx>, ChalkArenas<'tcx>>
-    for ChalkInferenceContext<'cx, 'tcx>
-{
-    fn into_goal(&self, domain_goal: DomainGoal<'tcx>) -> Goal<'tcx> {
-        self.infcx.tcx.mk_goal(GoalKind::DomainGoal(domain_goal))
-    }
-
-    fn cannot_prove(&self) -> Goal<'tcx> {
-        self.infcx.tcx.mk_goal(GoalKind::CannotProve)
-    }
-
-    fn into_hh_goal(&mut self, goal: Goal<'tcx>) -> ChalkHhGoal<'tcx> {
-        match *goal {
-            GoalKind::Implies(hypotheses, goal) => {
-                HhGoal::Implies(hypotheses.iter().cloned().collect(), goal)
-            }
-            GoalKind::And(left, right) => HhGoal::And(left, right),
-            GoalKind::Not(subgoal) => HhGoal::Not(subgoal),
-            GoalKind::DomainGoal(d) => HhGoal::DomainGoal(d),
-            GoalKind::Quantified(QuantifierKind::Universal, binder) => HhGoal::ForAll(binder),
-            GoalKind::Quantified(QuantifierKind::Existential, binder) => HhGoal::Exists(binder),
-            GoalKind::Subtype(a, b) => HhGoal::Unify(ty::Variance::Covariant, a.into(), b.into()),
-            GoalKind::CannotProve => HhGoal::CannotProve,
-        }
-    }
-
-    fn add_clauses(
-        &mut self,
-        env: &Environment<'tcx>,
-        clauses: Vec<Clause<'tcx>>,
-    ) -> Environment<'tcx> {
-        Environment {
-            clauses: self
-                .infcx
-                .tcx
-                .mk_clauses(env.clauses.iter().cloned().chain(clauses.into_iter())),
-        }
-    }
-}
-
-impl context::TruncateOps<ChalkArenas<'tcx>, ChalkArenas<'tcx>>
-    for ChalkInferenceContext<'cx, 'tcx>
-{
-    fn truncate_goal(
-        &mut self,
-        _subgoal: &InEnvironment<'tcx, Goal<'tcx>>,
-    ) -> Option<InEnvironment<'tcx, Goal<'tcx>>> {
-        None // FIXME we should truncate at some point!
-    }
-
-    fn truncate_answer(
-        &mut self,
-        _subst: &CanonicalVarValues<'tcx>,
-    ) -> Option<CanonicalVarValues<'tcx>> {
-        None // FIXME we should truncate at some point!
-    }
-}
-
-impl context::UnificationOps<ChalkArenas<'tcx>, ChalkArenas<'tcx>>
-    for ChalkInferenceContext<'cx, 'tcx>
-{
-    fn program_clauses(
-        &self,
-        environment: &Environment<'tcx>,
-        goal: &DomainGoal<'tcx>,
-    ) -> Vec<Clause<'tcx>> {
-        self.program_clauses_impl(environment, goal)
-    }
-
-    fn instantiate_binders_universally(&mut self, arg: &ty::Binder<Goal<'tcx>>) -> Goal<'tcx> {
-        self.infcx.replace_bound_vars_with_placeholders(arg).0
-    }
-
-    fn instantiate_binders_existentially(&mut self, arg: &ty::Binder<Goal<'tcx>>) -> Goal<'tcx> {
-        self.infcx
-            .replace_bound_vars_with_fresh_vars(
-                DUMMY_SP,
-                LateBoundRegionConversionTime::HigherRankedType,
-                arg,
-            )
-            .0
-    }
-
-    fn debug_ex_clause(&mut self, value: &'v ChalkExClause<'tcx>) -> Box<dyn Debug + 'v> {
-        let string = format!("{:?}", self.infcx.resolve_vars_if_possible(value));
-        Box::new(string)
-    }
-
-    fn canonicalize_goal(
-        &mut self,
-        value: &InEnvironment<'tcx, Goal<'tcx>>,
-    ) -> Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>> {
-        let mut _orig_values = OriginalQueryValues::default();
-        self.infcx.canonicalize_query(value, &mut _orig_values)
-    }
-
-    fn canonicalize_ex_clause(
-        &mut self,
-        value: &ChalkExClause<'tcx>,
-    ) -> Canonical<'tcx, ChalkExClause<'tcx>> {
-        self.infcx.canonicalize_response(value)
-    }
-
-    fn canonicalize_constrained_subst(
-        &mut self,
-        subst: CanonicalVarValues<'tcx>,
-        constraints: Vec<RegionConstraint<'tcx>>,
-    ) -> Canonical<'tcx, ConstrainedSubst<'tcx>> {
-        self.infcx.canonicalize_response(&ConstrainedSubst { subst, constraints })
-    }
-
-    fn u_canonicalize_goal(
-        &mut self,
-        value: &Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>>,
-    ) -> (Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>>, UniverseMap) {
-        (*value, UniverseMap)
-    }
-
-    fn invert_goal(
-        &mut self,
-        _value: &InEnvironment<'tcx, Goal<'tcx>>,
-    ) -> Option<InEnvironment<'tcx, Goal<'tcx>>> {
-        panic!("goal inversion not yet implemented")
-    }
-
-    fn unify_parameters(
-        &mut self,
-        environment: &Environment<'tcx>,
-        variance: ty::Variance,
-        a: &GenericArg<'tcx>,
-        b: &GenericArg<'tcx>,
-    ) -> Fallible<UnificationResult<'tcx>> {
-        self.infcx.commit_if_ok(|_| {
-            unify(self.infcx, *environment, variance, a, b)
-                .map_err(|_| chalk_engine::fallible::NoSolution)
-        })
-    }
-
-    fn sink_answer_subset(
-        &self,
-        value: &Canonical<'tcx, ConstrainedSubst<'tcx>>,
-    ) -> Canonical<'tcx, ConstrainedSubst<'tcx>> {
-        value.clone()
-    }
-
-    fn lift_delayed_literal(
-        &self,
-        value: DelayedLiteral<ChalkArenas<'tcx>>,
-    ) -> DelayedLiteral<ChalkArenas<'tcx>> {
-        match self.infcx.tcx.lift(&value) {
-            Some(literal) => literal,
-            None => bug!("cannot lift {:?}", value),
-        }
-    }
-
-    fn into_ex_clause(
-        &mut self,
-        result: UnificationResult<'tcx>,
-        ex_clause: &mut ChalkExClause<'tcx>,
-    ) {
-        into_ex_clause(result, ex_clause);
-    }
-}
-
-crate fn into_ex_clause(result: UnificationResult<'tcx>, ex_clause: &mut ChalkExClause<'tcx>) {
-    ex_clause.subgoals.extend(result.goals.into_iter().map(Literal::Positive));
-
-    // FIXME: restore this later once we get better at handling regions
-    let _ = result.constraints.len(); // trick `-D dead-code`
-    // ex_clause.constraints.extend(result.constraints);
-}
-
-type ChalkHhGoal<'tcx> = HhGoal<ChalkArenas<'tcx>>;
-
-type ChalkExClause<'tcx> = ExClause<ChalkArenas<'tcx>>;
-
-impl Debug for ChalkContext<'tcx> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "ChalkContext")
-    }
-}
-
-impl Debug for ChalkInferenceContext<'cx, 'tcx> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "ChalkInferenceContext")
-    }
-}
-
-impl ChalkContextLift<'tcx> for ChalkArenas<'a> {
-    type LiftedExClause = ChalkExClause<'tcx>;
-    type LiftedDelayedLiteral = DelayedLiteral<ChalkArenas<'tcx>>;
-    type LiftedLiteral = Literal<ChalkArenas<'tcx>>;
-
-    fn lift_ex_clause_to_tcx(
-        ex_clause: &ChalkExClause<'a>,
-        tcx: TyCtxt<'tcx>,
-    ) -> Option<Self::LiftedExClause> {
-        Some(ChalkExClause {
-            subst: tcx.lift(&ex_clause.subst)?,
-            delayed_literals: tcx.lift(&ex_clause.delayed_literals)?,
-            constraints: tcx.lift(&ex_clause.constraints)?,
-            subgoals: tcx.lift(&ex_clause.subgoals)?,
-        })
-    }
-
-    fn lift_delayed_literal_to_tcx(
-        literal: &DelayedLiteral<ChalkArenas<'a>>,
-        tcx: TyCtxt<'tcx>,
-    ) -> Option<Self::LiftedDelayedLiteral> {
-        Some(match literal {
-            DelayedLiteral::CannotProve(()) => DelayedLiteral::CannotProve(()),
-            DelayedLiteral::Negative(index) => DelayedLiteral::Negative(*index),
-            DelayedLiteral::Positive(index, subst) => {
-                DelayedLiteral::Positive(*index, tcx.lift(subst)?)
-            }
-        })
-    }
-
-    fn lift_literal_to_tcx(
-        literal: &Literal<ChalkArenas<'a>>,
-        tcx: TyCtxt<'tcx>,
-    ) -> Option<Self::LiftedLiteral> {
-        Some(match literal {
-            Literal::Negative(goal) => Literal::Negative(tcx.lift(goal)?),
-            Literal::Positive(goal) => Literal::Positive(tcx.lift(goal)?),
-        })
-    }
-}
-
-impl ExClauseFold<'tcx> for ChalkArenas<'tcx> {
-    fn fold_ex_clause_with<F: TypeFolder<'tcx>>(
-        ex_clause: &ChalkExClause<'tcx>,
-        folder: &mut F,
-    ) -> ChalkExClause<'tcx> {
-        ExClause {
-            subst: ex_clause.subst.fold_with(folder),
-            delayed_literals: ex_clause.delayed_literals.fold_with(folder),
-            constraints: ex_clause.constraints.fold_with(folder),
-            subgoals: ex_clause.subgoals.fold_with(folder),
-        }
-    }
-
-    fn visit_ex_clause_with<V: TypeVisitor<'tcx>>(
-        ex_clause: &ExClause<Self>,
-        visitor: &mut V,
-    ) -> bool {
-        let ExClause { subst, delayed_literals, constraints, subgoals } = ex_clause;
-        subst.visit_with(visitor)
-            || delayed_literals.visit_with(visitor)
-            || constraints.visit_with(visitor)
-            || subgoals.visit_with(visitor)
-    }
-}
-
-trait Upcast<'tcx>: 'tcx {
-    type Upcasted: 'tcx;
-
-    fn upcast(&self) -> Self::Upcasted;
-}
-
-impl<'tcx> Upcast<'tcx> for DelayedLiteral<ChalkArenas<'tcx>> {
-    type Upcasted = DelayedLiteral<ChalkArenas<'tcx>>;
-
-    fn upcast(&self) -> Self::Upcasted {
-        match self {
-            &DelayedLiteral::CannotProve(..) => DelayedLiteral::CannotProve(()),
-            &DelayedLiteral::Negative(index) => DelayedLiteral::Negative(index),
-            DelayedLiteral::Positive(index, subst) => {
-                DelayedLiteral::Positive(*index, subst.clone())
-            }
-        }
-    }
-}
-
-impl<'tcx> Upcast<'tcx> for Literal<ChalkArenas<'tcx>> {
-    type Upcasted = Literal<ChalkArenas<'tcx>>;
-
-    fn upcast(&self) -> Self::Upcasted {
-        match self {
-            &Literal::Negative(goal) => Literal::Negative(goal),
-            &Literal::Positive(goal) => Literal::Positive(goal),
-        }
-    }
-}
-
-impl<'tcx> Upcast<'tcx> for ExClause<ChalkArenas<'tcx>> {
-    type Upcasted = ExClause<ChalkArenas<'tcx>>;
-
-    fn upcast(&self) -> Self::Upcasted {
-        ExClause {
-            subst: self.subst.clone(),
-            delayed_literals: self.delayed_literals.iter().map(|l| l.upcast()).collect(),
-            constraints: self.constraints.clone(),
-            subgoals: self.subgoals.iter().map(|g| g.upcast()).collect(),
-        }
-    }
-}
-
-impl<'tcx, T> Upcast<'tcx> for Canonical<'tcx, T>
-where
-    T: Upcast<'tcx>,
-{
-    type Upcasted = Canonical<'tcx, T::Upcasted>;
-
-    fn upcast(&self) -> Self::Upcasted {
-        Canonical {
-            max_universe: self.max_universe,
-            value: self.value.upcast(),
-            variables: self.variables,
-        }
-    }
-}
-
-crate fn provide(p: &mut Providers<'_>) {
-    *p = Providers { evaluate_goal, ..*p };
-}
-
-crate fn evaluate_goal<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    goal: ChalkCanonicalGoal<'tcx>,
-) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, ()>>, traits::query::NoSolution> {
-    use crate::lowering::Lower;
-    use rustc::traits::WellFormed;
-
-    let goal = goal.unchecked_map(|goal| InEnvironment {
-        environment: goal.environment,
-        goal: match goal.goal {
-            ty::Predicate::WellFormed(ty) => {
-                tcx.mk_goal(GoalKind::DomainGoal(DomainGoal::WellFormed(WellFormed::Ty(ty))))
-            }
-
-            ty::Predicate::Subtype(predicate) => tcx.mk_goal(GoalKind::Quantified(
-                QuantifierKind::Universal,
-                predicate.map_bound(|pred| tcx.mk_goal(GoalKind::Subtype(pred.a, pred.b))),
-            )),
-
-            other => tcx.mk_goal(GoalKind::from_poly_domain_goal(other.lower(), tcx)),
-        },
-    });
-
-    debug!("evaluate_goal(goal = {:?})", goal);
-
-    let context = ChalkContext { _arenas: ChalkArenas { _phantom: PhantomData }, tcx };
-
-    let mut forest = Forest::new(context);
-    let solution = forest.solve(&goal);
-
-    debug!("evaluate_goal: solution = {:?}", solution);
-
-    solution.map(|ok| Ok(&*tcx.arena.alloc(ok))).unwrap_or(Err(traits::query::NoSolution))
-}
diff --git a/src/librustc_traits/chalk_context/program_clauses/builtin.rs b/src/librustc_traits/chalk_context/program_clauses/builtin.rs
deleted file mode 100644 (file)
index 7512cbb..0000000
+++ /dev/null
@@ -1,316 +0,0 @@
-use crate::generic_types;
-use crate::lowering::Lower;
-use rustc::traits::{Clause, GoalKind, ProgramClause, ProgramClauseCategory};
-use rustc::ty::subst::{GenericArg, InternalSubsts, Subst};
-use rustc::ty::{self, Ty, TyCtxt};
-use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
-
-/// Returns a predicate of the form
-/// `Implemented(ty: Trait) :- Implemented(nested: Trait)...`
-/// where `Trait` is specified by `trait_def_id`.
-fn builtin_impl_clause(
-    tcx: TyCtxt<'tcx>,
-    ty: Ty<'tcx>,
-    nested: &[GenericArg<'tcx>],
-    trait_def_id: DefId,
-) -> ProgramClause<'tcx> {
-    ProgramClause {
-        goal: ty::TraitPredicate {
-            trait_ref: ty::TraitRef { def_id: trait_def_id, substs: tcx.mk_substs_trait(ty, &[]) },
-        }
-        .lower(),
-        hypotheses: tcx.mk_goals(
-            nested
-                .iter()
-                .cloned()
-                .map(|nested_ty| ty::TraitRef {
-                    def_id: trait_def_id,
-                    substs: tcx.mk_substs_trait(nested_ty.expect_ty(), &[]),
-                })
-                .map(|trait_ref| ty::TraitPredicate { trait_ref })
-                .map(|pred| GoalKind::DomainGoal(pred.lower()))
-                .map(|goal_kind| tcx.mk_goal(goal_kind)),
-        ),
-        category: ProgramClauseCategory::Other,
-    }
-}
-
-crate fn assemble_builtin_unsize_impls<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    unsize_def_id: DefId,
-    source: Ty<'tcx>,
-    target: Ty<'tcx>,
-    clauses: &mut Vec<Clause<'tcx>>,
-) {
-    match (&source.kind, &target.kind) {
-        (ty::Dynamic(data_a, ..), ty::Dynamic(data_b, ..)) => {
-            if data_a.principal_def_id() != data_b.principal_def_id()
-                || data_b.auto_traits().any(|b| data_a.auto_traits().all(|a| a != b))
-            {
-                return;
-            }
-
-            // FIXME: rules for trait upcast
-        }
-
-        (_, &ty::Dynamic(..)) => {
-            // FIXME: basically, we should have something like:
-            // ```
-            // forall<T> {
-            //     Implemented(T: Unsize< for<...> dyn Trait<...> >) :-
-            //         for<...> Implemented(T: Trait<...>).
-            // }
-            // ```
-            // The question is: how to correctly handle the higher-ranked
-            // `for<...>` binder in order to have a generic rule?
-            // (Having generic rules is useful for caching, as we may be able
-            // to turn this function and others into tcx queries later on).
-        }
-
-        (ty::Array(_, length), ty::Slice(_)) => {
-            let ty_param = generic_types::bound(tcx, 0);
-            let array_ty = tcx.mk_ty(ty::Array(ty_param, length));
-            let slice_ty = tcx.mk_ty(ty::Slice(ty_param));
-
-            // `forall<T> { Implemented([T; N]: Unsize<[T]>). }`
-            let clause = ProgramClause {
-                goal: ty::TraitPredicate {
-                    trait_ref: ty::TraitRef {
-                        def_id: unsize_def_id,
-                        substs: tcx.mk_substs_trait(array_ty, &[slice_ty.into()]),
-                    },
-                }
-                .lower(),
-                hypotheses: ty::List::empty(),
-                category: ProgramClauseCategory::Other,
-            };
-
-            clauses.push(Clause::ForAll(ty::Binder::bind(clause)));
-        }
-
-        (ty::Infer(ty::TyVar(_)), _) | (_, ty::Infer(ty::TyVar(_))) => {
-            // FIXME: ambiguous
-        }
-
-        (ty::Adt(def_id_a, ..), ty::Adt(def_id_b, ..)) => {
-            if def_id_a != def_id_b {
-                return;
-            }
-
-            // FIXME: rules for struct unsizing
-        }
-
-        (&ty::Tuple(tys_a), &ty::Tuple(tys_b)) => {
-            if tys_a.len() != tys_b.len() {
-                return;
-            }
-
-            // FIXME: rules for tuple unsizing
-        }
-
-        _ => (),
-    }
-}
-
-crate fn assemble_builtin_sized_impls<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    sized_def_id: DefId,
-    ty: Ty<'tcx>,
-    clauses: &mut Vec<Clause<'tcx>>,
-) {
-    let mut push_builtin_impl = |ty: Ty<'tcx>, nested: &[GenericArg<'tcx>]| {
-        let clause = builtin_impl_clause(tcx, ty, nested, sized_def_id);
-        // Bind innermost bound vars that may exist in `ty` and `nested`.
-        clauses.push(Clause::ForAll(ty::Binder::bind(clause)));
-    };
-
-    match &ty.kind {
-        // Non parametric primitive types.
-        ty::Bool
-        | ty::Char
-        | ty::Int(..)
-        | ty::Uint(..)
-        | ty::Float(..)
-        | ty::Infer(ty::IntVar(_))
-        | ty::Infer(ty::FloatVar(_))
-        | ty::Error
-        | ty::Never => push_builtin_impl(ty, &[]),
-
-        // These ones are always `Sized`.
-        &ty::Array(_, length) => {
-            push_builtin_impl(tcx.mk_ty(ty::Array(generic_types::bound(tcx, 0), length)), &[]);
-        }
-        ty::RawPtr(ptr) => {
-            push_builtin_impl(generic_types::raw_ptr(tcx, ptr.mutbl), &[]);
-        }
-        &ty::Ref(_, _, mutbl) => {
-            push_builtin_impl(generic_types::ref_ty(tcx, mutbl), &[]);
-        }
-        ty::FnPtr(fn_ptr) => {
-            let fn_ptr = fn_ptr.skip_binder();
-            let fn_ptr = generic_types::fn_ptr(
-                tcx,
-                fn_ptr.inputs_and_output.len(),
-                fn_ptr.c_variadic,
-                fn_ptr.unsafety,
-                fn_ptr.abi,
-            );
-            push_builtin_impl(fn_ptr, &[]);
-        }
-        &ty::FnDef(def_id, ..) => {
-            push_builtin_impl(generic_types::fn_def(tcx, def_id), &[]);
-        }
-        &ty::Closure(def_id, ..) => {
-            push_builtin_impl(generic_types::closure(tcx, def_id), &[]);
-        }
-        &ty::Generator(def_id, ..) => {
-            push_builtin_impl(generic_types::generator(tcx, def_id), &[]);
-        }
-
-        // `Sized` if the last type is `Sized` (because else we will get a WF error anyway).
-        &ty::Tuple(type_list) => {
-            let type_list = generic_types::type_list(tcx, type_list.len());
-            push_builtin_impl(tcx.mk_ty(ty::Tuple(type_list)), &type_list);
-        }
-
-        // Struct def
-        ty::Adt(adt_def, _) => {
-            let substs = InternalSubsts::bound_vars_for_item(tcx, adt_def.did);
-            let adt = tcx.mk_ty(ty::Adt(adt_def, substs));
-            let sized_constraint = adt_def
-                .sized_constraint(tcx)
-                .iter()
-                .map(|ty| GenericArg::from(ty.subst(tcx, substs)))
-                .collect::<Vec<_>>();
-            push_builtin_impl(adt, &sized_constraint);
-        }
-
-        // Artificially trigger an ambiguity by adding two possible types to
-        // unify against.
-        ty::Infer(ty::TyVar(_)) => {
-            push_builtin_impl(tcx.types.i32, &[]);
-            push_builtin_impl(tcx.types.f32, &[]);
-        }
-
-        ty::Projection(_projection_ty) => {
-            // FIXME: add builtin impls from the associated type values found in
-            // trait impls of `projection_ty.trait_ref(tcx)`.
-        }
-
-        // The `Sized` bound can only come from the environment.
-        ty::Param(..) | ty::Placeholder(..) | ty::UnnormalizedProjection(..) => (),
-
-        // Definitely not `Sized`.
-        ty::Foreign(..) | ty::Str | ty::Slice(..) | ty::Dynamic(..) | ty::Opaque(..) => (),
-
-        ty::Bound(..)
-        | ty::GeneratorWitness(..)
-        | ty::Infer(ty::FreshTy(_))
-        | ty::Infer(ty::FreshIntTy(_))
-        | ty::Infer(ty::FreshFloatTy(_)) => bug!("unexpected type {:?}", ty),
-    }
-}
-
-crate fn assemble_builtin_copy_clone_impls<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    trait_def_id: DefId,
-    ty: Ty<'tcx>,
-    clauses: &mut Vec<Clause<'tcx>>,
-) {
-    let mut push_builtin_impl = |ty: Ty<'tcx>, nested: &[GenericArg<'tcx>]| {
-        let clause = builtin_impl_clause(tcx, ty, nested, trait_def_id);
-        // Bind innermost bound vars that may exist in `ty` and `nested`.
-        clauses.push(Clause::ForAll(ty::Binder::bind(clause)));
-    };
-
-    match &ty.kind {
-        // Implementations provided in libcore.
-        ty::Bool
-        | ty::Char
-        | ty::Int(..)
-        | ty::Uint(..)
-        | ty::Float(..)
-        | ty::RawPtr(..)
-        | ty::Never
-        | ty::Ref(_, _, hir::Mutability::Not) => (),
-
-        // Non parametric primitive types.
-        ty::Infer(ty::IntVar(_)) | ty::Infer(ty::FloatVar(_)) | ty::Error => {
-            push_builtin_impl(ty, &[])
-        }
-
-        // These implement `Copy`/`Clone` if their element types do.
-        &ty::Array(_, length) => {
-            let element_ty = generic_types::bound(tcx, 0);
-            push_builtin_impl(
-                tcx.mk_ty(ty::Array(element_ty, length)),
-                &[GenericArg::from(element_ty)],
-            );
-        }
-        &ty::Tuple(type_list) => {
-            let type_list = generic_types::type_list(tcx, type_list.len());
-            push_builtin_impl(tcx.mk_ty(ty::Tuple(type_list)), &**type_list);
-        }
-        &ty::Closure(def_id, ..) => {
-            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(),
-                _ => bug!(),
-            };
-            push_builtin_impl(closure_ty, &upvar_tys);
-        }
-
-        // These ones are always `Clone`.
-        ty::FnPtr(fn_ptr) => {
-            let fn_ptr = fn_ptr.skip_binder();
-            let fn_ptr = generic_types::fn_ptr(
-                tcx,
-                fn_ptr.inputs_and_output.len(),
-                fn_ptr.c_variadic,
-                fn_ptr.unsafety,
-                fn_ptr.abi,
-            );
-            push_builtin_impl(fn_ptr, &[]);
-        }
-        &ty::FnDef(def_id, ..) => {
-            push_builtin_impl(generic_types::fn_def(tcx, def_id), &[]);
-        }
-
-        // These depend on whatever user-defined impls might exist.
-        ty::Adt(_, _) => (),
-
-        // Artificially trigger an ambiguity by adding two possible types to
-        // unify against.
-        ty::Infer(ty::TyVar(_)) => {
-            push_builtin_impl(tcx.types.i32, &[]);
-            push_builtin_impl(tcx.types.f32, &[]);
-        }
-
-        ty::Projection(_projection_ty) => {
-            // FIXME: add builtin impls from the associated type values found in
-            // trait impls of `projection_ty.trait_ref(tcx)`.
-        }
-
-        // The `Copy`/`Clone` bound can only come from the environment.
-        ty::Param(..) | ty::Placeholder(..) | ty::UnnormalizedProjection(..) | ty::Opaque(..) => (),
-
-        // Definitely not `Copy`/`Clone`.
-        ty::Dynamic(..)
-        | ty::Foreign(..)
-        | ty::Generator(..)
-        | ty::Str
-        | ty::Slice(..)
-        | ty::Ref(_, _, hir::Mutability::Mut) => (),
-
-        ty::Bound(..)
-        | ty::GeneratorWitness(..)
-        | ty::Infer(ty::FreshTy(_))
-        | ty::Infer(ty::FreshIntTy(_))
-        | ty::Infer(ty::FreshFloatTy(_)) => bug!("unexpected type {:?}", ty),
-    }
-}
diff --git a/src/librustc_traits/chalk_context/program_clauses/mod.rs b/src/librustc_traits/chalk_context/program_clauses/mod.rs
deleted file mode 100644 (file)
index 38a4a72..0000000
+++ /dev/null
@@ -1,300 +0,0 @@
-mod builtin;
-mod primitive;
-
-use super::ChalkInferenceContext;
-use rustc::traits::{
-    Clause, DomainGoal, Environment, FromEnv, ProgramClause, ProgramClauseCategory, WellFormed,
-};
-use rustc::ty::{self, TyCtxt};
-use rustc_hir::def_id::DefId;
-use std::iter;
-
-use self::builtin::*;
-use self::primitive::*;
-
-fn assemble_clauses_from_impls<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    trait_def_id: DefId,
-    clauses: &mut Vec<Clause<'tcx>>,
-) {
-    tcx.for_each_impl(trait_def_id, |impl_def_id| {
-        clauses.extend(tcx.program_clauses_for(impl_def_id).into_iter().cloned());
-    });
-}
-
-fn assemble_clauses_from_assoc_ty_values<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    trait_def_id: DefId,
-    clauses: &mut Vec<Clause<'tcx>>,
-) {
-    tcx.for_each_impl(trait_def_id, |impl_def_id| {
-        for def_id in tcx.associated_item_def_ids(impl_def_id).iter() {
-            clauses.extend(tcx.program_clauses_for(*def_id).into_iter().cloned());
-        }
-    });
-}
-
-impl ChalkInferenceContext<'cx, 'tcx> {
-    pub(super) fn program_clauses_impl(
-        &self,
-        environment: &Environment<'tcx>,
-        goal: &DomainGoal<'tcx>,
-    ) -> Vec<Clause<'tcx>> {
-        use rustc::infer::canonical::OriginalQueryValues;
-        use rustc::traits::WhereClause::*;
-
-        let goal = self.infcx.resolve_vars_if_possible(goal);
-
-        debug!("program_clauses(goal = {:?})", goal);
-
-        let mut clauses = match goal {
-            DomainGoal::Holds(Implemented(trait_predicate)) => {
-                // These come from:
-                // * implementations of the trait itself (rule `Implemented-From-Impl`)
-                // * the trait decl (rule `Implemented-From-Env`)
-
-                let mut clauses = vec![];
-
-                assemble_clauses_from_impls(self.infcx.tcx, trait_predicate.def_id(), &mut clauses);
-
-                if Some(trait_predicate.def_id()) == self.infcx.tcx.lang_items().sized_trait() {
-                    assemble_builtin_sized_impls(
-                        self.infcx.tcx,
-                        trait_predicate.def_id(),
-                        trait_predicate.self_ty(),
-                        &mut clauses,
-                    );
-                }
-
-                if Some(trait_predicate.def_id()) == self.infcx.tcx.lang_items().unsize_trait() {
-                    let source = trait_predicate.self_ty();
-                    let target = trait_predicate.trait_ref.substs.type_at(1);
-                    assemble_builtin_unsize_impls(
-                        self.infcx.tcx,
-                        trait_predicate.def_id(),
-                        source,
-                        target,
-                        &mut clauses,
-                    );
-                }
-
-                if Some(trait_predicate.def_id()) == self.infcx.tcx.lang_items().copy_trait() {
-                    assemble_builtin_copy_clone_impls(
-                        self.infcx.tcx,
-                        trait_predicate.def_id(),
-                        trait_predicate.self_ty(),
-                        &mut clauses,
-                    );
-                }
-
-                if Some(trait_predicate.def_id()) == self.infcx.tcx.lang_items().clone_trait() {
-                    // For all builtin impls, the conditions for `Copy` and
-                    // `Clone` are the same.
-                    assemble_builtin_copy_clone_impls(
-                        self.infcx.tcx,
-                        trait_predicate.def_id(),
-                        trait_predicate.self_ty(),
-                        &mut clauses,
-                    );
-                }
-
-                // FIXME: we need to add special rules for other builtin impls:
-                // * `Generator`
-                // * `FnOnce` / `FnMut` / `Fn`
-                // * trait objects
-                // * auto traits
-
-                // Rule `Implemented-From-Env` will be computed from the environment.
-                clauses
-            }
-
-            DomainGoal::Holds(ProjectionEq(projection_predicate)) => {
-                // These come from:
-                // * the assoc type definition (rule `ProjectionEq-Placeholder`)
-                // * normalization of the assoc ty values (rule `ProjectionEq-Normalize`)
-                // * implied bounds from trait definitions (rule `Implied-Bound-From-Trait`)
-                // * implied bounds from type definitions (rule `Implied-Bound-From-Type`)
-
-                let clauses = self
-                    .infcx
-                    .tcx
-                    .program_clauses_for(projection_predicate.projection_ty.item_def_id)
-                    .into_iter()
-                    // only select `ProjectionEq-Placeholder` and `ProjectionEq-Normalize`
-                    .filter(|clause| clause.category() == ProgramClauseCategory::Other)
-                    .cloned()
-                    .collect::<Vec<_>>();
-
-                // Rules `Implied-Bound-From-Trait` and `Implied-Bound-From-Type` will be computed
-                // from the environment.
-                clauses
-            }
-
-            // For outlive requirements, just assume they hold. `ResolventOps::resolvent_clause`
-            // will register them as actual region constraints later.
-            DomainGoal::Holds(RegionOutlives(..)) | DomainGoal::Holds(TypeOutlives(..)) => {
-                vec![Clause::Implies(ProgramClause {
-                    goal,
-                    hypotheses: ty::List::empty(),
-                    category: ProgramClauseCategory::Other,
-                })]
-            }
-
-            DomainGoal::WellFormed(WellFormed::Trait(trait_predicate)) => {
-                // These come from -- the trait decl (rule `WellFormed-TraitRef`).
-                self.infcx
-                    .tcx
-                    .program_clauses_for(trait_predicate.def_id())
-                    .into_iter()
-                    // only select `WellFormed-TraitRef`
-                    .filter(|clause| clause.category() == ProgramClauseCategory::WellFormed)
-                    .cloned()
-                    .collect()
-            }
-
-            DomainGoal::WellFormed(WellFormed::Ty(ty)) => {
-                // These come from:
-                // * the associated type definition if `ty` refers to an unnormalized
-                //   associated type (rule `WellFormed-AssocTy`)
-                // * custom rules for built-in types
-                // * the type definition otherwise (rule `WellFormed-Type`)
-                let clauses = match ty.kind {
-                    ty::Projection(data) => self.infcx.tcx.program_clauses_for(data.item_def_id),
-
-                    // These types are always WF.
-                    ty::Bool
-                    | ty::Char
-                    | ty::Int(..)
-                    | ty::Uint(..)
-                    | ty::Float(..)
-                    | ty::Str
-                    | ty::Param(..)
-                    | ty::Placeholder(..)
-                    | ty::Error
-                    | ty::Never => {
-                        let wf_clause = ProgramClause {
-                            goal,
-                            hypotheses: ty::List::empty(),
-                            category: ProgramClauseCategory::WellFormed,
-                        };
-                        let wf_clause = Clause::Implies(wf_clause);
-
-                        self.infcx.tcx.mk_clauses(iter::once(wf_clause))
-                    }
-
-                    // Always WF (recall that we do not check for parameters to be WF).
-                    ty::RawPtr(ptr) => wf_clause_for_raw_ptr(self.infcx.tcx, ptr.mutbl),
-
-                    // Always WF (recall that we do not check for parameters to be WF).
-                    ty::FnPtr(fn_ptr) => {
-                        let fn_ptr = fn_ptr.skip_binder();
-                        wf_clause_for_fn_ptr(
-                            self.infcx.tcx,
-                            fn_ptr.inputs_and_output.len(),
-                            fn_ptr.c_variadic,
-                            fn_ptr.unsafety,
-                            fn_ptr.abi,
-                        )
-                    }
-
-                    // WF if inner type is `Sized`.
-                    ty::Slice(..) => wf_clause_for_slice(self.infcx.tcx),
-
-                    // WF if inner type is `Sized`.
-                    ty::Array(_, length) => wf_clause_for_array(self.infcx.tcx, length),
-
-                    // WF if all types but the last one are `Sized`.
-                    ty::Tuple(types) => wf_clause_for_tuple(self.infcx.tcx, types.len()),
-
-                    // WF if `sub_ty` outlives `region`.
-                    ty::Ref(_, _, mutbl) => wf_clause_for_ref(self.infcx.tcx, mutbl),
-
-                    ty::FnDef(def_id, ..) => wf_clause_for_fn_def(self.infcx.tcx, def_id),
-
-                    ty::Dynamic(..) => {
-                        // FIXME: no rules yet for trait objects
-                        ty::List::empty()
-                    }
-
-                    ty::Adt(def, ..) => self.infcx.tcx.program_clauses_for(def.did),
-
-                    // FIXME: these are probably wrong
-                    ty::Foreign(def_id)
-                    | ty::Closure(def_id, ..)
-                    | ty::Generator(def_id, ..)
-                    | ty::Opaque(def_id, ..) => self.infcx.tcx.program_clauses_for(def_id),
-
-                    // Artificially trigger an ambiguity.
-                    ty::Infer(..) => {
-                        let tcx = self.infcx.tcx;
-                        let types = [tcx.types.i32, tcx.types.u32, tcx.types.f32, tcx.types.f64];
-                        let clauses = types
-                            .iter()
-                            .cloned()
-                            .map(|ty| ProgramClause {
-                                goal: DomainGoal::WellFormed(WellFormed::Ty(ty)),
-                                hypotheses: ty::List::empty(),
-                                category: ProgramClauseCategory::WellFormed,
-                            })
-                            .map(|clause| Clause::Implies(clause));
-                        tcx.mk_clauses(clauses)
-                    }
-
-                    ty::GeneratorWitness(..) | ty::UnnormalizedProjection(..) | ty::Bound(..) => {
-                        bug!("unexpected type {:?}", ty)
-                    }
-                };
-
-                clauses
-                    .into_iter()
-                    .filter(|clause| clause.category() == ProgramClauseCategory::WellFormed)
-                    .cloned()
-                    .collect()
-            }
-
-            DomainGoal::FromEnv(FromEnv::Trait(..)) => {
-                // These come from:
-                // * implied bounds from trait definitions (rule `Implied-Bound-From-Trait`)
-                // * implied bounds from type definitions (rule `Implied-Bound-From-Type`)
-                // * implied bounds from assoc type defs (rules `Implied-Trait-From-AssocTy`,
-                //   `Implied-Bound-From-AssocTy` and `Implied-WC-From-AssocTy`)
-
-                // All of these rules are computed in the environment.
-                vec![]
-            }
-
-            DomainGoal::FromEnv(FromEnv::Ty(..)) => {
-                // There are no `FromEnv::Ty(..) :- ...` rules (this predicate only
-                // comes from the environment).
-                vec![]
-            }
-
-            DomainGoal::Normalize(projection_predicate) => {
-                // These come from -- assoc ty values (rule `Normalize-From-Impl`).
-                let mut clauses = vec![];
-
-                assemble_clauses_from_assoc_ty_values(
-                    self.infcx.tcx,
-                    projection_predicate.projection_ty.trait_ref(self.infcx.tcx).def_id,
-                    &mut clauses,
-                );
-
-                clauses
-            }
-        };
-
-        debug!("program_clauses: clauses = {:?}", clauses);
-        debug!("program_clauses: adding clauses from environment = {:?}", environment);
-
-        let mut _orig_query_values = OriginalQueryValues::default();
-        let canonical_environment =
-            self.infcx.canonicalize_query(environment, &mut _orig_query_values).value;
-        let env_clauses = self.infcx.tcx.program_clauses_for_env(canonical_environment);
-
-        debug!("program_clauses: env_clauses = {:?}", env_clauses);
-
-        clauses.extend(env_clauses.into_iter().cloned());
-        clauses.extend(environment.clauses.iter().cloned());
-        clauses
-    }
-}
diff --git a/src/librustc_traits/chalk_context/program_clauses/primitive.rs b/src/librustc_traits/chalk_context/program_clauses/primitive.rs
deleted file mode 100644 (file)
index ae4afe5..0000000
+++ /dev/null
@@ -1,168 +0,0 @@
-use crate::generic_types;
-use crate::lowering::Lower;
-use rustc::traits::{
-    Clause, Clauses, DomainGoal, GoalKind, ProgramClause, ProgramClauseCategory, WellFormed,
-};
-use rustc::ty::{self, TyCtxt};
-use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
-use rustc_target::spec::abi;
-use std::iter;
-
-crate fn wf_clause_for_raw_ptr(tcx: TyCtxt<'_>, mutbl: hir::Mutability) -> Clauses<'_> {
-    let ptr_ty = generic_types::raw_ptr(tcx, mutbl);
-
-    let wf_clause = ProgramClause {
-        goal: DomainGoal::WellFormed(WellFormed::Ty(ptr_ty)),
-        hypotheses: ty::List::empty(),
-        category: ProgramClauseCategory::WellFormed,
-    };
-    let wf_clause = Clause::Implies(wf_clause);
-
-    // `forall<T> { WellFormed(*const T). }`
-    tcx.mk_clauses(iter::once(wf_clause))
-}
-
-crate fn wf_clause_for_fn_ptr(
-    tcx: TyCtxt<'_>,
-    arity_and_output: usize,
-    variadic: bool,
-    unsafety: hir::Unsafety,
-    abi: abi::Abi,
-) -> Clauses<'_> {
-    let fn_ptr = generic_types::fn_ptr(tcx, arity_and_output, variadic, unsafety, abi);
-
-    let wf_clause = ProgramClause {
-        goal: DomainGoal::WellFormed(WellFormed::Ty(fn_ptr)),
-        hypotheses: ty::List::empty(),
-        category: ProgramClauseCategory::WellFormed,
-    };
-    let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
-
-    // `forall <T1, ..., Tn+1> { WellFormed(for<> fn(T1, ..., Tn) -> Tn+1). }`
-    // where `n + 1` == `arity_and_output`
-    tcx.mk_clauses(iter::once(wf_clause))
-}
-
-crate fn wf_clause_for_slice(tcx: TyCtxt<'_>) -> Clauses<'_> {
-    let ty = generic_types::bound(tcx, 0);
-    let slice_ty = tcx.mk_slice(ty);
-
-    let sized_trait = match tcx.lang_items().sized_trait() {
-        Some(def_id) => def_id,
-        None => return ty::List::empty(),
-    };
-    let sized_implemented =
-        ty::TraitRef { def_id: sized_trait, substs: tcx.mk_substs_trait(ty, ty::List::empty()) };
-    let sized_implemented: DomainGoal<'_> =
-        ty::TraitPredicate { trait_ref: sized_implemented }.lower();
-
-    let wf_clause = ProgramClause {
-        goal: DomainGoal::WellFormed(WellFormed::Ty(slice_ty)),
-        hypotheses: tcx.mk_goals(iter::once(tcx.mk_goal(GoalKind::DomainGoal(sized_implemented)))),
-        category: ProgramClauseCategory::WellFormed,
-    };
-    let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
-
-    // `forall<T> { WellFormed([T]) :- Implemented(T: Sized). }`
-    tcx.mk_clauses(iter::once(wf_clause))
-}
-
-crate fn wf_clause_for_array<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    length: &'tcx ty::Const<'tcx>,
-) -> Clauses<'tcx> {
-    let ty = generic_types::bound(tcx, 0);
-    let array_ty = tcx.mk_ty(ty::Array(ty, length));
-
-    let sized_trait = match tcx.lang_items().sized_trait() {
-        Some(def_id) => def_id,
-        None => return ty::List::empty(),
-    };
-    let sized_implemented =
-        ty::TraitRef { def_id: sized_trait, substs: tcx.mk_substs_trait(ty, ty::List::empty()) };
-    let sized_implemented: DomainGoal<'_> =
-        ty::TraitPredicate { trait_ref: sized_implemented }.lower();
-
-    let wf_clause = ProgramClause {
-        goal: DomainGoal::WellFormed(WellFormed::Ty(array_ty)),
-        hypotheses: tcx.mk_goals(iter::once(tcx.mk_goal(GoalKind::DomainGoal(sized_implemented)))),
-        category: ProgramClauseCategory::WellFormed,
-    };
-    let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
-
-    // `forall<T> { WellFormed([T; length]) :- Implemented(T: Sized). }`
-    tcx.mk_clauses(iter::once(wf_clause))
-}
-
-crate fn wf_clause_for_tuple(tcx: TyCtxt<'_>, arity: usize) -> Clauses<'_> {
-    let type_list = generic_types::type_list(tcx, arity);
-    let tuple_ty = tcx.mk_ty(ty::Tuple(type_list));
-
-    let sized_trait = match tcx.lang_items().sized_trait() {
-        Some(def_id) => def_id,
-        None => return ty::List::empty(),
-    };
-
-    // If `arity == 0` (i.e. the unit type) or `arity == 1`, this list of
-    // hypotheses is actually empty.
-    let sized_implemented = type_list[0..std::cmp::max(arity, 1) - 1]
-        .iter()
-        .map(|ty| ty::TraitRef {
-            def_id: sized_trait,
-            substs: tcx.mk_substs_trait(ty.expect_ty(), ty::List::empty()),
-        })
-        .map(|trait_ref| ty::TraitPredicate { trait_ref })
-        .map(|predicate| predicate.lower());
-
-    let wf_clause = ProgramClause {
-        goal: DomainGoal::WellFormed(WellFormed::Ty(tuple_ty)),
-        hypotheses: tcx.mk_goals(
-            sized_implemented.map(|domain_goal| tcx.mk_goal(GoalKind::DomainGoal(domain_goal))),
-        ),
-        category: ProgramClauseCategory::WellFormed,
-    };
-    let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
-
-    // ```
-    // forall<T1, ..., Tn-1, Tn> {
-    //     WellFormed((T1, ..., Tn)) :-
-    //         Implemented(T1: Sized),
-    //         ...
-    //         Implemented(Tn-1: Sized).
-    // }
-    // ```
-    tcx.mk_clauses(iter::once(wf_clause))
-}
-
-crate fn wf_clause_for_ref(tcx: TyCtxt<'_>, mutbl: hir::Mutability) -> Clauses<'_> {
-    let region = tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion::BrAnon(0)));
-    let ty = generic_types::bound(tcx, 1);
-    let ref_ty = tcx.mk_ref(region, ty::TypeAndMut { ty, mutbl });
-
-    let outlives: DomainGoal<'_> = ty::OutlivesPredicate(ty, region).lower();
-    let wf_clause = ProgramClause {
-        goal: DomainGoal::WellFormed(WellFormed::Ty(ref_ty)),
-        hypotheses: tcx.mk_goals(iter::once(tcx.mk_goal(outlives.into_goal()))),
-        category: ProgramClauseCategory::WellFormed,
-    };
-    let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
-
-    // `forall<'a, T> { WellFormed(&'a T) :- Outlives(T: 'a). }`
-    tcx.mk_clauses(iter::once(wf_clause))
-}
-
-crate fn wf_clause_for_fn_def(tcx: TyCtxt<'_>, def_id: DefId) -> Clauses<'_> {
-    let fn_def = generic_types::fn_def(tcx, def_id);
-
-    let wf_clause = ProgramClause {
-        goal: DomainGoal::WellFormed(WellFormed::Ty(fn_def)),
-        hypotheses: ty::List::empty(),
-        category: ProgramClauseCategory::WellFormed,
-    };
-    let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
-
-    // `forall <T1, ..., Tn+1> { WellFormed(fn some_fn(T1, ..., Tn) -> Tn+1). }`
-    // where `def_id` maps to the `some_fn` function definition
-    tcx.mk_clauses(iter::once(wf_clause))
-}
diff --git a/src/librustc_traits/chalk_context/resolvent_ops.rs b/src/librustc_traits/chalk_context/resolvent_ops.rs
deleted file mode 100644 (file)
index 796ce60..0000000
+++ /dev/null
@@ -1,297 +0,0 @@
-use chalk_engine::fallible::{Fallible, NoSolution};
-use chalk_engine::{context, ExClause, Literal};
-use rustc::ty::relate::{Relate, RelateResult, TypeRelation};
-use rustc::ty::subst::GenericArg;
-use rustc::ty::{self, Ty, TyCtxt};
-use rustc_infer::infer::canonical::{Canonical, CanonicalVarValues};
-use rustc_infer::infer::{InferCtxt, LateBoundRegionConversionTime};
-use rustc_infer::traits::{
-    Clause, DomainGoal, Environment, Goal, GoalKind, InEnvironment, ProgramClause, WhereClause,
-};
-use rustc_span::DUMMY_SP;
-
-use super::unify::*;
-use super::{ChalkArenas, ChalkExClause, ChalkInferenceContext, ConstrainedSubst};
-
-impl context::ResolventOps<ChalkArenas<'tcx>, ChalkArenas<'tcx>>
-    for ChalkInferenceContext<'cx, 'tcx>
-{
-    fn resolvent_clause(
-        &mut self,
-        environment: &Environment<'tcx>,
-        goal: &DomainGoal<'tcx>,
-        subst: &CanonicalVarValues<'tcx>,
-        clause: &Clause<'tcx>,
-    ) -> Fallible<Canonical<'tcx, ChalkExClause<'tcx>>> {
-        use chalk_engine::context::UnificationOps;
-
-        debug!("resolvent_clause(goal = {:?}, clause = {:?})", goal, clause);
-
-        let result = self.infcx.probe(|_| {
-            let ProgramClause { goal: consequence, hypotheses, .. } = match clause {
-                Clause::Implies(program_clause) => *program_clause,
-                Clause::ForAll(program_clause) => {
-                    self.infcx
-                        .replace_bound_vars_with_fresh_vars(
-                            DUMMY_SP,
-                            LateBoundRegionConversionTime::HigherRankedType,
-                            program_clause,
-                        )
-                        .0
-                }
-            };
-
-            let result =
-                unify(self.infcx, *environment, ty::Variance::Invariant, goal, &consequence)
-                    .map_err(|_| NoSolution)?;
-
-            let mut ex_clause = ExClause {
-                subst: subst.clone(),
-                delayed_literals: vec![],
-                constraints: vec![],
-                subgoals: vec![],
-            };
-
-            self.into_ex_clause(result, &mut ex_clause);
-
-            ex_clause.subgoals.extend(hypotheses.iter().map(|g| match g {
-                GoalKind::Not(g) => Literal::Negative(environment.with(*g)),
-                g => Literal::Positive(environment.with(*g)),
-            }));
-
-            // If we have a goal of the form `T: 'a` or `'a: 'b`, then just
-            // assume it is true (no subgoals) and register it as a constraint
-            // instead.
-            match goal {
-                DomainGoal::Holds(WhereClause::RegionOutlives(pred)) => {
-                    assert_eq!(ex_clause.subgoals.len(), 0);
-                    ex_clause.constraints.push(ty::OutlivesPredicate(pred.0.into(), pred.1));
-                }
-
-                DomainGoal::Holds(WhereClause::TypeOutlives(pred)) => {
-                    assert_eq!(ex_clause.subgoals.len(), 0);
-                    ex_clause.constraints.push(ty::OutlivesPredicate(pred.0.into(), pred.1));
-                }
-
-                _ => (),
-            };
-
-            let canonical_ex_clause = self.canonicalize_ex_clause(&ex_clause);
-            Ok(canonical_ex_clause)
-        });
-
-        debug!("resolvent_clause: result = {:?}", result);
-        result
-    }
-
-    fn apply_answer_subst(
-        &mut self,
-        ex_clause: ChalkExClause<'tcx>,
-        selected_goal: &InEnvironment<'tcx, Goal<'tcx>>,
-        answer_table_goal: &Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>>,
-        canonical_answer_subst: &Canonical<'tcx, ConstrainedSubst<'tcx>>,
-    ) -> Fallible<ChalkExClause<'tcx>> {
-        debug!(
-            "apply_answer_subst(ex_clause = {:?}, selected_goal = {:?})",
-            self.infcx.resolve_vars_if_possible(&ex_clause),
-            self.infcx.resolve_vars_if_possible(selected_goal)
-        );
-
-        let (answer_subst, _) = self
-            .infcx
-            .instantiate_canonical_with_fresh_inference_vars(DUMMY_SP, canonical_answer_subst);
-
-        let mut substitutor = AnswerSubstitutor {
-            infcx: self.infcx,
-            environment: selected_goal.environment,
-            answer_subst: answer_subst.subst,
-            binder_index: ty::INNERMOST,
-            ex_clause,
-        };
-
-        substitutor.relate(&answer_table_goal.value, &selected_goal).map_err(|_| NoSolution)?;
-
-        let mut ex_clause = substitutor.ex_clause;
-        ex_clause.constraints.extend(answer_subst.constraints);
-
-        debug!("apply_answer_subst: ex_clause = {:?}", ex_clause);
-        Ok(ex_clause)
-    }
-}
-
-struct AnswerSubstitutor<'cx, 'tcx> {
-    infcx: &'cx InferCtxt<'cx, 'tcx>,
-    environment: Environment<'tcx>,
-    answer_subst: CanonicalVarValues<'tcx>,
-    binder_index: ty::DebruijnIndex,
-    ex_clause: ChalkExClause<'tcx>,
-}
-
-impl AnswerSubstitutor<'cx, 'tcx> {
-    fn unify_free_answer_var(
-        &mut self,
-        answer_var: ty::BoundVar,
-        pending: GenericArg<'tcx>,
-    ) -> RelateResult<'tcx, ()> {
-        let answer_param = &self.answer_subst.var_values[answer_var];
-        let pending =
-            &ty::fold::shift_out_vars(self.infcx.tcx, &pending, self.binder_index.as_u32());
-
-        super::into_ex_clause(
-            unify(self.infcx, self.environment, ty::Variance::Invariant, answer_param, pending)?,
-            &mut self.ex_clause,
-        );
-
-        Ok(())
-    }
-}
-
-impl TypeRelation<'tcx> for AnswerSubstitutor<'cx, 'tcx> {
-    fn tcx(&self) -> TyCtxt<'tcx> {
-        self.infcx.tcx
-    }
-
-    fn param_env(&self) -> ty::ParamEnv<'tcx> {
-        // FIXME(oli-obk): learn chalk and create param envs
-        ty::ParamEnv::empty()
-    }
-
-    fn tag(&self) -> &'static str {
-        "chalk_context::answer_substitutor"
-    }
-
-    fn a_is_expected(&self) -> bool {
-        true
-    }
-
-    fn relate_with_variance<T: Relate<'tcx>>(
-        &mut self,
-        _variance: ty::Variance,
-        a: &T,
-        b: &T,
-    ) -> RelateResult<'tcx, T> {
-        // We don't care about variance.
-        self.relate(a, b)
-    }
-
-    fn binders<T: Relate<'tcx>>(
-        &mut self,
-        a: &ty::Binder<T>,
-        b: &ty::Binder<T>,
-    ) -> RelateResult<'tcx, ty::Binder<T>> {
-        self.binder_index.shift_in(1);
-        let result = self.relate(a.skip_binder(), b.skip_binder())?;
-        self.binder_index.shift_out(1);
-        Ok(ty::Binder::bind(result))
-    }
-
-    fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
-        let b = self.infcx.shallow_resolve(b);
-        debug!("AnswerSubstitutor::tys(a = {:?}, b = {:?})", a, b);
-
-        if let &ty::Bound(debruijn, bound_ty) = &a.kind {
-            // Free bound var
-            if debruijn == self.binder_index {
-                self.unify_free_answer_var(bound_ty.var, b.into())?;
-                return Ok(b);
-            }
-        }
-
-        match (&a.kind, &b.kind) {
-            (&ty::Bound(a_debruijn, a_bound), &ty::Bound(b_debruijn, b_bound)) => {
-                assert_eq!(a_debruijn, b_debruijn);
-                assert_eq!(a_bound.var, b_bound.var);
-                Ok(a)
-            }
-
-            // Those should have been canonicalized away.
-            (ty::Placeholder(..), _) => {
-                bug!("unexpected placeholder ty in `AnswerSubstitutor`: {:?} ", a);
-            }
-
-            // Everything else should just be a perfect match as well,
-            // and we forbid inference variables.
-            _ => match ty::relate::super_relate_tys(self, a, b) {
-                Ok(ty) => Ok(ty),
-                Err(err) => bug!("type mismatch in `AnswerSubstitutor`: {}", err),
-            },
-        }
-    }
-
-    fn regions(
-        &mut self,
-        a: ty::Region<'tcx>,
-        b: ty::Region<'tcx>,
-    ) -> RelateResult<'tcx, ty::Region<'tcx>> {
-        let b = match b {
-            &ty::ReVar(vid) => self
-                .infcx
-                .inner
-                .borrow_mut()
-                .unwrap_region_constraints()
-                .opportunistic_resolve_var(self.infcx.tcx, vid),
-
-            other => other,
-        };
-
-        if let &ty::ReLateBound(debruijn, bound) = a {
-            // Free bound region
-            if debruijn == self.binder_index {
-                self.unify_free_answer_var(bound.assert_bound_var(), b.into())?;
-                return Ok(b);
-            }
-        }
-
-        match (a, b) {
-            (&ty::ReLateBound(a_debruijn, a_bound), &ty::ReLateBound(b_debruijn, b_bound)) => {
-                assert_eq!(a_debruijn, b_debruijn);
-                assert_eq!(a_bound.assert_bound_var(), b_bound.assert_bound_var());
-            }
-
-            (ty::ReStatic, ty::ReStatic) | (ty::ReErased, ty::ReErased) => (),
-
-            (ty::ReEmpty(a_ui), ty::ReEmpty(b_ui)) => {
-                assert_eq!(a_ui, b_ui);
-            }
-
-            (&ty::ReFree(a_free), &ty::ReFree(b_free)) => {
-                assert_eq!(a_free, b_free);
-            }
-
-            _ => bug!("unexpected regions in `AnswerSubstitutor`: {:?}, {:?}", a, b),
-        }
-
-        Ok(a)
-    }
-
-    fn consts(
-        &mut self,
-        a: &'tcx ty::Const<'tcx>,
-        b: &'tcx ty::Const<'tcx>,
-    ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> {
-        if let ty::Const { val: ty::ConstKind::Bound(debruijn, bound_ct), .. } = a {
-            if *debruijn == self.binder_index {
-                self.unify_free_answer_var(*bound_ct, b.into())?;
-                return Ok(b);
-            }
-        }
-
-        match (a, b) {
-            (
-                ty::Const { val: ty::ConstKind::Bound(a_debruijn, a_bound), .. },
-                ty::Const { val: ty::ConstKind::Bound(b_debruijn, b_bound), .. },
-            ) => {
-                assert_eq!(a_debruijn, b_debruijn);
-                assert_eq!(a_bound, b_bound);
-                Ok(a)
-            }
-
-            // Everything else should just be a perfect match as well,
-            // and we forbid inference variables.
-            _ => match ty::relate::super_relate_consts(self, a, b) {
-                Ok(ct) => Ok(ct),
-                Err(err) => bug!("const mismatch in `AnswerSubstitutor`: {}", err),
-            },
-        }
-    }
-}
diff --git a/src/librustc_traits/chalk_context/unify.rs b/src/librustc_traits/chalk_context/unify.rs
deleted file mode 100644 (file)
index 3274a30..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-use rustc::ty;
-use rustc::ty::relate::{Relate, RelateResult, TypeRelation};
-use rustc_infer::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRelatingDelegate};
-use rustc_infer::infer::{InferCtxt, RegionVariableOrigin};
-use rustc_infer::traits::{DomainGoal, Environment, Goal, InEnvironment};
-use rustc_span::DUMMY_SP;
-
-crate struct UnificationResult<'tcx> {
-    crate goals: Vec<InEnvironment<'tcx, Goal<'tcx>>>,
-    crate constraints: Vec<super::RegionConstraint<'tcx>>,
-}
-
-crate fn unify<'me, 'tcx, T: Relate<'tcx>>(
-    infcx: &'me InferCtxt<'me, 'tcx>,
-    environment: Environment<'tcx>,
-    variance: ty::Variance,
-    a: &T,
-    b: &T,
-) -> RelateResult<'tcx, UnificationResult<'tcx>> {
-    debug!(
-        "unify(
-        a = {:?},
-        b = {:?},
-        environment = {:?},
-    )",
-        a, b, environment
-    );
-
-    let mut delegate = ChalkTypeRelatingDelegate::new(infcx, environment);
-
-    TypeRelating::new(infcx, &mut delegate, variance).relate(a, b)?;
-
-    debug!("unify: goals = {:?}, constraints = {:?}", delegate.goals, delegate.constraints);
-
-    Ok(UnificationResult { goals: delegate.goals, constraints: delegate.constraints })
-}
-
-struct ChalkTypeRelatingDelegate<'me, 'tcx> {
-    infcx: &'me InferCtxt<'me, 'tcx>,
-    environment: Environment<'tcx>,
-    goals: Vec<InEnvironment<'tcx, Goal<'tcx>>>,
-    constraints: Vec<super::RegionConstraint<'tcx>>,
-}
-
-impl ChalkTypeRelatingDelegate<'me, 'tcx> {
-    fn new(infcx: &'me InferCtxt<'me, 'tcx>, environment: Environment<'tcx>) -> Self {
-        Self { infcx, environment, goals: Vec::new(), constraints: Vec::new() }
-    }
-}
-
-impl TypeRelatingDelegate<'tcx> for &mut ChalkTypeRelatingDelegate<'_, 'tcx> {
-    fn create_next_universe(&mut self) -> ty::UniverseIndex {
-        self.infcx.create_next_universe()
-    }
-
-    fn next_existential_region_var(&mut self, _was_placeholder: bool) -> ty::Region<'tcx> {
-        self.infcx.next_region_var(RegionVariableOrigin::MiscVariable(DUMMY_SP))
-    }
-
-    fn next_placeholder_region(&mut self, placeholder: ty::PlaceholderRegion) -> ty::Region<'tcx> {
-        self.infcx.tcx.mk_region(ty::RePlaceholder(placeholder))
-    }
-
-    fn generalize_existential(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx> {
-        self.infcx
-            .next_region_var_in_universe(RegionVariableOrigin::MiscVariable(DUMMY_SP), universe)
-    }
-
-    fn push_outlives(&mut self, sup: ty::Region<'tcx>, sub: ty::Region<'tcx>) {
-        self.constraints.push(ty::OutlivesPredicate(sup.into(), sub));
-    }
-
-    fn push_domain_goal(&mut self, domain_goal: DomainGoal<'tcx>) {
-        let goal = self.environment.with(self.infcx.tcx.mk_goal(domain_goal.into_goal()));
-        self.goals.push(goal);
-    }
-
-    fn normalization() -> NormalizationStrategy {
-        NormalizationStrategy::Lazy
-    }
-
-    fn forbid_inference_vars() -> bool {
-        false
-    }
-}
index 2f854c045e50ecf870e8dce8e621b5da7d0870aa..b13a7a3acb16509458d57ca38a6bfa822b151f68 100644 (file)
@@ -5,11 +5,17 @@
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::canonical::{Canonical, QueryResponse};
 use rustc_infer::infer::TyCtxtInferExt;
-use rustc_infer::traits::query::dropck_outlives::trivial_dropck_outlives;
-use rustc_infer::traits::query::dropck_outlives::{DropckOutlivesResult, DtorckConstraint};
-use rustc_infer::traits::query::{CanonicalTyGoal, NoSolution};
-use rustc_infer::traits::{Normalized, ObligationCause, TraitEngine, TraitEngineExt};
+use rustc_infer::traits::TraitEngineExt as _;
 use rustc_span::source_map::{Span, DUMMY_SP};
+use rustc_trait_selection::traits::query::dropck_outlives::trivial_dropck_outlives;
+use rustc_trait_selection::traits::query::dropck_outlives::{
+    DropckOutlivesResult, DtorckConstraint,
+};
+use rustc_trait_selection::traits::query::normalize::AtExt;
+use rustc_trait_selection::traits::query::{CanonicalTyGoal, NoSolution};
+use rustc_trait_selection::traits::{
+    Normalized, ObligationCause, TraitEngine, TraitEngineExt as _,
+};
 
 crate fn provide(p: &mut Providers<'_>) {
     *p = Providers { dropck_outlives, adt_dtorck_constraint, ..*p };
index 4cf5b66b3cbeb67789331dcdea41edebc2ed11a0..87895d8e384da484681c621beaeb8c6bd657ffa1 100644 (file)
@@ -1,11 +1,11 @@
 use rustc::ty::query::Providers;
 use rustc::ty::{ParamEnvAnd, TyCtxt};
 use rustc_infer::infer::TyCtxtInferExt;
-use rustc_infer::traits::query::CanonicalPredicateGoal;
-use rustc_infer::traits::{
+use rustc_span::source_map::DUMMY_SP;
+use rustc_trait_selection::traits::query::CanonicalPredicateGoal;
+use rustc_trait_selection::traits::{
     EvaluationResult, Obligation, ObligationCause, OverflowError, SelectionContext, TraitQueryMode,
 };
-use rustc_span::source_map::DUMMY_SP;
 
 crate fn provide(p: &mut Providers<'_>) {
     *p = Providers { evaluate_obligation, ..*p };
diff --git a/src/librustc_traits/generic_types.rs b/src/librustc_traits/generic_types.rs
deleted file mode 100644 (file)
index 44a2c54..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-//! Utilities for creating generic types with bound vars in place of parameter values.
-
-use rustc::ty::subst::{GenericArg, InternalSubsts, SubstsRef};
-use rustc::ty::{self, Ty, TyCtxt};
-use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
-use rustc_target::spec::abi;
-
-crate fn bound(tcx: TyCtxt<'tcx>, index: u32) -> Ty<'tcx> {
-    let ty = ty::Bound(ty::INNERMOST, ty::BoundVar::from_u32(index).into());
-    tcx.mk_ty(ty)
-}
-
-crate fn raw_ptr(tcx: TyCtxt<'tcx>, mutbl: hir::Mutability) -> Ty<'tcx> {
-    tcx.mk_ptr(ty::TypeAndMut { ty: bound(tcx, 0), mutbl })
-}
-
-crate fn fn_ptr(
-    tcx: TyCtxt<'tcx>,
-    arity_and_output: usize,
-    c_variadic: bool,
-    unsafety: hir::Unsafety,
-    abi: abi::Abi,
-) -> Ty<'tcx> {
-    let inputs_and_output = tcx.mk_type_list(
-        (0..arity_and_output)
-            .map(|i| ty::BoundVar::from(i))
-            // DebruijnIndex(1) because we are going to inject these in a `PolyFnSig`
-            .map(|var| tcx.mk_ty(ty::Bound(ty::DebruijnIndex::from(1usize), var.into()))),
-    );
-
-    let fn_sig = ty::Binder::bind(ty::FnSig { inputs_and_output, c_variadic, unsafety, abi });
-    tcx.mk_fn_ptr(fn_sig)
-}
-
-crate fn type_list(tcx: TyCtxt<'tcx>, arity: usize) -> SubstsRef<'tcx> {
-    tcx.mk_substs(
-        (0..arity)
-            .map(|i| ty::BoundVar::from(i))
-            .map(|var| tcx.mk_ty(ty::Bound(ty::INNERMOST, var.into())))
-            .map(|ty| GenericArg::from(ty)),
-    )
-}
-
-crate fn ref_ty(tcx: TyCtxt<'tcx>, mutbl: hir::Mutability) -> Ty<'tcx> {
-    let region = tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion::BrAnon(0)));
-
-    tcx.mk_ref(region, ty::TypeAndMut { ty: bound(tcx, 1), mutbl })
-}
-
-crate fn fn_def(tcx: TyCtxt<'tcx>, def_id: DefId) -> Ty<'tcx> {
-    tcx.mk_ty(ty::FnDef(def_id, InternalSubsts::bound_vars_for_item(tcx, def_id)))
-}
-
-crate fn closure(tcx: TyCtxt<'tcx>, def_id: DefId) -> Ty<'tcx> {
-    tcx.mk_closure(def_id, 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::Movability::Movable,
-    )
-}
index 69424e3fac77639df169998626a5089db2cff211..4505a1e59d9ba936d3a17a8cfc81948b0bc3b551 100644 (file)
@@ -7,12 +7,14 @@
 use rustc_hir as hir;
 use rustc_infer::infer::canonical::{self, Canonical};
 use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
-use rustc_infer::traits::query::outlives_bounds::OutlivesBound;
-use rustc_infer::traits::query::{CanonicalTyGoal, Fallible, NoSolution};
-use rustc_infer::traits::wf;
-use rustc_infer::traits::FulfillmentContext;
-use rustc_infer::traits::{TraitEngine, TraitEngineExt};
+use rustc_infer::traits::TraitEngineExt as _;
 use rustc_span::source_map::DUMMY_SP;
+use rustc_trait_selection::infer::InferCtxtBuilderExt;
+use rustc_trait_selection::traits::query::outlives_bounds::OutlivesBound;
+use rustc_trait_selection::traits::query::{CanonicalTyGoal, Fallible, NoSolution};
+use rustc_trait_selection::traits::wf;
+use rustc_trait_selection::traits::FulfillmentContext;
+use rustc_trait_selection::traits::TraitEngine;
 use smallvec::{smallvec, SmallVec};
 
 crate fn provide(p: &mut Providers<'_>) {
@@ -84,7 +86,7 @@ fn compute_implied_outlives_bounds<'tcx>(
         // to avoids duplicate errors that otherwise show up.
         fulfill_cx.register_predicate_obligations(
             infcx,
-            obligations.iter().filter(|o| o.predicate.has_infer_types()).cloned(),
+            obligations.iter().filter(|o| o.predicate.has_infer_types_or_consts()).cloned(),
         );
 
         // From the full set of obligations, just filter down to the
index fefe82fdece93624f7010353ad85c32fc075e340..894e3ef3a8f83853196529f043794e40d39a07c1 100644 (file)
 #[macro_use]
 extern crate rustc;
 
-mod chalk_context;
 mod dropck_outlives;
 mod evaluate_obligation;
-mod generic_types;
 mod implied_outlives_bounds;
 pub mod lowering;
 mod normalize_erasing_regions;
@@ -28,7 +26,6 @@ pub fn provide(p: &mut Providers<'_>) {
     evaluate_obligation::provide(p);
     implied_outlives_bounds::provide(p);
     lowering::provide(p);
-    chalk_context::provide(p);
     normalize_projection_ty::provide(p);
     normalize_erasing_regions::provide(p);
     type_op::provide(p);
index 0e26e9461f4c3e00fbe8604fa664df905d82b41b..69d0bd09296877743026aa2868f3b6051cf3410d 100644 (file)
@@ -185,12 +185,12 @@ enum NodeKind {
 
     let node_kind = match node {
         Node::TraitItem(item) => match item.kind {
-            TraitItemKind::Method(..) => NodeKind::Fn,
+            TraitItemKind::Fn(..) => NodeKind::Fn,
             _ => NodeKind::Other,
         },
 
         Node::ImplItem(item) => match item.kind {
-            ImplItemKind::Method(..) => NodeKind::Fn,
+            ImplItemKind::Fn(..) => NodeKind::Fn,
             _ => NodeKind::Other,
         },
 
index 97b81c224d5939ace7f9cd94505d5be28d53a7fe..3a0c36a84ae813fddbefc8785613250f77934ee1 100644 (file)
@@ -108,13 +108,13 @@ fn lower(&self) -> PolyDomainGoal<'tcx> {
     }
 }
 
-/// Used for implied bounds related rules (see rustc guide).
+/// Used for implied bounds related rules (see rustc dev guide).
 trait IntoFromEnvGoal {
     /// Transforms an existing goal into a `FromEnv` goal.
     fn into_from_env_goal(self) -> Self;
 }
 
-/// Used for well-formedness related rules (see rustc guide).
+/// Used for well-formedness related rules (see rustc dev guide).
 trait IntoWellFormedGoal {
     /// Transforms an existing goal into a `WellFormed` goal.
     fn into_well_formed_goal(self) -> Self;
@@ -178,7 +178,7 @@ fn into_well_formed_goal(self) -> DomainGoal<'tcx> {
 fn program_clauses_for_trait(tcx: TyCtxt<'_>, def_id: DefId) -> Clauses<'_> {
     // `trait Trait<P1..Pn> where WC { .. } // P0 == Self`
 
-    // Rule Implemented-From-Env (see rustc guide)
+    // Rule Implemented-From-Env (see rustc dev guide)
     //
     // ```
     // forall<Self, P1..Pn> {
@@ -282,7 +282,7 @@ fn program_clauses_for_impl(tcx: TyCtxt<'tcx>, def_id: DefId) -> Clauses<'tcx> {
         return List::empty();
     }
 
-    // Rule Implemented-From-Impl (see rustc guide)
+    // Rule Implemented-From-Impl (see rustc dev guide)
     //
     // `impl<P0..Pn> Trait<A1..An> for A0 where WC { .. }`
     //
@@ -501,7 +501,7 @@ pub fn program_clauses_for_associated_type_def(tcx: TyCtxt<'_>, item_id: DefId)
 }
 
 pub fn program_clauses_for_associated_type_value(tcx: TyCtxt<'_>, item_id: DefId) -> Clauses<'_> {
-    // Rule Normalize-From-Impl (see rustc guide)
+    // Rule Normalize-From-Impl (see rustc dev guide)
     //
     // ```
     // impl<P0..Pn> Trait<A1..An> for A0 {
@@ -603,8 +603,8 @@ fn process_attrs(&mut self, hir_id: hir::HirId, attrs: &[ast::Attribute]) {
 impl Visitor<'tcx> for ClauseDumper<'tcx> {
     type Map = Map<'tcx>;
 
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, Self::Map> {
-        NestedVisitorMap::OnlyBodies(&self.tcx.hir())
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::OnlyBodies(self.tcx.hir())
     }
 
     fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
index 4e5f20d80b0d8d0ec445212aaca7d31ba6a4c04e..c2fb237a05b5476783e59a5222aac5b728ceeadb 100644 (file)
@@ -2,7 +2,8 @@
 use rustc::ty::query::Providers;
 use rustc::ty::{self, ParamEnvAnd, Ty, TyCtxt};
 use rustc_infer::infer::TyCtxtInferExt;
-use rustc_infer::traits::{Normalized, ObligationCause};
+use rustc_trait_selection::traits::query::normalize::AtExt;
+use rustc_trait_selection::traits::{Normalized, ObligationCause};
 use std::sync::atomic::Ordering;
 
 crate fn provide(p: &mut Providers<'_>) {
index b5678956347634717a7192d046ee0a03a6233733..57abff769de9b67e9407a63b9c1d8997c88d7c3f 100644 (file)
@@ -3,11 +3,13 @@
 use rustc_hir as hir;
 use rustc_infer::infer::canonical::{Canonical, QueryResponse};
 use rustc_infer::infer::TyCtxtInferExt;
-use rustc_infer::traits::query::{
+use rustc_infer::traits::TraitEngineExt as _;
+use rustc_span::DUMMY_SP;
+use rustc_trait_selection::infer::InferCtxtBuilderExt;
+use rustc_trait_selection::traits::query::{
     normalize::NormalizationResult, CanonicalProjectionGoal, NoSolution,
 };
-use rustc_infer::traits::{self, ObligationCause, SelectionContext, TraitEngineExt};
-use rustc_span::DUMMY_SP;
+use rustc_trait_selection::traits::{self, ObligationCause, SelectionContext};
 use std::sync::atomic::Ordering;
 
 crate fn provide(p: &mut Providers<'_>) {
index 411813380614114bea9c81ae99158fb9849baa12..e174c040e0da15b4da29298e853f080e42acff0c 100644 (file)
@@ -8,14 +8,18 @@
 use rustc_infer::infer::at::ToTrace;
 use rustc_infer::infer::canonical::{Canonical, QueryResponse};
 use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
-use rustc_infer::traits::query::type_op::ascribe_user_type::AscribeUserType;
-use rustc_infer::traits::query::type_op::eq::Eq;
-use rustc_infer::traits::query::type_op::normalize::Normalize;
-use rustc_infer::traits::query::type_op::prove_predicate::ProvePredicate;
-use rustc_infer::traits::query::type_op::subtype::Subtype;
-use rustc_infer::traits::query::{Fallible, NoSolution};
-use rustc_infer::traits::{Normalized, Obligation, ObligationCause, TraitEngine, TraitEngineExt};
+use rustc_infer::traits::TraitEngineExt as _;
 use rustc_span::DUMMY_SP;
+use rustc_trait_selection::infer::InferCtxtBuilderExt;
+use rustc_trait_selection::infer::InferCtxtExt;
+use rustc_trait_selection::traits::query::normalize::AtExt;
+use rustc_trait_selection::traits::query::type_op::ascribe_user_type::AscribeUserType;
+use rustc_trait_selection::traits::query::type_op::eq::Eq;
+use rustc_trait_selection::traits::query::type_op::normalize::Normalize;
+use rustc_trait_selection::traits::query::type_op::prove_predicate::ProvePredicate;
+use rustc_trait_selection::traits::query::type_op::subtype::Subtype;
+use rustc_trait_selection::traits::query::{Fallible, NoSolution};
+use rustc_trait_selection::traits::{Normalized, Obligation, ObligationCause, TraitEngine};
 use std::fmt;
 
 crate fn provide(p: &mut Providers<'_>) {
index 6e64df3492b0fedbf1c1adf5dede034bd4f8f4a0..cf0b4b82eea7261590744284c8be8fe9ac8e2778 100644 (file)
@@ -15,4 +15,6 @@ rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_hir = { path = "../librustc_hir" }
 rustc_infer = { path = "../librustc_infer" }
 rustc_span = { path = "../librustc_span" }
+rustc_session = { path = "../librustc_session" }
 rustc_target = { path = "../librustc_target" }
+rustc_trait_selection = { path = "../librustc_trait_selection" }
index e0ce6ad23a650928888f02c1d5f1144ee5ae7699..311ba383f3055fbe3a819f3c81fc5138e7f943fa 100644 (file)
@@ -3,8 +3,8 @@
 use rustc::middle::lang_items;
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc_infer::infer::TyCtxtInferExt;
-use rustc_infer::traits;
 use rustc_span::DUMMY_SP;
+use rustc_trait_selection::traits;
 
 fn is_copy_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
     is_item_raw(tcx, query, lang_items::CopyTraitLangItem)
index 484b774add462973a48e4479d8cb84f343399c31..a5abe7b6413cc23ceb6684237eeb731fbeb4b4ae 100644 (file)
@@ -1,8 +1,9 @@
 use rustc::ty::subst::SubstsRef;
 use rustc::ty::{self, Instance, TyCtxt, TypeFoldable};
 use rustc_hir::def_id::DefId;
-use rustc_infer::traits;
+use rustc_span::sym;
 use rustc_target::spec::abi::Abi;
+use rustc_trait_selection::traits;
 
 use log::debug;
 
@@ -31,23 +32,28 @@ pub fn resolve_instance<'tcx>(
                 debug!(" => intrinsic");
                 ty::InstanceDef::Intrinsic(def_id)
             }
-            _ => {
-                if Some(def_id) == tcx.lang_items().drop_in_place_fn() {
-                    let ty = substs.type_at(0);
-                    if ty.needs_drop(tcx, param_env.with_reveal_all()) {
-                        debug!(" => nontrivial drop glue");
-                        ty::InstanceDef::DropGlue(def_id, Some(ty))
-                    } else {
-                        debug!(" => trivial drop glue");
-                        ty::InstanceDef::DropGlue(def_id, None)
+            ty::FnDef(def_id, substs) if Some(def_id) == tcx.lang_items().drop_in_place_fn() => {
+                let ty = substs.type_at(0);
+
+                if ty.needs_drop(tcx, param_env) {
+                    // `DropGlue` requires a monomorphic aka concrete type.
+                    if ty.needs_subst() {
+                        return None;
                     }
+
+                    debug!(" => nontrivial drop glue");
+                    ty::InstanceDef::DropGlue(def_id, Some(ty))
                 } else {
-                    debug!(" => free item");
-                    ty::InstanceDef::Item(def_id)
+                    debug!(" => trivial drop glue");
+                    ty::InstanceDef::DropGlue(def_id, None)
                 }
             }
+            _ => {
+                debug!(" => free item");
+                ty::InstanceDef::Item(def_id)
+            }
         };
-        Some(Instance { def: def, substs: substs })
+        Some(Instance { def, substs })
     };
     debug!("resolve(def_id={:?}, substs={:?}) = {:?}", def_id, substs, result);
     result
@@ -70,7 +76,7 @@ fn resolve_associated_item<'tcx>(
     );
 
     let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs);
-    let vtbl = tcx.codegen_fulfill_obligation((param_env, ty::Binder::bind(trait_ref)));
+    let vtbl = tcx.codegen_fulfill_obligation((param_env, ty::Binder::bind(trait_ref)))?;
 
     // Now that we know which impl is being used, we can dispatch to
     // the actual function:
@@ -113,20 +119,44 @@ fn resolve_associated_item<'tcx>(
                 trait_closure_kind,
             ))
         }
-        traits::VtableFnPointer(ref data) => Some(Instance {
-            def: ty::InstanceDef::FnPtrShim(trait_item.def_id, data.fn_ty),
-            substs: rcvr_substs,
-        }),
+        traits::VtableFnPointer(ref data) => {
+            // `FnPtrShim` requires a monomorphic aka concrete type.
+            if data.fn_ty.needs_subst() {
+                return None;
+            }
+
+            Some(Instance {
+                def: ty::InstanceDef::FnPtrShim(trait_item.def_id, data.fn_ty),
+                substs: rcvr_substs,
+            })
+        }
         traits::VtableObject(ref data) => {
             let index = traits::get_vtable_index_of_object_method(tcx, data, def_id);
             Some(Instance { def: ty::InstanceDef::Virtual(def_id, index), substs: rcvr_substs })
         }
         traits::VtableBuiltin(..) => {
-            if tcx.lang_items().clone_trait().is_some() {
-                Some(Instance {
-                    def: ty::InstanceDef::CloneShim(def_id, trait_ref.self_ty()),
-                    substs: rcvr_substs,
-                })
+            if Some(trait_ref.def_id) == tcx.lang_items().clone_trait() {
+                // FIXME(eddyb) use lang items for methods instead of names.
+                let name = tcx.item_name(def_id);
+                if name == sym::clone {
+                    let self_ty = trait_ref.self_ty();
+
+                    // `CloneShim` requires a monomorphic aka concrete type.
+                    if self_ty.needs_subst() {
+                        return None;
+                    }
+
+                    Some(Instance {
+                        def: ty::InstanceDef::CloneShim(def_id, self_ty),
+                        substs: rcvr_substs,
+                    })
+                } else {
+                    assert_eq!(name, sym::clone_from);
+
+                    // Use the default `fn clone_from` from `trait Clone`.
+                    let substs = tcx.erase_regions(&rcvr_substs);
+                    Some(ty::Instance::new(def_id, substs))
+                }
             } else {
                 None
             }
index d466bbcca79bacadf94f57e469f41405d8ed97b4..4b522997537b7bf905d7a23b08e6ae93137bff08 100644 (file)
@@ -1,13 +1,13 @@
 use rustc::hir::map as hir_map;
-use rustc::session::CrateDisambiguator;
 use rustc::ty::subst::Subst;
 use rustc::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness};
 use rustc_data_structures::svh::Svh;
 use rustc_hir as hir;
 use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
-use rustc_infer::traits;
+use rustc_session::CrateDisambiguator;
 use rustc_span::symbol::Symbol;
 use rustc_span::Span;
+use rustc_trait_selection::traits;
 
 fn sized_constraint_for_ty<'tcx>(
     tcx: TyCtxt<'tcx>,
@@ -210,7 +210,7 @@ fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: DefId) -> &[DefId] {
     }
 }
 
-fn associated_items<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx ty::AssociatedItems {
+fn associated_items(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::AssociatedItems {
     let items = tcx.associated_item_def_ids(def_id).iter().map(|did| tcx.associated_item(*did));
     tcx.arena.alloc(ty::AssociatedItems::new(items))
 }
@@ -252,11 +252,8 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
     // are any errors at that point, so after type checking you can be
     // sure that this will succeed without errors anyway.
 
-    let unnormalized_env = ty::ParamEnv::new(
-        tcx.intern_predicates(&predicates),
-        traits::Reveal::UserFacing,
-        tcx.sess.opts.debugging_opts.chalk.then_some(def_id),
-    );
+    let unnormalized_env =
+        ty::ParamEnv::new(tcx.intern_predicates(&predicates), traits::Reveal::UserFacing, None);
 
     let body_id = tcx.hir().as_local_hir_id(def_id).map_or(hir::DUMMY_HIR_ID, |id| {
         tcx.hir().maybe_body_owned_by(id).map_or(id, |body| body.hir_id)
@@ -276,8 +273,7 @@ fn original_crate_name(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Symbol {
 }
 
 fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh {
-    assert_eq!(crate_num, LOCAL_CRATE);
-    tcx.hir().crate_hash
+    tcx.index_hir(crate_num).crate_hash
 }
 
 fn instance_def_size_estimate<'tcx>(
index 51a9b259c8f70927f2b556d56d421fbf156a4f24..e61a36f844f87bc3bc660a077d963a877bc18df7 100644 (file)
@@ -19,8 +19,10 @@ rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_errors = { path = "../librustc_errors" }
 rustc_hir = { path = "../librustc_hir" }
 rustc_target = { path = "../librustc_target" }
+rustc_session = { path = "../librustc_session" }
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
 rustc_ast = { path = "../librustc_ast" }
 rustc_span = { path = "../librustc_span" }
 rustc_index = { path = "../librustc_index" }
 rustc_infer = { path = "../librustc_infer" }
+rustc_trait_selection = { path = "../librustc_trait_selection" }
index fdcbd935524db8348de791d7e1d4ae124f809dbf..b61dbd8c9648e9d7b7023ddea262865b0c13b38b 100644 (file)
@@ -1,5 +1,5 @@
 For high-level intro to how type checking works in rustc, see the
-[type checking] chapter of the [rustc guide].
+[type checking] chapter of the [rustc dev guide].
 
-[type checking]: https://rust-lang.github.io/rustc-guide/type-checking.html
-[rustc guide]: https://rust-lang.github.io/rustc-guide/
+[type checking]: https://rustc-dev-guide.rust-lang.org/type-checking.html
+[rustc dev guide]: https://rustc-dev-guide.rust-lang.org/
index bef14d3f4a37b288ece32ac6d9f8cfd81055158f..9a8d161572bcfd3e28879e70f4e429cda5536e02 100644 (file)
@@ -6,13 +6,10 @@
 // ignore-tidy-filelength
 
 use crate::collect::PlaceholderHirTyCollector;
-use crate::lint;
 use crate::middle::lang_items::SizedTraitLangItem;
 use crate::middle::resolve_lifetime as rl;
 use crate::require_c_abi_if_c_variadic;
 use crate::util::common::ErrorReported;
-use rustc::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS;
-use rustc::session::{parse::feature_err, Session};
 use rustc::ty::subst::{self, InternalSubsts, Subst, SubstsRef};
 use rustc::ty::{self, Const, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
 use rustc::ty::{GenericParamDef, GenericParamDefKind};
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::print;
 use rustc_hir::{Constness, ExprKind, GenericArg, GenericArgs};
-use rustc_infer::traits;
-use rustc_infer::traits::astconv_object_safety_violations;
-use rustc_infer::traits::error_reporting::report_object_safety_error;
-use rustc_infer::traits::wf::object_region_bounds;
+use rustc_session::lint::builtin::{AMBIGUOUS_ASSOCIATED_ITEMS, LATE_BOUND_LIFETIME_ARGUMENTS};
+use rustc_session::parse::feature_err;
+use rustc_session::Session;
 use rustc_span::symbol::sym;
 use rustc_span::{MultiSpan, Span, DUMMY_SP};
 use rustc_target::spec::abi;
-use smallvec::SmallVec;
+use rustc_trait_selection::traits;
+use rustc_trait_selection::traits::astconv_object_safety_violations;
+use rustc_trait_selection::traits::error_reporting::report_object_safety_error;
+use rustc_trait_selection::traits::wf::object_region_bounds;
 
+use smallvec::SmallVec;
 use std::collections::BTreeSet;
 use std::iter;
 use std::slice;
@@ -340,7 +340,7 @@ fn check_generic_arg_count(
                     let mut multispan = MultiSpan::from_span(span);
                     multispan.push_span_label(span_late, note.to_string());
                     tcx.struct_span_lint_hir(
-                        lint::builtin::LATE_BOUND_LIFETIME_ARGUMENTS,
+                        LATE_BOUND_LIFETIME_ARGUMENTS,
                         args.args[0].id(),
                         multispan,
                         |lint| lint.build(msg).emit(),
@@ -661,7 +661,7 @@ pub fn create_substs_for_generic_args<'b>(
     /// Given the type/lifetime/const arguments provided to some path (along with
     /// an implicit `Self`, if this is a trait reference), returns the complete
     /// set of substitutions. This may involve applying defaulted type parameters.
-    /// Also returns back constriants on associated types.
+    /// Also returns back constraints on associated types.
     ///
     /// Example:
     ///
@@ -1441,12 +1441,14 @@ fn add_predicates_for_ast_type_binding(
         let (assoc_ident, def_scope) =
             tcx.adjust_ident_and_get_scope(binding.item_name, candidate.def_id(), hir_ref_id);
 
-        // We have already adjusted the item name above, so compare with `ident.modern()` instead
+        // We have already adjusted the item name above, so compare with `ident.normalize_to_macros_2_0()` instead
         // of calling `filter_by_name_and_kind`.
         let assoc_ty = tcx
             .associated_items(candidate.def_id())
             .filter_by_name_unhygienic(assoc_ident.name)
-            .find(|i| i.kind == ty::AssocKind::Type && i.ident.modern() == assoc_ident)
+            .find(|i| {
+                i.kind == ty::AssocKind::Type && i.ident.normalize_to_macros_2_0() == assoc_ident
+            })
             .expect("missing associated type");
 
         if !assoc_ty.vis.is_accessible_from(def_scope, tcx) {
@@ -1652,7 +1654,7 @@ fn conv_object_ty_poly_trait_ref(
         }
 
         for (projection_bound, _) in &bounds.projection_bounds {
-            for (_, def_ids) in &mut associated_types {
+            for def_ids in associated_types.values_mut() {
                 def_ids.remove(&projection_bound.projection_def_id());
             }
         }
@@ -2298,12 +2300,15 @@ pub fn associated_path_to_ty(
         let (assoc_ident, def_scope) =
             tcx.adjust_ident_and_get_scope(assoc_ident, trait_did, hir_ref_id);
 
-        // We have already adjusted the item name above, so compare with `ident.modern()` instead
+        // We have already adjusted the item name above, so compare with `ident.normalize_to_macros_2_0()` instead
         // of calling `filter_by_name_and_kind`.
         let item = tcx
             .associated_items(trait_did)
             .in_definition_order()
-            .find(|i| i.kind.namespace() == Namespace::TypeNS && i.ident.modern() == assoc_ident)
+            .find(|i| {
+                i.kind.namespace() == Namespace::TypeNS
+                    && i.ident.normalize_to_macros_2_0() == assoc_ident
+            })
             .expect("missing associated type");
 
         let ty = self.projected_ty_from_poly_trait_ref(span, item.def_id, assoc_segment, bound);
@@ -2588,7 +2593,7 @@ pub fn def_ids_for_value_path_segments(
             }
 
             // Case 4. Reference to a method or associated const.
-            DefKind::Method | DefKind::AssocConst => {
+            DefKind::AssocFn | DefKind::AssocConst => {
                 if segments.len() >= 2 {
                     let generics = tcx.generics_of(def_id);
                     path_segs.push(PathSeg(generics.parent.unwrap(), last - 1));
@@ -2924,7 +2929,7 @@ pub fn ty_of_fn(
 
         let tcx = self.tcx();
 
-        // We proactively collect all the infered type params to emit a single error per fn def.
+        // We proactively collect all the inferred type params to emit a single error per fn def.
         let mut visitor = PlaceholderHirTyCollector::default();
         for ty in decl.inputs {
             visitor.visit_ty(ty);
index 2c71fec6809f7747194ac1860449f4a9f938e0ac..20737b44e7c17574ecb14729d1c7349116f579e6 100644 (file)
@@ -4,9 +4,9 @@
 use rustc_hir as hir;
 use rustc_hir::ExprKind;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
-use rustc_infer::traits::ObligationCauseCode;
-use rustc_infer::traits::{IfExpressionCause, MatchExpressionArmCause, ObligationCause};
 use rustc_span::Span;
+use rustc_trait_selection::traits::ObligationCauseCode;
+use rustc_trait_selection::traits::{IfExpressionCause, MatchExpressionArmCause, ObligationCause};
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     pub fn check_match(
index 67bfb090253f0ac17297003417d4f1a9f8244ae2..2315b42aec54c7b4ced0bf96c6beb1d9490f0964 100644 (file)
@@ -1,17 +1,17 @@
 use super::method::MethodCallee;
 use super::{FnCtxt, Needs, PlaceOp};
 
-use rustc::session::DiagnosticMessageId;
 use rustc::ty::adjustment::{Adjust, Adjustment, OverloadedDeref};
 use rustc::ty::{self, TraitRef, Ty, TyCtxt, WithConstness};
 use rustc::ty::{ToPredicate, TypeFoldable};
+use rustc_ast::ast::Ident;
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_infer::infer::{InferCtxt, InferOk};
-use rustc_infer::traits::{self, TraitEngine};
-
-use rustc_ast::ast::Ident;
+use rustc_session::DiagnosticMessageId;
 use rustc_span::Span;
+use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
+use rustc_trait_selection::traits::{self, TraitEngine};
 
 use std::iter;
 
index ff100c261f14aaf6444eac232e14760bf9618e1e..2875d38a996a04e72934315a5972dc831747b621 100644 (file)
 use super::FnCtxt;
 
 use crate::hir::def_id::DefId;
-use crate::lint;
 use crate::type_error_struct;
 use crate::util::common::ErrorReported;
 use rustc::middle::lang_items;
-use rustc::session::Session;
 use rustc::ty::adjustment::AllowTwoPhase;
 use rustc::ty::cast::{CastKind, CastTy};
 use rustc::ty::error::TypeError;
 use rustc_ast::ast;
 use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
-use rustc_infer::traits;
-use rustc_infer::traits::error_reporting::report_object_safety_error;
+use rustc_session::lint;
+use rustc_session::Session;
 use rustc_span::Span;
+use rustc_trait_selection::traits;
+use rustc_trait_selection::traits::error_reporting::report_object_safety_error;
 
 /// Reifies a cast check to be checked once we have full type information for
 /// a function context.
index 816de5dadbc1501e62dd0a6022635c95cf738638..49b7a997311044f80ffba4a850c8a32990c94d0c 100644 (file)
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_infer::infer::LateBoundRegionConversionTime;
 use rustc_infer::infer::{InferOk, InferResult};
-use rustc_infer::traits::error_reporting::ArgKind;
-use rustc_infer::traits::Obligation;
 use rustc_span::source_map::Span;
 use rustc_target::spec::abi::Abi;
+use rustc_trait_selection::traits::error_reporting::ArgKind;
+use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
+use rustc_trait_selection::traits::Obligation;
 use std::cmp;
 use std::iter;
 
@@ -675,7 +676,7 @@ fn deduce_future_output_from_projection(
         // 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).in_definition_order().nth(0).unwrap().def_id;
+            self.tcx.associated_items(future_trait).in_definition_order().next().unwrap().def_id;
         if output_assoc_item != predicate.projection_ty.item_def_id {
             span_bug!(
                 cause_span,
index 3720b74d92e07ad403f83e0598779efd5c7f737c..b0d74651847a90080ad4a88b8fb8acaebb4394fd 100644 (file)
@@ -52,7 +52,6 @@
 
 use crate::astconv::AstConv;
 use crate::check::{FnCtxt, Needs};
-use rustc::session::parse::feature_err;
 use rustc::ty::adjustment::{
     Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCast,
 };
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_infer::infer::{Coercion, InferOk, InferResult};
-use rustc_infer::traits::{self, ObligationCause, ObligationCauseCode};
+use rustc_session::parse::feature_err;
 use rustc_span::symbol::sym;
 use rustc_span::{self, Span};
 use rustc_target::spec::abi::Abi;
+use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
+use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode};
+
 use smallvec::{smallvec, SmallVec};
 use std::ops::Deref;
 
@@ -111,7 +113,7 @@ fn identity(_: Ty<'_>) -> Vec<Adjustment<'_>> {
     vec![]
 }
 
-fn simple<'tcx>(kind: Adjust<'tcx>) -> impl FnOnce(Ty<'tcx>) -> Vec<Adjustment<'tcx>> {
+fn simple(kind: Adjust<'tcx>) -> impl FnOnce(Ty<'tcx>) -> Vec<Adjustment<'tcx>> {
     move |target| vec![Adjustment { kind, target }]
 }
 
index 8b54b5343756ad7771e30f909fb71cd4a69d8fb0..a2832d92d4aebdbc62a2843d3bc1420671bd623e 100644 (file)
@@ -1,4 +1,3 @@
-use rustc::hir::map::Map;
 use rustc::ty::error::{ExpectedFound, TypeError};
 use rustc::ty::subst::{InternalSubsts, Subst};
 use rustc::ty::util::ExplicitSelf;
@@ -10,8 +9,9 @@
 use rustc_hir::intravisit;
 use rustc_hir::{GenericParamKind, ImplItemKind, TraitItemKind};
 use rustc_infer::infer::{self, InferOk, TyCtxtInferExt};
-use rustc_infer::traits::{self, ObligationCause, ObligationCauseCode, Reveal};
 use rustc_span::Span;
+use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
+use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode, Reveal};
 
 use super::{potentially_plural_count, FnCtxt, Inherited};
 
@@ -402,7 +402,7 @@ fn extract_spans_for_error_reporting<'a, 'tcx>(
     let tcx = infcx.tcx;
     let impl_m_hir_id = tcx.hir().as_local_hir_id(impl_m.def_id).unwrap();
     let (impl_m_output, impl_m_iter) = match tcx.hir().expect_impl_item(impl_m_hir_id).kind {
-        ImplItemKind::Method(ref impl_m_sig, _) => {
+        ImplItemKind::Fn(ref impl_m_sig, _) => {
             (&impl_m_sig.decl.output, impl_m_sig.decl.inputs.iter())
         }
         _ => bug!("{:?} is not a method", impl_m),
@@ -412,8 +412,8 @@ fn extract_spans_for_error_reporting<'a, 'tcx>(
         TypeError::Mutability => {
             if let Some(trait_m_hir_id) = tcx.hir().as_local_hir_id(trait_m.def_id) {
                 let trait_m_iter = match tcx.hir().expect_trait_item(trait_m_hir_id).kind {
-                    TraitItemKind::Method(ref trait_m_sig, _) => trait_m_sig.decl.inputs.iter(),
-                    _ => bug!("{:?} is not a TraitItemKind::Method", trait_m),
+                    TraitItemKind::Fn(ref trait_m_sig, _) => trait_m_sig.decl.inputs.iter(),
+                    _ => bug!("{:?} is not a TraitItemKind::Fn", trait_m),
                 };
 
                 impl_m_iter
@@ -440,10 +440,10 @@ fn extract_spans_for_error_reporting<'a, 'tcx>(
             if let Some(trait_m_hir_id) = tcx.hir().as_local_hir_id(trait_m.def_id) {
                 let (trait_m_output, trait_m_iter) =
                     match tcx.hir().expect_trait_item(trait_m_hir_id).kind {
-                        TraitItemKind::Method(ref trait_m_sig, _) => {
+                        TraitItemKind::Fn(ref trait_m_sig, _) => {
                             (&trait_m_sig.decl.output, trait_m_sig.decl.inputs.iter())
                         }
-                        _ => bug!("{:?} is not a TraitItemKind::Method", trait_m),
+                        _ => bug!("{:?} is not a TraitItemKind::Fn", trait_m),
                     };
 
                 let impl_iter = impl_sig.inputs().iter();
@@ -708,7 +708,7 @@ fn compare_number_of_method_arguments<'tcx>(
         let trait_m_hir_id = tcx.hir().as_local_hir_id(trait_m.def_id);
         let trait_span = if let Some(trait_id) = trait_m_hir_id {
             match tcx.hir().expect_trait_item(trait_id).kind {
-                TraitItemKind::Method(ref trait_m_sig, _) => {
+                TraitItemKind::Fn(ref trait_m_sig, _) => {
                     let pos = if trait_number_args > 0 { trait_number_args - 1 } else { 0 };
                     if let Some(arg) = trait_m_sig.decl.inputs.get(pos) {
                         Some(if pos == 0 {
@@ -731,7 +731,7 @@ fn compare_number_of_method_arguments<'tcx>(
         };
         let impl_m_hir_id = tcx.hir().as_local_hir_id(impl_m.def_id).unwrap();
         let impl_span = match tcx.hir().expect_impl_item(impl_m_hir_id).kind {
-            ImplItemKind::Method(ref impl_m_sig, _) => {
+            ImplItemKind::Fn(ref impl_m_sig, _) => {
                 let pos = if impl_number_args > 0 { impl_number_args - 1 } else { 0 };
                 if let Some(arg) = impl_m_sig.decl.inputs.get(pos) {
                     if pos == 0 {
@@ -872,7 +872,7 @@ fn compare_synthetic_generics<'tcx>(
                         let impl_m = tcx.hir().as_local_hir_id(impl_m.def_id)?;
                         let impl_m = tcx.hir().impl_item(hir::ImplItemId { hir_id: impl_m });
                         let input_tys = match impl_m.kind {
-                            hir::ImplItemKind::Method(ref sig, _) => sig.decl.inputs,
+                            hir::ImplItemKind::Fn(ref sig, _) => sig.decl.inputs,
                             _ => unreachable!(),
                         };
                         struct Visitor(Option<Span>, hir::def_id::DefId);
@@ -889,10 +889,10 @@ fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) {
                                     }
                                 }
                             }
-                            type Map = Map<'v>;
+                            type Map = intravisit::ErasedMap<'v>;
                             fn nested_visit_map(
                                 &mut self,
-                            ) -> intravisit::NestedVisitorMap<'_, Self::Map>
+                            ) -> intravisit::NestedVisitorMap<Self::Map>
                             {
                                 intravisit::NestedVisitorMap::None
                             }
index 0c5f3d3e99d75e274635a27da38d46e038c40d06..0556c80e4f70775fa17b4e010f9f95cbfec3aeab 100644 (file)
@@ -1,6 +1,8 @@
 use crate::check::FnCtxt;
 use rustc_infer::infer::InferOk;
-use rustc_infer::traits::{self, ObligationCause};
+use rustc_trait_selection::infer::InferCtxtExt as _;
+use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
+use rustc_trait_selection::traits::{self, ObligationCause};
 
 use rustc::ty::adjustment::AllowTwoPhase;
 use rustc::ty::{self, AssocItem, Ty};
@@ -236,8 +238,7 @@ pub fn get_conversion_methods(
                     //
                     // FIXME? Other potential candidate methods: `as_ref` and
                     // `as_mut`?
-                    .find(|a| a.check_name(sym::rustc_conversion_suggestion))
-                    .is_some()
+                    .any(|a| a.check_name(sym::rustc_conversion_suggestion))
         });
 
         methods
@@ -374,7 +375,7 @@ pub fn check_ref(
     ) -> Option<(Span, &'static str, String)> {
         let sm = self.sess().source_map();
         let sp = expr.span;
-        if !sm.span_to_filename(sp).is_real() {
+        if sm.is_imported(sp) {
             // Ignore if span is from within a macro #41858, #58298. We previously used the macro
             // call span, but that breaks down when the type error comes from multiple calls down.
             return None;
@@ -524,9 +525,9 @@ pub fn check_ref(
             {
                 // We have `&T`, check if what was expected was `T`. If so,
                 // we may want to suggest removing a `&`.
-                if !sm.span_to_filename(expr.span).is_real() {
+                if sm.is_imported(expr.span) {
                     if let Ok(code) = sm.span_to_snippet(sp) {
-                        if code.chars().next() == Some('&') {
+                        if code.starts_with('&') {
                             return Some((
                                 sp,
                                 "consider removing the borrow",
@@ -602,7 +603,7 @@ pub fn check_for_cast(
             // FIXME(estebank): modify once we decide to suggest `as` casts
             return false;
         }
-        if !self.tcx.sess.source_map().span_to_filename(expr.span).is_real() {
+        if self.tcx.sess.source_map().is_imported(expr.span) {
             // Ignore if span is from within a macro.
             return false;
         }
index ead7536f8c664a9a23599998a40e93332541a140..e48ebbbb23514b153438220d9c04b8d3b185784d 100644 (file)
@@ -9,9 +9,12 @@
 use rustc::ty::{self, Predicate, Ty, TyCtxt};
 use rustc_errors::struct_span_err;
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
-use rustc_infer::infer::{InferOk, SuppressRegionErrors, TyCtxtInferExt};
-use rustc_infer::traits::{ObligationCause, TraitEngine, TraitEngineExt};
+use rustc_infer::infer::{InferOk, RegionckMode, TyCtxtInferExt};
+use rustc_infer::traits::TraitEngineExt as _;
 use rustc_span::Span;
+use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
+use rustc_trait_selection::traits::query::dropck_outlives::AtExt;
+use rustc_trait_selection::traits::{ObligationCause, TraitEngine, TraitEngineExt};
 
 /// This function confirms that the `Drop` implementation identified by
 /// `drop_impl_did` is not any more specialized than the type it is
@@ -136,7 +139,7 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>(
             drop_impl_did,
             &region_scope_tree,
             &outlives_env,
-            SuppressRegionErrors::default(),
+            RegionckMode::default(),
         );
         Ok(())
     })
index ff9fec004bbb508f79305e597ff151391819be1d..617c54a738e6eaf2b7298160cb6f5cfa93dbf241 100644 (file)
@@ -18,6 +18,7 @@
 use crate::util::common::ErrorReported;
 
 use rustc::middle::lang_items;
+use rustc::mir::interpret::ErrorHandled;
 use rustc::ty;
 use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
 use rustc::ty::Ty;
 use rustc_hir::{ExprKind, QPath};
 use rustc_infer::infer;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
-use rustc_infer::traits::{self, ObligationCauseCode};
 use rustc_span::hygiene::DesugaringKind;
 use rustc_span::source_map::Span;
 use rustc_span::symbol::{kw, sym, Symbol};
+use rustc_trait_selection::traits::{self, ObligationCauseCode};
 
 use std::fmt::Display;
 
@@ -404,7 +405,7 @@ fn check_expr_addr_of(
         let needs = Needs::maybe_mut_place(mutbl);
         let ty = self.check_expr_with_expectation_and_needs(&oprnd, hint, needs);
 
-        let tm = ty::TypeAndMut { ty: ty, mutbl: mutbl };
+        let tm = ty::TypeAndMut { ty, mutbl };
         match kind {
             _ if tm.ty.references_error() => self.tcx.types.err,
             hir::BorrowKind::Raw => {
@@ -1039,11 +1040,18 @@ fn check_expr_repeat(
         };
 
         if element_ty.references_error() {
-            tcx.types.err
-        } else if let Ok(count) = count {
-            tcx.mk_ty(ty::Array(t, count))
-        } else {
-            tcx.types.err
+            return tcx.types.err;
+        }
+        match count {
+            Ok(count) => tcx.mk_ty(ty::Array(t, count)),
+            Err(ErrorHandled::TooGeneric) => {
+                self.tcx.sess.span_err(
+                    tcx.def_span(count_def_id),
+                    "array lengths can't depend on generic parameters",
+                );
+                tcx.types.err
+            }
+            Err(ErrorHandled::Reported) => tcx.types.err,
         }
     }
 
@@ -1195,7 +1203,7 @@ fn check_expr_struct_fields(
             .fields
             .iter()
             .enumerate()
-            .map(|(i, field)| (field.ident.modern(), (i, field)))
+            .map(|(i, field)| (field.ident.normalize_to_macros_2_0(), (i, field)))
             .collect::<FxHashMap<_, _>>();
 
         let mut seen_fields = FxHashMap::default();
@@ -1461,7 +1469,9 @@ fn check_field(
                     let (ident, def_scope) =
                         self.tcx.adjust_ident_and_get_scope(field, base_def.did, self.body_id);
                     let fields = &base_def.non_enum_variant().fields;
-                    if let Some(index) = fields.iter().position(|f| f.ident.modern() == ident) {
+                    if let Some(index) =
+                        fields.iter().position(|f| f.ident.normalize_to_macros_2_0() == ident)
+                    {
                         let field = &fields[index];
                         let field_ty = self.field_ty(expr.span, field, substs);
                         // Save the index of all fields regardless of their visibility in case
@@ -1621,7 +1631,7 @@ fn ban_take_value_of_method(&self, expr: &hir::Expr<'_>, expr_t: Ty<'tcx>, field
     }
 
     fn point_at_param_definition(&self, err: &mut DiagnosticBuilder<'_>, param: ty::ParamTy) {
-        let generics = self.tcx.generics_of(self.body_id.owner_def_id());
+        let generics = self.tcx.generics_of(self.body_id.owner.to_def_id());
         let generic_param = generics.type_param(&param, self.tcx);
         if let ty::GenericParamDefKind::Type { synthetic: Some(..), .. } = generic_param.kind {
             return;
index 50692e0f10487516cfe9b3ab186531cd4fb34d42..cdf68256a7a88198d6a3cd65fd3db0aad64b5efa 100644 (file)
@@ -4,7 +4,6 @@
 //! types computed here.
 
 use super::FnCtxt;
-use rustc::hir::map::Map;
 use rustc::middle::region::{self, YieldData};
 use rustc::ty::{self, Ty};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -209,9 +208,9 @@ pub fn resolve_interior<'a, 'tcx>(
 // librustc/middle/region.rs since `expr_count` is compared against the results
 // there.
 impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
-    type Map = Map<'tcx>;
+    type Map = intravisit::ErasedMap<'tcx>;
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
         NestedVisitorMap::None
     }
 
@@ -237,7 +236,7 @@ fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
                         // ZST in a temporary, so skip its type, just in case it
                         // can significantly complicate the generator type.
                         Res::Def(DefKind::Fn, _)
-                        | Res::Def(DefKind::Method, _)
+                        | Res::Def(DefKind::AssocFn, _)
                         | Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) => {
                             // NOTE(eddyb) this assumes a path expression has
                             // no nested expressions to keep track of.
index 3572eda5c1399006db8cfc33f03d6a70181a27e6..dd5e5726e83677b520bcebb14c77046e983bde65 100644 (file)
@@ -147,9 +147,9 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
             ),
             "rustc_peek" => (1, vec![param(0)], param(0)),
             "caller_location" => (0, vec![], tcx.caller_location_ty()),
-            "panic_if_uninhabited" => (1, Vec::new(), tcx.mk_unit()),
-            "init" => (1, Vec::new(), param(0)),
-            "uninit" => (1, Vec::new(), param(0)),
+            "assert_inhabited" | "assert_zero_valid" | "assert_uninit_valid" => {
+                (1, Vec::new(), tcx.mk_unit())
+            }
             "forget" => (1, vec![param(0)], tcx.mk_unit()),
             "transmute" => (2, vec![param(0)], param(1)),
             "move_val_init" => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()),
@@ -297,14 +297,25 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
 
             "try" => {
                 let mut_u8 = tcx.mk_mut_ptr(tcx.types.u8);
-                let fn_ty = ty::Binder::bind(tcx.mk_fn_sig(
+                let try_fn_ty = ty::Binder::bind(tcx.mk_fn_sig(
                     iter::once(mut_u8),
                     tcx.mk_unit(),
                     false,
                     hir::Unsafety::Normal,
                     Abi::Rust,
                 ));
-                (0, vec![tcx.mk_fn_ptr(fn_ty), mut_u8, mut_u8], tcx.types.i32)
+                let catch_fn_ty = ty::Binder::bind(tcx.mk_fn_sig(
+                    [mut_u8, mut_u8].iter().cloned(),
+                    tcx.mk_unit(),
+                    false,
+                    hir::Unsafety::Normal,
+                    Abi::Rust,
+                ));
+                (
+                    0,
+                    vec![tcx.mk_fn_ptr(try_fn_ty), mut_u8, tcx.mk_fn_ptr(catch_fn_ty)],
+                    tcx.types.i32,
+                )
             }
 
             "va_start" | "va_end" => match mk_va_list_ty(hir::Mutability::Mut) {
index 108affe5a86c0161fcff0f0f95a383e270e97afc..48c72567b5c31ae8a15d454491e0b3aaf8947a8d 100644 (file)
@@ -11,8 +11,8 @@
 use rustc::ty::{self, GenericParamDefKind, Ty};
 use rustc_hir as hir;
 use rustc_infer::infer::{self, InferOk};
-use rustc_infer::traits;
 use rustc_span::Span;
+use rustc_trait_selection::traits;
 
 use std::ops::Deref;
 
index 9b8d88e94b60b0d0f2c8095b3f9cc16e3e20faa8..3cf7b65e30f2f377688d4a08ac238cb51e07ea9d 100644 (file)
@@ -1,6 +1,6 @@
-//! Method lookup: the secret sauce of Rust. See the [rustc guide] for more information.
+//! Method lookup: the secret sauce of Rust. See the [rustc dev guide] for more information.
 //!
-//! [rustc guide]: https://rust-lang.github.io/rustc-guide/method-lookup.html
+//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/method-lookup.html
 
 mod confirm;
 pub mod probe;
@@ -22,8 +22,9 @@
 use rustc_hir::def::{CtorOf, DefKind, Namespace};
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::{self, InferOk};
-use rustc_infer::traits;
 use rustc_span::Span;
+use rustc_trait_selection::traits;
+use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
 
 use self::probe::{IsSuggestion, ProbeScope};
 
@@ -459,12 +460,14 @@ pub fn resolve_ufcs(
             ProbeScope::TraitsInScope,
         )?;
         debug!("resolve_ufcs: pick={:?}", pick);
-        for import_id in pick.import_ids {
-            let import_def_id = tcx.hir().local_def_id(import_id);
-            debug!("resolve_ufcs: used_trait_import: {:?}", import_def_id);
-            Lrc::get_mut(&mut self.tables.borrow_mut().used_trait_imports)
-                .unwrap()
-                .insert(import_def_id);
+        {
+            let mut tables = self.tables.borrow_mut();
+            let used_trait_imports = Lrc::get_mut(&mut tables.used_trait_imports).unwrap();
+            for import_id in pick.import_ids {
+                let import_def_id = tcx.hir().local_def_id(import_id);
+                debug!("resolve_ufcs: used_trait_import: {:?}", import_def_id);
+                used_trait_imports.insert(import_def_id);
+            }
         }
 
         let def_kind = pick.item.def_kind();
index a52cabd8894779b4e023916118b1d8829cbb8bbc..45b1c7d6ea7409f19927698d519efc45dfa59a7d 100644 (file)
@@ -8,9 +8,7 @@
 use crate::hir::def::DefKind;
 use crate::hir::def_id::DefId;
 
-use rustc::lint;
 use rustc::middle::stability;
-use rustc::session::config::nightly_options;
 use rustc::ty::subst::{InternalSubsts, Subst, SubstsRef};
 use rustc::ty::GenericParamDefKind;
 use rustc::ty::{
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_infer::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
 use rustc_infer::infer::{self, InferOk, TyCtxtInferExt};
-use rustc_infer::traits::query::method_autoderef::MethodAutoderefBadTy;
-use rustc_infer::traits::query::method_autoderef::{CandidateStep, MethodAutoderefStepsResult};
-use rustc_infer::traits::query::CanonicalTyGoal;
-use rustc_infer::traits::{self, ObligationCause};
+use rustc_session::config::nightly_options;
+use rustc_session::lint;
 use rustc_span::{symbol::Symbol, Span, DUMMY_SP};
+use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
+use rustc_trait_selection::traits::query::method_autoderef::MethodAutoderefBadTy;
+use rustc_trait_selection::traits::query::method_autoderef::{
+    CandidateStep, MethodAutoderefStepsResult,
+};
+use rustc_trait_selection::traits::query::CanonicalTyGoal;
+use rustc_trait_selection::traits::{self, ObligationCause};
 use std::cmp::max;
 use std::iter;
 use std::mem;
@@ -572,7 +575,7 @@ fn push_candidate(&mut self, candidate: Candidate<'tcx>, is_inherent: bool) {
     }
 
     fn assemble_inherent_candidates(&mut self) {
-        let steps = self.steps.clone();
+        let steps = Lrc::clone(&self.steps);
         for step in steps.iter() {
             self.assemble_probe(&step.self_ty);
         }
@@ -635,87 +638,51 @@ fn assemble_probe(&mut self, self_ty: &Canonical<'tcx, QueryResponse<'tcx, Ty<'t
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
             ty::Slice(_) => {
-                let lang_def_id = lang_items.slice_impl();
-                self.assemble_inherent_impl_for_primitive(lang_def_id);
-
-                let lang_def_id = lang_items.slice_u8_impl();
-                self.assemble_inherent_impl_for_primitive(lang_def_id);
-
-                let lang_def_id = lang_items.slice_alloc_impl();
-                self.assemble_inherent_impl_for_primitive(lang_def_id);
-
-                let lang_def_id = lang_items.slice_u8_alloc_impl();
-                self.assemble_inherent_impl_for_primitive(lang_def_id);
-            }
-            ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::Mutability::Not }) => {
-                let lang_def_id = lang_items.const_ptr_impl();
-                self.assemble_inherent_impl_for_primitive(lang_def_id);
-            }
-            ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::Mutability::Mut }) => {
-                let lang_def_id = lang_items.mut_ptr_impl();
-                self.assemble_inherent_impl_for_primitive(lang_def_id);
-            }
-            ty::Int(ast::IntTy::I8) => {
-                let lang_def_id = lang_items.i8_impl();
-                self.assemble_inherent_impl_for_primitive(lang_def_id);
-            }
-            ty::Int(ast::IntTy::I16) => {
-                let lang_def_id = lang_items.i16_impl();
-                self.assemble_inherent_impl_for_primitive(lang_def_id);
-            }
-            ty::Int(ast::IntTy::I32) => {
-                let lang_def_id = lang_items.i32_impl();
-                self.assemble_inherent_impl_for_primitive(lang_def_id);
-            }
-            ty::Int(ast::IntTy::I64) => {
-                let lang_def_id = lang_items.i64_impl();
-                self.assemble_inherent_impl_for_primitive(lang_def_id);
-            }
-            ty::Int(ast::IntTy::I128) => {
-                let lang_def_id = lang_items.i128_impl();
-                self.assemble_inherent_impl_for_primitive(lang_def_id);
-            }
-            ty::Int(ast::IntTy::Isize) => {
-                let lang_def_id = lang_items.isize_impl();
-                self.assemble_inherent_impl_for_primitive(lang_def_id);
-            }
-            ty::Uint(ast::UintTy::U8) => {
-                let lang_def_id = lang_items.u8_impl();
-                self.assemble_inherent_impl_for_primitive(lang_def_id);
-            }
-            ty::Uint(ast::UintTy::U16) => {
-                let lang_def_id = lang_items.u16_impl();
-                self.assemble_inherent_impl_for_primitive(lang_def_id);
-            }
-            ty::Uint(ast::UintTy::U32) => {
-                let lang_def_id = lang_items.u32_impl();
-                self.assemble_inherent_impl_for_primitive(lang_def_id);
-            }
-            ty::Uint(ast::UintTy::U64) => {
-                let lang_def_id = lang_items.u64_impl();
-                self.assemble_inherent_impl_for_primitive(lang_def_id);
+                for &lang_def_id in &[
+                    lang_items.slice_impl(),
+                    lang_items.slice_u8_impl(),
+                    lang_items.slice_alloc_impl(),
+                    lang_items.slice_u8_alloc_impl(),
+                ] {
+                    self.assemble_inherent_impl_for_primitive(lang_def_id);
+                }
             }
-            ty::Uint(ast::UintTy::U128) => {
-                let lang_def_id = lang_items.u128_impl();
+            ty::RawPtr(ty::TypeAndMut { ty: _, mutbl }) => {
+                let lang_def_id = match mutbl {
+                    hir::Mutability::Not => lang_items.const_ptr_impl(),
+                    hir::Mutability::Mut => lang_items.mut_ptr_impl(),
+                };
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
-            ty::Uint(ast::UintTy::Usize) => {
-                let lang_def_id = lang_items.usize_impl();
+            ty::Int(i) => {
+                let lang_def_id = match i {
+                    ast::IntTy::I8 => lang_items.i8_impl(),
+                    ast::IntTy::I16 => lang_items.i16_impl(),
+                    ast::IntTy::I32 => lang_items.i32_impl(),
+                    ast::IntTy::I64 => lang_items.i64_impl(),
+                    ast::IntTy::I128 => lang_items.i128_impl(),
+                    ast::IntTy::Isize => lang_items.isize_impl(),
+                };
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
-            ty::Float(ast::FloatTy::F32) => {
-                let lang_def_id = lang_items.f32_impl();
-                self.assemble_inherent_impl_for_primitive(lang_def_id);
-
-                let lang_def_id = lang_items.f32_runtime_impl();
+            ty::Uint(i) => {
+                let lang_def_id = match i {
+                    ast::UintTy::U8 => lang_items.u8_impl(),
+                    ast::UintTy::U16 => lang_items.u16_impl(),
+                    ast::UintTy::U32 => lang_items.u32_impl(),
+                    ast::UintTy::U64 => lang_items.u64_impl(),
+                    ast::UintTy::U128 => lang_items.u128_impl(),
+                    ast::UintTy::Usize => lang_items.usize_impl(),
+                };
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
-            ty::Float(ast::FloatTy::F64) => {
-                let lang_def_id = lang_items.f64_impl();
-                self.assemble_inherent_impl_for_primitive(lang_def_id);
-
-                let lang_def_id = lang_items.f64_runtime_impl();
-                self.assemble_inherent_impl_for_primitive(lang_def_id);
+            ty::Float(f) => {
+                let (lang_def_id1, lang_def_id2) = match f {
+                    ast::FloatTy::F32 => (lang_items.f32_impl(), lang_items.f32_runtime_impl()),
+                    ast::FloatTy::F64 => (lang_items.f64_impl(), lang_items.f64_runtime_impl()),
+                };
+                self.assemble_inherent_impl_for_primitive(lang_def_id1);
+                self.assemble_inherent_impl_for_primitive(lang_def_id2);
             }
             _ => {}
         }
@@ -1040,7 +1007,7 @@ fn pick(mut self) -> PickResult<'tcx> {
             return r;
         }
 
-        debug!("pick: actual search failed, assemble diagnotics");
+        debug!("pick: actual search failed, assemble diagnostics");
 
         let static_candidates = mem::take(&mut self.static_candidates);
         let private_candidate = self.private_candidate.take();
@@ -1403,6 +1370,7 @@ fn consider_probe(
                     let predicate = trait_ref.without_const().to_predicate();
                     let obligation = traits::Obligation::new(cause, self.param_env, predicate);
                     if !self.predicate_may_hold(&obligation) {
+                        result = ProbeResult::NoMatch;
                         if self.probe(|_| {
                             match self.select_trait_candidate(trait_ref) {
                                 Err(_) => return true,
@@ -1413,7 +1381,6 @@ fn consider_probe(
                                         // Determine exactly which obligation wasn't met, so
                                         // that we can give more context in the error.
                                         if !self.predicate_may_hold(&obligation) {
-                                            result = ProbeResult::NoMatch;
                                             let o = self.resolve_vars_if_possible(obligation);
                                             let predicate =
                                                 self.resolve_vars_if_possible(&predicate);
@@ -1431,7 +1398,6 @@ fn consider_probe(
                                 _ => {
                                     // Some nested subobligation of this predicate
                                     // failed.
-                                    result = ProbeResult::NoMatch;
                                     let predicate = self.resolve_vars_if_possible(&predicate);
                                     possibly_unsatisfied_predicates.push((predicate, None));
                                 }
@@ -1551,21 +1517,18 @@ fn probe_for_lev_candidate(&mut self) -> Result<Option<ty::AssocItem>, MethodErr
 
             let method_names = pcx.candidate_method_names();
             pcx.allow_similar_names = false;
-            let applicable_close_candidates: Vec<ty::AssocItem> =
-                method_names
-                    .iter()
-                    .filter_map(|&method_name| {
-                        pcx.reset();
-                        pcx.method_name = Some(method_name);
-                        pcx.assemble_inherent_candidates();
-                        pcx.assemble_extension_candidates_for_traits_in_scope(hir::DUMMY_HIR_ID)
-                            .map_or(None, |_| {
-                                pcx.pick_core()
-                                    .and_then(|pick| pick.ok())
-                                    .and_then(|pick| Some(pick.item))
-                            })
-                    })
-                    .collect();
+            let applicable_close_candidates: Vec<ty::AssocItem> = method_names
+                .iter()
+                .filter_map(|&method_name| {
+                    pcx.reset();
+                    pcx.method_name = Some(method_name);
+                    pcx.assemble_inherent_candidates();
+                    pcx.assemble_extension_candidates_for_traits_in_scope(hir::DUMMY_HIR_ID)
+                        .map_or(None, |_| {
+                            pcx.pick_core().and_then(|pick| pick.ok()).map(|pick| pick.item)
+                        })
+                })
+                .collect();
 
             if applicable_close_candidates.is_empty() {
                 Ok(None)
index 95faa353e9b65c0b12ea1cef72b7103746d62654..2f0eb5e06709a0191fc4ebb04d8686684172f168 100644 (file)
@@ -4,7 +4,6 @@
 use crate::check::FnCtxt;
 use crate::middle::lang_items::FnOnceTraitLangItem;
 use rustc::hir::map as hir_map;
-use rustc::hir::map::Map;
 use rustc::ty::print::with_crate_prefix;
 use rustc::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
 use rustc_ast::ast;
 use rustc_hir::intravisit;
 use rustc_hir::{ExprKind, Node, QPath};
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
-use rustc_infer::traits::Obligation;
 use rustc_span::symbol::kw;
 use rustc_span::{source_map, FileName, Span};
+use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
+use rustc_trait_selection::traits::Obligation;
 
 use std::cmp::Ordering;
 
@@ -427,7 +427,7 @@ pub fn report_method_error<'b>(
                         });
 
                     if let Some((field, field_ty)) = field_receiver {
-                        let scope = self.tcx.parent_module(self.body_id);
+                        let scope = self.tcx.parent_module(self.body_id).to_def_id();
                         let is_accessible = field.vis.is_accessible_from(scope, self.tcx);
 
                         if is_accessible {
@@ -547,10 +547,13 @@ macro_rules! report_function {
                                 (&self_ty.kind, parent_pred)
                             {
                                 if let ty::Adt(def, _) = p.skip_binder().trait_ref.self_ty().kind {
-                                    let id = self.tcx.hir().as_local_hir_id(def.did).unwrap();
-                                    let node = self.tcx.hir().get(id);
+                                    let node = self
+                                        .tcx
+                                        .hir()
+                                        .as_local_hir_id(def.did)
+                                        .map(|id| self.tcx.hir().get(id));
                                     match node {
-                                        hir::Node::Item(hir::Item { kind, .. }) => {
+                                        Some(hir::Node::Item(hir::Item { kind, .. })) => {
                                             if let Some(g) = kind.generics() {
                                                 let key = match &g.where_clause.predicates[..] {
                                                     [.., pred] => {
@@ -825,7 +828,7 @@ fn suggest_use_candidates(
         candidates: Vec<DefId>,
     ) {
         let module_did = self.tcx.parent_module(self.body_id);
-        let module_id = self.tcx.hir().as_local_hir_id(module_did).unwrap();
+        let module_id = self.tcx.hir().as_local_hir_id(module_did.to_def_id()).unwrap();
         let krate = self.tcx.hir().krate();
         let (span, found_use) = UsePlacementFinder::check(self.tcx, krate, module_id);
         if let Some(span) = span {
@@ -930,15 +933,15 @@ fn suggest_traits_to_import<'b>(
                             if let ty::AssocKind::Method = item.kind {
                                 let id = self.tcx.hir().as_local_hir_id(item.def_id);
                                 if let Some(hir::Node::TraitItem(hir::TraitItem {
-                                    kind: hir::TraitItemKind::Method(fn_sig, method),
+                                    kind: hir::TraitItemKind::Fn(fn_sig, method),
                                     ..
                                 })) = id.map(|id| self.tcx.hir().get(id))
                                 {
                                     let self_first_arg = match method {
-                                        hir::TraitMethod::Required([ident, ..]) => {
+                                        hir::TraitFn::Required([ident, ..]) => {
                                             ident.name == kw::SelfLower
                                         }
-                                        hir::TraitMethod::Provided(body_id) => {
+                                        hir::TraitFn::Provided(body_id) => {
                                             match &self.tcx.hir().body(*body_id).params[..] {
                                                 [hir::Param {
                                                     pat:
@@ -1343,9 +1346,9 @@ fn visit_mod(&mut self, module: &'tcx hir::Mod<'tcx>, _: Span, hir_id: hir::HirI
         }
     }
 
-    type Map = Map<'tcx>;
+    type Map = intravisit::ErasedMap<'tcx>;
 
-    fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> {
+    fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
         intravisit::NestedVisitorMap::None
     }
 }
index 4c214bd15e87e58a75ef0f0473f91212e05ad65a..368f64e4d41aab6716185803f0153936619e06e5 100644 (file)
 use crate::astconv::{AstConv, GenericArgCountMismatch, PathSeg};
 use crate::middle::lang_items;
 use rustc::hir::map::blocks::FnLikeNode;
-use rustc::hir::map::Map;
 use rustc::middle::region;
 use rustc::mir::interpret::ConstValue;
-use rustc::session::parse::feature_err;
 use rustc::ty::adjustment::{
     Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCast,
 };
 use rustc_index::vec::Idx;
 use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse};
 use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282;
-use rustc_infer::infer::opaque_types::OpaqueTypeDecl;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_infer::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
 use rustc_infer::infer::{self, InferCtxt, InferOk, InferResult, TyCtxtInferExt};
-use rustc_infer::traits::error_reporting::recursive_type_with_infinite_size_error;
-use rustc_infer::traits::{self, ObligationCause, ObligationCauseCode, TraitEngine};
+use rustc_session::config::{self, EntryFnType};
+use rustc_session::lint;
+use rustc_session::parse::feature_err;
+use rustc_session::Session;
 use rustc_span::hygiene::DesugaringKind;
 use rustc_span::source_map::{original_sp, DUMMY_SP};
 use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::{self, BytePos, MultiSpan, Span};
 use rustc_target::spec::abi::Abi;
+use rustc_trait_selection::infer::InferCtxtExt as _;
+use rustc_trait_selection::opaque_types::{InferCtxtExt as _, OpaqueTypeDecl};
+use rustc_trait_selection::traits::error_reporting::recursive_type_with_infinite_size_error;
+use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
+use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
+use rustc_trait_selection::traits::{
+    self, ObligationCause, ObligationCauseCode, TraitEngine, TraitEngineExt,
+};
 
 use std::cell::{Cell, Ref, RefCell, RefMut};
 use std::cmp;
 use std::ops::{self, Deref};
 use std::slice;
 
-use crate::lint;
 use crate::require_c_abi_if_c_variadic;
-use crate::session::config::EntryFnType;
-use crate::session::Session;
 use crate::util::common::{indenter, ErrorReported};
 use crate::TypeAndSubsts;
 
@@ -457,7 +461,7 @@ pub enum Diverges {
         /// where all arms diverge), we may be
         /// able to provide a more informative
         /// message to the user.
-        /// If this is `None`, a default messsage
+        /// If this is `None`, a default message
         /// will be generated, which is suitable
         /// for most cases.
         custom_note: Option<&'static str>,
@@ -634,9 +638,8 @@ pub struct InheritedBuilder<'tcx> {
 
 impl Inherited<'_, 'tcx> {
     pub fn build(tcx: TyCtxt<'tcx>, def_id: DefId) -> InheritedBuilder<'tcx> {
-        let hir_id_root = if def_id.is_local() {
-            let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
-            DefId::local(hir_id.owner)
+        let hir_id_root = if let Some(def_id) = def_id.as_local() {
+            tcx.hir().local_def_id_to_hir_id(def_id).owner.to_def_id()
         } else {
             def_id
         };
@@ -737,8 +740,8 @@ fn visit_impl_item(&mut self, _: &'tcx hir::ImplItem<'tcx>) {}
 }
 
 pub fn check_wf_new(tcx: TyCtxt<'_>) {
-    let mut visit = wfcheck::CheckTypeWellFormedVisitor::new(tcx);
-    tcx.hir().krate().par_visit_all_item_likes(&mut visit);
+    let visit = wfcheck::CheckTypeWellFormedVisitor::new(tcx);
+    tcx.hir().krate().par_visit_all_item_likes(&visit);
 }
 
 fn check_mod_item_types(tcx: TyCtxt<'_>, module_def_id: DefId) {
@@ -811,14 +814,14 @@ fn primary_body_of(
         },
         Node::TraitItem(item) => match item.kind {
             hir::TraitItemKind::Const(ref ty, Some(body)) => Some((body, Some(ty), None, None)),
-            hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body)) => {
+            hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => {
                 Some((body, None, Some(&sig.header), Some(&sig.decl)))
             }
             _ => None,
         },
         Node::ImplItem(item) => match item.kind {
             hir::ImplItemKind::Const(ref ty, body) => Some((body, Some(ty), None, None)),
-            hir::ImplItemKind::Method(ref sig, body) => {
+            hir::ImplItemKind::Fn(ref sig, body) => {
                 Some((body, None, Some(&sig.header), Some(&sig.decl)))
             }
             _ => None,
@@ -896,7 +899,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                 ty::Opaque(def_id, substs) => {
                     debug!("fixup_opaque_types: found type {:?}", ty);
                     // Here, we replace any inference variables that occur within
-                    // the substs of an opaque type. By definition, any type occuring
+                    // the substs of an opaque type. By definition, any type occurring
                     // in the substs has a corresponding generic parameter, which is what
                     // we replace it with.
                     // This replacement is only run on the function signature, so any
@@ -1124,7 +1127,7 @@ fn typeck_tables_of_with_fallback<'tcx>(
 
     // Consistency check our TypeckTables instance can hold all ItemLocalIds
     // it will need to hold.
-    assert_eq!(tables.local_id_root, Some(DefId::local(id.owner)));
+    assert_eq!(tables.local_id_root, Some(id.owner.to_def_id()));
 
     tables
 }
@@ -1172,9 +1175,9 @@ fn assign(&mut self, span: Span, nid: hir::HirId, ty_opt: Option<LocalTy<'tcx>>)
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> {
-    type Map = Map<'tcx>;
+    type Map = intravisit::ErasedMap<'tcx>;
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
         NestedVisitorMap::None
     }
 
@@ -1733,7 +1736,7 @@ pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item<'tcx>) {
 
             for item in items.iter() {
                 let item = tcx.hir().trait_item(item.id);
-                if let hir::TraitItemKind::Method(sig, _) = &item.kind {
+                if let hir::TraitItemKind::Fn(sig, _) = &item.kind {
                     let abi = sig.header.abi;
                     fn_maybe_err(tcx, item.ident.span, abi);
                 }
@@ -1891,13 +1894,16 @@ fn check_specialization_validity<'tcx>(
 ) {
     let kind = match impl_item.kind {
         hir::ImplItemKind::Const(..) => ty::AssocKind::Const,
-        hir::ImplItemKind::Method(..) => ty::AssocKind::Method,
+        hir::ImplItemKind::Fn(..) => ty::AssocKind::Method,
         hir::ImplItemKind::OpaqueTy(..) => ty::AssocKind::OpaqueTy,
         hir::ImplItemKind::TyAlias(_) => ty::AssocKind::Type,
     };
 
-    let mut ancestor_impls = trait_def
-        .ancestors(tcx, impl_id)
+    let ancestors = match trait_def.ancestors(tcx, impl_id) {
+        Ok(ancestors) => ancestors,
+        Err(_) => return,
+    };
+    let mut ancestor_impls = ancestors
         .skip(1)
         .filter_map(|parent| {
             if parent.is_from_trait() {
@@ -1937,7 +1943,7 @@ fn check_specialization_validity<'tcx>(
         }
     });
 
-    // If `opt_result` is `None`, we have only encoutered `default impl`s that don't contain the
+    // If `opt_result` is `None`, we have only encountered `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(()));
 
@@ -2014,7 +2020,7 @@ fn check_impl_items_against_trait<'tcx>(
                         err.emit()
                     }
                 }
-                hir::ImplItemKind::Method(..) => {
+                hir::ImplItemKind::Fn(..) => {
                     let opt_trait_span = tcx.hir().span_if_local(ty_trait_item.def_id);
                     if ty_trait_item.kind == ty::AssocKind::Method {
                         compare_impl_method(
@@ -2078,16 +2084,17 @@ fn check_impl_items_against_trait<'tcx>(
 
     // Check for missing items from trait
     let mut missing_items = Vec::new();
-    for trait_item in tcx.associated_items(impl_trait_ref.def_id).in_definition_order() {
-        let is_implemented = trait_def
-            .ancestors(tcx, impl_id)
-            .leaf_def(tcx, trait_item.ident, trait_item.kind)
-            .map(|node_item| !node_item.node.is_from_trait())
-            .unwrap_or(false);
-
-        if !is_implemented && !traits::impl_is_default(tcx, impl_id) {
-            if !trait_item.defaultness.has_value() {
-                missing_items.push(*trait_item);
+    if let Ok(ancestors) = trait_def.ancestors(tcx, impl_id) {
+        for trait_item in tcx.associated_items(impl_trait_ref.def_id).in_definition_order() {
+            let is_implemented = ancestors
+                .leaf_def(tcx, trait_item.ident, trait_item.kind)
+                .map(|node_item| !node_item.node.is_from_trait())
+                .unwrap_or(false);
+
+            if !is_implemented && !traits::impl_is_default(tcx, impl_id) {
+                if !trait_item.defaultness.has_value() {
+                    missing_items.push(*trait_item);
+                }
             }
         }
     }
@@ -2900,14 +2907,14 @@ fn resolve_vars_with_obligations(&self, mut ty: Ty<'tcx>) -> Ty<'tcx> {
         debug!("resolve_vars_with_obligations(ty={:?})", ty);
 
         // No Infer()? Nothing needs doing.
-        if !ty.has_infer_types() && !ty.has_infer_consts() {
+        if !ty.has_infer_types_or_consts() {
             debug!("resolve_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() {
+        if !ty.has_infer_types_or_consts() {
             debug!("resolve_vars_with_obligations: ty={:?}", ty);
             return ty;
         }
@@ -2976,7 +2983,7 @@ fn write_resolution(&self, hir_id: hir::HirId, r: Result<(DefKind, DefId), Error
 
     pub fn write_method_call(&self, hir_id: hir::HirId, method: MethodCallee<'tcx>) {
         debug!("write_method_call(hir_id={:?}, method={:?})", hir_id, method);
-        self.write_resolution(hir_id, Ok((DefKind::Method, method.def_id)));
+        self.write_resolution(hir_id, Ok((DefKind::AssocFn, method.def_id)));
         self.write_substs(hir_id, method.substs);
 
         // When the method is confirmed, the `method.substs` includes
@@ -3452,7 +3459,7 @@ fn fallback_if_possible(&self, ty: Ty<'tcx>, mode: FallbackMode) -> bool {
                 //  }
                 //  ```
                 //
-                // In the above snippet, the inference varaible created by
+                // In the above snippet, the inference variable created by
                 // instantiating `Option<Foo>` will be completely unconstrained.
                 // We treat this as a non-defining use by making the inference
                 // variable fall back to the opaque type itself.
@@ -4234,7 +4241,7 @@ pub fn impl_self_ty(
         let substs = self.fresh_substs_for_item(span, did);
         let substd_ty = self.instantiate_type_scheme(span, &substs, &ity);
 
-        TypeAndSubsts { substs: substs, ty: substd_ty }
+        TypeAndSubsts { substs, ty: substd_ty }
     }
 
     /// Unifies the output type with the expected type early, for more coercions
@@ -4733,9 +4740,7 @@ fn parent_item_span(&self, id: hir::HirId) -> Option<Span> {
         let node = self.tcx.hir().get(self.tcx.hir().get_parent_item(id));
         match node {
             Node::Item(&hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. })
-            | Node::ImplItem(&hir::ImplItem {
-                kind: hir::ImplItemKind::Method(_, body_id), ..
-            }) => {
+            | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(_, body_id), .. }) => {
                 let body = self.tcx.hir().body(body_id);
                 if let ExprKind::Block(block, _) = &body.value.kind {
                     return Some(block.span);
@@ -4769,12 +4774,12 @@ fn get_node_fn_decl(
             }
             Node::TraitItem(&hir::TraitItem {
                 ident,
-                kind: hir::TraitItemKind::Method(ref sig, ..),
+                kind: hir::TraitItemKind::Fn(ref sig, ..),
                 ..
             }) => Some((&sig.decl, ident, true)),
             Node::ImplItem(&hir::ImplItem {
                 ident,
-                kind: hir::ImplItemKind::Method(ref sig, ..),
+                kind: hir::ImplItemKind::Fn(ref sig, ..),
                 ..
             }) => Some((&sig.decl, ident, false)),
             _ => None,
@@ -4859,11 +4864,11 @@ fn suggest_fn_call(
             match hir.get_if_local(def_id) {
                 Some(Node::Item(hir::Item { kind: ItemKind::Fn(.., body_id), .. }))
                 | Some(Node::ImplItem(hir::ImplItem {
-                    kind: hir::ImplItemKind::Method(_, body_id),
+                    kind: hir::ImplItemKind::Fn(_, body_id),
                     ..
                 }))
                 | Some(Node::TraitItem(hir::TraitItem {
-                    kind: hir::TraitItemKind::Method(.., hir::TraitMethod::Provided(body_id)),
+                    kind: hir::TraitItemKind::Fn(.., hir::TraitFn::Provided(body_id)),
                     ..
                 })) => {
                     let body = hir.body(*body_id);
@@ -4934,7 +4939,7 @@ fn suggest_fn_call(
                         .join(", ")
                 }
                 Some(Node::TraitItem(hir::TraitItem {
-                    kind: hir::TraitItemKind::Method(.., hir::TraitMethod::Required(idents)),
+                    kind: hir::TraitItemKind::Fn(.., hir::TraitFn::Required(idents)),
                     ..
                 })) => {
                     sugg_call = idents
@@ -5244,7 +5249,7 @@ fn suggest_missing_await(
                     .tcx
                     .associated_items(future_trait)
                     .in_definition_order()
-                    .nth(0)
+                    .next()
                     .unwrap()
                     .def_id;
                 let predicate =
@@ -5364,7 +5369,7 @@ pub fn instantiate_value_path(
                     is_alias_variant_ctor = true;
                 }
             }
-            Res::Def(DefKind::Method, def_id) | Res::Def(DefKind::AssocConst, def_id) => {
+            Res::Def(DefKind::AssocFn, def_id) | Res::Def(DefKind::AssocConst, def_id) => {
                 let container = tcx.associated_item(def_id).container;
                 debug!("instantiate_value_path: def_id={:?} container={:?}", def_id, container);
                 match container {
@@ -5783,7 +5788,7 @@ fn fatally_break_rust(sess: &Session) {
     handler.note_without_error(&format!(
         "rustc {} running on {}",
         option_env!("CFG_VERSION").unwrap_or("unknown_version"),
-        crate::session::config::host_triple(),
+        config::host_triple(),
     ));
 }
 
index bf3511a26143cc1d1ef40b46dbe51f2022675e2d..f589805e1e2610ce0a7d1404a19467e9fca14e4a 100644 (file)
@@ -10,6 +10,7 @@
 use rustc_hir as hir;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_span::Span;
+use rustc_trait_selection::infer::InferCtxtExt;
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// Checks a `a <op>= b`
@@ -860,7 +861,7 @@ enum Op {
 }
 
 /// Dereferences a single level of immutable referencing.
-fn deref_ty_if_possible<'tcx>(ty: Ty<'tcx>) -> Ty<'tcx> {
+fn deref_ty_if_possible(ty: Ty<'tcx>) -> Ty<'tcx> {
     match ty.kind {
         ty::Ref(_, ty, hir::Mutability::Not) => ty,
         _ => ty,
index b7aac707a9838835458a543fc2c8d052c4d8755b..0f3884de84e1282048189a45a90147d4487439bd 100644 (file)
@@ -11,9 +11,9 @@
 use rustc_hir::{HirId, Pat, PatKind};
 use rustc_infer::infer;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
-use rustc_infer::traits::{ObligationCause, Pattern};
 use rustc_span::hygiene::DesugaringKind;
 use rustc_span::source_map::{Span, Spanned};
+use rustc_trait_selection::traits::{ObligationCause, Pattern};
 
 use std::cmp;
 use std::collections::hash_map::Entry::{Occupied, Vacant};
@@ -63,6 +63,22 @@ struct TopInfo<'tcx> {
     ///              found type `std::result::Result<_, _>`
     /// ```
     span: Option<Span>,
+    /// This refers to the parent pattern. Used to provide extra diagnostic information on errors.
+    /// ```text
+    /// error[E0308]: mismatched types
+    ///   --> $DIR/const-in-struct-pat.rs:8:17
+    ///   |
+    /// L | struct f;
+    ///   | --------- unit struct defined here
+    /// ...
+    /// L |     let Thing { f } = t;
+    ///   |                 ^
+    ///   |                 |
+    ///   |                 expected struct `std::string::String`, found struct `f`
+    ///   |                 `f` is interpreted as a unit struct, not a new binding
+    ///   |                 help: bind the struct field to a different name instead: `f: other_f`
+    /// ```
+    parent_pat: Option<&'tcx Pat<'tcx>>,
 }
 
 impl<'tcx> FnCtxt<'_, 'tcx> {
@@ -98,7 +114,7 @@ fn demand_eqtype_pat(
 enum AdjustMode {
     /// Peel off all immediate reference types.
     Peel,
-    /// Reset binding mode to the inital mode.
+    /// Reset binding mode to the initial mode.
     Reset,
     /// Pass on the input binding mode and expected type.
     Pass,
@@ -120,7 +136,8 @@ pub fn check_pat_top(
         span: Option<Span>,
         origin_expr: bool,
     ) {
-        self.check_pat(pat, expected, INITIAL_BM, TopInfo { expected, origin_expr, span });
+        let info = TopInfo { expected, origin_expr, span, parent_pat: None };
+        self.check_pat(pat, expected, INITIAL_BM, info);
     }
 
     /// Type check the given `pat` against the `expected` type
@@ -161,8 +178,9 @@ fn check_pat(
                 self.check_pat_struct(pat, qpath, fields, etc, expected, def_bm, ti)
             }
             PatKind::Or(pats) => {
+                let parent_pat = Some(pat);
                 for pat in pats {
-                    self.check_pat(pat, expected, def_bm, ti);
+                    self.check_pat(pat, expected, def_bm, TopInfo { parent_pat, ..ti });
                 }
                 expected
             }
@@ -501,7 +519,7 @@ fn emit_err_pat_range(
 
     fn check_pat_ident(
         &self,
-        pat: &Pat<'_>,
+        pat: &'tcx Pat<'tcx>,
         ba: hir::BindingAnnotation,
         var_id: HirId,
         sub: Option<&'tcx Pat<'tcx>>,
@@ -546,7 +564,7 @@ fn check_pat_ident(
         }
 
         if let Some(p) = sub {
-            self.check_pat(&p, expected, def_bm, ti);
+            self.check_pat(&p, expected, def_bm, TopInfo { parent_pat: Some(&pat), ..ti });
         }
 
         local_ty
@@ -559,8 +577,16 @@ fn check_binding_alt_eq_ty(&self, span: Span, var_id: HirId, ty: Ty<'tcx>, ti: T
             let var_ty = self.resolve_vars_with_obligations(var_ty);
             let msg = format!("first introduced with type `{}` here", var_ty);
             err.span_label(hir.span(var_id), msg);
-            let in_arm = hir.parent_iter(var_id).any(|(_, n)| matches!(n, hir::Node::Arm(..)));
-            let pre = if in_arm { "in the same arm, " } else { "" };
+            let in_match = hir.parent_iter(var_id).any(|(_, n)| {
+                matches!(
+                    n,
+                    hir::Node::Expr(hir::Expr {
+                        kind: hir::ExprKind::Match(.., hir::MatchSource::Normal),
+                        ..
+                    })
+                )
+            });
+            let pre = if in_match { "in the same arm, " } else { "" };
             err.note(&format!("{}a binding must have the same type in all alternatives", pre));
             err.emit();
         }
@@ -647,6 +673,7 @@ fn check_pat_struct(
             variant_ty
         } else {
             for field in fields {
+                let ti = TopInfo { parent_pat: Some(&pat), ..ti };
                 self.check_pat(&field.pat, self.tcx.types.err, def_bm, ti);
             }
             return self.tcx.types.err;
@@ -656,9 +683,7 @@ fn check_pat_struct(
         self.demand_eqtype_pat(pat.span, expected, pat_ty, ti);
 
         // Type-check subpatterns.
-        if self
-            .check_struct_pat_fields(pat_ty, pat.hir_id, pat.span, variant, fields, etc, def_bm, ti)
-        {
+        if self.check_struct_pat_fields(pat_ty, &pat, variant, fields, etc, def_bm, ti) {
             pat_ty
         } else {
             self.tcx.types.err
@@ -682,7 +707,7 @@ fn check_pat_path(
                 self.set_tainted_by_errors();
                 return tcx.types.err;
             }
-            Res::Def(DefKind::Method, _)
+            Res::Def(DefKind::AssocFn, _)
             | Res::Def(DefKind::Ctor(_, CtorKind::Fictive), _)
             | Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) => {
                 report_unexpected_variant_res(tcx, res, pat.span, qpath);
@@ -691,23 +716,62 @@ fn check_pat_path(
             Res::Def(DefKind::Ctor(_, CtorKind::Const), _)
             | Res::SelfCtor(..)
             | Res::Def(DefKind::Const, _)
-            | Res::Def(DefKind::AssocConst, _) => {} // OK
+            | Res::Def(DefKind::AssocConst, _)
+            | Res::Def(DefKind::ConstParam, _) => {} // OK
             _ => bug!("unexpected pattern resolution: {:?}", res),
         }
 
         // Type-check the path.
-        let pat_ty = self.instantiate_value_path(segments, opt_ty, res, pat.span, pat.hir_id).0;
-        if let Some(mut err) =
+        let (pat_ty, pat_res) =
+            self.instantiate_value_path(segments, opt_ty, res, pat.span, pat.hir_id);
+        if let Some(err) =
             self.demand_suptype_with_origin(&self.pattern_cause(ti, pat.span), expected, pat_ty)
         {
-            err.emit();
+            self.emit_bad_pat_path(err, pat.span, res, pat_res, segments, ti.parent_pat);
         }
         pat_ty
     }
 
+    fn emit_bad_pat_path(
+        &self,
+        mut e: DiagnosticBuilder<'_>,
+        pat_span: Span,
+        res: Res,
+        pat_res: Res,
+        segments: &'b [hir::PathSegment<'b>],
+        parent_pat: Option<&Pat<'_>>,
+    ) {
+        if let Some(span) = self.tcx.hir().res_span(pat_res) {
+            e.span_label(span, &format!("{} defined here", res.descr()));
+            if let [hir::PathSegment { ident, .. }] = &*segments {
+                e.span_label(
+                    pat_span,
+                    &format!(
+                        "`{}` is interpreted as {} {}, not a new binding",
+                        ident,
+                        res.article(),
+                        res.descr(),
+                    ),
+                );
+                let (msg, sugg) = match parent_pat {
+                    Some(Pat { kind: hir::PatKind::Struct(..), .. }) => (
+                        "bind the struct field to a different name instead",
+                        format!("{}: other_{}", ident, ident.as_str().to_lowercase()),
+                    ),
+                    _ => (
+                        "introduce a new binding instead",
+                        format!("other_{}", ident.as_str().to_lowercase()),
+                    ),
+                };
+                e.span_suggestion(ident.span, msg, sugg, Applicability::HasPlaceholders);
+            }
+        }
+        e.emit();
+    }
+
     fn check_pat_tuple_struct(
         &self,
-        pat: &Pat<'_>,
+        pat: &'tcx Pat<'tcx>,
         qpath: &hir::QPath<'_>,
         subpats: &'tcx [&'tcx Pat<'tcx>],
         ddpos: Option<usize>,
@@ -717,8 +781,9 @@ fn check_pat_tuple_struct(
     ) -> Ty<'tcx> {
         let tcx = self.tcx;
         let on_error = || {
+            let parent_pat = Some(pat);
             for pat in subpats {
-                self.check_pat(&pat, tcx.types.err, def_bm, ti);
+                self.check_pat(&pat, tcx.types.err, def_bm, TopInfo { parent_pat, ..ti });
             }
         };
         let report_unexpected_res = |res: Res| {
@@ -729,7 +794,7 @@ fn check_pat_tuple_struct(
             );
             let mut err = struct_span_err!(tcx.sess, pat.span, E0164, "{}", msg);
             match (res, &pat.kind) {
-                (Res::Def(DefKind::Fn, _), _) | (Res::Def(DefKind::Method, _), _) => {
+                (Res::Def(DefKind::Fn, _), _) | (Res::Def(DefKind::AssocFn, _), _) => {
                     err.span_label(pat.span, "`fn` calls are not allowed in patterns");
                     err.help(
                         "for more information, visit \
@@ -766,7 +831,7 @@ fn check_pat_tuple_struct(
                 on_error();
                 return tcx.types.err;
             }
-            Res::Def(DefKind::AssocConst, _) | Res::Def(DefKind::Method, _) => {
+            Res::Def(DefKind::AssocConst, _) | Res::Def(DefKind::AssocFn, _) => {
                 report_unexpected_res(res);
                 return tcx.types.err;
             }
@@ -793,7 +858,7 @@ fn check_pat_tuple_struct(
             };
             for (i, subpat) in subpats.iter().enumerate_and_adjust(variant.fields.len(), ddpos) {
                 let field_ty = self.field_ty(subpat.span, &variant.fields[i], substs);
-                self.check_pat(&subpat, field_ty, def_bm, ti);
+                self.check_pat(&subpat, field_ty, def_bm, TopInfo { parent_pat: Some(&pat), ..ti });
 
                 self.tcx.check_stability(variant.fields[i].did, Some(pat.hir_id), subpat.span);
             }
@@ -841,7 +906,7 @@ fn e0023(
         // N-arity-tuple, e.g., `V_i((p_0, .., p_N))`. Meanwhile, the user supplied a pattern
         // with the subpatterns directly in the tuple variant pattern, e.g., `V_i(p_0, .., p_N)`.
         let missing_parenthesis = match (&expected.kind, fields, had_err) {
-            // #67037: only do this if we could sucessfully type-check the expected type against
+            // #67037: only do this if we could successfully type-check the expected type against
             // the tuple struct pattern. Otherwise the substs could get out of range on e.g.,
             // `let P() = U;` where `P != U` with `struct P<T>(T);`.
             (ty::Adt(_, substs), [field], false) => {
@@ -938,8 +1003,7 @@ fn check_pat_tuple(
     fn check_struct_pat_fields(
         &self,
         adt_ty: Ty<'tcx>,
-        pat_id: HirId,
-        span: Span,
+        pat: &'tcx Pat<'tcx>,
         variant: &'tcx ty::VariantDef,
         fields: &'tcx [hir::FieldPat<'tcx>],
         etc: bool,
@@ -950,7 +1014,7 @@ fn check_struct_pat_fields(
 
         let (substs, adt) = match adt_ty.kind {
             ty::Adt(adt, substs) => (substs, adt),
-            _ => span_bug!(span, "struct pattern is not an ADT"),
+            _ => span_bug!(pat.span, "struct pattern is not an ADT"),
         };
         let kind_name = adt.variant_descr();
 
@@ -959,7 +1023,7 @@ fn check_struct_pat_fields(
             .fields
             .iter()
             .enumerate()
-            .map(|(i, field)| (field.ident.modern(), (i, field)))
+            .map(|(i, field)| (field.ident.normalize_to_macros_2_0(), (i, field)))
             .collect::<FxHashMap<_, _>>();
 
         // Keep track of which fields have already appeared in the pattern.
@@ -983,7 +1047,7 @@ fn check_struct_pat_fields(
                         .get(&ident)
                         .map(|(i, f)| {
                             self.write_field_index(field.hir_id, *i);
-                            self.tcx.check_stability(f.did, Some(pat_id), span);
+                            self.tcx.check_stability(f.did, Some(pat.hir_id), span);
                             self.field_ty(span, f, substs)
                         })
                         .unwrap_or_else(|| {
@@ -994,13 +1058,13 @@ fn check_struct_pat_fields(
                 }
             };
 
-            self.check_pat(&field.pat, field_ty, def_bm, ti);
+            self.check_pat(&field.pat, field_ty, def_bm, TopInfo { parent_pat: Some(&pat), ..ti });
         }
 
         let mut unmentioned_fields = variant
             .fields
             .iter()
-            .map(|field| field.ident.modern())
+            .map(|field| field.ident.normalize_to_macros_2_0())
             .filter(|ident| !used_fields.contains_key(&ident))
             .collect::<Vec<_>>();
 
@@ -1017,7 +1081,7 @@ fn check_struct_pat_fields(
         if variant.is_field_list_non_exhaustive() && !adt.did.is_local() && !etc {
             struct_span_err!(
                 tcx.sess,
-                span,
+                pat.span,
                 E0638,
                 "`..` required with {} marked as non-exhaustive",
                 kind_name
@@ -1029,14 +1093,14 @@ fn check_struct_pat_fields(
         if kind_name == "union" {
             if fields.len() != 1 {
                 tcx.sess
-                    .struct_span_err(span, "union patterns should have exactly one field")
+                    .struct_span_err(pat.span, "union patterns should have exactly one field")
                     .emit();
             }
             if etc {
-                tcx.sess.struct_span_err(span, "`..` cannot be used in union patterns").emit();
+                tcx.sess.struct_span_err(pat.span, "`..` cannot be used in union patterns").emit();
             }
         } else if !etc && !unmentioned_fields.is_empty() {
-            self.error_unmentioned_fields(span, &unmentioned_fields, variant);
+            self.error_unmentioned_fields(pat.span, &unmentioned_fields, variant);
         }
         no_field_errors
     }
@@ -1196,7 +1260,7 @@ fn check_pat_box(
 
     fn check_pat_ref(
         &self,
-        pat: &Pat<'_>,
+        pat: &'tcx Pat<'tcx>,
         inner: &'tcx Pat<'tcx>,
         mutbl: hir::Mutability,
         expected: Ty<'tcx>,
@@ -1236,7 +1300,7 @@ fn check_pat_ref(
         } else {
             (tcx.types.err, tcx.types.err)
         };
-        self.check_pat(&inner, inner_ty, def_bm, ti);
+        self.check_pat(&inner, inner_ty, def_bm, TopInfo { parent_pat: Some(&pat), ..ti });
         rptr_ty
     }
 
index c0e33637fd0477577901ba29a38ff3b31874eb2a..57a89614eb18c5100a44d175912746e80207ed5f 100644 (file)
@@ -76,7 +76,6 @@
 use crate::check::FnCtxt;
 use crate::mem_categorization as mc;
 use crate::middle::region;
-use rustc::hir::map::Map;
 use rustc::ty::adjustment;
 use rustc::ty::subst::{GenericArgKind, SubstsRef};
 use rustc::ty::{self, Ty};
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::PatKind;
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
-use rustc_infer::infer::{self, RegionObligation, SuppressRegionErrors};
+use rustc_infer::infer::{self, RegionObligation, RegionckMode};
 use rustc_span::Span;
+use rustc_trait_selection::infer::OutlivesEnvironmentExt;
+use rustc_trait_selection::opaque_types::InferCtxtExt;
 use std::mem;
 use std::ops::Deref;
 
@@ -122,10 +123,7 @@ pub fn regionck_expr(&self, body: &'tcx hir::Body<'tcx>) {
             rcx.visit_body(body);
             rcx.visit_region_obligations(id);
         }
-        rcx.resolve_regions_and_report_errors(SuppressRegionErrors::when_nll_is_enabled(self.tcx));
-
-        assert!(self.tables.borrow().free_region_map.is_empty());
-        self.tables.borrow_mut().free_region_map = rcx.outlives_environment.into_free_region_map();
+        rcx.resolve_regions_and_report_errors(RegionckMode::for_item_body(self.tcx));
     }
 
     /// Region checking during the WF phase for items. `wf_tys` are the
@@ -143,7 +141,7 @@ pub fn regionck_item(&self, item_id: hir::HirId, span: Span, wf_tys: &[Ty<'tcx>]
         rcx.outlives_environment.add_implied_bounds(self, wf_tys, item_id, span);
         rcx.outlives_environment.save_implied_bounds(item_id);
         rcx.visit_region_obligations(item_id);
-        rcx.resolve_regions_and_report_errors(SuppressRegionErrors::default());
+        rcx.resolve_regions_and_report_errors(RegionckMode::default());
     }
 
     /// Region check a function body. Not invoked on closures, but
@@ -166,13 +164,7 @@ pub fn regionck_fn(&self, fn_id: hir::HirId, body: &'tcx hir::Body<'tcx>) {
             rcx.visit_fn_body(fn_id, body, self.tcx.hir().span(fn_id));
         }
 
-        rcx.resolve_regions_and_report_errors(SuppressRegionErrors::when_nll_is_enabled(self.tcx));
-
-        // In this mode, we also copy the free-region-map into the
-        // tables of the enclosing fcx. In the other regionck modes
-        // (e.g., `regionck_item`), we don't have an enclosing tables.
-        assert!(self.tables.borrow().free_region_map.is_empty());
-        self.tables.borrow_mut().free_region_map = rcx.outlives_environment.into_free_region_map();
+        rcx.resolve_regions_and_report_errors(RegionckMode::for_item_body(self.tcx));
     }
 }
 
@@ -353,7 +345,7 @@ fn visit_region_obligations(&mut self, hir_id: hir::HirId) {
         self.select_all_obligations_or_error();
     }
 
-    fn resolve_regions_and_report_errors(&self, suppress: SuppressRegionErrors) {
+    fn resolve_regions_and_report_errors(&self, mode: RegionckMode) {
         self.infcx.process_registered_region_obligations(
             self.outlives_environment.region_bound_pairs_map(),
             self.implicit_region_bound,
@@ -364,7 +356,7 @@ fn resolve_regions_and_report_errors(&self, suppress: SuppressRegionErrors) {
             self.subject_def_id,
             &self.region_scope_tree,
             &self.outlives_environment,
-            suppress,
+            mode,
         );
     }
 
@@ -415,9 +407,9 @@ impl<'a, 'tcx> Visitor<'tcx> for RegionCtxt<'a, 'tcx> {
     // hierarchy, and in particular the relationships between free
     // regions, until regionck, as described in #3238.
 
-    type Map = Map<'tcx>;
+    type Map = intravisit::ErasedMap<'tcx>;
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
         NestedVisitorMap::None
     }
 
index b5ed6335dc011873e45405c97e5ab8a85806d3fd..1b5f151870c2f7400f449384b83d8479a756c5c5 100644 (file)
@@ -35,7 +35,6 @@
 use crate::expr_use_visitor as euv;
 use crate::mem_categorization as mc;
 use crate::mem_categorization::PlaceBase;
-use rustc::hir::map::Map;
 use rustc::ty::{self, Ty, TyCtxt, UpvarSubsts};
 use rustc_ast::ast;
 use rustc_data_structures::fx::FxIndexMap;
@@ -60,9 +59,9 @@ struct InferBorrowKindVisitor<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for InferBorrowKindVisitor<'a, 'tcx> {
-    type Map = Map<'tcx>;
+    type Map = intravisit::ErasedMap<'tcx>;
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
         NestedVisitorMap::None
     }
 
@@ -119,7 +118,7 @@ fn analyze_closure(
             for (&var_hir_id, _) in upvars.iter() {
                 let upvar_id = ty::UpvarId {
                     var_path: ty::UpvarPath { hir_id: var_hir_id },
-                    closure_expr_id: LocalDefId::from_def_id(closure_def_id),
+                    closure_expr_id: closure_def_id.expect_local(),
                 };
                 debug!("seed upvar_id {:?}", upvar_id);
                 // Adding the upvar Id to the list of Upvars, which will be added
@@ -229,7 +228,7 @@ fn final_upvar_tys(&self, closure_id: hir::HirId) -> Vec<Ty<'tcx>> {
                     let upvar_ty = self.node_ty(var_hir_id);
                     let upvar_id = ty::UpvarId {
                         var_path: ty::UpvarPath { hir_id: var_hir_id },
-                        closure_expr_id: LocalDefId::from_def_id(closure_def_id),
+                        closure_expr_id: closure_def_id.expect_local(),
                     };
                     let capture = self.tables.borrow().upvar_capture(upvar_id);
 
index e8e34a4e8f0791d8cc8939f1f61b2c87324f91b2..3255d7b435c8fb55ce387c055494107c45613e29 100644 (file)
@@ -2,23 +2,24 @@
 use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter};
 
 use rustc::middle::lang_items;
-use rustc::session::parse::feature_err;
 use rustc::ty::subst::{InternalSubsts, Subst};
+use rustc::ty::trait_def::TraitSpecializationKind;
 use rustc::ty::{
     self, AdtKind, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness,
 };
 use rustc_ast::ast;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
+use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
+use rustc_hir::itemlikevisit::ParItemLikeVisitor;
 use rustc_hir::ItemKind;
-use rustc_infer::infer::opaque_types::may_define_opaque_type;
-use rustc_infer::traits::{self, ObligationCause, ObligationCauseCode};
+use rustc_session::parse::feature_err;
 use rustc_span::symbol::sym;
 use rustc_span::Span;
-
-use rustc_hir as hir;
-use rustc_hir::itemlikevisit::ParItemLikeVisitor;
+use rustc_trait_selection::opaque_types::may_define_opaque_type;
+use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
+use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode};
 
 /// Helper type of a temporary returned by `.for_item(...)`.
 /// This is necessary because we can't write the following bound:
@@ -173,7 +174,7 @@ pub fn check_trait_item(tcx: TyCtxt<'_>, def_id: DefId) {
     let trait_item = tcx.hir().expect_trait_item(hir_id);
 
     let method_sig = match trait_item.kind {
-        hir::TraitItemKind::Method(ref sig, _) => Some(sig),
+        hir::TraitItemKind::Fn(ref sig, _) => Some(sig),
         _ => None,
     };
     check_object_unsafe_self_trait_by_name(tcx, &trait_item);
@@ -207,7 +208,7 @@ fn check_object_unsafe_self_trait_by_name(tcx: TyCtxt<'_>, item: &hir::TraitItem
         {
             trait_should_be_self.push(ty.span)
         }
-        hir::TraitItemKind::Method(sig, _) => {
+        hir::TraitItemKind::Fn(sig, _) => {
             for ty in sig.decl.inputs {
                 if could_be_self(trait_def_id, ty) {
                     trait_should_be_self.push(ty.span);
@@ -247,7 +248,7 @@ pub fn check_impl_item(tcx: TyCtxt<'_>, def_id: DefId) {
     let impl_item = tcx.hir().expect_impl_item(hir_id);
 
     let method_sig = match impl_item.kind {
-        hir::ImplItemKind::Method(ref sig, _) => Some(sig),
+        hir::ImplItemKind::Fn(ref sig, _) => Some(sig),
         _ => None,
     };
 
@@ -411,7 +412,9 @@ fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) {
     let trait_def_id = tcx.hir().local_def_id(item.hir_id);
 
     let trait_def = tcx.trait_def(trait_def_id);
-    if trait_def.is_marker {
+    if trait_def.is_marker
+        || matches!(trait_def.specialization_kind, TraitSpecializationKind::Marker)
+    {
         for associated_def_id in &*tcx.associated_item_def_ids(trait_def_id) {
             struct_span_err!(
                 tcx.sess,
index 380e256c9fc9a0d15e92cf627b68a040ca8fea48..fd92284effb322842c8af3ffb8309889fd6fc2de 100644 (file)
@@ -4,18 +4,18 @@
 
 use crate::check::FnCtxt;
 
-use rustc::hir::map::Map;
 use rustc::ty::adjustment::{Adjust, Adjustment, PointerCast};
 use rustc::ty::fold::{TypeFoldable, TypeFolder};
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc_data_structures::sync::Lrc;
 use rustc_hir as hir;
-use rustc_hir::def_id::{DefId, DefIdSet, DefIndex};
+use rustc_hir::def_id::DefIdSet;
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282;
 use rustc_infer::infer::InferCtxt;
 use rustc_span::symbol::sym;
 use rustc_span::Span;
+use rustc_trait_selection::opaque_types::InferCtxtExt;
 
 use std::mem;
 
@@ -61,7 +61,6 @@ pub fn resolve_type_vars_in_body(
         wbcx.visit_fru_field_types();
         wbcx.visit_opaque_types(body.value.span);
         wbcx.visit_coercion_casts();
-        wbcx.visit_free_region_map();
         wbcx.visit_user_provided_tys();
         wbcx.visit_user_provided_sigs();
         wbcx.visit_generator_interior_types();
@@ -108,11 +107,11 @@ fn new(
         body: &'tcx hir::Body<'tcx>,
         rustc_dump_user_substs: bool,
     ) -> WritebackCx<'cx, 'tcx> {
-        let owner = body.id().hir_id;
+        let owner = body.id().hir_id.owner;
 
         WritebackCx {
             fcx,
-            tables: ty::TypeckTables::empty(Some(DefId::local(owner.owner))),
+            tables: ty::TypeckTables::empty(Some(owner.to_def_id())),
             body,
             rustc_dump_user_substs,
         }
@@ -124,7 +123,7 @@ fn tcx(&self) -> TyCtxt<'tcx> {
 
     fn write_ty_to_tables(&mut self, hir_id: hir::HirId, ty: Ty<'tcx>) {
         debug!("write_ty_to_tables({:?}, {:?})", hir_id, ty);
-        assert!(!ty.needs_infer() && !ty.has_placeholders());
+        assert!(!ty.needs_infer() && !ty.has_placeholders() && !ty.has_free_regions());
         self.tables.node_types_mut().insert(hir_id, ty);
     }
 
@@ -243,9 +242,9 @@ fn fix_index_builtin_expr(&mut self, e: &hir::Expr<'_>) {
 // traffic in node-ids or update tables in the type context etc.
 
 impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> {
-    type Map = Map<'tcx>;
+    type Map = intravisit::ErasedMap<'tcx>;
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
         NestedVisitorMap::None
     }
 
@@ -326,9 +325,10 @@ fn visit_upvar_capture_map(&mut self) {
             let new_upvar_capture = match *upvar_capture {
                 ty::UpvarCapture::ByValue => ty::UpvarCapture::ByValue,
                 ty::UpvarCapture::ByRef(ref upvar_borrow) => {
-                    let r = upvar_borrow.region;
-                    let r = self.resolve(&r, &upvar_id.var_path.hir_id);
-                    ty::UpvarCapture::ByRef(ty::UpvarBorrow { kind: upvar_borrow.kind, region: r })
+                    ty::UpvarCapture::ByRef(ty::UpvarBorrow {
+                        kind: upvar_borrow.kind,
+                        region: self.tcx().lifetimes.re_erased,
+                    })
                 }
             };
             debug!("Upvar capture for {:?} resolved to {:?}", upvar_id, new_upvar_capture);
@@ -342,7 +342,7 @@ fn visit_closures(&mut self) {
         let common_local_id_root = fcx_tables.local_id_root.unwrap();
 
         for (&id, &origin) in fcx_tables.closure_kind_origins().iter() {
-            let hir_id = hir::HirId { owner: common_local_id_root.index, local_id: id };
+            let hir_id = hir::HirId { owner: common_local_id_root.expect_local(), local_id: id };
             self.tables.closure_kind_origins_mut().insert(hir_id, origin);
         }
     }
@@ -357,11 +357,6 @@ fn visit_coercion_casts(&mut self) {
         }
     }
 
-    fn visit_free_region_map(&mut self) {
-        self.tables.free_region_map = self.fcx.tables.borrow().free_region_map.clone();
-        debug_assert!(!self.tables.free_region_map.elements().any(|r| r.has_local_value()));
-    }
-
     fn visit_user_provided_tys(&mut self) {
         let fcx_tables = self.fcx.tables.borrow();
         debug_assert_eq!(fcx_tables.local_id_root, self.tables.local_id_root);
@@ -369,7 +364,7 @@ fn visit_user_provided_tys(&mut self) {
 
         let mut errors_buffer = Vec::new();
         for (&local_id, c_ty) in fcx_tables.user_provided_types().iter() {
-            let hir_id = hir::HirId { owner: common_local_id_root.index, local_id };
+            let hir_id = hir::HirId { owner: common_local_id_root.expect_local(), local_id };
 
             if cfg!(debug_assertions) && c_ty.has_local_value() {
                 span_bug!(hir_id.to_span(self.fcx.tcx), "writeback: `{:?}` is a local value", c_ty);
@@ -426,8 +421,7 @@ fn visit_generator_interior_types(&mut self) {
     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();
-            let instantiated_ty =
-                self.tcx().erase_regions(&self.resolve(&opaque_defn.concrete_ty, &hir_id));
+            let instantiated_ty = self.resolve(&opaque_defn.concrete_ty, &hir_id);
 
             debug_assert!(!instantiated_ty.has_escaping_bound_vars());
 
@@ -563,7 +557,7 @@ fn visit_liberated_fn_sigs(&mut self) {
         let common_local_id_root = fcx_tables.local_id_root.unwrap();
 
         for (&local_id, fn_sig) in fcx_tables.liberated_fn_sigs().iter() {
-            let hir_id = hir::HirId { owner: common_local_id_root.index, local_id };
+            let hir_id = hir::HirId { owner: common_local_id_root.expect_local(), local_id };
             let fn_sig = self.resolve(fn_sig, &hir_id);
             self.tables.liberated_fn_sigs_mut().insert(hir_id, fn_sig.clone());
         }
@@ -575,7 +569,7 @@ fn visit_fru_field_types(&mut self) {
         let common_local_id_root = fcx_tables.local_id_root.unwrap();
 
         for (&local_id, ftys) in fcx_tables.fru_field_types().iter() {
-            let hir_id = hir::HirId { owner: common_local_id_root.index, local_id };
+            let hir_id = hir::HirId { owner: common_local_id_root.expect_local(), local_id };
             let ftys = self.resolve(ftys, &hir_id);
             self.tables.fru_field_types_mut().insert(hir_id, ftys);
         }
@@ -603,23 +597,14 @@ fn to_span(&self, _: TyCtxt<'_>) -> Span {
     }
 }
 
-impl Locatable for DefIndex {
-    fn to_span(&self, tcx: TyCtxt<'_>) -> Span {
-        let hir_id = tcx.hir().def_index_to_hir_id(*self);
-        tcx.hir().span(hir_id)
-    }
-}
-
 impl Locatable for hir::HirId {
     fn to_span(&self, tcx: TyCtxt<'_>) -> Span {
         tcx.hir().span(*self)
     }
 }
 
-///////////////////////////////////////////////////////////////////////////
-// The Resolver. This is the type folding engine that detects
-// unresolved types and so forth.
-
+/// The Resolver. This is the type folding engine that detects
+/// unresolved types and so forth.
 struct Resolver<'cx, 'tcx> {
     tcx: TyCtxt<'tcx>,
     infcx: &'cx InferCtxt<'cx, 'tcx>,
@@ -652,7 +637,7 @@ fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
 
     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
         match self.infcx.fully_resolve(&t) {
-            Ok(t) => t,
+            Ok(t) => self.infcx.tcx.erase_regions(&t),
             Err(_) => {
                 debug!("Resolver::fold_ty: input type `{:?}` not fully resolvable", t);
                 self.report_error(t);
@@ -661,15 +646,14 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
         }
     }
 
-    // FIXME This should be carefully checked
-    // We could use `self.report_error` but it doesn't accept a ty::Region, right now.
     fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
-        self.infcx.fully_resolve(&r).unwrap_or(self.tcx.lifetimes.re_static)
+        debug_assert!(!r.is_late_bound(), "Should not be resolving bound region.");
+        self.tcx.lifetimes.re_erased
     }
 
     fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
         match self.infcx.fully_resolve(&ct) {
-            Ok(ct) => ct,
+            Ok(ct) => self.infcx.tcx.erase_regions(&ct),
             Err(_) => {
                 debug!("Resolver::fold_const: input const `{:?}` not fully resolvable", ct);
                 // FIXME: we'd like to use `self.report_error`, but it doesn't yet
index 3517e09133c280038b7f7394d1219be9c905f943..d0414af5b213866e85f833224d2a1e99cfa55074 100644 (file)
@@ -1,4 +1,3 @@
-use crate::lint;
 use rustc::ty::TyCtxt;
 use rustc_ast::ast;
 use rustc_data_structures::fx::FxHashMap;
@@ -7,6 +6,7 @@
 use rustc_hir::def_id::{DefId, DefIdSet, LOCAL_CRATE};
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_hir::print::visibility_qualified;
+use rustc_session::lint;
 use rustc_span::Span;
 
 pub fn check_crate(tcx: TyCtxt<'_>) {
index aa39a191b3df6e3ee8ac3276c70c4d0e790273c1..e24d9bebf657fd730cee09280c26499a0b679507 100644 (file)
 use rustc_hir::ItemKind;
 use rustc_infer::infer;
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
-use rustc_infer::infer::{SuppressRegionErrors, TyCtxtInferExt};
-use rustc_infer::traits::misc::{can_type_implement_copy, CopyImplementationError};
-use rustc_infer::traits::predicate_for_trait_def;
-use rustc_infer::traits::{self, ObligationCause, TraitEngine};
+use rustc_infer::infer::{RegionckMode, TyCtxtInferExt};
+use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
+use rustc_trait_selection::traits::misc::{can_type_implement_copy, CopyImplementationError};
+use rustc_trait_selection::traits::predicate_for_trait_def;
+use rustc_trait_selection::traits::{self, ObligationCause, TraitEngine, TraitEngineExt};
 
 pub fn check_trait(tcx: TyCtxt<'_>, trait_def_id: DefId) {
     let lang_items = tcx.lang_items();
@@ -306,7 +307,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: DefId) {
                             impl_did,
                             &region_scope_tree,
                             &outlives_env,
-                            SuppressRegionErrors::default(),
+                            RegionckMode::default(),
                         );
                     }
                 }
@@ -322,7 +323,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: DefId) {
     }
 }
 
-pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUnsizedInfo {
+pub fn coerce_unsized_info(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUnsizedInfo {
     debug!("compute_coerce_unsized_info(impl_did={:?})", impl_did);
     let coerce_unsized_trait = tcx.lang_items().coerce_unsized_trait().unwrap();
 
@@ -567,7 +568,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn
             impl_did,
             &region_scope_tree,
             &outlives_env,
-            SuppressRegionErrors::default(),
+            RegionckMode::default(),
         );
 
         CoerceUnsizedInfo { custom_kind: kind }
index fcded27463e92d5860107066e8a77c347c78df9a..7513759c76b015ffe8675b757592cb26655b93a8 100644 (file)
@@ -3,7 +3,7 @@
 use rustc_hir as hir;
 use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
-use rustc_infer::traits::{self, SkipLeakCheck};
+use rustc_trait_selection::traits::{self, SkipLeakCheck};
 
 pub fn crate_inherent_impls_overlap_check(tcx: TyCtxt<'_>, crate_num: CrateNum) {
     assert_eq!(crate_num, LOCAL_CRATE);
@@ -23,14 +23,12 @@ fn impls_have_common_items(&self, impl1: DefId, impl2: DefId) -> bool {
         let impl_items2 = self.tcx.associated_items(impl2);
 
         for item1 in impl_items1.in_definition_order() {
-            let collision = impl_items2
-                .filter_by_name_unhygienic(item1.ident.name)
-                .find(|item2| {
-                    // Symbols and namespace match, compare hygienically.
-                    item1.kind.namespace() == item2.kind.namespace()
-                        && item1.ident.modern() == item2.ident.modern()
-                })
-                .is_some();
+            let collision = impl_items2.filter_by_name_unhygienic(item1.ident.name).any(|item2| {
+                // Symbols and namespace match, compare hygienically.
+                item1.kind.namespace() == item2.kind.namespace()
+                    && item1.ident.normalize_to_macros_2_0()
+                        == item2.ident.normalize_to_macros_2_0()
+            });
 
             if collision {
                 return true;
@@ -53,11 +51,12 @@ fn check_for_common_items_in_impls(
             let collision = impl_items2.filter_by_name_unhygienic(item1.ident.name).find(|item2| {
                 // Symbols and namespace match, compare hygienically.
                 item1.kind.namespace() == item2.kind.namespace()
-                    && item1.ident.modern() == item2.ident.modern()
+                    && item1.ident.normalize_to_macros_2_0()
+                        == item2.ident.normalize_to_macros_2_0()
             });
 
             if let Some(item2) = collision {
-                let name = item1.ident.modern();
+                let name = item1.ident.normalize_to_macros_2_0();
                 let mut err = struct_span_err!(
                     self.tcx.sess,
                     self.tcx.span_of_impl(item1.def_id).unwrap(),
index d24ee5f156bcf2d14383e32d77e65a347e214784..27b2c19499ccd61f89ba71aca9627dccafcea8cc 100644 (file)
@@ -9,8 +9,8 @@
 use rustc::ty::{self, TyCtxt, TypeFoldable};
 use rustc_errors::struct_span_err;
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
-use rustc_infer::traits;
 use rustc_span::Span;
+use rustc_trait_selection::traits;
 
 mod builtin;
 mod inherent_impls;
@@ -76,6 +76,22 @@ fn enforce_trait_manually_implementable(tcx: TyCtxt<'_>, impl_def_id: DefId, tra
         return;
     }
 
+    if let ty::trait_def::TraitSpecializationKind::AlwaysApplicable =
+        tcx.trait_def(trait_def_id).specialization_kind
+    {
+        if !tcx.features().specialization && !tcx.features().min_specialization {
+            let span = impl_header_span(tcx, impl_def_id);
+            tcx.sess
+                .struct_span_err(
+                    span,
+                    "implementing `rustc_specialization_trait` traits is unstable",
+                )
+                .help("add `#![feature(min_specialization)]` to the crate attributes to enable")
+                .emit();
+            return;
+        }
+    }
+
     let trait_name = if did == li.fn_trait() {
         "Fn"
     } else if did == li.fn_mut_trait() {
index a8e5a0ddf26869f341c63d8269a8e04deaf431be..fc77aad8688c69e3c44147db45af5e2f7b4d9e58 100644 (file)
@@ -6,7 +6,7 @@
 use rustc_hir as hir;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_infer::infer::TyCtxtInferExt;
-use rustc_infer::traits;
+use rustc_trait_selection::traits;
 
 pub fn check(tcx: TyCtxt<'_>) {
     let mut orphan = OrphanChecker { tcx };
@@ -174,7 +174,7 @@ fn visit_item(&mut self, item: &hir::Item<'_>) {
             // impl !Send for (A, B) { }
             // ```
             //
-            // This final impl is legal according to the orpan
+            // This final impl is legal according to the orphan
             // rules, but it invalidates the reasoning from
             // `two_foos` above.
             debug!(
index a6044217403634c08f818c63f11e9d9f5e9ca32e..3b25f67aacc63b14772537ba640c708f0f1755df 100644 (file)
@@ -69,11 +69,11 @@ fn check_unsafety_coherence(
                     .emit();
                 }
 
-                (_, _, Unsafety::Unsafe, hir::ImplPolarity::Negative) => {
+                (_, _, Unsafety::Unsafe, hir::ImplPolarity::Negative(_)) => {
                     // Reported in AST validation
                     self.tcx.sess.delay_span_bug(item.span, "unsafe negative impl");
                 }
-                (_, _, Unsafety::Normal, hir::ImplPolarity::Negative)
+                (_, _, Unsafety::Normal, hir::ImplPolarity::Negative(_))
                 | (Unsafety::Unsafe, _, Unsafety::Unsafe, hir::ImplPolarity::Positive)
                 | (Unsafety::Normal, Some(_), Unsafety::Unsafe, hir::ImplPolarity::Positive)
                 | (Unsafety::Normal, None, Unsafety::Normal, _) => {
index 2dad3d1d6d708ebd7df19d9def195df8c39767cf..7145b948f2f5a96159222a942ca280c39853bb7f 100644 (file)
 use crate::astconv::{AstConv, Bounds, SizedByDefault};
 use crate::check::intrinsic::intrinsic_operation_unsafety;
 use crate::constrained_generic_params as cgp;
-use crate::lint;
 use crate::middle::lang_items;
 use crate::middle::resolve_lifetime as rl;
 use rustc::hir::map::blocks::FnLikeNode;
 use rustc::hir::map::Map;
 use rustc::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
 use rustc::mir::mono::Linkage;
-use rustc::session::parse::feature_err;
 use rustc::ty::query::Providers;
 use rustc::ty::subst::{InternalSubsts, Subst};
 use rustc::ty::util::Discr;
@@ -42,6 +40,8 @@
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::{GenericParamKind, Node, Unsafety};
+use rustc_session::lint;
+use rustc_session::parse::feature_err;
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::{Span, DUMMY_SP};
 use rustc_target::spec::abi;
@@ -105,9 +105,9 @@ pub struct ItemCtxt<'tcx> {
 crate struct PlaceholderHirTyCollector(crate Vec<Span>);
 
 impl<'v> Visitor<'v> for PlaceholderHirTyCollector {
-    type Map = Map<'v>;
+    type Map = intravisit::ErasedMap<'v>;
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
         NestedVisitorMap::None
     }
     fn visit_ty(&mut self, t: &'v hir::Ty<'v>) {
@@ -151,7 +151,7 @@ struct CollectItemTypesVisitor<'tcx> {
         .unwrap_or(&"ParamName");
 
     let mut sugg: Vec<_> =
-        placeholder_types.iter().map(|sp| (*sp, type_name.to_string())).collect();
+        placeholder_types.iter().map(|sp| (*sp, (*type_name).to_string())).collect();
     if generics.is_empty() {
         sugg.push((span, format!("<{}>", type_name)));
     } else if let Some(arg) = generics.iter().find(|arg| match arg.name {
@@ -160,7 +160,7 @@ struct CollectItemTypesVisitor<'tcx> {
     }) {
         // Account for `_` already present in cases like `struct S<_>(_);` and suggest
         // `struct S<T>(T);` instead of `struct S<_, T>(T);`.
-        sugg.push((arg.span, type_name.to_string()));
+        sugg.push((arg.span, (*type_name).to_string()));
     } else {
         sugg.push((
             generics.iter().last().unwrap().span.shrink_to_hi(),
@@ -201,8 +201,8 @@ fn reject_placeholder_type_signatures_in_item(tcx: TyCtxt<'tcx>, item: &'tcx hir
 impl Visitor<'tcx> for CollectItemTypesVisitor<'tcx> {
     type Map = Map<'tcx>;
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
-        NestedVisitorMap::OnlyBodies(&self.tcx.hir())
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::OnlyBodies(self.tcx.hir())
     }
 
     fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
@@ -715,7 +715,7 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::HirId) {
     tcx.generics_of(def_id);
 
     match trait_item.kind {
-        hir::TraitItemKind::Method(..) => {
+        hir::TraitItemKind::Fn(..) => {
             tcx.type_of(def_id);
             tcx.fn_sig(def_id);
         }
@@ -745,7 +745,7 @@ fn convert_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::HirId) {
     tcx.predicates_of(def_id);
     let impl_item = tcx.hir().expect_impl_item(impl_item_id);
     match impl_item.kind {
-        hir::ImplItemKind::Method(..) => {
+        hir::ImplItemKind::Fn(..) => {
             tcx.fn_sig(def_id);
         }
         hir::ImplItemKind::TyAlias(_) | hir::ImplItemKind::OpaqueTy(_) => {
@@ -828,7 +828,7 @@ fn convert_variant(
         .iter()
         .map(|f| {
             let fid = tcx.hir().local_def_id(f.hir_id);
-            let dup_span = seen_fields.get(&f.ident.modern()).cloned();
+            let dup_span = seen_fields.get(&f.ident.normalize_to_macros_2_0()).cloned();
             if let Some(prev_span) = dup_span {
                 struct_span_err!(
                     tcx.sess,
@@ -841,7 +841,7 @@ fn convert_variant(
                 .span_label(prev_span, format!("`{}` first declared here", f.ident))
                 .emit();
             } else {
-                seen_fields.insert(f.ident.modern(), f.span);
+                seen_fields.insert(f.ident.normalize_to_macros_2_0(), f.span);
             }
 
             ty::FieldDef {
@@ -1032,8 +1032,23 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::TraitDef {
     }
 
     let is_marker = tcx.has_attr(def_id, sym::marker);
+    let spec_kind = if tcx.has_attr(def_id, sym::rustc_unsafe_specialization_marker) {
+        ty::trait_def::TraitSpecializationKind::Marker
+    } else if tcx.has_attr(def_id, sym::rustc_specialization_trait) {
+        ty::trait_def::TraitSpecializationKind::AlwaysApplicable
+    } else {
+        ty::trait_def::TraitSpecializationKind::None
+    };
     let def_path_hash = tcx.def_path_hash(def_id);
-    let def = ty::TraitDef::new(def_id, unsafety, paren_sugar, is_auto, is_marker, def_path_hash);
+    let def = ty::TraitDef::new(
+        def_id,
+        unsafety,
+        paren_sugar,
+        is_auto,
+        is_marker,
+        spec_kind,
+        def_path_hash,
+    );
     tcx.arena.alloc(def)
 }
 
@@ -1045,9 +1060,9 @@ struct LateBoundRegionsDetector<'tcx> {
     }
 
     impl Visitor<'tcx> for LateBoundRegionsDetector<'tcx> {
-        type Map = Map<'tcx>;
+        type Map = intravisit::ErasedMap<'tcx>;
 
-        fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
+        fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
             NestedVisitorMap::None
         }
 
@@ -1121,13 +1136,13 @@ fn has_late_bound_regions<'tcx>(
 
     match node {
         Node::TraitItem(item) => match item.kind {
-            hir::TraitItemKind::Method(ref sig, _) => {
+            hir::TraitItemKind::Fn(ref sig, _) => {
                 has_late_bound_regions(tcx, &item.generics, &sig.decl)
             }
             _ => None,
         },
         Node::ImplItem(item) => match item.kind {
-            hir::ImplItemKind::Method(ref sig, _) => {
+            hir::ImplItemKind::Fn(ref sig, _) => {
                 has_late_bound_regions(tcx, &item.generics, &sig.decl)
             }
             _ => None,
@@ -1395,7 +1410,7 @@ fn are_suggestable_generic_args(generic_args: &[hir::GenericArg<'_>]) -> bool {
         .any(is_suggestable_infer_ty)
 }
 
-/// Whether `ty` is a type with `_` placeholders that can be infered. Used in diagnostics only to
+/// Whether `ty` is a type with `_` placeholders that can be inferred. Used in diagnostics only to
 /// use inference to provide suggestions for the appropriate type if possible.
 fn is_suggestable_infer_ty(ty: &hir::Ty<'_>) -> bool {
     use hir::TyKind::*;
@@ -1437,12 +1452,12 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
 
     match tcx.hir().get(hir_id) {
         TraitItem(hir::TraitItem {
-            kind: TraitItemKind::Method(sig, TraitMethod::Provided(_)),
+            kind: TraitItemKind::Fn(sig, TraitFn::Provided(_)),
             ident,
             generics,
             ..
         })
-        | ImplItem(hir::ImplItem { kind: ImplItemKind::Method(sig, _), ident, generics, .. })
+        | ImplItem(hir::ImplItem { kind: ImplItemKind::Fn(sig, _), ident, generics, .. })
         | Item(hir::Item { kind: ItemKind::Fn(sig, generics, _), ident, .. }) => {
             match get_infer_ret_ty(&sig.decl.output) {
                 Some(ty) => {
@@ -1474,7 +1489,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
         }
 
         TraitItem(hir::TraitItem {
-            kind: TraitItemKind::Method(FnSig { header, decl }, _),
+            kind: TraitItemKind::Fn(FnSig { header, decl }, _),
             ident,
             generics,
             ..
@@ -1548,7 +1563,7 @@ fn impl_polarity(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ImplPolarity {
     let is_rustc_reservation = tcx.has_attr(def_id, sym::rustc_reservation_impl);
     let item = tcx.hir().expect_item(hir_id);
     match &item.kind {
-        hir::ItemKind::Impl { polarity: hir::ImplPolarity::Negative, .. } => {
+        hir::ItemKind::Impl { polarity: hir::ImplPolarity::Negative(_), .. } => {
             if is_rustc_reservation {
                 tcx.sess.span_err(item.span, "reservation impls can't be negative");
             }
@@ -2341,8 +2356,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
             codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE;
         } else if attr.check_name(sym::rustc_std_internal_symbol) {
             codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL;
-        } else if attr.check_name(sym::no_debug) {
-            codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_DEBUG;
         } else if attr.check_name(sym::used) {
             codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED;
         } else if attr.check_name(sym::thread_local) {
index ec87112b7a8e076b47e13b838f7988ffc18ad734..41c205bc11b3594de9f7ea67f9cc117d6224e50e 100644 (file)
@@ -1,5 +1,4 @@
 use rustc::hir::map::Map;
-use rustc::session::parse::feature_err;
 use rustc::ty::subst::{GenericArgKind, InternalSubsts, Subst};
 use rustc::ty::util::IntTypeExt;
 use rustc::ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable};
 use rustc_hir::intravisit;
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::Node;
-use rustc_infer::traits;
+use rustc_session::parse::feature_err;
 use rustc_span::symbol::{sym, Ident};
 use rustc_span::{Span, DUMMY_SP};
+use rustc_trait_selection::traits;
 
 use super::ItemCtxt;
 use super::{bad_placeholder_type, is_suggestable_infer_ty};
@@ -27,7 +27,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
 
     match tcx.hir().get(hir_id) {
         Node::TraitItem(item) => match item.kind {
-            TraitItemKind::Method(..) => {
+            TraitItemKind::Fn(..) => {
                 let substs = InternalSubsts::identity_for_item(tcx, def_id);
                 tcx.mk_fn_def(def_id, substs)
             }
@@ -47,7 +47,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
         },
 
         Node::ImplItem(item) => match item.kind {
-            ImplItemKind::Method(..) => {
+            ImplItemKind::Fn(..) => {
                 let substs = InternalSubsts::identity_for_item(tcx, def_id);
                 tcx.mk_fn_def(def_id, substs)
             }
@@ -529,8 +529,8 @@ fn check(&mut self, def_id: DefId) {
     impl<'tcx> intravisit::Visitor<'tcx> for ConstraintLocator<'tcx> {
         type Map = Map<'tcx>;
 
-        fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> {
-            intravisit::NestedVisitorMap::All(&self.tcx.hir())
+        fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
+            intravisit::NestedVisitorMap::All(self.tcx.hir())
         }
         fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) {
             if let hir::ExprKind::Closure(..) = ex.kind {
index 9b187d461cdeb05e2a4dde7d14de57fd175d1bc8..b16aa6ff3b2e4c41bc0473b04e8f452f388dc02d 100644 (file)
@@ -36,7 +36,7 @@ pub fn parameters_for_impl<'tcx>(
     vec.into_iter().collect()
 }
 
-/// If `include_projections` is false, returns the list of parameters that are
+/// If `include_nonconstraining` is false, returns the list of parameters that are
 /// constrained by `t` - i.e., the value of each parameter in the list is
 /// uniquely determined by `t` (see RFC 447). If it is true, return the list
 /// of parameters whose values are needed in order to constrain `ty` - these
@@ -79,10 +79,18 @@ fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
     }
 
     fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> bool {
-        if let ty::ConstKind::Param(data) = c.val {
-            self.parameters.push(Parameter::from(data));
+        match c.val {
+            ty::ConstKind::Unevaluated(..) if !self.include_nonconstraining => {
+                // Constant expressions are not injective
+                return c.ty.visit_with(self);
+            }
+            ty::ConstKind::Param(data) => {
+                self.parameters.push(Parameter::from(data));
+            }
+            _ => {}
         }
-        false
+
+        c.super_visit_with(self)
     }
 }
 
index 6666b1699943e71dc50f7b2da226e0ec5bd022ba..a45d8ce6823a3ddae3722dc9c309f0fb66af1b5a 100644 (file)
@@ -519,7 +519,7 @@ fn walk_captures(&mut self, closure_expr: &hir::Expr<'_>, fn_decl_span: Span) {
             for &var_id in upvars.keys() {
                 let upvar_id = ty::UpvarId {
                     var_path: ty::UpvarPath { hir_id: var_id },
-                    closure_expr_id: closure_def_id.to_local(),
+                    closure_expr_id: closure_def_id.expect_local(),
                 };
                 let upvar_capture = self.mc.tables.upvar_capture(upvar_id);
                 let captured_place = return_if_err!(self.cat_captured_var(
index 0a765a1f9c93cb58075b03693a7661384f6cb04d..42cb4fcf85dcb9584d11c76b1b18d2bad109925d 100644 (file)
@@ -9,6 +9,8 @@
 //! fixed, but for the moment it's easier to do these checks early.
 
 use crate::constrained_generic_params as cgp;
+use min_specialization::check_min_specialization;
+
 use rustc::ty::query::Providers;
 use rustc::ty::{self, TyCtxt, TypeFoldable};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
+use rustc_span::Span;
+
 use std::collections::hash_map::Entry::{Occupied, Vacant};
 
-use rustc_span::Span;
+mod min_specialization;
 
 /// Checks that all the type/lifetime parameters on an impl also
 /// appear in the trait ref or self type (or are constrained by a
@@ -60,7 +64,9 @@ pub fn impl_wf_check(tcx: TyCtxt<'_>) {
 }
 
 fn check_mod_impl_wf(tcx: TyCtxt<'_>, module_def_id: DefId) {
-    tcx.hir().visit_item_likes_in_module(module_def_id, &mut ImplWfCheck { tcx });
+    let min_specialization = tcx.features().min_specialization;
+    tcx.hir()
+        .visit_item_likes_in_module(module_def_id, &mut ImplWfCheck { tcx, min_specialization });
 }
 
 pub fn provide(providers: &mut Providers<'_>) {
@@ -69,6 +75,7 @@ pub fn provide(providers: &mut Providers<'_>) {
 
 struct ImplWfCheck<'tcx> {
     tcx: TyCtxt<'tcx>,
+    min_specialization: bool,
 }
 
 impl ItemLikeVisitor<'tcx> for ImplWfCheck<'tcx> {
@@ -77,6 +84,9 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
             let impl_def_id = self.tcx.hir().local_def_id(item.hir_id);
             enforce_impl_params_are_constrained(self.tcx, impl_def_id, items);
             enforce_impl_items_are_distinct(self.tcx, items);
+            if self.min_specialization {
+                check_min_specialization(self.tcx, impl_def_id, item.span);
+            }
         }
     }
 
@@ -227,7 +237,7 @@ fn enforce_impl_items_are_distinct(tcx: TyCtxt<'_>, impl_item_refs: &[hir::ImplI
             hir::ImplItemKind::TyAlias(_) => &mut seen_type_items,
             _ => &mut seen_value_items,
         };
-        match seen_items.entry(impl_item.ident.modern()) {
+        match seen_items.entry(impl_item.ident.normalize_to_macros_2_0()) {
             Occupied(entry) => {
                 let mut err = struct_span_err!(
                     tcx.sess,
diff --git a/src/librustc_typeck/impl_wf_check/min_specialization.rs b/src/librustc_typeck/impl_wf_check/min_specialization.rs
new file mode 100644 (file)
index 0000000..cae8837
--- /dev/null
@@ -0,0 +1,409 @@
+//! # Minimal Specialization
+//!
+//! This module contains the checks for sound specialization used when the
+//! `min_specialization` feature is enabled. This requires that the impl is
+//! *always applicable*.
+//!
+//! If `impl1` specializes `impl2` then `impl1` is always applicable if we know
+//! that all the bounds of `impl2` are satisfied, and all of the bounds of
+//! `impl1` are satisfied for some choice of lifetimes then we know that
+//! `impl1` applies for any choice of lifetimes.
+//!
+//! ## Basic approach
+//!
+//! To enforce this requirement on specializations we take the following
+//! approach:
+//!
+//! 1. Match up the substs for `impl2` so that the implemented trait and
+//!    self-type match those for `impl1`.
+//! 2. Check for any direct use of `'static` in the substs of `impl2`.
+//! 3. Check that all of the generic parameters of `impl1` occur at most once
+//!    in the *unconstrained* substs for `impl2`. A parameter is constrained if
+//!    its value is completely determined by an associated type projection
+//!    predicate.
+//! 4. Check that all predicates on `impl1` either exist on `impl2` (after
+//!    matching substs), or are well-formed predicates for the trait's type
+//!    arguments.
+//!
+//! ## Example
+//!
+//! Suppose we have the following always applicable impl:
+//!
+//! ```rust
+//! impl<T> SpecExtend<T> for std::vec::IntoIter<T> { /* specialized impl */ }
+//! impl<T, I: Iterator<Item=T>> SpecExtend<T> for I { /* default impl */ }
+//! ```
+//!
+//! We get that the subst for `impl2` are `[T, std::vec::IntoIter<T>]`. `T` is
+//! constrained to be `<I as Iterator>::Item`, so we check only
+//! `std::vec::IntoIter<T>` for repeated parameters, which it doesn't have. The
+//! predicates of `impl1` are only `T: Sized`, which is also a predicate of
+//! `impl2`. So this specialization is sound.
+//!
+//! ## Extensions
+//!
+//! Unfortunately not all specializations in the standard library are allowed
+//! by this. So there are two extensions to these rules that allow specializing
+//! on some traits: that is, using them as bounds on the specializing impl,
+//! even when they don't occur in the base impl.
+//!
+//! ### rustc_specialization_trait
+//!
+//! If a trait is always applicable, then it's sound to specialize on it. We
+//! check trait is always applicable in the same way as impls, except that step
+//! 4 is now "all predicates on `impl1` are always applicable". We require that
+//! `specialization` or `min_specialization` is enabled to implement these
+//! traits.
+//!
+//! ### rustc_unsafe_specialization_marker
+//!
+//! There are also some specialization on traits with no methods, including the
+//! stable `FusedIterator` trait. We allow marking marker traits with an
+//! unstable attribute that means we ignore them in point 3 of the checks
+//! above. This is unsound, in the sense that the specialized impl may be used
+//! when it doesn't apply, but we allow it in the short term since it can't
+//! cause use after frees with purely safe code in the same way as specializing
+//! on traits with methods can.
+
+use crate::constrained_generic_params as cgp;
+
+use rustc::middle::region::ScopeTree;
+use rustc::ty::subst::{GenericArg, InternalSubsts, SubstsRef};
+use rustc::ty::trait_def::TraitSpecializationKind;
+use rustc::ty::{self, InstantiatedPredicates, TyCtxt, TypeFoldable};
+use rustc_data_structures::fx::FxHashSet;
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
+use rustc_infer::infer::outlives::env::OutlivesEnvironment;
+use rustc_infer::infer::{InferCtxt, RegionckMode, TyCtxtInferExt};
+use rustc_infer::traits::specialization_graph::Node;
+use rustc_span::Span;
+use rustc_trait_selection::traits::{self, translate_substs, wf};
+
+pub(super) fn check_min_specialization(tcx: TyCtxt<'_>, impl_def_id: DefId, span: Span) {
+    if let Some(node) = parent_specialization_node(tcx, impl_def_id) {
+        tcx.infer_ctxt().enter(|infcx| {
+            check_always_applicable(&infcx, impl_def_id, node, span);
+        });
+    }
+}
+
+fn parent_specialization_node(tcx: TyCtxt<'_>, impl1_def_id: DefId) -> Option<Node> {
+    let trait_ref = tcx.impl_trait_ref(impl1_def_id)?;
+    let trait_def = tcx.trait_def(trait_ref.def_id);
+
+    let impl2_node = trait_def.ancestors(tcx, impl1_def_id).ok()?.nth(1)?;
+
+    let always_applicable_trait =
+        matches!(trait_def.specialization_kind, TraitSpecializationKind::AlwaysApplicable);
+    if impl2_node.is_from_trait() && !always_applicable_trait {
+        // Implementing a normal trait isn't a specialization.
+        return None;
+    }
+    Some(impl2_node)
+}
+
+/// Check that `impl1` is a sound specialization
+fn check_always_applicable(
+    infcx: &InferCtxt<'_, '_>,
+    impl1_def_id: DefId,
+    impl2_node: Node,
+    span: Span,
+) {
+    if let Some((impl1_substs, impl2_substs)) =
+        get_impl_substs(infcx, impl1_def_id, impl2_node, span)
+    {
+        let impl2_def_id = impl2_node.def_id();
+        debug!(
+            "check_always_applicable(\nimpl1_def_id={:?},\nimpl2_def_id={:?},\nimpl2_substs={:?}\n)",
+            impl1_def_id, impl2_def_id, impl2_substs
+        );
+
+        let tcx = infcx.tcx;
+
+        let parent_substs = if impl2_node.is_from_trait() {
+            impl2_substs.to_vec()
+        } else {
+            unconstrained_parent_impl_substs(tcx, impl2_def_id, impl2_substs)
+        };
+
+        check_static_lifetimes(tcx, &parent_substs, span);
+        check_duplicate_params(tcx, impl1_substs, &parent_substs, span);
+
+        check_predicates(infcx, impl1_def_id, impl1_substs, impl2_node, impl2_substs, span);
+    }
+}
+
+/// Given a specializing impl `impl1`, and the base impl `impl2`, returns two
+/// substitutions `(S1, S2)` that equate their trait references. The returned
+/// types are expressed in terms of the generics of `impl1`.
+///
+/// Example
+///
+/// impl<A, B> Foo<A> for B { /* impl2 */ }
+/// impl<C> Foo<Vec<C>> for C { /* impl1 */ }
+///
+/// Would return `S1 = [C]` and `S2 = [Vec<C>, C]`.
+fn get_impl_substs<'tcx>(
+    infcx: &InferCtxt<'_, 'tcx>,
+    impl1_def_id: DefId,
+    impl2_node: Node,
+    span: Span,
+) -> Option<(SubstsRef<'tcx>, SubstsRef<'tcx>)> {
+    let tcx = infcx.tcx;
+    let param_env = tcx.param_env(impl1_def_id);
+
+    let impl1_substs = InternalSubsts::identity_for_item(tcx, impl1_def_id);
+    let impl2_substs = translate_substs(infcx, param_env, impl1_def_id, impl1_substs, impl2_node);
+
+    // Conservatively use an empty `ParamEnv`.
+    let outlives_env = OutlivesEnvironment::new(ty::ParamEnv::empty());
+    infcx.resolve_regions_and_report_errors(
+        impl1_def_id,
+        &ScopeTree::default(),
+        &outlives_env,
+        RegionckMode::default(),
+    );
+    let impl2_substs = match infcx.fully_resolve(&impl2_substs) {
+        Ok(s) => s,
+        Err(_) => {
+            tcx.sess.struct_span_err(span, "could not resolve substs on overridden impl").emit();
+            return None;
+        }
+    };
+    Some((impl1_substs, impl2_substs))
+}
+
+/// Returns a list of all of the unconstrained subst of the given impl.
+///
+/// For example given the impl:
+///
+/// impl<'a, T, I> ... where &'a I: IntoIterator<Item=&'a T>
+///
+/// This would return the substs corresponding to `['a, I]`, because knowing
+/// `'a` and `I` determines the value of `T`.
+fn unconstrained_parent_impl_substs<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    impl_def_id: DefId,
+    impl_substs: SubstsRef<'tcx>,
+) -> Vec<GenericArg<'tcx>> {
+    let impl_generic_predicates = tcx.predicates_of(impl_def_id);
+    let mut unconstrained_parameters = FxHashSet::default();
+    let mut constrained_params = FxHashSet::default();
+    let impl_trait_ref = tcx.impl_trait_ref(impl_def_id);
+
+    // Unfortunately the functions in `constrained_generic_parameters` don't do
+    // what we want here. We want only a list of constrained parameters while
+    // the functions in `cgp` add the constrained parameters to a list of
+    // unconstrained parameters.
+    for (predicate, _) in impl_generic_predicates.predicates.iter() {
+        if let ty::Predicate::Projection(proj) = predicate {
+            let projection_ty = proj.skip_binder().projection_ty;
+            let projected_ty = proj.skip_binder().ty;
+
+            let unbound_trait_ref = projection_ty.trait_ref(tcx);
+            if Some(unbound_trait_ref) == impl_trait_ref {
+                continue;
+            }
+
+            unconstrained_parameters.extend(cgp::parameters_for(&projection_ty, true));
+
+            for param in cgp::parameters_for(&projected_ty, false) {
+                if !unconstrained_parameters.contains(&param) {
+                    constrained_params.insert(param.0);
+                }
+            }
+
+            unconstrained_parameters.extend(cgp::parameters_for(&projected_ty, true));
+        }
+    }
+
+    impl_substs
+        .iter()
+        .enumerate()
+        .filter(|&(idx, _)| !constrained_params.contains(&(idx as u32)))
+        .map(|(_, arg)| *arg)
+        .collect()
+}
+
+/// Check that parameters of the derived impl don't occur more than once in the
+/// equated substs of the base impl.
+///
+/// For example forbid the following:
+///
+/// impl<A> Tr for A { }
+/// impl<B> Tr for (B, B) { }
+///
+/// Note that only consider the unconstrained parameters of the base impl:
+///
+/// impl<S, I: IntoIterator<Item = S>> Tr<S> for I { }
+/// impl<T> Tr<T> for Vec<T> { }
+///
+/// The substs for the parent impl here are `[T, Vec<T>]`, which repeats `T`,
+/// but `S` is constrained in the parent impl, so `parent_substs` is only
+/// `[Vec<T>]`. This means we allow this impl.
+fn check_duplicate_params<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    impl1_substs: SubstsRef<'tcx>,
+    parent_substs: &Vec<GenericArg<'tcx>>,
+    span: Span,
+) {
+    let mut base_params = cgp::parameters_for(parent_substs, true);
+    base_params.sort_by_key(|param| param.0);
+    if let (_, [duplicate, ..]) = base_params.partition_dedup() {
+        let param = impl1_substs[duplicate.0 as usize];
+        tcx.sess
+            .struct_span_err(span, &format!("specializing impl repeats parameter `{}`", param))
+            .emit();
+    }
+}
+
+/// Check that `'static` lifetimes are not introduced by the specializing impl.
+///
+/// For example forbid the following:
+///
+/// impl<A> Tr for A { }
+/// impl Tr for &'static i32 { }
+fn check_static_lifetimes<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    parent_substs: &Vec<GenericArg<'tcx>>,
+    span: Span,
+) {
+    if tcx.any_free_region_meets(parent_substs, |r| *r == ty::ReStatic) {
+        tcx.sess.struct_span_err(span, &format!("cannot specialize on `'static` lifetime")).emit();
+    }
+}
+
+/// Check whether predicates on the specializing impl (`impl1`) are allowed.
+///
+/// Each predicate `P` must be:
+///
+/// * global (not reference any parameters)
+/// * `T: Tr` predicate where `Tr` is an always-applicable trait
+/// * on the base `impl impl2`
+///     * Currently this check is done using syntactic equality, which is
+///       conservative but generally sufficient.
+/// * a well-formed predicate of a type argument of the trait being implemented,
+///   including the `Self`-type.
+fn check_predicates<'tcx>(
+    infcx: &InferCtxt<'_, 'tcx>,
+    impl1_def_id: DefId,
+    impl1_substs: SubstsRef<'tcx>,
+    impl2_node: Node,
+    impl2_substs: SubstsRef<'tcx>,
+    span: Span,
+) {
+    let tcx = infcx.tcx;
+    let impl1_predicates = tcx.predicates_of(impl1_def_id).instantiate(tcx, impl1_substs);
+    let mut impl2_predicates = if impl2_node.is_from_trait() {
+        // Always applicable traits have to be always applicable without any
+        // assumptions.
+        InstantiatedPredicates::empty()
+    } else {
+        tcx.predicates_of(impl2_node.def_id()).instantiate(tcx, impl2_substs)
+    };
+    debug!(
+        "check_always_applicable(\nimpl1_predicates={:?},\nimpl2_predicates={:?}\n)",
+        impl1_predicates, impl2_predicates,
+    );
+
+    // Since impls of always applicable traits don't get to assume anything, we
+    // can also assume their supertraits apply.
+    //
+    // For example, we allow:
+    //
+    // #[rustc_specialization_trait]
+    // trait AlwaysApplicable: Debug { }
+    //
+    // impl<T> Tr for T { }
+    // impl<T: AlwaysApplicable> Tr for T { }
+    //
+    // Specializing on `AlwaysApplicable` allows also specializing on `Debug`
+    // which is sound because we forbid impls like the following
+    //
+    // impl<D: Debug> AlwaysApplicable for D { }
+    let always_applicable_traits: Vec<_> = impl1_predicates
+        .predicates
+        .iter()
+        .filter(|predicate| {
+            matches!(
+                trait_predicate_kind(tcx, predicate),
+                Some(TraitSpecializationKind::AlwaysApplicable)
+            )
+        })
+        .copied()
+        .collect();
+
+    // Include the well-formed predicates of the type parameters of the impl.
+    for ty in tcx.impl_trait_ref(impl1_def_id).unwrap().substs.types() {
+        if let Some(obligations) = wf::obligations(
+            infcx,
+            tcx.param_env(impl1_def_id),
+            tcx.hir().as_local_hir_id(impl1_def_id).unwrap(),
+            ty,
+            span,
+        ) {
+            impl2_predicates
+                .predicates
+                .extend(obligations.into_iter().map(|obligation| obligation.predicate))
+        }
+    }
+    impl2_predicates.predicates.extend(traits::elaborate_predicates(tcx, always_applicable_traits));
+
+    for predicate in impl1_predicates.predicates {
+        if !impl2_predicates.predicates.contains(&predicate) {
+            check_specialization_on(tcx, &predicate, span)
+        }
+    }
+}
+
+fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: &ty::Predicate<'tcx>, span: Span) {
+    debug!("can_specialize_on(predicate = {:?})", predicate);
+    match predicate {
+        // Global predicates are either always true or always false, so we
+        // are fine to specialize on.
+        _ if predicate.is_global() => (),
+        // We allow specializing on explicitly marked traits with no associated
+        // items.
+        ty::Predicate::Trait(pred, hir::Constness::NotConst) => {
+            if !matches!(
+                trait_predicate_kind(tcx, predicate),
+                Some(TraitSpecializationKind::Marker)
+            ) {
+                tcx.sess
+                    .struct_span_err(
+                        span,
+                        &format!(
+                            "cannot specialize on trait `{}`",
+                            tcx.def_path_str(pred.def_id()),
+                        ),
+                    )
+                    .emit()
+            }
+        }
+        _ => tcx
+            .sess
+            .struct_span_err(span, &format!("cannot specialize on `{:?}`", predicate))
+            .emit(),
+    }
+}
+
+fn trait_predicate_kind<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    predicate: &ty::Predicate<'tcx>,
+) -> Option<TraitSpecializationKind> {
+    match predicate {
+        ty::Predicate::Trait(pred, hir::Constness::NotConst) => {
+            Some(tcx.trait_def(pred.def_id()).specialization_kind)
+        }
+        ty::Predicate::Trait(_, hir::Constness::Const)
+        | ty::Predicate::RegionOutlives(_)
+        | ty::Predicate::TypeOutlives(_)
+        | ty::Predicate::Projection(_)
+        | ty::Predicate::WellFormed(_)
+        | ty::Predicate::Subtype(_)
+        | ty::Predicate::ObjectSafe(_)
+        | ty::Predicate::ClosureKind(..)
+        | ty::Predicate::ConstEvaluatable(..) => None,
+    }
+}
index c5f339d6b7648eb0a5192cc9cbc279c07d78f56e..e487e0d265c3ef0387ac3755d0be2f69ef882d2d 100644 (file)
@@ -64,6 +64,7 @@
 #![feature(nll)]
 #![feature(try_blocks)]
 #![feature(never_type)]
+#![feature(slice_partition_dedup)]
 #![recursion_limit = "256"]
 
 #[macro_use]
 mod structured_errors;
 mod variance;
 
-use rustc::lint;
 use rustc::middle;
-use rustc::session;
-use rustc::session::config::EntryFnType;
 use rustc::ty::query::Providers;
 use rustc::ty::subst::SubstsRef;
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_hir::Node;
 use rustc_infer::infer::{InferOk, TyCtxtInferExt};
-use rustc_infer::traits::{ObligationCause, ObligationCauseCode, TraitEngine, TraitEngineExt};
+use rustc_infer::traits::TraitEngineExt as _;
+use rustc_session::config::EntryFnType;
 use rustc_span::{Span, DUMMY_SP};
 use rustc_target::spec::abi::Abi;
+use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
+use rustc_trait_selection::traits::{
+    ObligationCause, ObligationCauseCode, TraitEngine, TraitEngineExt as _,
+};
 
 use std::iter;
 
index a4569a147567f4635033de4c6dd858fc1cb6e2f9..7d8bf71cf97b7e455d8783ad05e9275dcaa33307 100644 (file)
@@ -59,6 +59,7 @@
 use rustc_hir::PatKind;
 use rustc_infer::infer::InferCtxt;
 use rustc_span::Span;
+use rustc_trait_selection::infer::InferCtxtExt;
 
 #[derive(Clone, Debug)]
 pub enum PlaceBase {
@@ -425,7 +426,7 @@ fn cat_expr_adjusted_with<F>(
             | Res::Def(DefKind::ConstParam, _)
             | Res::Def(DefKind::AssocConst, _)
             | Res::Def(DefKind::Fn, _)
-            | Res::Def(DefKind::Method, _)
+            | Res::Def(DefKind::AssocFn, _)
             | Res::SelfCtor(..) => Ok(self.cat_rvalue(hir_id, span, expr_ty)),
 
             Res::Def(DefKind::Static, _) => Ok(Place {
@@ -469,7 +470,7 @@ fn cat_upvar(
 
         let upvar_id = ty::UpvarId {
             var_path: ty::UpvarPath { hir_id: var_id },
-            closure_expr_id: closure_expr_def_id.to_local(),
+            closure_expr_id: closure_expr_def_id.expect_local(),
         };
         let var_ty = self.node_ty(var_id)?;
 
index fcbeb5b210decad42e3dad661e0c327931944d38..44473fee643c638d3aafce57f8c01bcd1cebf576 100644 (file)
@@ -31,10 +31,10 @@ pub fn infer_predicates<'tcx>(
         predicates_added = false;
 
         let mut visitor = InferVisitor {
-            tcx: tcx,
+            tcx,
             global_inferred_outlives: &mut global_inferred_outlives,
             predicates_added: &mut predicates_added,
-            explicit_map: explicit_map,
+            explicit_map,
         };
 
         // Visit all the crates and infer predicates
index 99b7b2001a9e9a29812a2ecf8ec6d3ec7da509c2..a4f8472ae28913bf7b3d8027edeccec5225a3784 100644 (file)
@@ -1,6 +1,6 @@
-use rustc::session::Session;
 use rustc::ty::{Ty, TypeFoldable};
 use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticId};
+use rustc_session::Session;
 use rustc_span::Span;
 
 pub trait StructuredDiagnostic<'tcx> {
index 6f5caea250b0719efda46dc9f36d521b529f132b..54f84272ae8e03830e5b496f7403ea5c24339611 100644 (file)
@@ -105,13 +105,13 @@ fn visit_item(&mut self, item: &hir::Item<'_>) {
     }
 
     fn visit_trait_item(&mut self, trait_item: &hir::TraitItem<'_>) {
-        if let hir::TraitItemKind::Method(..) = trait_item.kind {
+        if let hir::TraitItemKind::Fn(..) = trait_item.kind {
             self.visit_node_helper(trait_item.hir_id);
         }
     }
 
     fn visit_impl_item(&mut self, impl_item: &hir::ImplItem<'_>) {
-        if let hir::ImplItemKind::Method(..) = impl_item.kind {
+        if let hir::ImplItemKind::Fn(..) = impl_item.kind {
             self.visit_node_helper(impl_item.hir_id);
         }
     }
index ddde11b38448bbf88e094ce3c53f600efc00f6ee..3cbb42bb5f30984a2904d05a9f061b62c4434ef5 100644 (file)
@@ -1,7 +1,7 @@
-//! Module for inferring the variance of type and lifetime parameters. See the [rustc guide]
+//! Module for inferring the variance of type and lifetime parameters. See the [rustc dev guide]
 //! chapter for more info.
 //!
-//! [rustc guide]: https://rust-lang.github.io/rustc-guide/variance.html
+//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/variance.html
 
 use hir::Node;
 use rustc::ty::query::Providers;
@@ -54,13 +54,13 @@ fn variances_of(tcx: TyCtxt<'_>, item_def_id: DefId) -> &[ty::Variance] {
         },
 
         Node::TraitItem(item) => match item.kind {
-            hir::TraitItemKind::Method(..) => {}
+            hir::TraitItemKind::Fn(..) => {}
 
             _ => unsupported(),
         },
 
         Node::ImplItem(item) => match item.kind {
-            hir::ImplItemKind::Method(..) => {}
+            hir::ImplItemKind::Fn(..) => {}
 
             _ => unsupported(),
         },
index dd593a6abb4fe5a28535db015b9ee706182d17d8..7e6ec96b379d8924249bac47ab6c36f05ed7ebb4 100644 (file)
@@ -77,8 +77,8 @@ pub fn determine_parameters_to_be_inferred<'a, 'tcx>(
 
     // See the following for a discussion on dep-graph management.
     //
-    // - https://rust-lang.github.io/rustc-guide/query.html
-    // - https://rust-lang.github.io/rustc-guide/variance.html
+    // - https://rustc-dev-guide.rust-lang.org/query.html
+    // - https://rustc-dev-guide.rust-lang.org/variance.html
     tcx.hir().krate().visit_all_item_likes(&mut terms_cx);
 
     terms_cx
@@ -164,13 +164,13 @@ fn visit_item(&mut self, item: &hir::Item<'_>) {
     }
 
     fn visit_trait_item(&mut self, trait_item: &hir::TraitItem<'_>) {
-        if let hir::TraitItemKind::Method(..) = trait_item.kind {
+        if let hir::TraitItemKind::Fn(..) = trait_item.kind {
             self.add_inferreds_for_item(trait_item.hir_id);
         }
     }
 
     fn visit_impl_item(&mut self, impl_item: &hir::ImplItem<'_>) {
-        if let hir::ImplItemKind::Method(..) = impl_item.kind {
+        if let hir::ImplItemKind::Fn(..) = impl_item.kind {
             self.add_inferreds_for_item(impl_item.hir_id);
         }
     }
index e4f7bc30e3fcfc6b3ed972b6323888189a7424e0..5a5f547068d63261e759a5e4992f328393815827 100644 (file)
@@ -1,3 +1,3 @@
-For more information about how `librustdoc` works, see the [rustc guide].
+For more information about how `librustdoc` works, see the [rustc dev guide].
 
-[rustc guide]: https://rust-lang.github.io/rustc-guide/rustdoc.html
+[rustc dev guide]: https://rustc-dev-guide.rust-lang.org/rustdoc.html
index 289923b45e64847a79d7e541e0f44a9e7cd360fb..c85b21a55007f1e0a72444cd9c39f5e8d1de44e0 100644 (file)
@@ -1,7 +1,7 @@
 use rustc::ty::{self, Region, RegionVid, TypeFoldable};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
-use rustc_infer::traits::auto_trait::{self, AutoTraitResult};
+use rustc_trait_selection::traits::auto_trait::{self, AutoTraitResult};
 
 use std::fmt::Debug;
 
@@ -493,7 +493,7 @@ fn param_env_to_generics(
                     // Writing a projection trait bound of the form
                     // <T as Trait>::Name : ?Sized
                     // is illegal, because ?Sized bounds can only
-                    // be written in the (here, nonexistant) definition
+                    // be written in the (here, nonexistent) definition
                     // of the type.
                     // Therefore, we make sure that we never add a ?Sized
                     // bound for projections
index 4a1e2570d06c56e6620b2e6624bee7cf0606be0d..e66f8697717940aaed8cd5d7811c7d8d603b2ad3 100644 (file)
@@ -1,3 +1,4 @@
+use crate::rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
 use rustc::ty::subst::Subst;
 use rustc::ty::{ToPredicate, WithConstness};
 use rustc_hir as hir;
index 618dfa0d33aae5bd68e6daa7bef40ef8a9382b9e..153f7af9f97cae1d3151579e295bd1686be6af60 100644 (file)
@@ -12,7 +12,6 @@
 use rustc_metadata::creader::LoadedMacro;
 use rustc_mir::const_eval::is_min_const_fn;
 use rustc_span::hygiene::MacroKind;
-use rustc_span::symbol::sym;
 use rustc_span::Span;
 
 use crate::clean::{self, GetDefId, ToSource, TypeKind};
@@ -42,11 +41,7 @@ pub fn try_inline(
     attrs: Option<Attrs<'_>>,
     visited: &mut FxHashSet<DefId>,
 ) -> Option<Vec<clean::Item>> {
-    let did = if let Some(did) = res.opt_def_id() {
-        did
-    } else {
-        return None;
-    };
+    let did = res.opt_def_id()?;
     if did.is_local() {
         return None;
     }
@@ -198,7 +193,6 @@ pub fn build_external_trait(cx: &DocContext<'_>, did: DefId) -> clean::Trait {
     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);
     let is_auto = cx.tcx.trait_is_auto(did);
     clean::Trait {
         auto: auto_trait,
@@ -206,7 +200,6 @@ pub fn build_external_trait(cx: &DocContext<'_>, did: DefId) -> clean::Trait {
         generics,
         items: trait_items,
         bounds: supertrait_bounds,
-        is_spotlight,
         is_auto,
     }
 }
@@ -581,7 +574,7 @@ fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean:
                     name: ref _name,
                 },
             ref bounds,
-        } => !(*s == "Self" && did == trait_did) && !bounds.is_empty(),
+        } => !(bounds.is_empty() || *s == "Self" && did == trait_did),
         _ => true,
     });
     g
index 7c845a9b66bbdea112bd7f1396bab14903824a94..e69d4ddc2d01b4f97276daea97faecd768dc8082 100644 (file)
@@ -50,7 +50,7 @@
 pub use self::types::Visibility::{Inherited, Public};
 pub use self::types::*;
 
-const FN_OUTPUT_NAME: &'static str = "Output";
+const FN_OUTPUT_NAME: &str = "Output";
 
 pub trait Clean<T> {
     fn clean(&self, cx: &DocContext<'_>) -> T;
@@ -141,6 +141,7 @@ fn clean(&self, cx: &DocContext<'_>) -> ExternalCrate {
             cx.tcx
                 .hir()
                 .krate()
+                .item
                 .module
                 .item_ids
                 .iter()
@@ -194,6 +195,7 @@ fn clean(&self, cx: &DocContext<'_>) -> ExternalCrate {
             cx.tcx
                 .hir()
                 .krate()
+                .item
                 .module
                 .item_ids
                 .iter()
@@ -1013,7 +1015,6 @@ fn clean(&self, cx: &DocContext<'_>) -> FnRetTy {
 impl Clean<Item> for doctree::Trait<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> Item {
         let attrs = self.attrs.clean(cx);
-        let is_spotlight = attrs.has_doc_flag(sym::spotlight);
         Item {
             name: Some(self.name.clean(cx)),
             attrs,
@@ -1028,7 +1029,6 @@ fn clean(&self, cx: &DocContext<'_>) -> Item {
                 items: self.items.iter().map(|ti| ti.clean(cx)).collect(),
                 generics: self.generics.clean(cx),
                 bounds: self.bounds.clean(cx),
-                is_spotlight,
                 is_auto: self.is_auto.clean(cx),
             }),
         }
@@ -1078,16 +1078,36 @@ fn clean(&self, cx: &DocContext<'_>) -> PolyTrait {
     }
 }
 
+impl Clean<TypeKind> for hir::def::DefKind {
+    fn clean(&self, _: &DocContext<'_>) -> TypeKind {
+        match *self {
+            hir::def::DefKind::Mod => TypeKind::Module,
+            hir::def::DefKind::Struct => TypeKind::Struct,
+            hir::def::DefKind::Union => TypeKind::Union,
+            hir::def::DefKind::Enum => TypeKind::Enum,
+            hir::def::DefKind::Trait => TypeKind::Trait,
+            hir::def::DefKind::TyAlias => TypeKind::Typedef,
+            hir::def::DefKind::ForeignTy => TypeKind::Foreign,
+            hir::def::DefKind::TraitAlias => TypeKind::TraitAlias,
+            hir::def::DefKind::Fn => TypeKind::Function,
+            hir::def::DefKind::Const => TypeKind::Const,
+            hir::def::DefKind::Static => TypeKind::Static,
+            hir::def::DefKind::Macro(_) => TypeKind::Macro,
+            _ => TypeKind::Foreign,
+        }
+    }
+}
+
 impl Clean<Item> for hir::TraitItem<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> Item {
         let inner = match self.kind {
             hir::TraitItemKind::Const(ref ty, default) => {
                 AssocConstItem(ty.clean(cx), default.map(|e| print_const_expr(cx, e)))
             }
-            hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body)) => {
+            hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => {
                 MethodItem((sig, &self.generics, body, None).clean(cx))
             }
-            hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Required(ref names)) => {
+            hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(ref names)) => {
                 let (generics, decl) = enter_impl_trait(cx, || {
                     (self.generics.clean(cx), (&*sig.decl, &names[..]).clean(cx))
                 });
@@ -1118,7 +1138,7 @@ fn clean(&self, cx: &DocContext<'_>) -> Item {
             hir::ImplItemKind::Const(ref ty, expr) => {
                 AssocConstItem(ty.clean(cx), Some(print_const_expr(cx, expr)))
             }
-            hir::ImplItemKind::Method(ref sig, body) => {
+            hir::ImplItemKind::Fn(ref sig, body) => {
                 MethodItem((sig, &self.generics, body, Some(self.defaultness)).clean(cx))
             }
             hir::ImplItemKind::TyAlias(ref ty) => {
index 9c3bedfe37c7a8563c0d14db3228658bf00b3ba9..73f2c399e56982bc67a2312044bc59d86dc69d3a 100644 (file)
@@ -836,8 +836,8 @@ pub struct Method {
     pub decl: FnDecl,
     pub header: hir::FnHeader,
     pub defaultness: Option<hir::Defaultness>,
-    pub all_types: Vec<Type>,
-    pub ret_types: Vec<Type>,
+    pub all_types: Vec<(Type, TypeKind)>,
+    pub ret_types: Vec<(Type, TypeKind)>,
 }
 
 #[derive(Clone, Debug)]
@@ -845,8 +845,8 @@ pub struct TyMethod {
     pub header: hir::FnHeader,
     pub decl: FnDecl,
     pub generics: Generics,
-    pub all_types: Vec<Type>,
-    pub ret_types: Vec<Type>,
+    pub all_types: Vec<(Type, TypeKind)>,
+    pub ret_types: Vec<(Type, TypeKind)>,
 }
 
 #[derive(Clone, Debug)]
@@ -854,8 +854,8 @@ pub struct Function {
     pub decl: FnDecl,
     pub generics: Generics,
     pub header: hir::FnHeader,
-    pub all_types: Vec<Type>,
-    pub ret_types: Vec<Type>,
+    pub all_types: Vec<(Type, TypeKind)>,
+    pub ret_types: Vec<(Type, TypeKind)>,
 }
 
 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
@@ -951,7 +951,6 @@ pub struct Trait {
     pub items: Vec<Item>,
     pub generics: Generics,
     pub bounds: Vec<GenericBound>,
-    pub is_spotlight: bool,
     pub is_auto: bool,
 }
 
@@ -1043,7 +1042,7 @@ pub enum PrimitiveType {
     Never,
 }
 
-#[derive(Clone, Copy, Debug)]
+#[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)]
 pub enum TypeKind {
     Enum,
     Function,
index 99e3d731d0d6fc46d2b2801bc59fbcd58fc75aad..b54af499187097e5b22e3e860f705f44ab15dab3 100644 (file)
@@ -121,9 +121,7 @@ pub fn external_generic_args(
     let args: Vec<_> = substs
         .iter()
         .filter_map(|kind| match kind.unpack() {
-            GenericArgKind::Lifetime(lt) => {
-                lt.clean(cx).and_then(|lt| Some(GenericArg::Lifetime(lt)))
-            }
+            GenericArgKind::Lifetime(lt) => lt.clean(cx).map(|lt| GenericArg::Lifetime(lt)),
             GenericArgKind::Type(_) if skip_self => {
                 skip_self = false;
                 None
@@ -186,7 +184,7 @@ pub fn get_real_types(
     arg: &Type,
     cx: &DocContext<'_>,
     recurse: i32,
-) -> FxHashSet<Type> {
+) -> FxHashSet<(Type, TypeKind)> {
     let arg_s = arg.print().to_string();
     let mut res = FxHashSet::default();
     if recurse >= 10 {
@@ -211,7 +209,11 @@ pub fn get_real_types(
                                 if !adds.is_empty() {
                                     res.extend(adds);
                                 } else if !ty.is_full_generic() {
-                                    res.insert(ty);
+                                    if let Some(did) = ty.def_id() {
+                                        if let Some(kind) = cx.tcx.def_kind(did).clean(cx) {
+                                            res.insert((ty, kind));
+                                        }
+                                    }
                                 }
                             }
                         }
@@ -227,13 +229,21 @@ pub fn get_real_types(
                     if !adds.is_empty() {
                         res.extend(adds);
                     } else if !ty.is_full_generic() {
-                        res.insert(ty.clone());
+                        if let Some(did) = ty.def_id() {
+                            if let Some(kind) = cx.tcx.def_kind(did).clean(cx) {
+                                res.insert((ty.clone(), kind));
+                            }
+                        }
                     }
                 }
             }
         }
     } else {
-        res.insert(arg.clone());
+        if let Some(did) = arg.def_id() {
+            if let Some(kind) = cx.tcx.def_kind(did).clean(cx) {
+                res.insert((arg.clone(), kind));
+            }
+        }
         if let Some(gens) = arg.generics() {
             for gen in gens.iter() {
                 if gen.is_full_generic() {
@@ -241,8 +251,10 @@ pub fn get_real_types(
                     if !adds.is_empty() {
                         res.extend(adds);
                     }
-                } else {
-                    res.insert(gen.clone());
+                } else if let Some(did) = gen.def_id() {
+                    if let Some(kind) = cx.tcx.def_kind(did).clean(cx) {
+                        res.insert((gen.clone(), kind));
+                    }
                 }
             }
         }
@@ -258,7 +270,7 @@ pub fn get_all_types(
     generics: &Generics,
     decl: &FnDecl,
     cx: &DocContext<'_>,
-) -> (Vec<Type>, Vec<Type>) {
+) -> (Vec<(Type, TypeKind)>, Vec<(Type, TypeKind)>) {
     let mut all_types = FxHashSet::default();
     for arg in decl.inputs.values.iter() {
         if arg.type_.is_self_type() {
@@ -268,7 +280,11 @@ pub fn get_all_types(
         if !args.is_empty() {
             all_types.extend(args);
         } else {
-            all_types.insert(arg.type_.clone());
+            if let Some(did) = arg.type_.def_id() {
+                if let Some(kind) = cx.tcx.def_kind(did).clean(cx) {
+                    all_types.insert((arg.type_.clone(), kind));
+                }
+            }
         }
     }
 
@@ -276,7 +292,11 @@ pub fn get_all_types(
         FnRetTy::Return(ref return_type) => {
             let mut ret = get_real_types(generics, &return_type, cx, 0);
             if ret.is_empty() {
-                ret.insert(return_type.clone());
+                if let Some(did) = return_type.def_id() {
+                    if let Some(kind) = cx.tcx.def_kind(did).clean(cx) {
+                        ret.insert((return_type.clone(), kind));
+                    }
+                }
             }
             ret.into_iter().collect()
         }
index 33b3e800374e33bfa7f28926d42738f50da7c4e7..179c5bfacf32ea047d7a1721dabe2e68146c5795 100644 (file)
@@ -1,17 +1,17 @@
 use std::collections::BTreeMap;
+use std::convert::TryFrom;
 use std::ffi::OsStr;
 use std::fmt;
 use std::path::PathBuf;
 
-use rustc::lint::Level;
-use rustc::session;
-use rustc::session::config::{
+use rustc_session::config::{self, parse_crate_types_from_list, parse_externs, CrateType};
+use rustc_session::config::{
     build_codegen_options, build_debugging_options, get_cmd_lint_options, host_triple,
     nightly_options,
 };
-use rustc::session::config::{parse_crate_types_from_list, parse_externs, CrateType};
-use rustc::session::config::{CodegenOptions, DebuggingOptions, ErrorOutputType, Externs};
-use rustc::session::search_paths::SearchPath;
+use rustc_session::config::{CodegenOptions, DebuggingOptions, ErrorOutputType, Externs};
+use rustc_session::lint::Level;
+use rustc_session::search_paths::SearchPath;
 use rustc_span::edition::{Edition, DEFAULT_EDITION};
 use rustc_target::spec::TargetTriple;
 
 use crate::passes::{self, Condition, DefaultPassOption};
 use crate::theme;
 
+#[derive(Clone, Copy, PartialEq, Eq, Debug)]
+pub enum OutputFormat {
+    Json,
+    Html,
+}
+
+impl OutputFormat {
+    pub fn is_json(&self) -> bool {
+        match self {
+            OutputFormat::Json => true,
+            _ => false,
+        }
+    }
+}
+
+impl TryFrom<&str> for OutputFormat {
+    type Error = String;
+
+    fn try_from(value: &str) -> Result<Self, Self::Error> {
+        match value {
+            "json" => Ok(OutputFormat::Json),
+            "html" => Ok(OutputFormat::Html),
+            _ => Err(format!("unknown output format `{}`", value)),
+        }
+    }
+}
+
 /// Configuration options for rustdoc.
 #[derive(Clone)]
 pub struct Options {
@@ -115,6 +142,8 @@ pub struct Options {
     pub crate_version: Option<String>,
     /// Collected options specific to outputting final pages.
     pub render_options: RenderOptions,
+    /// Output format rendering (used only for "show-coverage" option for the moment)
+    pub output_format: Option<OutputFormat>,
 }
 
 impl fmt::Debug for Options {
@@ -269,9 +298,9 @@ fn println_condition(condition: Condition) {
             return Err(0);
         }
 
-        let color = session::config::parse_color(&matches);
-        let (json_rendered, _artifacts) = session::config::parse_json(&matches);
-        let error_format = session::config::parse_error_format(&matches, color, json_rendered);
+        let color = config::parse_color(&matches);
+        let (json_rendered, _artifacts) = config::parse_json(&matches);
+        let error_format = config::parse_error_format(&matches, color, json_rendered);
 
         let codegen_options = build_codegen_options(matches, error_format);
         let debugging_options = build_debugging_options(matches, error_format);
@@ -425,14 +454,6 @@ fn println_condition(condition: Condition) {
             }
         }
 
-        match matches.opt_str("w").as_ref().map(|s| &**s) {
-            Some("html") | None => {}
-            Some(s) => {
-                diag.struct_err(&format!("unknown output format: {}", s)).emit();
-                return Err(1);
-            }
-        }
-
         let index_page = matches.opt_str("index-page").map(|s| PathBuf::from(&s));
         if let Some(ref index_page) = index_page {
             if !index_page.is_file() {
@@ -469,6 +490,29 @@ fn println_condition(condition: Condition) {
             }
         };
 
+        let output_format = match matches.opt_str("output-format") {
+            Some(s) => match OutputFormat::try_from(s.as_str()) {
+                Ok(o) => {
+                    if o.is_json() && !show_coverage {
+                        diag.struct_err("json output format isn't supported for doc generation")
+                            .emit();
+                        return Err(1);
+                    } else if !o.is_json() && show_coverage {
+                        diag.struct_err(
+                            "html output format isn't supported for the --show-coverage option",
+                        )
+                        .emit();
+                        return Err(1);
+                    }
+                    Some(o)
+                }
+                Err(e) => {
+                    diag.struct_err(&e).emit();
+                    return Err(1);
+                }
+            },
+            None => None,
+        };
         let crate_name = matches.opt_str("crate-name");
         let proc_macro_crate = crate_types.contains(&CrateType::ProcMacro);
         let playground_url = matches.opt_str("playground-url");
@@ -553,6 +597,7 @@ fn println_condition(condition: Condition) {
                 generate_search_filter,
                 generate_redirect_pages,
             },
+            output_format,
         })
     }
 
@@ -568,6 +613,9 @@ fn check_deprecated_options(matches: &getopts::Matches, diag: &rustc_errors::Han
 
     for flag in deprecated_flags.iter() {
         if matches.opt_present(flag) {
+            if *flag == "output-format" && matches.opt_present("show-coverage") {
+                continue;
+            }
             let mut err =
                 diag.struct_warn(&format!("the '{}' flag is considered deprecated", flag));
             err.warn(
index 8bc34e949f175649cd0ec54e72eb92aac4d2c31e..f0b9ad2852f5115a480e5bcd99c88e705b654810 100644 (file)
@@ -1,23 +1,22 @@
 use rustc::middle::cstore::CrateStore;
 use rustc::middle::privacy::AccessLevels;
-use rustc::session::config::ErrorOutputType;
-use rustc::session::DiagnosticOutput;
-use rustc::session::{self, config};
 use rustc::ty::{Ty, TyCtxt};
+use rustc_ast::ast::CRATE_NODE_ID;
+use rustc_attr as attr;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_driver::abort_on_err;
+use rustc_errors::emitter::{Emitter, EmitterWriter};
+use rustc_errors::json::JsonEmitter;
 use rustc_feature::UnstableFeatures;
 use rustc_hir::def::Namespace::TypeNS;
 use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE};
 use rustc_hir::HirId;
 use rustc_interface::interface;
 use rustc_resolve as resolve;
+use rustc_session::config::ErrorOutputType;
 use rustc_session::lint;
-
-use rustc_ast::ast::CRATE_NODE_ID;
-use rustc_attr as attr;
-use rustc_errors::emitter::{Emitter, EmitterWriter};
-use rustc_errors::json::JsonEmitter;
+use rustc_session::DiagnosticOutput;
+use rustc_session::{config, Session};
 use rustc_span::source_map;
 use rustc_span::symbol::sym;
 use rustc_span::DUMMY_SP;
@@ -34,8 +33,8 @@
 
 use crate::passes::{self, Condition::*, ConditionalPass};
 
-pub use rustc::session::config::{CodegenOptions, DebuggingOptions, Input, Options};
-pub use rustc::session::search_paths::SearchPath;
+pub use rustc_session::config::{CodegenOptions, DebuggingOptions, Input, Options};
+pub use rustc_session::search_paths::SearchPath;
 
 pub type ExternalPaths = FxHashMap<DefId, (Vec<String>, clean::TypeKind)>;
 
@@ -68,7 +67,7 @@ pub struct DocContext<'tcx> {
 }
 
 impl<'tcx> DocContext<'tcx> {
-    pub fn sess(&self) -> &session::Session {
+    pub fn sess(&self) -> &Session {
         &self.tcx.sess
     }
 
@@ -228,6 +227,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
         mut manual_passes,
         display_warnings,
         render_options,
+        output_format,
         ..
     } = options;
 
@@ -385,6 +385,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
 
                 let mut renderinfo = RenderInfo::default();
                 renderinfo.access_levels = access_levels;
+                renderinfo.output_format = output_format;
 
                 let mut ctxt = DocContext {
                     tcx,
index ecc394a2bc992082dc558992658a7fa080023bf1..9c9a00295c3fa2026c6e5b29672d9380cf838103 100644 (file)
@@ -90,14 +90,14 @@ pub fn write<P, C, E>(&self, path: P, contents: C) -> Result<(), E>
             let sender = self.errors.sender.clone().unwrap();
             rayon::spawn(move || match fs::write(&path, &contents) {
                 Ok(_) => {
-                    sender
-                        .send(None)
-                        .expect(&format!("failed to send error on \"{}\"", path.display()));
+                    sender.send(None).unwrap_or_else(|_| {
+                        panic!("failed to send error on \"{}\"", path.display())
+                    });
                 }
                 Err(e) => {
-                    sender
-                        .send(Some(format!("\"{}\": {}", path.display(), e)))
-                        .expect(&format!("failed to send non-error on \"{}\"", path.display()));
+                    sender.send(Some(format!("\"{}\": {}", path.display(), e))).unwrap_or_else(
+                        |_| panic!("failed to send non-error on \"{}\"", path.display()),
+                    );
                 }
             });
             Ok(())
index becdeaba50f782dd241275557256b19a8cf207fd..41b8e66d265922242d0c7002d325657d4fb37729 100644 (file)
@@ -44,7 +44,7 @@ pub fn new(
         vis: &'hir hir::Visibility<'hir>,
     ) -> Module<'hir> {
         Module {
-            name: name,
+            name,
             id: hir::CRATE_HIR_ID,
             vis,
             where_outer: rustc_span::DUMMY_SP,
index ec615fc8589762dba432a388df67218833fe8c7f..e60ff37fd279aa9725c27cc43232b1d086a6c5c0 100644 (file)
@@ -63,22 +63,10 @@ impl Buffer {
         Buffer { for_html: false, buffer: String::new() }
     }
 
-    crate fn is_empty(&self) -> bool {
-        self.buffer.is_empty()
-    }
-
     crate fn into_inner(self) -> String {
         self.buffer
     }
 
-    crate fn insert_str(&mut self, idx: usize, s: &str) {
-        self.buffer.insert_str(idx, s);
-    }
-
-    crate fn push_str(&mut self, s: &str) {
-        self.buffer.push_str(s);
-    }
-
     // Intended for consumption by write! and writeln! (std::fmt) but without
     // the fmt::Result return type imposed by fmt::Write (and avoiding the trait
     // import).
index 0b4bb304fe9e05ae378f8af7c8d7a73e156f601d..02f1947c99e5fd1e469075d9ef5cc85f93a822ba 100644 (file)
@@ -135,7 +135,7 @@ trait Writer {
     fn string<T: Display>(&mut self, text: T, klass: Class) -> io::Result<()>;
 }
 
-// Implement `Writer` for anthing that can be written to, this just implements
+// Implement `Writer` for anything that can be written to, this just implements
 // the default rustdoc behaviour.
 impl<U: Write> Writer for U {
     fn string<T: Display>(&mut self, text: T, klass: Class) -> io::Result<()> {
index 4a0f4e5a4c9c832773b231352087ed3c0acd7ba9..0b2b0cdc18b092e5c135c8cded2d3ef400566479 100644 (file)
@@ -62,7 +62,7 @@ impl<'a> From<&'a clean::Item> for ItemType {
     fn from(item: &'a clean::Item) -> ItemType {
         let inner = match item.inner {
             clean::StrippedItem(box ref item) => item,
-            ref inner @ _ => inner,
+            ref inner => inner,
         };
 
         match *inner {
@@ -194,7 +194,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     }
 }
 
-pub const NAMESPACE_TYPE: &'static str = "t";
-pub const NAMESPACE_VALUE: &'static str = "v";
-pub const NAMESPACE_MACRO: &'static str = "m";
-pub const NAMESPACE_KEYWORD: &'static str = "k";
+pub const NAMESPACE_TYPE: &str = "t";
+pub const NAMESPACE_VALUE: &str = "v";
+pub const NAMESPACE_MACRO: &str = "m";
+pub const NAMESPACE_KEYWORD: &str = "k";
index ed007fe383c1db9b98e51d2044b9ef3a4899b668..e13bf270440e20bfce4d11d5150e35acd8526c43 100644 (file)
@@ -296,7 +296,7 @@ fn dont_escape(c: u8) -> bool {
                         ""
                     }
                 )),
-                playground_button.as_ref().map(String::as_str),
+                playground_button.as_deref(),
                 Some((s1.as_str(), s2)),
             ));
             Some(Event::Html(s.into()))
@@ -315,7 +315,7 @@ fn dont_escape(c: u8) -> bool {
                         ""
                     }
                 )),
-                playground_button.as_ref().map(String::as_str),
+                playground_button.as_deref(),
                 None,
             ));
             Some(Event::Html(s.into()))
@@ -844,11 +844,7 @@ impl<'a> Iterator for ParserWrapper<'a> {
         type Item = String;
 
         fn next(&mut self) -> Option<String> {
-            let next_event = self.inner.next();
-            if next_event.is_none() {
-                return None;
-            }
-            let next_event = next_event.unwrap();
+            let next_event = self.inner.next()?;
             let (ret, is_in) = match next_event {
                 Event::Start(Tag::Paragraph) => (None, 1),
                 Event::Start(Tag::Heading(_)) => (None, 1),
@@ -869,12 +865,8 @@ fn next(&mut self) -> Option<String> {
         }
     }
     let mut s = String::with_capacity(md.len() * 3 / 2);
-    let mut p = ParserWrapper { inner: Parser::new(md), is_in: 0, is_first: true };
-    while let Some(t) = p.next() {
-        if !t.is_empty() {
-            s.push_str(&t);
-        }
-    }
+    let p = ParserWrapper { inner: Parser::new(md), is_in: 0, is_first: true };
+    p.filter(|t| !t.is_empty()).for_each(|i| s.push_str(&i));
     s
 }
 
index 4aa3fa39fb4ba6b01eba5dbbb4e2dd9539378567..eb7a367acf439cb41ec7704f0f16d2260d690354 100644 (file)
@@ -44,7 +44,6 @@
 
 use rustc::middle::privacy::AccessLevels;
 use rustc::middle::stability;
-use rustc_ast::ast;
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::flock;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -59,8 +58,8 @@
 use serde::ser::SerializeSeq;
 use serde::{Serialize, Serializer};
 
-use crate::clean::{self, AttributesExt, Deprecation, GetDefId, SelfTy};
-use crate::config::RenderOptions;
+use crate::clean::{self, AttributesExt, Deprecation, GetDefId, SelfTy, TypeKind};
+use crate::config::{OutputFormat, RenderOptions};
 use crate::docfs::{DocFS, ErrorStorage, PathError};
 use crate::doctree;
 use crate::html::escape::Escape;
@@ -270,6 +269,7 @@ pub struct RenderInfo {
     pub deref_trait_did: Option<DefId>,
     pub deref_mut_trait_did: Option<DefId>,
     pub owned_box_did: Option<DefId>,
+    pub output_format: Option<OutputFormat>,
 }
 
 // Helper structs for rendering items/sidebars and carrying along contextual
@@ -302,19 +302,25 @@ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
 
 /// A type used for the search index.
 #[derive(Debug)]
-struct Type {
+struct RenderType {
+    ty: Option<DefId>,
+    idx: Option<usize>,
     name: Option<String>,
-    generics: Option<Vec<String>>,
+    generics: Option<Vec<Generic>>,
 }
 
-impl Serialize for Type {
+impl Serialize for RenderType {
     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
     where
         S: Serializer,
     {
         if let Some(name) = &self.name {
             let mut seq = serializer.serialize_seq(None)?;
-            seq.serialize_element(&name)?;
+            if let Some(id) = self.idx {
+                seq.serialize_element(&id)?;
+            } else {
+                seq.serialize_element(&name)?;
+            }
             if let Some(generics) = &self.generics {
                 seq.serialize_element(&generics)?;
             }
@@ -325,11 +331,32 @@ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
     }
 }
 
+/// A type used for the search index.
+#[derive(Debug)]
+struct Generic {
+    name: String,
+    defid: Option<DefId>,
+    idx: Option<usize>,
+}
+
+impl Serialize for Generic {
+    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+    where
+        S: Serializer,
+    {
+        if let Some(id) = self.idx {
+            serializer.serialize_some(&id)
+        } else {
+            serializer.serialize_some(&self.name)
+        }
+    }
+}
+
 /// Full type of functions/methods in the search index.
 #[derive(Debug)]
 struct IndexItemFunctionType {
-    inputs: Vec<Type>,
-    output: Option<Vec<Type>>,
+    inputs: Vec<TypeWithKind>,
+    output: Option<Vec<TypeWithKind>>,
 }
 
 impl Serialize for IndexItemFunctionType {
@@ -340,8 +367,8 @@ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
         // If we couldn't figure out a type, just write `null`.
         let mut iter = self.inputs.iter();
         if match self.output {
-            Some(ref output) => iter.chain(output.iter()).any(|ref i| i.name.is_none()),
-            None => iter.any(|ref i| i.name.is_none()),
+            Some(ref output) => iter.chain(output.iter()).any(|ref i| i.ty.name.is_none()),
+            None => iter.any(|ref i| i.ty.name.is_none()),
         } {
             serializer.serialize_none()
         } else {
@@ -359,6 +386,31 @@ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
     }
 }
 
+#[derive(Debug)]
+pub struct TypeWithKind {
+    ty: RenderType,
+    kind: TypeKind,
+}
+
+impl From<(RenderType, TypeKind)> for TypeWithKind {
+    fn from(x: (RenderType, TypeKind)) -> TypeWithKind {
+        TypeWithKind { ty: x.0, kind: x.1 }
+    }
+}
+
+impl Serialize for TypeWithKind {
+    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+    where
+        S: Serializer,
+    {
+        let mut seq = serializer.serialize_seq(None)?;
+        seq.serialize_element(&self.ty.name)?;
+        let x: ItemType = self.kind.into();
+        seq.serialize_element(&x)?;
+        seq.end()
+    }
+}
+
 thread_local!(static CACHE_KEY: RefCell<Arc<Cache>> = Default::default());
 thread_local!(pub static CURRENT_DEPTH: Cell<usize> = Cell::new(0));
 
@@ -1313,7 +1365,8 @@ fn krate(self, mut krate: clean::Crate) -> Result<(), Error> {
                          <p>Version {}</p>\
                      </div>\
                      <a id='all-types' href='index.html'><p>Back to index</p></a>",
-                crate_name, version
+                crate_name,
+                Escape(version),
             )
         } else {
             String::new()
@@ -1541,7 +1594,7 @@ fn build_sidebar_items(&self, m: &clean::Module) -> BTreeMap<String, Vec<NameDoc
         }
 
         if self.shared.sort_modules_alphabetically {
-            for (_, items) in &mut map {
+            for items in map.values_mut() {
                 items.sort();
             }
         }
@@ -1564,7 +1617,7 @@ fn src_href(&self, item: &clean::Item) -> Option<String> {
 
         let mut path = String::new();
 
-        // We can safely ignore macros from other libraries
+        // We can safely ignore synthetic `SourceFile`s.
         let file = match item.source.filename {
             FileName::Real(ref path) => path,
             _ => return None,
@@ -2324,7 +2377,7 @@ fn item_function(w: &mut Buffer, cx: &Context, it: &clean::Item, f: &clean::Func
         f.generics.print()
     )
     .len();
-    write!(w, "{}<pre class='rust fn'>", render_spotlight_traits(it));
+    write!(w, "<pre class='rust fn'>");
     render_attributes(w, it, false);
     write!(
         w,
@@ -2527,13 +2580,7 @@ fn trait_item(w: &mut Buffer, cx: &Context, m: &clean::Item, t: &clean::Item) {
         let item_type = m.type_();
         let id = cx.derive_id(format!("{}.{}", item_type, name));
         let ns_id = cx.derive_id(format!("{}.{}", name, item_type.name_space()));
-        write!(
-            w,
-            "<h3 id='{id}' class='method'>{extra}<code id='{ns_id}'>",
-            extra = render_spotlight_traits(m),
-            id = id,
-            ns_id = ns_id
-        );
+        write!(w, "<h3 id='{id}' class='method'><code id='{ns_id}'>", id = id, ns_id = ns_id);
         render_assoc_item(w, m, AssocItemLink::Anchor(Some(&id)), ItemType::Impl);
         write!(w, "</code>");
         render_stability_since(w, m, t);
@@ -2726,7 +2773,7 @@ fn naive_assoc_href(it: &clean::Item, link: AssocItemLink<'_>) -> String {
     let name = it.name.as_ref().unwrap();
     let ty = match it.type_() {
         Typedef | AssocType => AssocType,
-        s @ _ => s,
+        s => s,
     };
 
     let anchor = format!("#{}.{}", ty, name);
@@ -3130,26 +3177,7 @@ fn item_enum(w: &mut Buffer, cx: &Context, it: &clean::Item, e: &clean::Enum) {
     render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All)
 }
 
-fn render_attribute(attr: &ast::MetaItem) -> Option<String> {
-    let path = pprust::path_to_string(&attr.path);
-
-    if attr.is_word() {
-        Some(path)
-    } else if let Some(v) = attr.value_str() {
-        Some(format!("{} = {:?}", path, v))
-    } else if let Some(values) = attr.meta_item_list() {
-        let display: Vec<_> = values
-            .iter()
-            .filter_map(|attr| attr.meta_item().and_then(|mi| render_attribute(mi)))
-            .collect();
-
-        if !display.is_empty() { Some(format!("{}({})", path, display.join(", "))) } else { None }
-    } else {
-        None
-    }
-}
-
-const ATTRIBUTE_WHITELIST: &'static [Symbol] = &[
+const ATTRIBUTE_WHITELIST: &[Symbol] = &[
     sym::export_name,
     sym::lang,
     sym::link_section,
@@ -3174,9 +3202,8 @@ fn render_attributes(w: &mut Buffer, it: &clean::Item, top: bool) {
         if !ATTRIBUTE_WHITELIST.contains(&attr.name_or_empty()) {
             continue;
         }
-        if let Some(s) = render_attribute(&attr.meta().unwrap()) {
-            attrs.push_str(&format!("#[{}]\n", s));
-        }
+
+        attrs.push_str(&pprust::attribute_to_string(&attr));
     }
     if !attrs.is_empty() {
         write!(
@@ -3400,10 +3427,8 @@ fn render_assoc_items(
         let deref_impl =
             traits.iter().find(|t| t.inner_impl().trait_.def_id() == c.deref_trait_did);
         if let Some(impl_) = deref_impl {
-            let has_deref_mut = traits
-                .iter()
-                .find(|t| t.inner_impl().trait_.def_id() == c.deref_mut_trait_did)
-                .is_some();
+            let has_deref_mut =
+                traits.iter().any(|t| t.inner_impl().trait_.def_id() == c.deref_mut_trait_did);
             render_deref_methods(w, cx, impl_, containing_item, has_deref_mut);
         }
 
@@ -3519,76 +3544,6 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool) -> bool {
     }
 }
 
-fn render_spotlight_traits(item: &clean::Item) -> String {
-    match item.inner {
-        clean::FunctionItem(clean::Function { ref decl, .. })
-        | clean::TyMethodItem(clean::TyMethod { ref decl, .. })
-        | clean::MethodItem(clean::Method { ref decl, .. })
-        | clean::ForeignFunctionItem(clean::Function { ref decl, .. }) => spotlight_decl(decl),
-        _ => String::new(),
-    }
-}
-
-fn spotlight_decl(decl: &clean::FnDecl) -> String {
-    let mut out = Buffer::html();
-    let mut trait_ = String::new();
-
-    if let Some(did) = decl.output.def_id() {
-        let c = cache();
-        if let Some(impls) = c.impls.get(&did) {
-            for i in impls {
-                let impl_ = i.inner_impl();
-                if impl_.trait_.def_id().map_or(false, |d| c.traits[&d].is_spotlight) {
-                    if out.is_empty() {
-                        out.push_str(&format!(
-                            "<h3 class=\"important\">Important traits for {}</h3>\
-                                      <code class=\"content\">",
-                            impl_.for_.print()
-                        ));
-                        trait_.push_str(&impl_.for_.print().to_string());
-                    }
-
-                    //use the "where" class here to make it small
-                    out.push_str(&format!(
-                        "<span class=\"where fmt-newline\">{}</span>",
-                        impl_.print()
-                    ));
-                    let t_did = impl_.trait_.def_id().unwrap();
-                    for it in &impl_.items {
-                        if let clean::TypedefItem(ref tydef, _) = it.inner {
-                            out.push_str("<span class=\"where fmt-newline\">    ");
-                            assoc_type(
-                                &mut out,
-                                it,
-                                &[],
-                                Some(&tydef.type_),
-                                AssocItemLink::GotoSource(t_did, &FxHashSet::default()),
-                                "",
-                            );
-                            out.push_str(";</span>");
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    if !out.is_empty() {
-        out.insert_str(
-            0,
-            &format!(
-                "<div class=\"important-traits\"><div class='tooltip'>ⓘ\
-                                    <span class='tooltiptext'>Important traits for {}</span></div>\
-                                    <div class=\"content hidden\">",
-                trait_
-            ),
-        );
-        out.push_str("</code></div></div>");
-    }
-
-    out.into_inner()
-}
-
 fn render_impl(
     w: &mut Buffer,
     cx: &Context,
@@ -3600,7 +3555,7 @@ fn render_impl(
     use_absolute: Option<bool>,
     is_on_foreign_type: bool,
     show_default_items: bool,
-    // This argument is used to reference same type with different pathes to avoid duplication
+    // This argument is used to reference same type with different paths to avoid duplication
     // in documentation pages for trait with automatic implementations like "Send" and "Sync".
     aliases: &[String],
 ) {
@@ -3695,14 +3650,13 @@ fn doc_impl_item(
                 (true, " hidden")
             };
         match item.inner {
-            clean::MethodItem(clean::Method { ref decl, .. })
-            | clean::TyMethodItem(clean::TyMethod { ref decl, .. }) => {
+            clean::MethodItem(clean::Method { .. })
+            | clean::TyMethodItem(clean::TyMethod { .. }) => {
                 // Only render when the method is not static or we allow static methods
                 if render_method_item {
                     let id = cx.derive_id(format!("{}.{}", item_type, name));
                     let ns_id = cx.derive_id(format!("{}.{}", name, item_type.name_space()));
                     write!(w, "<h4 id='{}' class=\"{}{}\">", id, item_type, extra_class);
-                    write!(w, "{}", spotlight_decl(decl));
                     write!(w, "<code id='{}'>", ns_id);
                     render_assoc_item(w, item, link.anchor(&id), ItemType::Impl);
                     write!(w, "</code>");
@@ -3815,7 +3769,7 @@ fn render_default_items(
     ) {
         for trait_item in &t.items {
             let n = trait_item.name.clone();
-            if i.items.iter().find(|m| m.name == n).is_some() {
+            if i.items.iter().any(|m| m.name == n) {
                 continue;
             }
             let did = i.trait_.as_ref().unwrap().def_id().unwrap();
@@ -3974,7 +3928,7 @@ fn print_sidebar(cx: &Context, it: &clean::Item, buffer: &mut Buffer) {
                 "<div class='block version'>\
                     <p>Version {}</p>\
                     </div>",
-                version
+                Escape(version)
             );
         }
     }
@@ -4609,7 +4563,7 @@ fn item_keyword(w: &mut Buffer, cx: &Context, it: &clean::Item) {
     document(w, cx, it)
 }
 
-crate const BASIC_KEYWORDS: &'static str = "rust, rustlang, rust-lang";
+crate const BASIC_KEYWORDS: &str = "rust, rustlang, rust-lang";
 
 fn make_item_keywords(it: &clean::Item) -> String {
     format!("{}, {}", BASIC_KEYWORDS, it.name.as_ref().unwrap())
index a0a35e4ce4b852d555d298b9ada5be64876d14f7..ed0de2b311955874864e05babb5645f9f128540d 100644 (file)
@@ -12,7 +12,7 @@
 use serde::Serialize;
 
 use super::{plain_summary_line, shorten, Impl, IndexItem, IndexItemFunctionType, ItemType};
-use super::{RenderInfo, Type};
+use super::{Generic, RenderInfo, RenderType, TypeWithKind};
 
 /// Indicates where an external crate can be found.
 pub enum ExternalLocation {
@@ -139,6 +139,7 @@ pub fn from_krate(
             deref_trait_did,
             deref_mut_trait_did,
             owned_box_did,
+            ..
         } = renderinfo;
 
         let external_paths =
@@ -587,17 +588,20 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String {
     let mut lastpathid = 0usize;
 
     for item in search_index {
-        item.parent_idx = item.parent.map(|defid| {
+        item.parent_idx = item.parent.and_then(|defid| {
             if defid_to_pathid.contains_key(&defid) {
-                *defid_to_pathid.get(&defid).expect("no pathid")
+                defid_to_pathid.get(&defid).map(|x| *x)
             } else {
                 let pathid = lastpathid;
                 defid_to_pathid.insert(defid, pathid);
                 lastpathid += 1;
 
-                let &(ref fqp, short) = paths.get(&defid).unwrap();
-                crate_paths.push((short, fqp.last().unwrap().clone()));
-                pathid
+                if let Some(&(ref fqp, short)) = paths.get(&defid) {
+                    crate_paths.push((short, fqp.last().unwrap().clone()));
+                    Some(pathid)
+                } else {
+                    None
+                }
             }
         });
 
@@ -646,20 +650,25 @@ fn get_index_search_type(item: &clean::Item) -> Option<IndexItemFunctionType> {
         _ => return None,
     };
 
-    let inputs =
-        all_types.iter().map(|arg| get_index_type(&arg)).filter(|a| a.name.is_some()).collect();
+    let inputs = all_types
+        .iter()
+        .map(|(ty, kind)| TypeWithKind::from((get_index_type(&ty), *kind)))
+        .filter(|a| a.ty.name.is_some())
+        .collect();
     let output = ret_types
         .iter()
-        .map(|arg| get_index_type(&arg))
-        .filter(|a| a.name.is_some())
+        .map(|(ty, kind)| TypeWithKind::from((get_index_type(&ty), *kind)))
+        .filter(|a| a.ty.name.is_some())
         .collect::<Vec<_>>();
     let output = if output.is_empty() { None } else { Some(output) };
 
     Some(IndexItemFunctionType { inputs, output })
 }
 
-fn get_index_type(clean_type: &clean::Type) -> Type {
-    let t = Type {
+fn get_index_type(clean_type: &clean::Type) -> RenderType {
+    let t = RenderType {
+        ty: clean_type.def_id(),
+        idx: None,
         name: get_index_type_name(clean_type, true).map(|s| s.to_ascii_lowercase()),
         generics: get_generics(clean_type),
     };
@@ -684,12 +693,17 @@ fn get_index_type_name(clean_type: &clean::Type, accept_generic: bool) -> Option
     }
 }
 
-fn get_generics(clean_type: &clean::Type) -> Option<Vec<String>> {
+fn get_generics(clean_type: &clean::Type) -> Option<Vec<Generic>> {
     clean_type.generics().and_then(|types| {
         let r = types
             .iter()
-            .filter_map(|t| get_index_type_name(t, false))
-            .map(|s| s.to_ascii_lowercase())
+            .filter_map(|t| {
+                if let Some(name) = get_index_type_name(t, false) {
+                    Some(Generic { name: name.to_ascii_lowercase(), defid: t.def_id(), idx: None })
+                } else {
+                    None
+                }
+            })
             .collect::<Vec<_>>();
         if r.is_empty() { None } else { Some(r) }
     })
index 79e7d3d783b807e422d19bab59008e9ebc7ac19a..86f46b2d7e15422214dfc8ca029583447eec6ecd 100644 (file)
@@ -35,7 +35,7 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
         // If we're including source files, and we haven't seen this file yet,
         // then we need to render it out to the filesystem.
         if self.scx.include_sources
-            // skip all invalid or macro spans
+            // skip all synthetic "files"
             && item.source.filename.is_real()
             // skip non-local items
             && item.def_id.is_local()
index 2870c6e0a6147c76c3df5342b4c6b23f950bc335..3f12fb893a440596248d307ab5970c4af663a6e2 100644 (file)
@@ -341,7 +341,6 @@ function getSearchElement() {
     function handleEscape(ev) {
         var help = getHelpElement();
         var search = getSearchElement();
-        hideModal();
         if (hasClass(help, "hidden") === false) {
             displayHelp(false, ev, help);
         } else if (hasClass(search, "hidden") === false) {
@@ -373,7 +372,6 @@ function getSearchElement() {
             case "s":
             case "S":
                 displayHelp(false, ev);
-                hideModal();
                 ev.preventDefault();
                 focusSearchBar();
                 break;
@@ -386,7 +384,6 @@ function getSearchElement() {
 
             case "?":
                 if (ev.shiftKey) {
-                    hideModal();
                     displayHelp(true, ev);
                 }
                 break;
@@ -526,13 +523,14 @@ function getSearchElement() {
     }
 
     function initSearch(rawSearchIndex) {
-        var currentResults, index, searchIndex;
         var MAX_LEV_DISTANCE = 3;
         var MAX_RESULTS = 200;
         var GENERICS_DATA = 1;
         var NAME = 0;
         var INPUTS_DATA = 0;
         var OUTPUT_DATA = 1;
+        var NO_TYPE_FILTER = -1;
+        var currentResults, index, searchIndex;
         var params = getQueryStringParams();
 
         // Populate search bar with query string search term when provided,
@@ -559,7 +557,7 @@ function getSearchElement() {
                         return i;
                     }
                 }
-                return -1;
+                return NO_TYPE_FILTER;
             }
 
             var valLower = query.query.toLowerCase(),
@@ -722,6 +720,13 @@ function getSearchElement() {
                 };
             }
 
+            function getObjectFromId(id) {
+                if (typeof id === "number") {
+                    return searchIndex[id];
+                }
+                return {'name': id};
+            }
+
             function checkGenerics(obj, val) {
                 // The names match, but we need to be sure that all generics kinda
                 // match as well.
@@ -738,8 +743,10 @@ function getSearchElement() {
                         for (var y = 0; y < vlength; ++y) {
                             var lev = { pos: -1, lev: MAX_LEV_DISTANCE + 1};
                             var elength = elems.length;
+                            var firstGeneric = getObjectFromId(val.generics[y]).name;
                             for (var x = 0; x < elength; ++x) {
-                                var tmp_lev = levenshtein(elems[x], val.generics[y]);
+                                var tmp_lev = levenshtein(getObjectFromId(elems[x]).name,
+                                                          firstGeneric);
                                 if (tmp_lev < lev.lev) {
                                     lev.lev = tmp_lev;
                                     lev.pos = x;
@@ -774,8 +781,9 @@ function getSearchElement() {
 
                                 for (var y = 0; allFound === true && y < val.generics.length; ++y) {
                                     allFound = false;
+                                    var firstGeneric = getObjectFromId(val.generics[y]).name;
                                     for (x = 0; allFound === false && x < elems.length; ++x) {
-                                        allFound = elems[x] === val.generics[y];
+                                        allFound = getObjectFromId(elems[x]).name === firstGeneric;
                                     }
                                     if (allFound === true) {
                                         elems.splice(x - 1, 1);
@@ -832,16 +840,22 @@ function getSearchElement() {
                 return lev_distance + 1;
             }
 
-            function findArg(obj, val, literalSearch) {
+            function findArg(obj, val, literalSearch, typeFilter) {
                 var lev_distance = MAX_LEV_DISTANCE + 1;
 
-                if (obj && obj.type && obj.type[INPUTS_DATA] &&
-                      obj.type[INPUTS_DATA].length > 0) {
+                if (obj && obj.type && obj.type[INPUTS_DATA] && obj.type[INPUTS_DATA].length > 0) {
                     var length = obj.type[INPUTS_DATA].length;
                     for (var i = 0; i < length; i++) {
-                        var tmp = checkType(obj.type[INPUTS_DATA][i], val, literalSearch);
-                        if (literalSearch === true && tmp === true) {
-                            return true;
+                        var tmp = obj.type[INPUTS_DATA][i];
+                        if (typePassesFilter(typeFilter, tmp[1]) === false) {
+                            continue;
+                        }
+                        tmp = checkType(tmp, val, literalSearch);
+                        if (literalSearch === true) {
+                            if (tmp === true) {
+                                return true;
+                            }
+                            continue;
                         }
                         lev_distance = Math.min(tmp, lev_distance);
                         if (lev_distance === 0) {
@@ -852,20 +866,20 @@ function getSearchElement() {
                 return literalSearch === true ? false : lev_distance;
             }
 
-            function checkReturned(obj, val, literalSearch) {
+            function checkReturned(obj, val, literalSearch, typeFilter) {
                 var lev_distance = MAX_LEV_DISTANCE + 1;
 
                 if (obj && obj.type && obj.type.length > OUTPUT_DATA) {
                     var ret = obj.type[OUTPUT_DATA];
-                    if (!obj.type[OUTPUT_DATA].length) {
+                    if (typeof ret[0] === "string") {
                         ret = [ret];
                     }
                     for (var x = 0; x < ret.length; ++x) {
-                        var r = ret[x];
-                        if (typeof r === "string") {
-                            r = [r];
+                        var tmp = ret[x];
+                        if (typePassesFilter(typeFilter, tmp[1]) === false) {
+                            continue;
                         }
-                        var tmp = checkType(r, val, literalSearch);
+                        tmp = checkType(tmp, val, literalSearch);
                         if (literalSearch === true) {
                             if (tmp === true) {
                                 return true;
@@ -920,7 +934,7 @@ function getSearchElement() {
 
             function typePassesFilter(filter, type) {
                 // No filter
-                if (filter < 0) return true;
+                if (filter <= NO_TYPE_FILTER) return true;
 
                 // Exact match
                 if (filter === type) return true;
@@ -929,11 +943,13 @@ function getSearchElement() {
                 var name = itemTypes[type];
                 switch (itemTypes[filter]) {
                     case "constant":
-                        return (name == "associatedconstant");
+                        return name === "associatedconstant";
                     case "fn":
-                        return (name == "method" || name == "tymethod");
+                        return name === "method" || name === "tymethod";
                     case "type":
-                        return (name == "primitive" || name == "keyword");
+                        return name === "primitive" || name === "associatedtype";
+                    case "trait":
+                        return name === "traitalias";
                 }
 
                 // No match
@@ -962,42 +978,33 @@ function getSearchElement() {
                     if (filterCrates !== undefined && searchIndex[i].crate !== filterCrates) {
                         continue;
                     }
-                    in_args = findArg(searchIndex[i], val, true);
-                    returned = checkReturned(searchIndex[i], val, true);
+                    in_args = findArg(searchIndex[i], val, true, typeFilter);
+                    returned = checkReturned(searchIndex[i], val, true, typeFilter);
                     ty = searchIndex[i];
                     fullId = generateId(ty);
 
-                    if (searchWords[i] === val.name) {
-                        // filter type: ... queries
-                        if (typePassesFilter(typeFilter, searchIndex[i].ty) &&
-                            results[fullId] === undefined)
-                        {
-                            results[fullId] = {id: i, index: -1};
-                        }
-                    } else if ((in_args === true || returned === true) &&
-                               typePassesFilter(typeFilter, searchIndex[i].ty)) {
-                        if (in_args === true || returned === true) {
-                            if (in_args === true) {
-                                results_in_args[fullId] = {
-                                    id: i,
-                                    index: -1,
-                                    dontValidate: true,
-                                };
-                            }
-                            if (returned === true) {
-                                results_returned[fullId] = {
-                                    id: i,
-                                    index: -1,
-                                    dontValidate: true,
-                                };
-                            }
-                        } else {
-                            results[fullId] = {
-                                id: i,
-                                index: -1,
-                                dontValidate: true,
-                            };
-                        }
+                    if (searchWords[i] === val.name
+                        && typePassesFilter(typeFilter, searchIndex[i].ty)
+                        && results[fullId] === undefined) {
+                        results[fullId] = {
+                            id: i,
+                            index: -1,
+                            dontValidate: true,
+                        };
+                    }
+                    if (in_args === true && results_in_args[fullId] === undefined) {
+                        results_in_args[fullId] = {
+                            id: i,
+                            index: -1,
+                            dontValidate: true,
+                        };
+                    }
+                    if (returned === true && results_returned[fullId] === undefined) {
+                        results_returned[fullId] = {
+                            id: i,
+                            index: -1,
+                            dontValidate: true,
+                        };
                     }
                 }
                 query.inputs = [val];
@@ -1028,7 +1035,7 @@ function getSearchElement() {
 
                     // allow searching for void (no output) functions as well
                     var typeOutput = type.length > OUTPUT_DATA ? type[OUTPUT_DATA].name : "";
-                    returned = checkReturned(ty, output, true);
+                    returned = checkReturned(ty, output, true, NO_TYPE_FILTER);
                     if (output.name === "*" || returned === true) {
                         in_args = false;
                         var is_module = false;
@@ -1129,16 +1136,8 @@ function getSearchElement() {
                             lev += 1;
                         }
                     }
-                    if ((in_args = findArg(ty, valGenerics)) <= MAX_LEV_DISTANCE) {
-                        if (typePassesFilter(typeFilter, ty.ty) === false) {
-                            in_args = MAX_LEV_DISTANCE + 1;
-                        }
-                    }
-                    if ((returned = checkReturned(ty, valGenerics)) <= MAX_LEV_DISTANCE) {
-                        if (typePassesFilter(typeFilter, ty.ty) === false) {
-                            returned = MAX_LEV_DISTANCE + 1;
-                        }
-                    }
+                    in_args = findArg(ty, valGenerics, false, typeFilter);
+                    returned = checkReturned(ty, valGenerics, false, typeFilter);
 
                     lev += lev_add;
                     if (lev > 0 && val.length > 3 && searchWords[j].indexOf(val) > -1) {
@@ -2504,31 +2503,6 @@ function getSearchElement() {
         lineNumbersFunc(e);
     });
 
-    function showModal(content) {
-        var modal = document.createElement("div");
-        modal.id = "important";
-        addClass(modal, "modal");
-        modal.innerHTML = "<div class=\"modal-content\"><div class=\"close\" id=\"modal-close\">✕" +
-                          "</div><div class=\"whiter\"></div><span class=\"docblock\">" + content +
-                          "</span></div>";
-        document.getElementsByTagName("body")[0].appendChild(modal);
-        document.getElementById("modal-close").onclick = hideModal;
-        modal.onclick = hideModal;
-    }
-
-    function hideModal() {
-        var modal = document.getElementById("important");
-        if (modal) {
-            modal.parentNode.removeChild(modal);
-        }
-    }
-
-    onEachLazy(document.getElementsByClassName("important-traits"), function(e) {
-        e.onclick = function() {
-            showModal(e.lastElementChild.innerHTML);
-        };
-    });
-
     // In the search display, allows to switch between tabs.
     function printTab(nb) {
         if (nb === 0 || nb === 1 || nb === 2) {
index 0dfe82c50146964cefadabac61c91ad9384fb78f..8887bca3c5962a7e1eaa6ae71e2785da0a4a8fb4 100644 (file)
@@ -143,12 +143,9 @@ code, pre, a.test-arrow {
        border-radius: 3px;
        padding: 0 0.1em;
 }
-.docblock pre code, .docblock-short pre code, .docblock code.spotlight {
+.docblock pre code, .docblock-short pre code {
        padding: 0;
 }
-.docblock code.spotlight :last-child {
-       padding-bottom: 0.6em;
-}
 pre {
        padding: 14px;
 }
@@ -503,7 +500,7 @@ h4 > code, h3 > code, .invisible > code {
        font-size: 0.8em;
 }
 
-.content .methods > div:not(.important-traits) {
+.content .methods > div {
        margin-left: 40px;
        margin-bottom: 15px;
 }
@@ -1035,7 +1032,7 @@ h3 > .collapse-toggle, h4 > .collapse-toggle {
 
 .information {
        position: absolute;
-       left: -20px;
+       left: -25px;
        margin-top: 7px;
        z-index: 1;
 }
@@ -1050,12 +1047,13 @@ h3 > .collapse-toggle, h4 > .collapse-toggle {
        width: 120px;
        display: none;
        text-align: center;
-       padding: 5px 3px;
+       padding: 5px 3px 3px 3px;
        border-radius: 6px;
        margin-left: 5px;
        top: -5px;
        left: 105%;
        z-index: 10;
+       font-size: 16px;
 }
 
 .tooltip:hover .tooltiptext {
@@ -1066,14 +1064,20 @@ h3 > .collapse-toggle, h4 > .collapse-toggle {
        content: " ";
        position: absolute;
        top: 50%;
-       left: 11px;
+       left: 16px;
        margin-top: -5px;
        border-width: 5px;
        border-style: solid;
 }
 
-.important-traits .tooltip .tooltiptext {
+.tooltip.compile_fail, .tooltip.ignore {
+       font-weight: bold;
+       font-size: 20px;
+}
+
+.tooltip .tooltiptext {
        border: 1px solid;
+       font-weight: normal;
 }
 
 pre.rust {
@@ -1117,17 +1121,6 @@ pre.rust {
        font-size: 16px;
 }
 
-.important-traits {
-       cursor: pointer;
-       z-index: 2;
-}
-
-h4 > .important-traits {
-       position: absolute;
-       left: -44px;
-       top: 2px;
-}
-
 #all-types {
        text-align: center;
        border: 1px solid;
@@ -1354,12 +1347,6 @@ h4 > .important-traits {
                z-index: 1;
        }
 
-       h4 > .important-traits {
-               position: absolute;
-               left: -22px;
-               top: 24px;
-       }
-
        #titles > div > div.count {
                float: left;
                width: 100%;
@@ -1462,82 +1449,12 @@ h4 > .important-traits {
        }
 }
 
-.modal {
-       position: fixed;
-       width: 100vw;
-       height: 100vh;
-       z-index: 10000;
-       top: 0;
-       left: 0;
-}
-
-.modal-content {
-       display: block;
-       max-width: 60%;
-       min-width: 200px;
-       padding: 8px;
-       top: 40%;
-       position: absolute;
-       left: 50%;
-       transform: translate(-50%, -40%);
-       border: 1px solid;
-       border-radius: 4px;
-       border-top-right-radius: 0;
-}
-
-.modal-content > .docblock {
-       margin: 0;
-}
-
 h3.important {
        margin: 0;
        margin-bottom: 13px;
        font-size: 19px;
 }
 
-.modal-content > .docblock > code.content {
-       margin: 0;
-       padding: 0;
-       font-size: 20px;
-}
-
-.modal-content > .close {
-       position: absolute;
-       font-weight: 900;
-       right: -25px;
-       top: -1px;
-       font-size: 18px;
-       width: 25px;
-       padding-right: 2px;
-       border-top-right-radius: 5px;
-       border-bottom-right-radius: 5px;
-       text-align: center;
-       border: 1px solid;
-       border-right: 0;
-       cursor: pointer;
-}
-
-.modal-content > .whiter {
-       height: 25px;
-       position: absolute;
-       width: 3px;
-       right: -2px;
-       top: 0px;
-}
-
-#main > div.important-traits {
-       position: absolute;
-       left: -24px;
-       margin-top: 16px;
-}
-
-.content > .methods > .method > div.important-traits {
-       position: absolute;
-       font-weight: 400;
-       left: -42px;
-       margin-top: 2px;
-}
-
 kbd {
        display: inline-block;
        padding: 3px 5px;
index 9a0e7bbabcba932d35ee51c3be0c90a16fff30a9..ff32a0fa09e4d1a9c26f274f05733b1ac2beb47b 100644 (file)
@@ -254,7 +254,7 @@ a.test-arrow:hover{
 }
 
 pre.compile_fail {
-       border-left: 2px solid rgba(255,0,0,.6);
+       border-left: 2px solid rgba(255,0,0,.8);
 }
 
 pre.compile_fail:hover, .information:hover + pre.compile_fail {
@@ -270,7 +270,7 @@ pre.ignore:hover, .information:hover + pre.ignore {
 }
 
 .tooltip.compile_fail {
-       color: rgba(255,0,0,.6);
+       color: rgba(255,0,0,.8);
 }
 
 .information > .compile_fail:hover {
@@ -282,7 +282,7 @@ pre.ignore:hover, .information:hover + pre.ignore {
 }
 
 .information > .ignore:hover {
-       color: rgba(255,142,0,1);
+       color: #ff9200;
 }
 
 .search-failed a {
@@ -290,20 +290,15 @@ pre.ignore:hover, .information:hover + pre.ignore {
 }
 
 .tooltip .tooltiptext {
-       background-color: black;
+       background-color: #000;
        color: #fff;
+       border-color: #000;
 }
 
 .tooltip .tooltiptext::after {
        border-color: transparent black transparent transparent;
 }
 
-.important-traits .tooltip .tooltiptext {
-       background-color: white;
-       color: black;
-       border-color: black;
-}
-
 #titles > div:not(.selected) {
        background-color: #252525;
        border-top-color: #252525;
@@ -317,33 +312,6 @@ pre.ignore:hover, .information:hover + pre.ignore {
        color: #888;
 }
 
-.modal {
-       background-color: rgba(0,0,0,0.3);
-}
-
-.modal-content {
-       background-color: #272727;
-       border-color: #999;
-}
-
-.modal-content > .close {
-       background-color: #272727;
-       border-color: #999;
-}
-
-.modal-content > .close:hover {
-       background-color: #ff1f1f;
-       color: white;
-}
-
-.modal-content > .whiter {
-       background-color: #272727;
-}
-
-.modal-content > .close:hover + .whiter {
-       background-color: #ff1f1f;
-}
-
 @media (max-width: 700px) {
        .sidebar-menu {
                background-color: #505050;
index ca8ea1c456a2c86745d8390b0f4031b015544be1..2b2819f7126b4aa2582623296248fd3424e42f41 100644 (file)
@@ -248,7 +248,7 @@ a.test-arrow:hover{
 }
 
 pre.compile_fail {
-       border-left: 2px solid rgba(255,0,0,.4);
+       border-left: 2px solid rgba(255,0,0,.5);
 }
 
 pre.compile_fail:hover, .information:hover + pre.compile_fail {
@@ -256,7 +256,7 @@ pre.compile_fail:hover, .information:hover + pre.compile_fail {
 }
 
 pre.ignore {
-       border-left: 2px solid rgba(255,142,0,.4);
+       border-left: 2px solid rgba(255,142,0,.6);
 }
 
 pre.ignore:hover, .information:hover + pre.ignore {
@@ -264,7 +264,7 @@ pre.ignore:hover, .information:hover + pre.ignore {
 }
 
 .tooltip.compile_fail {
-       color: rgba(255,0,0,.3);
+       color: rgba(255,0,0,.5);
 }
 
 .information > .compile_fail:hover {
@@ -272,11 +272,11 @@ pre.ignore:hover, .information:hover + pre.ignore {
 }
 
 .tooltip.ignore {
-       color: rgba(255,142,0,.3);
+       color: rgba(255,142,0,.6);
 }
 
 .information > .ignore:hover {
-       color: rgba(255,142,0,1);
+       color: #ff9200;
 }
 
 .search-failed a {
@@ -284,7 +284,7 @@ pre.ignore:hover, .information:hover + pre.ignore {
 }
 
 .tooltip .tooltiptext {
-       background-color: black;
+       background-color: #000;
        color: #fff;
 }
 
@@ -292,12 +292,6 @@ pre.ignore:hover, .information:hover + pre.ignore {
        border-color: transparent black transparent transparent;
 }
 
-.important-traits .tooltip .tooltiptext {
-       background-color: white;
-       color: black;
-       border-color: black;
-}
-
 #titles > div:not(.selected) {
        background-color: #e6e6e6;
        border-top-color: #e6e6e6;
@@ -311,33 +305,6 @@ pre.ignore:hover, .information:hover + pre.ignore {
        color: #888;
 }
 
-.modal {
-       background-color: rgba(0,0,0,0.3);
-}
-
-.modal-content {
-       background-color: #eee;
-       border-color: #999;
-}
-
-.modal-content > .close {
-       background-color: #eee;
-       border-color: #999;
-}
-
-.modal-content > .close:hover {
-       background-color: #ff1f1f;
-       color: white;
-}
-
-.modal-content > .whiter {
-       background-color: #eee;
-}
-
-.modal-content > .close:hover + .whiter {
-       background-color: #ff1f1f;
-}
-
 @media (max-width: 700px) {
        .sidebar-menu {
                background-color: #F1F1F1;
index 9fc1d76185fb7bf6aa12c41efe419c648f9bfe0c..6790f3bd5d0b19d2cf9cf573e5c0292ea4d965d9 100644 (file)
 //! directly written to a `Write` handle.
 
 /// The file contents of the main `rustdoc.css` file, responsible for the core layout of the page.
-pub static RUSTDOC_CSS: &'static str = include_str!("static/rustdoc.css");
+pub static RUSTDOC_CSS: &str = include_str!("static/rustdoc.css");
 
 /// The file contents of `settings.css`, responsible for the items on the settings page.
-pub static SETTINGS_CSS: &'static str = include_str!("static/settings.css");
+pub static SETTINGS_CSS: &str = include_str!("static/settings.css");
 
 /// The file contents of the `noscript.css` file, used in case JS isn't supported or is disabled.
-pub static NOSCRIPT_CSS: &'static str = include_str!("static/noscript.css");
+pub static NOSCRIPT_CSS: &str = include_str!("static/noscript.css");
 
 /// The file contents of `normalize.css`, included to even out standard elements between browser
 /// implementations.
-pub static NORMALIZE_CSS: &'static str = include_str!("static/normalize.css");
+pub static NORMALIZE_CSS: &str = include_str!("static/normalize.css");
 
 /// The file contents of `main.js`, which contains the core JavaScript used on documentation pages,
 /// including search behavior and docblock folding, among others.
-pub static MAIN_JS: &'static str = include_str!("static/main.js");
+pub static MAIN_JS: &str = include_str!("static/main.js");
 
 /// The file contents of `settings.js`, which contains the JavaScript used to handle the settings
 /// page.
-pub static SETTINGS_JS: &'static str = include_str!("static/settings.js");
+pub static SETTINGS_JS: &str = include_str!("static/settings.js");
 
 /// The file contents of `storage.js`, which contains functionality related to browser Local
 /// Storage, used to store documentation settings.
-pub static STORAGE_JS: &'static str = include_str!("static/storage.js");
+pub static STORAGE_JS: &str = include_str!("static/storage.js");
 
 /// The file contents of `brush.svg`, the icon used for the theme-switch button.
-pub static BRUSH_SVG: &'static [u8] = include_bytes!("static/brush.svg");
+pub static BRUSH_SVG: &[u8] = include_bytes!("static/brush.svg");
 
 /// The file contents of `wheel.svg`, the icon used for the settings button.
-pub static WHEEL_SVG: &'static [u8] = include_bytes!("static/wheel.svg");
+pub static WHEEL_SVG: &[u8] = include_bytes!("static/wheel.svg");
 
 /// The file contents of `down-arrow.svg`, the icon used for the crate choice combobox.
-pub static DOWN_ARROW_SVG: &'static [u8] = include_bytes!("static/down-arrow.svg");
+pub static DOWN_ARROW_SVG: &[u8] = include_bytes!("static/down-arrow.svg");
 
 /// The contents of `COPYRIGHT.txt`, the license listing for files distributed with documentation
 /// output.
-pub static COPYRIGHT: &'static [u8] = include_bytes!("static/COPYRIGHT.txt");
+pub static COPYRIGHT: &[u8] = include_bytes!("static/COPYRIGHT.txt");
 
 /// The contents of `LICENSE-APACHE.txt`, the text of the Apache License, version 2.0.
-pub static LICENSE_APACHE: &'static [u8] = include_bytes!("static/LICENSE-APACHE.txt");
+pub static LICENSE_APACHE: &[u8] = include_bytes!("static/LICENSE-APACHE.txt");
 
 /// The contents of `LICENSE-MIT.txt`, the text of the MIT License.
-pub static LICENSE_MIT: &'static [u8] = include_bytes!("static/LICENSE-MIT.txt");
+pub static LICENSE_MIT: &[u8] = include_bytes!("static/LICENSE-MIT.txt");
 
 /// The contents of `rust-logo.png`, the default icon of the documentation.
-pub static RUST_LOGO: &'static [u8] = include_bytes!("static/rust-logo.png");
+pub static RUST_LOGO: &[u8] = include_bytes!("static/rust-logo.png");
 /// The contents of `favicon.ico`, the default favicon of the documentation.
-pub static RUST_FAVICON: &'static [u8] = include_bytes!("static/favicon.ico");
+pub static RUST_FAVICON: &[u8] = include_bytes!("static/favicon.ico");
 
 /// The built-in themes given to every documentation site.
 pub mod themes {
     /// The "light" theme, selected by default when no setting is available. Used as the basis for
     /// the `--check-theme` functionality.
-    pub static LIGHT: &'static str = include_str!("static/themes/light.css");
+    pub static LIGHT: &str = include_str!("static/themes/light.css");
 
     /// The "dark" theme.
-    pub static DARK: &'static str = include_str!("static/themes/dark.css");
+    pub static DARK: &str = include_str!("static/themes/dark.css");
 }
 
 /// Files related to the Fira Sans font.
 pub mod fira_sans {
     /// The file `FiraSans-Regular.woff`, the Regular variant of the Fira Sans font.
-    pub static REGULAR: &'static [u8] = include_bytes!("static/FiraSans-Regular.woff");
+    pub static REGULAR: &[u8] = include_bytes!("static/FiraSans-Regular.woff");
 
     /// The file `FiraSans-Medium.woff`, the Medium variant of the Fira Sans font.
-    pub static MEDIUM: &'static [u8] = include_bytes!("static/FiraSans-Medium.woff");
+    pub static MEDIUM: &[u8] = include_bytes!("static/FiraSans-Medium.woff");
 
     /// The file `FiraSans-LICENSE.txt`, the license text for the Fira Sans font.
-    pub static LICENSE: &'static [u8] = include_bytes!("static/FiraSans-LICENSE.txt");
+    pub static LICENSE: &[u8] = include_bytes!("static/FiraSans-LICENSE.txt");
 }
 
 /// Files related to the Source Serif Pro font.
 pub mod source_serif_pro {
     /// The file `SourceSerifPro-Regular.ttf.woff`, the Regular variant of the Source Serif Pro
     /// font.
-    pub static REGULAR: &'static [u8] = include_bytes!("static/SourceSerifPro-Regular.ttf.woff");
+    pub static REGULAR: &[u8] = include_bytes!("static/SourceSerifPro-Regular.ttf.woff");
 
     /// The file `SourceSerifPro-Bold.ttf.woff`, the Bold variant of the Source Serif Pro font.
-    pub static BOLD: &'static [u8] = include_bytes!("static/SourceSerifPro-Bold.ttf.woff");
+    pub static BOLD: &[u8] = include_bytes!("static/SourceSerifPro-Bold.ttf.woff");
 
     /// The file `SourceSerifPro-It.ttf.woff`, the Italic variant of the Source Serif Pro font.
-    pub static ITALIC: &'static [u8] = include_bytes!("static/SourceSerifPro-It.ttf.woff");
+    pub static ITALIC: &[u8] = include_bytes!("static/SourceSerifPro-It.ttf.woff");
 
     /// The file `SourceSerifPro-LICENSE.txt`, the license text for the Source Serif Pro font.
-    pub static LICENSE: &'static [u8] = include_bytes!("static/SourceSerifPro-LICENSE.md");
+    pub static LICENSE: &[u8] = include_bytes!("static/SourceSerifPro-LICENSE.md");
 }
 
 /// Files related to the Source Code Pro font.
 pub mod source_code_pro {
     /// The file `SourceCodePro-Regular.woff`, the Regular variant of the Source Code Pro font.
-    pub static REGULAR: &'static [u8] = include_bytes!("static/SourceCodePro-Regular.woff");
+    pub static REGULAR: &[u8] = include_bytes!("static/SourceCodePro-Regular.woff");
 
     /// The file `SourceCodePro-Semibold.woff`, the Semibold variant of the Source Code Pro font.
-    pub static SEMIBOLD: &'static [u8] = include_bytes!("static/SourceCodePro-Semibold.woff");
+    pub static SEMIBOLD: &[u8] = include_bytes!("static/SourceCodePro-Semibold.woff");
 
     /// The file `SourceCodePro-LICENSE.txt`, the license text of the Source Code Pro font.
-    pub static LICENSE: &'static [u8] = include_bytes!("static/SourceCodePro-LICENSE.txt");
+    pub static LICENSE: &[u8] = include_bytes!("static/SourceCodePro-LICENSE.txt");
 }
 
 /// Files related to the sidebar in rustdoc sources.
 pub mod sidebar {
     /// File script to handle sidebar.
-    pub static SOURCE_SCRIPT: &'static str = include_str!("static/source-script.js");
+    pub static SOURCE_SCRIPT: &str = include_str!("static/source-script.js");
 }
index 4ea14ab9077c6dff2702e54c3ea41178a4159e4c..3c1f0509bba4d04b98e6b02e75cdc3e26f3a42f1 100644 (file)
@@ -38,6 +38,7 @@
 extern crate rustc_session;
 extern crate rustc_span as rustc_span;
 extern crate rustc_target;
+extern crate rustc_trait_selection;
 extern crate rustc_typeck;
 extern crate test as testing;
 #[macro_use]
@@ -48,8 +49,8 @@
 use std::panic;
 use std::process;
 
-use rustc::session::config::{make_crate_type_option, ErrorOutputType, RustcOptGroup};
-use rustc::session::{early_error, early_warn};
+use rustc_session::config::{make_crate_type_option, ErrorOutputType, RustcOptGroup};
+use rustc_session::{early_error, early_warn};
 
 #[macro_use]
 mod externalfiles;
index d4a7f3313a49b19844947642f5935f5114b9537a..f48224512ba4f9b54b45edc88f684dad9afe8aef 100644 (file)
@@ -1,4 +1,5 @@
 use crate::clean;
+use crate::config::OutputFormat;
 use crate::core::DocContext;
 use crate::fold::{self, DocFolder};
 use crate::passes::Pass;
@@ -6,6 +7,8 @@
 use rustc_ast::attr;
 use rustc_span::symbol::sym;
 use rustc_span::FileName;
+use serde::Serialize;
+use serde_json;
 
 use std::collections::BTreeMap;
 use std::ops;
     description: "counts the number of items with and without documentation",
 };
 
-fn calculate_doc_coverage(krate: clean::Crate, _: &DocContext<'_>) -> clean::Crate {
-    let mut calc = CoverageCalculator::default();
+fn calculate_doc_coverage(krate: clean::Crate, ctx: &DocContext<'_>) -> clean::Crate {
+    let mut calc = CoverageCalculator::new();
     let krate = calc.fold_crate(krate);
 
-    calc.print_results();
+    calc.print_results(ctx.renderinfo.borrow().output_format);
 
     krate
 }
 
-#[derive(Default, Copy, Clone)]
+#[derive(Default, Copy, Clone, Serialize)]
 struct ItemCount {
     total: u64,
     with_docs: u64,
@@ -64,13 +67,41 @@ fn add_assign(&mut self, rhs: Self) {
     }
 }
 
-#[derive(Default)]
 struct CoverageCalculator {
     items: BTreeMap<FileName, ItemCount>,
 }
 
+fn limit_filename_len(filename: String) -> String {
+    let nb_chars = filename.chars().count();
+    if nb_chars > 35 {
+        "...".to_string()
+            + &filename[filename.char_indices().nth(nb_chars - 32).map(|x| x.0).unwrap_or(0)..]
+    } else {
+        filename
+    }
+}
+
 impl CoverageCalculator {
-    fn print_results(&self) {
+    fn new() -> CoverageCalculator {
+        CoverageCalculator { items: Default::default() }
+    }
+
+    fn to_json(&self) -> String {
+        serde_json::to_string(
+            &self
+                .items
+                .iter()
+                .map(|(k, v)| (k.to_string(), v))
+                .collect::<BTreeMap<String, &ItemCount>>(),
+        )
+        .expect("failed to convert JSON data to string")
+    }
+
+    fn print_results(&self, output_format: Option<OutputFormat>) {
+        if output_format.map(|o| o.is_json()).unwrap_or_else(|| false) {
+            println!("{}", self.to_json());
+            return;
+        }
         let mut total = ItemCount::default();
 
         fn print_table_line() {
@@ -93,15 +124,7 @@ fn print_table_record(name: &str, count: ItemCount, percentage: f64) {
 
         for (file, &count) in &self.items {
             if let Some(percentage) = count.percentage() {
-                let mut name = file.to_string();
-                // if a filename is too long, shorten it so we don't blow out the table
-                // FIXME(misdreavus): this needs to count graphemes, and probably also track
-                // double-wide characters...
-                if name.len() > 35 {
-                    name = "...".to_string() + &name[name.len() - 32..];
-                }
-
-                print_table_record(&name, count, percentage);
+                print_table_record(&limit_filename_len(file.to_string()), count, percentage);
 
                 total += count;
             }
index 7aa90d667813fb8ecb40f8fdf3baa725291e439c..113c781e33205bc4ba89202d88c7906bc6303640 100644 (file)
@@ -1,4 +1,3 @@
-use rustc::lint;
 use rustc::ty;
 use rustc_ast::ast::{self, Ident};
 use rustc_errors::Applicability;
@@ -12,6 +11,7 @@
 };
 use rustc_hir::def_id::DefId;
 use rustc_resolve::ParentScope;
+use rustc_session::lint;
 use rustc_span::symbol::Symbol;
 use rustc_span::DUMMY_SP;
 
@@ -149,7 +149,7 @@ fn resolve(
                 // In case this is a trait item, skip the
                 // early return and try looking for the trait.
                 let value = match res {
-                    Res::Def(DefKind::Method, _) | Res::Def(DefKind::AssocConst, _) => true,
+                    Res::Def(DefKind::AssocFn, _) | Res::Def(DefKind::AssocConst, _) => true,
                     Res::Def(DefKind::AssocTy, _) => false,
                     Res::Def(DefKind::Variant, _) => {
                         return handle_variant(cx, res, extra_fragment);
@@ -348,7 +348,7 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> {
         let parent_node = self.cx.as_local_hir_id(item.def_id).and_then(|hir_id| {
             // FIXME: this fails hard for impls in non-module scope, but is necessary for the
             // current `resolve()` implementation.
-            match self.cx.as_local_hir_id(self.cx.tcx.parent_module(hir_id)).unwrap() {
+            match self.cx.as_local_hir_id(self.cx.tcx.parent_module(hir_id).to_def_id()).unwrap() {
                 id if id != hir_id => Some(id),
                 _ => None,
             }
@@ -813,7 +813,7 @@ fn ambiguity_error(
 
                     for (res, ns) in candidates {
                         let (action, mut suggestion) = match res {
-                            Res::Def(DefKind::Method, _) | Res::Def(DefKind::Fn, _) => {
+                            Res::Def(DefKind::AssocFn, _) | Res::Def(DefKind::Fn, _) => {
                                 ("add parentheses", format!("{}()", path_str))
                             }
                             Res::Def(DefKind::Macro(..), _) => {
index 71cff637c12727f0cd5152b4413021190f355cf4..38f371783e994d257462b0e88e25c03f54c6657c 100644 (file)
@@ -1,9 +1,9 @@
 //! Contains information about "passes", used to modify crate information during the documentation
 //! process.
 
-use rustc::lint;
 use rustc::middle::privacy::AccessLevels;
 use rustc_hir::def_id::{DefId, DefIdSet};
+use rustc_session::lint;
 use rustc_span::{InnerSpan, Span, DUMMY_SP};
 use std::mem;
 use std::ops::Range;
index b63dbbf80d86421939f50ec0e37f72ea093aaefa..c5aa4677d56595fad27ec1adea342cf5807eba25 100644 (file)
@@ -1,5 +1,4 @@
 use rustc::hir::map::Map;
-use rustc::session::{self, config, DiagnosticOutput};
 use rustc::util::common::ErrorReported;
 use rustc_ast::ast;
 use rustc_ast::with_globals;
@@ -8,6 +7,7 @@
 use rustc_hir as hir;
 use rustc_hir::intravisit;
 use rustc_interface::interface;
+use rustc_session::{self, config, DiagnosticOutput, Session};
 use rustc_span::edition::Edition;
 use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::sym;
@@ -52,7 +52,7 @@ pub fn run(options: Options) -> i32 {
         cg: options.codegen_options.clone(),
         externs: options.externs.clone(),
         unstable_features: UnstableFeatures::from_environment(),
-        lint_cap: Some(::rustc::lint::Level::Allow),
+        lint_cap: Some(rustc_session::lint::Level::Allow),
         actually_rustdoc: true,
         debugging_opts: config::DebuggingOptions { ..config::basic_debugging_options() },
         edition: options.edition,
@@ -107,12 +107,12 @@ pub fn run(options: Options) -> i32 {
                 let mut hir_collector = HirCollector {
                     sess: compiler.session(),
                     collector: &mut collector,
-                    map: *tcx.hir(),
+                    map: tcx.hir(),
                     codes: ErrorCodes::from(
                         compiler.session().opts.unstable_features.is_nightly_build(),
                     ),
                 };
-                hir_collector.visit_testable("".to_string(), &krate.attrs, |this| {
+                hir_collector.visit_testable("".to_string(), &krate.item.attrs, |this| {
                     intravisit::walk_crate(this, krate);
                 });
             });
@@ -146,6 +146,7 @@ fn scrape_test_config(krate: &::rustc_hir::Crate) -> TestOptions {
         TestOptions { no_crate_inject: false, display_warnings: false, attrs: Vec::new() };
 
     let test_attrs: Vec<_> = krate
+        .item
         .attrs
         .iter()
         .filter(|a| a.check_name(sym::doc))
@@ -449,7 +450,7 @@ pub fn make_test(
                         }
 
                         if !found_macro {
-                            if let ast::ItemKind::Mac(..) = item.kind {
+                            if let ast::ItemKind::MacCall(..) = item.kind {
                                 found_macro = true;
                             }
                         }
@@ -853,9 +854,9 @@ fn register_header(&mut self, name: &str, level: u32) {
 }
 
 struct HirCollector<'a, 'hir> {
-    sess: &'a session::Session,
+    sess: &'a Session,
     collector: &'a mut Collector,
-    map: &'a Map<'hir>,
+    map: Map<'hir>,
     codes: ErrorCodes,
 }
 
@@ -903,8 +904,8 @@ fn visit_testable<F: FnOnce(&mut Self)>(
 impl<'a, 'hir> intravisit::Visitor<'hir> for HirCollector<'a, 'hir> {
     type Map = Map<'hir>;
 
-    fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> {
-        intravisit::NestedVisitorMap::All(&self.map)
+    fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
+        intravisit::NestedVisitorMap::All(self.map)
     }
 
     fn visit_item(&mut self, item: &'hir hir::Item) {
@@ -955,7 +956,7 @@ fn visit_struct_field(&mut self, f: &'hir hir::StructField) {
     }
 
     fn visit_macro_def(&mut self, macro_def: &'hir hir::MacroDef) {
-        self.visit_testable(macro_def.name.to_string(), &macro_def.attrs, |_| ());
+        self.visit_testable(macro_def.ident.to_string(), &macro_def.attrs, |_| ());
     }
 }
 
index 8f2f88d08bf7a94727d76d9619b8c112ab47ed73..feaf391c95afbc861d61845795e316d73587a87e 100644 (file)
@@ -64,11 +64,11 @@ fn store_path(&mut self, did: DefId) {
 
     pub fn visit(mut self, krate: &'tcx hir::Crate) -> Module<'tcx> {
         let mut module = self.visit_mod_contents(
-            krate.span,
-            krate.attrs,
+            krate.item.span,
+            krate.item.attrs,
             &Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Public },
             hir::CRATE_HIR_ID,
-            &krate.module,
+            &krate.item.module,
             None,
         );
         // Attach the crate's exported macros to the top-level module:
@@ -620,8 +620,8 @@ fn visit_local_macro(
         def: &'tcx hir::MacroDef,
         renamed: Option<ast::Name>,
     ) -> Macro<'tcx> {
-        debug!("visit_local_macro: {}", def.name);
-        let tts = def.body.trees().collect::<Vec<_>>();
+        debug!("visit_local_macro: {}", def.ident);
+        let tts = def.ast.body.inner_tokens().trees().collect::<Vec<_>>();
         // Extract the spans of all matchers. They represent the "interface" of the macro.
         let matchers = tts.chunks(4).map(|arm| arm[0].span()).collect();
 
@@ -629,7 +629,7 @@ fn visit_local_macro(
             hid: def.hir_id,
             def_id: self.cx.tcx.hir().local_def_id(def.hir_id),
             attrs: &def.attrs,
-            name: renamed.unwrap_or(def.name),
+            name: renamed.unwrap_or(def.ident.name),
             whence: def.span,
             matchers,
             imported_from: None,
index 8965c6860c4e950c5827ce7a161ee5ad19196e9e..25f3ddcbebab69f848ebceae9b668022ef625a2e 100644 (file)
 #[derive(Debug, Default, Copy, Clone)]
 pub struct System;
 
-// The AllocRef impl just forwards to the GlobalAlloc impl, which is in `std::sys::*::alloc`.
+// The AllocRef impl checks the layout size to be non-zero and forwards to the GlobalAlloc impl,
+// which is in `std::sys::*::alloc`.
 #[unstable(feature = "allocator_api", issue = "32838")]
 unsafe impl AllocRef for System {
     #[inline]
-    unsafe fn alloc(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr> {
-        NonNull::new(GlobalAlloc::alloc(self, layout)).ok_or(AllocErr)
+    fn alloc(&mut self, layout: Layout) -> Result<(NonNull<u8>, usize), AllocErr> {
+        if layout.size() == 0 {
+            Ok((layout.dangling(), 0))
+        } else {
+            unsafe {
+                NonNull::new(GlobalAlloc::alloc(self, layout))
+                    .ok_or(AllocErr)
+                    .map(|p| (p, layout.size()))
+            }
+        }
     }
 
     #[inline]
-    unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr> {
-        NonNull::new(GlobalAlloc::alloc_zeroed(self, layout)).ok_or(AllocErr)
+    fn alloc_zeroed(&mut self, layout: Layout) -> Result<(NonNull<u8>, usize), AllocErr> {
+        if layout.size() == 0 {
+            Ok((layout.dangling(), 0))
+        } else {
+            unsafe {
+                NonNull::new(GlobalAlloc::alloc_zeroed(self, layout))
+                    .ok_or(AllocErr)
+                    .map(|p| (p, layout.size()))
+            }
+        }
     }
 
     #[inline]
     unsafe fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout) {
-        GlobalAlloc::dealloc(self, ptr.as_ptr(), layout)
+        if layout.size() != 0 {
+            GlobalAlloc::dealloc(self, ptr.as_ptr(), layout)
+        }
     }
 
     #[inline]
@@ -157,8 +176,18 @@ unsafe fn realloc(
         ptr: NonNull<u8>,
         layout: Layout,
         new_size: usize,
-    ) -> Result<NonNull<u8>, AllocErr> {
-        NonNull::new(GlobalAlloc::realloc(self, ptr.as_ptr(), layout, new_size)).ok_or(AllocErr)
+    ) -> Result<(NonNull<u8>, usize), AllocErr> {
+        match (layout.size(), new_size) {
+            (0, 0) => Ok((layout.dangling(), 0)),
+            (0, _) => self.alloc(Layout::from_size_align_unchecked(new_size, layout.align())),
+            (_, 0) => {
+                self.dealloc(ptr, layout);
+                Ok((layout.dangling(), 0))
+            }
+            (_, _) => NonNull::new(GlobalAlloc::realloc(self, ptr.as_ptr(), layout, new_size))
+                .ok_or(AllocErr)
+                .map(|p| (p, new_size)),
+        }
     }
 }
 
index 97db0ff3791d728f00fa24312607c7f0409ca157..34317c7a2ee3d9ab2cb10f0d06409749604dfea5 100644 (file)
@@ -92,6 +92,7 @@
 // a backtrace or actually symbolizing it.
 
 use crate::env;
+use crate::ffi::c_void;
 use crate::fmt;
 use crate::sync::atomic::{AtomicUsize, Ordering::SeqCst};
 use crate::sync::Mutex;
@@ -144,10 +145,16 @@ fn _assert<T: Send + Sync>() {}
 }
 
 struct BacktraceFrame {
-    frame: backtrace::Frame,
+    frame: RawFrame,
     symbols: Vec<BacktraceSymbol>,
 }
 
+enum RawFrame {
+    Actual(backtrace::Frame),
+    #[cfg(test)]
+    Fake,
+}
+
 struct BacktraceSymbol {
     name: Option<Vec<u8>>,
     filename: Option<BytesOrWide>,
@@ -162,8 +169,8 @@ enum BytesOrWide {
 impl fmt::Debug for Backtrace {
     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
         let mut capture = match &self.inner {
-            Inner::Unsupported => return fmt.write_str("unsupported backtrace"),
-            Inner::Disabled => return fmt.write_str("disabled backtrace"),
+            Inner::Unsupported => return fmt.write_str("<unsupported>"),
+            Inner::Disabled => return fmt.write_str("<disabled>"),
             Inner::Captured(c) => c.lock().unwrap(),
         };
         capture.resolve();
@@ -193,11 +200,11 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
         if let Some(fn_name) = self.name.as_ref().map(|b| backtrace::SymbolName::new(b)) {
             write!(fmt, "fn: \"{:#}\"", fn_name)?;
         } else {
-            write!(fmt, "fn: \"<unknown>\"")?;
+            write!(fmt, "fn: <unknown>")?;
         }
 
         if let Some(fname) = self.filename.as_ref() {
-            write!(fmt, ", file: {:?}", fname)?;
+            write!(fmt, ", file: \"{:?}\"", fname)?;
         }
 
         if let Some(line) = self.lineno.as_ref() {
@@ -293,7 +300,10 @@ fn create(ip: usize) -> Backtrace {
         let mut actual_start = None;
         unsafe {
             backtrace::trace_unsynchronized(|frame| {
-                frames.push(BacktraceFrame { frame: frame.clone(), symbols: Vec::new() });
+                frames.push(BacktraceFrame {
+                    frame: RawFrame::Actual(frame.clone()),
+                    symbols: Vec::new(),
+                });
                 if frame.symbol_address() as usize == ip && actual_start.is_none() {
                     actual_start = Some(frames.len());
                 }
@@ -393,8 +403,13 @@ fn resolve(&mut self) {
         let _lock = lock();
         for frame in self.frames.iter_mut() {
             let symbols = &mut frame.symbols;
+            let frame = match &frame.frame {
+                RawFrame::Actual(frame) => frame,
+                #[cfg(test)]
+                RawFrame::Fake => unimplemented!(),
+            };
             unsafe {
-                backtrace::resolve_frame_unsynchronized(&frame.frame, |symbol| {
+                backtrace::resolve_frame_unsynchronized(frame, |symbol| {
                     symbols.push(BacktraceSymbol {
                         name: symbol.name().map(|m| m.as_bytes().to_vec()),
                         filename: symbol.filename_raw().map(|b| match b {
@@ -408,3 +423,65 @@ fn resolve(&mut self) {
         }
     }
 }
+
+impl RawFrame {
+    fn ip(&self) -> *mut c_void {
+        match self {
+            RawFrame::Actual(frame) => frame.ip(),
+            #[cfg(test)]
+            RawFrame::Fake => 1 as *mut c_void,
+        }
+    }
+}
+
+#[test]
+fn test_debug() {
+    let backtrace = Backtrace {
+        inner: Inner::Captured(Mutex::new(Capture {
+            actual_start: 1,
+            resolved: true,
+            frames: vec![
+                BacktraceFrame {
+                    frame: RawFrame::Fake,
+                    symbols: vec![BacktraceSymbol {
+                        name: Some(b"std::backtrace::Backtrace::create".to_vec()),
+                        filename: Some(BytesOrWide::Bytes(b"rust/backtrace.rs".to_vec())),
+                        lineno: Some(100),
+                    }],
+                },
+                BacktraceFrame {
+                    frame: RawFrame::Fake,
+                    symbols: vec![BacktraceSymbol {
+                        name: Some(b"__rust_maybe_catch_panic".to_vec()),
+                        filename: None,
+                        lineno: None,
+                    }],
+                },
+                BacktraceFrame {
+                    frame: RawFrame::Fake,
+                    symbols: vec![
+                        BacktraceSymbol {
+                            name: Some(b"std::rt::lang_start_internal".to_vec()),
+                            filename: Some(BytesOrWide::Bytes(b"rust/rt.rs".to_vec())),
+                            lineno: Some(300),
+                        },
+                        BacktraceSymbol {
+                            name: Some(b"std::rt::lang_start".to_vec()),
+                            filename: Some(BytesOrWide::Bytes(b"rust/rt.rs".to_vec())),
+                            lineno: Some(400),
+                        },
+                    ],
+                },
+            ],
+        })),
+    };
+
+    #[rustfmt::skip]
+    let expected = "Backtrace [\
+    \n    { fn: \"__rust_maybe_catch_panic\" },\
+    \n    { fn: \"std::rt::lang_start_internal\", file: \"rust/rt.rs\", line: 300 },\
+    \n    { fn: \"std::rt::lang_start\", file: \"rust/rt.rs\", line: 400 },\
+    \n]";
+
+    assert_eq!(format!("{:#?}", backtrace), expected);
+}
index d0e1a01b006549b8223c59388bbc0bc53a043a52..44f8e8bd1717a97d892553553050476b19c79505 100644 (file)
@@ -2461,7 +2461,7 @@ pub fn new() -> RandomState {
         KEYS.with(|keys| {
             let (k0, k1) = keys.get();
             keys.set((k0.wrapping_add(1), k1));
-            RandomState { k0: k0, k1: k1 }
+            RandomState { k0, k1 }
         })
     }
 }
index af35a5d9b7c47966f1fcde33cf28ffb9e42869d6..6aad082a97f9a48ac40f0308429915c431a9cfcb 100644 (file)
@@ -723,8 +723,8 @@ pub struct ArgsOs {
 /// (such as `*` and `?`). On Windows this is not done, and such arguments are
 /// passed as-is.
 ///
-/// On glibc Linux, arguments are retrieved by placing a function in .init_array.
-/// glibc passes argc, argv, and envp to functions in .init_array, as a non-standard extension.
+/// On glibc Linux systems, arguments are retrieved by placing a function in ".init_array".
+/// Glibc passes argc, argv, and envp to functions in ".init_array", as a non-standard extension.
 /// This allows `std::env::args` to work even in a `cdylib` or `staticlib`, as it does on macOS
 /// and Windows.
 ///
@@ -758,8 +758,8 @@ pub fn args() -> Args {
 /// set to arbitrary text, and it may not even exist, so this property should
 /// not be relied upon for security purposes.
 ///
-/// On glibc Linux, arguments are retrieved by placing a function in .init_array.
-/// glibc passes argc, argv, and envp to functions in .init_array, as a non-standard extension.
+/// On glibc Linux systems, arguments are retrieved by placing a function in ".init_array".
+/// Glibc passes argc, argv, and envp to functions in ".init_array", as a non-standard extension.
 /// This allows `std::env::args` to work even in a `cdylib` or `staticlib`, as it does on macOS
 /// and Windows.
 ///
index b480581e21ba90c093664699ae88974dd8dd9bef..2a370f192964f8b5ae0841abfc6006128024abe8 100644 (file)
@@ -135,7 +135,7 @@ fn backtrace(&self) -> Option<&Backtrace> {
     /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_deprecated(since = "1.41.0", reason = "use the Display impl or to_string()")]
+    #[rustc_deprecated(since = "1.42.0", reason = "use the Display impl or to_string()")]
     fn description(&self) -> &str {
         "description() is deprecated; use Display"
     }
@@ -552,6 +552,9 @@ fn description(&self) -> &str {
     }
 }
 
+#[unstable(feature = "try_reserve", reason = "new API", issue = "48043")]
+impl Error for alloc::collections::TryReserveError {}
+
 // Copied from `any.rs`.
 impl dyn Error + 'static {
     /// Returns `true` if the boxed type is the same as `T`
index 941ea6a767c57d4a7d9621324774fcdbe8e62bb9..20425aea8d5177841f7ab5768bd203276eb6415a 100644 (file)
@@ -4,6 +4,9 @@
 //! *[See also the `f32` primitive type](../../std/primitive.f32.html).*
 //!
 //! Mathematically significant numbers are provided in the `consts` sub-module.
+//!
+//! Although using these constants won’t cause compilation warnings,
+//! new code should use the associated constants directly on the primitive type.
 
 #![stable(feature = "rust1", since = "1.0.0")]
 #![allow(missing_docs)]
index d89b38e1a003501c1002639537b890d1bbee9163..a1128a589a64a61b6cfea01c9d49603bea65dedb 100644 (file)
@@ -4,6 +4,9 @@
 //! *[See also the `f64` primitive type](../../std/primitive.f64.html).*
 //!
 //! Mathematically significant numbers are provided in the `consts` sub-module.
+//!
+//! Although using these constants won’t cause compilation warnings,
+//! new code should use the associated constants directly on the primitive type.
 
 #![stable(feature = "rust1", since = "1.0.0")]
 #![allow(missing_docs)]
index 09be3f1305052d4df072733e24fb151796e6fac8..e20fcfafa229b08f8d6711e05ee7765f46e96efd 100644 (file)
@@ -407,7 +407,7 @@ pub fn create<P: AsRef<Path>>(path: P) -> io::Result<File> {
     ///
     /// It is equivalent to `OpenOptions::new()` but allows you to write more
     /// readable code. Instead of `OpenOptions::new().read(true).open("foo.txt")`
-    /// you can write `File::with_options().read(true).open("foo.txt"). This
+    /// you can write `File::with_options().read(true).open("foo.txt")`. This
     /// also avoids the need to import `OpenOptions`.
     ///
     /// See the [`OpenOptions::new`] function for more details.
index 7b1beb1ecda80089bc6df13eceebb3ae39c99b5d..c0675eeba98da602fba6d31893d89578bb86d3e5 100644 (file)
@@ -1,12 +1,14 @@
 //! Asynchronous values.
 
-use core::cell::Cell;
-use core::marker::Unpin;
-use core::ops::{Drop, Generator, GeneratorState};
-use core::option::Option;
-use core::pin::Pin;
-use core::ptr::NonNull;
-use core::task::{Context, Poll};
+#[cfg(bootstrap)]
+use core::{
+    cell::Cell,
+    marker::Unpin,
+    ops::{Drop, Generator, GeneratorState},
+    pin::Pin,
+    ptr::NonNull,
+    task::{Context, Poll},
+};
 
 #[doc(inline)]
 #[stable(feature = "futures_api", since = "1.36.0")]
@@ -17,6 +19,7 @@
 /// This function returns a `GenFuture` underneath, but hides it in `impl Trait` to give
 /// better error messages (`impl Future` rather than `GenFuture<[closure.....]>`).
 // This is `const` to avoid extra errors after we recover from `const async fn`
+#[cfg(bootstrap)]
 #[doc(hidden)]
 #[unstable(feature = "gen_future", issue = "50547")]
 pub const fn from_generator<T: Generator<Yield = ()>>(x: T) -> impl Future<Output = T::Return> {
@@ -24,6 +27,7 @@ pub const fn from_generator<T: Generator<Yield = ()>>(x: T) -> impl Future<Outpu
 }
 
 /// A wrapper around generators used to implement `Future` for `async`/`await` code.
+#[cfg(bootstrap)]
 #[doc(hidden)]
 #[unstable(feature = "gen_future", issue = "50547")]
 #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
@@ -31,8 +35,10 @@ pub const fn from_generator<T: Generator<Yield = ()>>(x: T) -> impl Future<Outpu
 
 // We rely on the fact that async/await futures are immovable in order to create
 // self-referential borrows in the underlying generator.
+#[cfg(bootstrap)]
 impl<T: Generator<Yield = ()>> !Unpin for GenFuture<T> {}
 
+#[cfg(bootstrap)]
 #[doc(hidden)]
 #[unstable(feature = "gen_future", issue = "50547")]
 impl<T: Generator<Yield = ()>> Future for GenFuture<T> {
@@ -41,22 +47,22 @@ fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
         // Safe because we're !Unpin + !Drop mapping to a ?Unpin value
         let gen = unsafe { Pin::map_unchecked_mut(self, |s| &mut s.0) };
         let _guard = unsafe { set_task_context(cx) };
-        match gen.resume(
-            #[cfg(not(bootstrap))]
-            (),
-        ) {
+        match gen.resume(()) {
             GeneratorState::Yielded(()) => Poll::Pending,
             GeneratorState::Complete(x) => Poll::Ready(x),
         }
     }
 }
 
+#[cfg(bootstrap)]
 thread_local! {
     static TLS_CX: Cell<Option<NonNull<Context<'static>>>> = Cell::new(None);
 }
 
+#[cfg(bootstrap)]
 struct SetOnDrop(Option<NonNull<Context<'static>>>);
 
+#[cfg(bootstrap)]
 impl Drop for SetOnDrop {
     fn drop(&mut self) {
         TLS_CX.with(|tls_cx| {
@@ -67,6 +73,7 @@ fn drop(&mut self) {
 
 // Safety: the returned guard must drop before `cx` is dropped and before
 // any previous guard is dropped.
+#[cfg(bootstrap)]
 unsafe fn set_task_context(cx: &mut Context<'_>) -> SetOnDrop {
     // transmute the context's lifetime to 'static so we can store it.
     let cx = core::mem::transmute::<&mut Context<'_>, &mut Context<'static>>(cx);
@@ -74,6 +81,7 @@ unsafe fn set_task_context(cx: &mut Context<'_>) -> SetOnDrop {
     SetOnDrop(old_cx)
 }
 
+#[cfg(bootstrap)]
 #[doc(hidden)]
 #[unstable(feature = "gen_future", issue = "50547")]
 /// Polls a future in the current thread-local task waker.
index 9787cbb556bd237ba7c76bfaee5142c981cc303e..f36aa1846a16c172333b1397ed01204fbeaa890b 100644 (file)
@@ -96,7 +96,7 @@ impl<T> Cursor<T> {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new(inner: T) -> Cursor<T> {
-        Cursor { pos: 0, inner: inner }
+        Cursor { pos: 0, inner }
     }
 
     /// Consumes this cursor, returning the underlying value.
index a50dd9575de32f1fdf17bcbd14c7cdecad3221d3..dc831432c176f22d861f30fd8b1d5871071239f2 100644 (file)
@@ -371,7 +371,7 @@ fn read_to_end_with_reservation<R, F>(
     F: FnMut(&R) -> usize,
 {
     let start_len = buf.len();
-    let mut g = Guard { len: buf.len(), buf: buf };
+    let mut g = Guard { len: buf.len(), buf };
     let ret;
     loop {
         if g.len == g.buf.len() {
@@ -497,7 +497,6 @@ pub(crate) fn default_write_vectored<F>(write: F, bufs: &[IoSlice<'_>]) -> Resul
 /// [`&str`]: ../../std/primitive.str.html
 /// [slice]: ../../std/primitive.slice.html
 #[stable(feature = "rust1", since = "1.0.0")]
-#[doc(spotlight)]
 pub trait Read {
     /// Pull some bytes from this source into the specified buffer, returning
     /// how many bytes were read.
@@ -939,7 +938,7 @@ fn take(self, limit: u64) -> Take<Self>
     where
         Self: Sized,
     {
-        Take { inner: self, limit: limit }
+        Take { inner: self, limit }
     }
 }
 
@@ -1051,6 +1050,7 @@ fn deref_mut(&mut self) -> &mut [u8] {
 /// ABI compatible with the `iovec` type on Unix platforms and `WSABUF` on
 /// Windows.
 #[stable(feature = "iovec", since = "1.36.0")]
+#[derive(Copy, Clone)]
 #[repr(transparent)]
 pub struct IoSlice<'a>(sys::io::IoSlice<'a>);
 
@@ -1228,7 +1228,6 @@ pub fn initialize(&self, buf: &mut [u8]) {
 ///
 /// [`write_all`]: #method.write_all
 #[stable(feature = "rust1", since = "1.0.0")]
-#[doc(spotlight)]
 pub trait Write {
     /// Write a buffer into this writer, returning how many bytes were written.
     ///
index d410faca30d9e65b481461a7d4f090cbc53db26c..0fb0757792ed7c3ade51ac38223d597db3aed1ee 100644 (file)
@@ -792,10 +792,14 @@ fn print_to<T>(
 {
     let result = local_s
         .try_with(|s| {
-            if let Ok(mut borrowed) = s.try_borrow_mut() {
-                if let Some(w) = borrowed.as_mut() {
-                    return w.write_fmt(args);
-                }
+            // Note that we completely remove a local sink to write to in case
+            // our printing recursively panics/prints, so the recursive
+            // panic/print goes to the global sink instead of our local sink.
+            let prev = s.borrow_mut().take();
+            if let Some(mut w) = prev {
+                let result = w.write_fmt(args);
+                *s.borrow_mut() = Some(w);
+                return result;
             }
             global_s().write_fmt(args)
         })
index 3c69c1160d5b57088dbcec1aa18d91bba2190f6a..314424631fcbf7a16d4caa5a8ec3cc2c4eb32bbc 100644 (file)
@@ -234,12 +234,55 @@ mod crate_keyword {}
 
 #[doc(keyword = "else")]
 //
-/// What to do when an [`if`] condition does not hold.
+/// What expression to evaluate when an [`if`] condition evaluates to [`false`].
 ///
-/// The documentation for this keyword is [not yet complete]. Pull requests welcome!
+/// `else` expressions are optional. When no else expressions are supplied it is assumed to evaluate
+/// to the unit type `()`.
+///
+/// The type that the `else` blocks evaluate to must be compatible with the type that the `if` block
+/// evaluates to.
+///
+/// As can be seen below, `else` must be followed by either: `if`, `if let`, or a block `{}` and it
+/// will return the value of that expression.
+///
+/// ```rust
+/// let result = if true == false {
+///     "oh no"
+/// } else if "something" == "other thing" {
+///     "oh dear"
+/// } else if let Some(200) = "blarg".parse::<i32>().ok() {
+///     "uh oh"
+/// } else {
+///     println!("Sneaky side effect.");
+///     "phew, nothing's broken"
+/// };
+/// ```
+///
+/// Here's another example but here we do not try and return an expression:
+///
+/// ```rust
+/// if true == false {
+///     println!("oh no");
+/// } else if "something" == "other thing" {
+///     println!("oh dear");
+/// } else if let Some(200) = "blarg".parse::<i32>().ok() {
+///     println!("uh oh");
+/// } else {
+///     println!("phew, nothing's broken");
+/// }
+/// ```
 ///
+/// The above is _still_ an expression but it will always evaluate to `()`.
+///
+/// There is possibly no limit to the number of `else` blocks that could follow an `if` expression
+/// however if you have several then a [`match`] expression might be preferable.
+///
+/// Read more about control flow in the [Rust Book].
+///
+/// [Rust Book]: ../book/ch03-05-control-flow.html#handling-multiple-conditions-with-else-if
+/// [`match`]: keyword.match.html
+/// [`false`]: keyword.false.html
 /// [`if`]: keyword.if.html
-/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601
 mod else_keyword {}
 
 #[doc(keyword = "enum")]
@@ -637,10 +680,18 @@ mod impl_keyword {}
 //
 /// Iterate over a series of values with [`for`].
 ///
-/// The documentation for this keyword is [not yet complete]. Pull requests welcome!
+/// The expression immediately following `in` must implement the [`Iterator`] trait.
+///
+/// ## Literal Examples:
+///
+///    * `for _ **in** 1..3 {}` - Iterate over an exclusive range up to but excluding 3.
+///    * `for _ **in** 1..=3 {}` - Iterate over an inclusive range up to and includeing 3.
+///
+/// (Read more about [range patterns])
 ///
+/// [`Iterator`]: ../book/ch13-04-performance.html
+/// [`range patterns`]: ../reference/patterns.html?highlight=range#range-patterns
 /// [`for`]: keyword.for.html
-/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601
 mod in_keyword {}
 
 #[doc(keyword = "let")]
@@ -925,9 +976,15 @@ mod mut_keyword {}
 //
 /// Make an item visible to others.
 ///
-/// The documentation for this keyword is [not yet complete]. Pull requests welcome!
+/// The keyword `pub` makes any module, function, or data structure accessible from inside
+/// of external modules. The `pub` keyword may also be used in a `use` declaration to re-export
+/// an identifier from a namespace.
 ///
-/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601
+/// For more information on the `pub` keyword, please see the visibility section
+/// of the [reference] and for some examples, see [Rust by Example].
+///
+/// [reference]:../reference/visibility-and-privacy.html?highlight=pub#visibility-and-privacy
+/// [Rust by Example]:../rust-by-example/mod/visibility.html
 mod pub_keyword {}
 
 #[doc(keyword = "ref")]
index 7b3c702b929c0b9a3cfa0e355220545b6fc1b103..1f122b02b6a29b1398c4df5b301f615256db5894 100644 (file)
 #![feature(arbitrary_self_types)]
 #![feature(array_error_internals)]
 #![feature(asm)]
-#![feature(assoc_int_consts)]
 #![feature(associated_type_bounds)]
 #![feature(atomic_mut_ptr)]
 #![feature(box_syntax)]
 #![feature(c_variadic)]
+#![cfg_attr(not(bootstrap), feature(cfg_accessible))]
 #![feature(cfg_target_has_atomic)]
 #![feature(cfg_target_thread_local)]
 #![feature(char_error_internals)]
 #![feature(doc_cfg)]
 #![feature(doc_keyword)]
 #![feature(doc_masked)]
-#![feature(doc_spotlight)]
 #![feature(dropck_eyepatch)]
 #![feature(duration_constants)]
 #![feature(exact_size_is_empty)]
 #![feature(shrink_to)]
 #![feature(slice_concat_ext)]
 #![feature(slice_internals)]
-#![feature(specialization)]
+#![cfg_attr(bootstrap, feature(specialization))]
+#![cfg_attr(not(bootstrap), feature(min_specialization))]
 #![feature(staged_api)]
 #![feature(std_internals)]
 #![feature(stdsimd)]
index 9e1ac8754d9b058d3ea1e20ec53f8d9290011690..7fd7de56f4615a1a97fb589e2ecec1469ba6fea5 100644 (file)
@@ -185,7 +185,7 @@ macro_rules! eprintln {
 /// builds or when debugging in release mode is significantly faster.
 ///
 /// Note that the macro is intended as a debugging tool and therefore you
-/// should avoid having uses of it in version control for longer periods.
+/// should avoid having uses of it in version control for long periods.
 /// Use cases involving debug output that should be added to version control
 /// are better served by macros such as [`debug!`] from the [`log`] crate.
 ///
index a59d7f0263bb0a3b7955d9cb407a3b7b7c34be45..57cba6b1f7a1be6949bb0d85dd8d5a15e43f2d57 100644 (file)
@@ -901,7 +901,7 @@ impl ToSocketAddrs for str {
     type Iter = vec::IntoIter<SocketAddr>;
     fn to_socket_addrs(&self) -> io::Result<vec::IntoIter<SocketAddr>> {
         // try to parse as a regular SocketAddr first
-        if let Some(addr) = self.parse().ok() {
+        if let Ok(addr) = self.parse() {
             return Ok(vec![addr].into_iter());
         }
 
index 200b00b119595e7038e1890082d7e24a4b3ece19..edc28033c9b8323401654efae890b6d3548682c4 100644 (file)
@@ -651,7 +651,7 @@ pub fn is_benchmarking(&self) -> bool {
 
     /// Returns [`true`] if this address is reserved by IANA for future use. [IETF RFC 1112]
     /// defines the block of reserved addresses as `240.0.0.0/4`. This range normally includes the
-    /// broadcast address `255.255.255.255`, but this implementation explicitely excludes it, since
+    /// broadcast address `255.255.255.255`, but this implementation explicitly excludes it, since
     /// it is obviously not reserved for future use.
     ///
     /// [IETF RFC 1112]: https://tools.ietf.org/html/rfc1112
index 868a7e261c4972b2d0a0828828c4e7951bf5e578..3f38ee5471081afeac9354c8c89dff56abd45876 100644 (file)
@@ -206,7 +206,7 @@ fn ipv6_addr_from_head_tail(head: &[u16], tail: &[u16]) -> Ipv6Addr {
         }
 
         // read `::` if previous code parsed less than 8 groups
-        if !self.read_given_char(':').is_some() || !self.read_given_char(':').is_some() {
+        if self.read_given_char(':').is_none() || self.read_given_char(':').is_none() {
             return None;
         }
 
index dd71201b50b91a632a17128f167540dd3e8c8ccd..d22b44a06666295787ed0a614c5418b35ad51ecb 100644 (file)
@@ -34,7 +34,7 @@ pub trait MetadataExt {
     /// }
     /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
-    #[rustc_deprecated(since = "1.8.0", reason = "other methods of this trait are now prefered")]
+    #[rustc_deprecated(since = "1.8.0", reason = "other methods of this trait are now preferred")]
     #[allow(deprecated)]
     fn as_raw_stat(&self) -> &raw::stat;
 
index 8b12aaaa7e2fd25c6cdf69b9a9d06ffbe122d8c4..10078bd4aee823b7ebd1397e7d781356e334f18d 100644 (file)
@@ -14,7 +14,6 @@
 use crate::intrinsics;
 use crate::mem::{self, ManuallyDrop};
 use crate::process;
-use crate::raw;
 use crate::sync::atomic::{AtomicBool, Ordering};
 use crate::sys::stdio::panic_output;
 use crate::sys_common::backtrace::{self, RustBacktrace};
 // hook up these functions, but it is not this day!
 #[allow(improper_ctypes)]
 extern "C" {
-    fn __rust_maybe_catch_panic(
-        f: fn(*mut u8),
-        data: *mut u8,
-        data_ptr: *mut usize,
-        vtable_ptr: *mut usize,
-    ) -> u32;
+    fn __rust_panic_cleanup(payload: *mut u8) -> *mut (dyn Any + Send + 'static);
 
     /// `payload` is actually a `*mut &mut dyn BoxMeUp` but that would cause FFI warnings.
     /// It cannot be `Box<dyn BoxMeUp>` because the other end of this call does not depend
@@ -247,54 +241,88 @@ pub unsafe fn r#try<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>>
     union Data<F, R> {
         f: ManuallyDrop<F>,
         r: ManuallyDrop<R>,
+        p: ManuallyDrop<Box<dyn Any + Send>>,
     }
 
     // We do some sketchy operations with ownership here for the sake of
-    // performance. We can only  pass pointers down to
-    // `__rust_maybe_catch_panic` (can't pass objects by value), so we do all
-    // the ownership tracking here manually using a union.
+    // performance. We can only pass pointers down to `do_call` (can't pass
+    // objects by value), so we do all the ownership tracking here manually
+    // using a union.
     //
     // We go through a transition where:
     //
-    // * First, we set the data to be the closure that we're going to call.
+    // * First, we set the data field `f` to be the argumentless closure that we're going to call.
     // * When we make the function call, the `do_call` function below, we take
-    //   ownership of the function pointer. At this point the `Data` union is
+    //   ownership of the function pointer. At this point the `data` union is
     //   entirely uninitialized.
     // * If the closure successfully returns, we write the return value into the
-    //   data's return slot. Note that `ptr::write` is used as it's overwriting
-    //   uninitialized data.
-    // * Finally, when we come back out of the `__rust_maybe_catch_panic` we're
+    //   data's return slot (field `r`).
+    // * If the closure panics (`do_catch` below), we write the panic payload into field `p`.
+    // * Finally, when we come back out of the `try` intrinsic we're
     //   in one of two states:
     //
     //      1. The closure didn't panic, in which case the return value was
-    //         filled in. We move it out of `data` and return it.
-    //      2. The closure panicked, in which case the return value wasn't
-    //         filled in. In this case the entire `data` union is invalid, so
-    //         there is no need to drop anything.
+    //         filled in. We move it out of `data.r` and return it.
+    //      2. The closure panicked, in which case the panic payload was
+    //         filled in. We move it out of `data.p` and return it.
     //
     // Once we stack all that together we should have the "most efficient'
     // method of calling a catch panic whilst juggling ownership.
-    let mut any_data = 0;
-    let mut any_vtable = 0;
     let mut data = Data { f: ManuallyDrop::new(f) };
 
-    let r = __rust_maybe_catch_panic(
-        do_call::<F, R>,
-        &mut data as *mut _ as *mut u8,
-        &mut any_data,
-        &mut any_vtable,
-    );
-
-    return if r == 0 {
+    let data_ptr = &mut data as *mut _ as *mut u8;
+    return if do_try(do_call::<F, R>, data_ptr, do_catch::<F, R>) == 0 {
         Ok(ManuallyDrop::into_inner(data.r))
     } else {
-        update_panic_count(-1);
-        Err(mem::transmute(raw::TraitObject {
-            data: any_data as *mut _,
-            vtable: any_vtable as *mut _,
-        }))
+        Err(ManuallyDrop::into_inner(data.p))
     };
 
+    // Compatibility wrapper around the try intrinsic for bootstrap.
+    //
+    // We also need to mark it #[inline(never)] to work around a bug on MinGW
+    // targets: the unwinding implementation was relying on UB, but this only
+    // becomes a problem in practice if inlining is involved.
+    #[cfg(not(bootstrap))]
+    use intrinsics::r#try as do_try;
+    #[cfg(bootstrap)]
+    #[inline(never)]
+    unsafe fn do_try(try_fn: fn(*mut u8), data: *mut u8, catch_fn: fn(*mut u8, *mut u8)) -> i32 {
+        use crate::mem::MaybeUninit;
+        #[cfg(target_env = "msvc")]
+        type TryPayload = [u64; 2];
+        #[cfg(not(target_env = "msvc"))]
+        type TryPayload = *mut u8;
+
+        let mut payload: MaybeUninit<TryPayload> = MaybeUninit::uninit();
+        let payload_ptr = payload.as_mut_ptr() as *mut u8;
+        let r = intrinsics::r#try(try_fn, data, payload_ptr);
+        if r != 0 {
+            #[cfg(target_env = "msvc")]
+            {
+                catch_fn(data, payload_ptr)
+            }
+            #[cfg(not(target_env = "msvc"))]
+            {
+                catch_fn(data, payload.assume_init())
+            }
+        }
+        r
+    }
+
+    // We consider unwinding to be rare, so mark this function as cold. However,
+    // do not mark it no-inline -- that decision is best to leave to the
+    // optimizer (in most cases this function is not inlined even as a normal,
+    // non-cold function, though, as of the writing of this comment).
+    #[cold]
+    unsafe fn cleanup(payload: *mut u8) -> Box<dyn Any + Send + 'static> {
+        let obj = Box::from_raw(__rust_panic_cleanup(payload));
+        update_panic_count(-1);
+        obj
+    }
+
+    // See comment on do_try above for why #[inline(never)] is needed on bootstrap.
+    #[cfg_attr(bootstrap, inline(never))]
+    #[cfg_attr(not(bootstrap), inline)]
     fn do_call<F: FnOnce() -> R, R>(data: *mut u8) {
         unsafe {
             let data = data as *mut Data<F, R>;
@@ -303,6 +331,19 @@ fn do_call<F: FnOnce() -> R, R>(data: *mut u8) {
             data.r = ManuallyDrop::new(f());
         }
     }
+
+    // We *do* want this part of the catch to be inlined: this allows the
+    // compiler to properly track accesses to the Data union and optimize it
+    // away most of the time.
+    #[inline]
+    fn do_catch<F: FnOnce() -> R, R>(data: *mut u8, payload: *mut u8) {
+        unsafe {
+            let data = data as *mut Data<F, R>;
+            let data = &mut (*data);
+            let obj = cleanup(payload);
+            data.p = ManuallyDrop::new(obj);
+        }
+    }
 }
 
 /// Determines whether the current thread is unwinding because of panic.
index 7c0efe828c27acff030c97a114b8dc5797631dc0..6712f5ba5808c4f14c361a34021cf92d8c33adf3 100644 (file)
     PartialEq, PartialOrd, RustcDecodable, RustcEncodable,
 };
 
+#[cfg(not(bootstrap))]
+#[unstable(
+    feature = "cfg_accessible",
+    issue = "64797",
+    reason = "`cfg_accessible` is not fully implemented"
+)]
+#[doc(hidden)]
+pub use core::prelude::v1::cfg_accessible;
+
 // The file so far is equivalent to src/libcore/prelude/v1.rs,
 // and below to src/liballoc/prelude.rs.
 // Those files are duplicated rather than using glob imports
index d4b41e11c0e82ccae35a1e7734869da0218fa8a1..adad90f56d1cf57810770e9568e083b0d714e872 100644 (file)
@@ -771,7 +771,7 @@ mod prim_tuple {}
 #[doc(primitive = "f32")]
 /// The 32-bit floating point type.
 ///
-/// *[See also the `std::f32` module](f32/index.html).*
+/// *[See also the `std::f32::consts` module](f32/consts/index.html).*
 ///
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_f32 {}
@@ -780,7 +780,7 @@ mod prim_f32 {}
 //
 /// The 64-bit floating point type.
 ///
-/// *[See also the `std::f64` module](f64/index.html).*
+/// *[See also the `std::f64::consts` module](f64/consts/index.html).*
 ///
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_f64 {}
@@ -788,80 +788,60 @@ mod prim_f64 {}
 #[doc(primitive = "i8")]
 //
 /// The 8-bit signed integer type.
-///
-/// *[See also the `std::i8` module](i8/index.html).*
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_i8 {}
 
 #[doc(primitive = "i16")]
 //
 /// The 16-bit signed integer type.
-///
-/// *[See also the `std::i16` module](i16/index.html).*
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_i16 {}
 
 #[doc(primitive = "i32")]
 //
 /// The 32-bit signed integer type.
-///
-/// *[See also the `std::i32` module](i32/index.html).*
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_i32 {}
 
 #[doc(primitive = "i64")]
 //
 /// The 64-bit signed integer type.
-///
-/// *[See also the `std::i64` module](i64/index.html).*
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_i64 {}
 
 #[doc(primitive = "i128")]
 //
 /// The 128-bit signed integer type.
-///
-/// *[See also the `std::i128` module](i128/index.html).*
 #[stable(feature = "i128", since = "1.26.0")]
 mod prim_i128 {}
 
 #[doc(primitive = "u8")]
 //
 /// The 8-bit unsigned integer type.
-///
-/// *[See also the `std::u8` module](u8/index.html).*
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_u8 {}
 
 #[doc(primitive = "u16")]
 //
 /// The 16-bit unsigned integer type.
-///
-/// *[See also the `std::u16` module](u16/index.html).*
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_u16 {}
 
 #[doc(primitive = "u32")]
 //
 /// The 32-bit unsigned integer type.
-///
-/// *[See also the `std::u32` module](u32/index.html).*
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_u32 {}
 
 #[doc(primitive = "u64")]
 //
 /// The 64-bit unsigned integer type.
-///
-/// *[See also the `std::u64` module](u64/index.html).*
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_u64 {}
 
 #[doc(primitive = "u128")]
 //
 /// The 128-bit unsigned integer type.
-///
-/// *[See also the `std::u128` module](u128/index.html).*
 #[stable(feature = "i128", since = "1.26.0")]
 mod prim_u128 {}
 
@@ -869,8 +849,6 @@ mod prim_u128 {}
 //
 /// The pointer-sized signed integer type.
 ///
-/// *[See also the `std::isize` module](isize/index.html).*
-///
 /// The size of this primitive is how many bytes it takes to reference any
 /// location in memory. For example, on a 32 bit target, this is 4 bytes
 /// and on a 64 bit target, this is 8 bytes.
@@ -881,8 +859,6 @@ mod prim_isize {}
 //
 /// The pointer-sized unsigned integer type.
 ///
-/// *[See also the `std::usize` module](usize/index.html).*
-///
 /// The size of this primitive is how many bytes it takes to reference any
 /// location in memory. For example, on a 32 bit target, this is 4 bytes
 /// and on a 64 bit target, this is 8 bytes.
index c51aa7619db77c3935dcb67aaeca3f0fa9463302..0274268f69f25b34f43084bf1b82bc2b4cd34489 100644 (file)
@@ -40,7 +40,7 @@ struct Consumer<T, Addition> {
     tail: UnsafeCell<*mut Node<T>>, // where to pop from
     tail_prev: AtomicPtr<Node<T>>,  // where to pop from
     cache_bound: usize,             // maximum cache size
-    cached_nodes: AtomicUsize,      // number of nodes marked as cachable
+    cached_nodes: AtomicUsize,      // number of nodes marked as cacheable
     addition: Addition,
 }
 
index 6eeddc28512d95716c9e271de8c244e3a8646cbf..0cb16b19d7326767cb2282cd74edfea3489f66d0 100644 (file)
@@ -416,7 +416,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 
 impl<'mutex, T: ?Sized> MutexGuard<'mutex, T> {
     unsafe fn new(lock: &'mutex Mutex<T>) -> LockResult<MutexGuard<'mutex, T>> {
-        poison::map_result(lock.poison.borrow(), |guard| MutexGuard { lock: lock, poison: guard })
+        poison::map_result(lock.poison.borrow(), |guard| MutexGuard { lock, poison: guard })
     }
 }
 
index b99b4d8d9fdf012bb15caa6138e836176113a543..1e6b6c430be906e241e80ee1f03161504497b097 100644 (file)
@@ -363,7 +363,7 @@ pub fn call_once_force<F>(&self, f: F)
     /// assert!(handle.join().is_err());
     /// assert_eq!(INIT.is_completed(), false);
     /// ```
-    #[stable(feature = "once_is_completed", since = "1.44.0")]
+    #[stable(feature = "once_is_completed", since = "1.43.0")]
     #[inline]
     pub fn is_completed(&self) -> bool {
         // An `Acquire` load is enough because that makes all the initialization
index fdd29af8581856c50b70499514247835822287f5..50f54dbf14306a1644d0ab77345156d2d968c385 100644 (file)
@@ -465,16 +465,13 @@ fn from(t: T) -> Self {
 
 impl<'rwlock, T: ?Sized> RwLockReadGuard<'rwlock, T> {
     unsafe fn new(lock: &'rwlock RwLock<T>) -> LockResult<RwLockReadGuard<'rwlock, T>> {
-        poison::map_result(lock.poison.borrow(), |_| RwLockReadGuard { lock: lock })
+        poison::map_result(lock.poison.borrow(), |_| RwLockReadGuard { lock })
     }
 }
 
 impl<'rwlock, T: ?Sized> RwLockWriteGuard<'rwlock, T> {
     unsafe fn new(lock: &'rwlock RwLock<T>) -> LockResult<RwLockWriteGuard<'rwlock, T>> {
-        poison::map_result(lock.poison.borrow(), |guard| RwLockWriteGuard {
-            lock: lock,
-            poison: guard,
-        })
+        poison::map_result(lock.poison.borrow(), |guard| RwLockWriteGuard { lock, poison: guard })
     }
 }
 
index 976e122463d1b80ea9f60350ffb8dad875e9b741..d5f475b4310fde64b7f0f50154c14d345ce3788f 100644 (file)
@@ -1,5 +1,6 @@
 use crate::mem;
 
+#[derive(Copy, Clone)]
 pub struct IoSlice<'a>(&'a [u8]);
 
 impl<'a> IoSlice<'a> {
index 976e122463d1b80ea9f60350ffb8dad875e9b741..d5f475b4310fde64b7f0f50154c14d345ce3788f 100644 (file)
@@ -1,5 +1,6 @@
 use crate::mem;
 
+#[derive(Copy, Clone)]
 pub struct IoSlice<'a>(&'a [u8]);
 
 impl<'a> IoSlice<'a> {
index b54c115a2b6b670a7e4ea53cffe06962b6131c03..76a9b427b39c6e66de5bb673dfff9d598671323c 100644 (file)
@@ -151,7 +151,7 @@ unsafe fn from_raw_sized_unchecked(ptr: *mut u8, size: usize) -> *mut Self {
 /// It is also possible to obtain a mutable reference `&mut UserRef<T>`. Unlike
 /// regular mutable references, these are not exclusive. Userspace may always
 /// write to the backing memory at any time, so it can't be assumed that there
-/// the pointed-to memory is uniquely borrowed. The two different refence types
+/// the pointed-to memory is uniquely borrowed. The two different reference types
 /// are used solely to indicate intent: a mutable reference is for writing to
 /// user memory, an immutable reference for reading from user memory.
 #[unstable(feature = "sgx_platform", issue = "56975")]
index 976e122463d1b80ea9f60350ffb8dad875e9b741..d5f475b4310fde64b7f0f50154c14d345ce3788f 100644 (file)
@@ -1,5 +1,6 @@
 use crate::mem;
 
+#[derive(Copy, Clone)]
 pub struct IoSlice<'a>(&'a [u8]);
 
 impl<'a> IoSlice<'a> {
index b4a64e93c842b606d31fc978bf4698cda8b39d6b..deb5ee76bd035381f91e76e18bccc87de4ad5d6e 100644 (file)
@@ -3,6 +3,7 @@
 
 use libc::{c_void, iovec};
 
+#[derive(Copy, Clone)]
 #[repr(transparent)]
 pub struct IoSlice<'a> {
     vec: iovec,
index 06876cb06149e5ce4b7392b546bee73df4de864f..fbcb006ecdf11e6a4a3b6f3b4f938bf53ac193f9 100644 (file)
@@ -156,7 +156,7 @@ pub fn cvt_r<T, F>(mut f: F) -> crate::io::Result<T>
 
 // On Unix-like platforms, libc::abort will unregister signal handlers
 // including the SIGABRT handler, preventing the abort from being blocked, and
-// fclose streams, with the side effect of flushing them so libc bufferred
+// fclose streams, with the side effect of flushing them so libc buffered
 // output will be printed.  Additionally the shell will generally print a more
 // understandable error message like "Abort trap" rather than "Illegal
 // instruction" that intrinsics::abort would cause, as intrinsics::abort is
index 79b0dc02978f37c5f521898ed0c7c9280ee921f3..b37675e0a0a008a4afdcb01fd7dda5522a585330 100644 (file)
@@ -280,7 +280,7 @@ pub fn set_timeout(&self, dur: Option<Duration>, kind: libc::c_int) -> io::Resul
                 };
                 let mut timeout = libc::timeval {
                     tv_sec: secs,
-                    tv_usec: (dur.subsec_nanos() / 1000) as libc::suseconds_t,
+                    tv_usec: dur.subsec_micros() as libc::suseconds_t,
                 };
                 if timeout.tv_sec == 0 && timeout.tv_usec == 0 {
                     timeout.tv_usec = 1;
index 83f052c898ba35cae9418a1dab91ec2aae8faea0..859da691ad27868c485fa3ed038011e3e8317571 100644 (file)
@@ -19,9 +19,9 @@
     if #[cfg(target_os = "fuchsia")] {
         // fuchsia doesn't have /dev/null
     } else if #[cfg(target_os = "redox")] {
-        const DEV_NULL: &'static str = "null:\0";
+        const DEV_NULL: &str = "null:\0";
     } else {
-        const DEV_NULL: &'static str = "/dev/null\0";
+        const DEV_NULL: &str = "/dev/null\0";
     }
 }
 
index 528fe321efbce32cb0e83500ff55dd8872caaa02..2626ca37cf8b866d326e9e8665d226356c2d2568 100644 (file)
@@ -13,6 +13,10 @@ impl Handler {
     pub unsafe fn new() -> Handler {
         make_handler()
     }
+
+    fn null() -> Handler {
+        Handler { _data: crate::ptr::null_mut() }
+    }
 }
 
 impl Drop for Handler {
@@ -41,8 +45,9 @@ mod imp {
     use libc::{mmap, munmap};
     use libc::{sigaction, sighandler_t, SA_ONSTACK, SA_SIGINFO, SIGBUS, SIG_DFL};
     use libc::{sigaltstack, SIGSTKSZ, SS_DISABLE};
-    use libc::{MAP_ANON, MAP_PRIVATE, PROT_READ, PROT_WRITE, SIGSEGV};
+    use libc::{MAP_ANON, MAP_PRIVATE, PROT_NONE, PROT_READ, PROT_WRITE, SIGSEGV};
 
+    use crate::sys::unix::os::page_size;
     use crate::sys_common::thread_info;
 
     #[cfg(any(target_os = "linux", target_os = "android"))]
@@ -108,13 +113,20 @@ unsafe fn siginfo_si_addr(info: *mut libc::siginfo_t) -> usize {
     }
 
     static mut MAIN_ALTSTACK: *mut libc::c_void = ptr::null_mut();
+    static mut NEED_ALTSTACK: bool = false;
 
     pub unsafe fn init() {
         let mut action: sigaction = mem::zeroed();
-        action.sa_flags = SA_SIGINFO | SA_ONSTACK;
-        action.sa_sigaction = signal_handler as sighandler_t;
-        sigaction(SIGSEGV, &action, ptr::null_mut());
-        sigaction(SIGBUS, &action, ptr::null_mut());
+        for &signal in &[SIGSEGV, SIGBUS] {
+            sigaction(signal, ptr::null_mut(), &mut action);
+            // Configure our signal handler if one is not already set.
+            if action.sa_sigaction == SIG_DFL {
+                action.sa_flags = SA_SIGINFO | SA_ONSTACK;
+                action.sa_sigaction = signal_handler as sighandler_t;
+                sigaction(signal, &action, ptr::null_mut());
+                NEED_ALTSTACK = true;
+            }
+        }
 
         let handler = make_handler();
         MAIN_ALTSTACK = handler._data;
@@ -126,12 +138,22 @@ pub unsafe fn cleanup() {
     }
 
     unsafe fn get_stackp() -> *mut libc::c_void {
-        let stackp =
-            mmap(ptr::null_mut(), SIGSTKSZ, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
+        let stackp = mmap(
+            ptr::null_mut(),
+            SIGSTKSZ + page_size(),
+            PROT_READ | PROT_WRITE,
+            MAP_PRIVATE | MAP_ANON,
+            -1,
+            0,
+        );
         if stackp == MAP_FAILED {
             panic!("failed to allocate an alternative stack");
         }
-        stackp
+        let guard_result = libc::mprotect(stackp, page_size(), PROT_NONE);
+        if guard_result != 0 {
+            panic!("failed to set up alternative stack guard page");
+        }
+        stackp.add(page_size())
     }
 
     #[cfg(any(
@@ -152,6 +174,9 @@ unsafe fn get_stack() -> libc::stack_t {
     }
 
     pub unsafe fn make_handler() -> Handler {
+        if !NEED_ALTSTACK {
+            return Handler::null();
+        }
         let mut stack = mem::zeroed();
         sigaltstack(ptr::null(), &mut stack);
         // Configure alternate signal stack, if one is not already set.
@@ -160,7 +185,7 @@ pub unsafe fn make_handler() -> Handler {
             sigaltstack(&stack, ptr::null_mut());
             Handler { _data: stack.ss_sp as *mut libc::c_void }
         } else {
-            Handler { _data: ptr::null_mut() }
+            Handler::null()
         }
     }
 
@@ -176,7 +201,9 @@ pub unsafe fn drop_handler(handler: &mut Handler) {
                 ss_size: SIGSTKSZ,
             };
             sigaltstack(&stack, ptr::null_mut());
-            munmap(handler._data, SIGSTKSZ);
+            // We know from `get_stackp` that the alternate stack we installed is part of a mapping
+            // that started one page earlier, so walk back a page and unmap from there.
+            munmap(handler._data.sub(page_size()), SIGSTKSZ + page_size());
         }
     }
 }
@@ -191,14 +218,12 @@ pub unsafe fn drop_handler(handler: &mut Handler) {
     target_os = "openbsd"
 )))]
 mod imp {
-    use crate::ptr;
-
     pub unsafe fn init() {}
 
     pub unsafe fn cleanup() {}
 
     pub unsafe fn make_handler() -> super::Handler {
-        super::Handler { _data: ptr::null_mut() }
+        super::Handler::null()
     }
 
     pub unsafe fn drop_handler(_handler: &mut super::Handler) {}
index f1a2c8446ff8b40c7d096702746b8f78be31f128..0f68ebf8da9cc43577482eb6f62dad433e701007 100644 (file)
@@ -3,6 +3,7 @@
 
 use libc::{c_void, iovec};
 
+#[derive(Copy, Clone)]
 #[repr(transparent)]
 pub struct IoSlice<'a> {
     vec: iovec,
index 12bbfa1d4e1a6e8151f71dd4fe57e0cbe119a0bf..e23191c94311fddd284a38123431b20b78fdc2c4 100644 (file)
@@ -103,7 +103,7 @@ pub fn cvt_r<T, F>(mut f: F) -> crate::io::Result<T>
 
 // On Unix-like platforms, libc::abort will unregister signal handlers
 // including the SIGABRT handler, preventing the abort from being blocked, and
-// fclose streams, with the side effect of flushing them so libc bufferred
+// fclose streams, with the side effect of flushing them so libc buffered
 // output will be printed.  Additionally the shell will generally print a more
 // understandable error message like "Abort trap" rather than "Illegal
 // instruction" that intrinsics::abort would cause, as intrinsics::abort is
index ee20ea6dab87a25fe5e7ef68958ec9b966e2a7dd..0ad2e152855b79dd937647354af773762e8d291f 100644 (file)
@@ -1,6 +1,7 @@
 use crate::marker::PhantomData;
 use crate::slice;
 
+#[derive(Copy, Clone)]
 #[repr(transparent)]
 pub struct IoSlice<'a> {
     vec: wasi::Ciovec,
index 976e122463d1b80ea9f60350ffb8dad875e9b741..d5f475b4310fde64b7f0f50154c14d345ce3788f 100644 (file)
@@ -1,5 +1,6 @@
 use crate::mem;
 
+#[derive(Copy, Clone)]
 pub struct IoSlice<'a>(&'a [u8]);
 
 impl<'a> IoSlice<'a> {
index 4d377341be30f33672d5dc1859f4a60170ca5665..7f93ef8795308f0cfd1ce65c66c15acda0a49453 100644 (file)
@@ -295,6 +295,7 @@ pub struct WSADATA {
     pub szSystemStatus: [u8; WSASYS_STATUS_LEN + 1],
 }
 
+#[derive(Copy, Clone)]
 #[repr(C)]
 pub struct WSABUF {
     pub len: ULONG,
@@ -1044,6 +1045,10 @@ pub fn SetFileInformationByHandle(_hFile: HANDLE,
                     _dwBufferSize: DWORD) -> BOOL {
         SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); 0
     }
+    pub fn GetSystemTimePreciseAsFileTime(lpSystemTimeAsFileTime: LPFILETIME)
+                                          -> () {
+        GetSystemTimeAsFileTime(lpSystemTimeAsFileTime)
+    }
     pub fn SleepConditionVariableSRW(ConditionVariable: PCONDITION_VARIABLE,
                                      SRWLock: PSRWLOCK,
                                      dwMilliseconds: DWORD,
index 9d8018fd5e864acb9c2c46a1d599e96d353e412c..5525d2832526f0f4baaa69e5590a83e998e8e097 100644 (file)
@@ -2,6 +2,7 @@
 use crate::slice;
 use crate::sys::c;
 
+#[derive(Copy, Clone)]
 #[repr(transparent)]
 pub struct IoSlice<'a> {
     vec: c::WSABUF,
index 86667ca7ab2dd22880021af592f4cb3c9d29f20c..900260169c767a88b975cfc12c6c698612f2f138 100644 (file)
@@ -74,7 +74,7 @@ impl SystemTime {
     pub fn now() -> SystemTime {
         unsafe {
             let mut t: SystemTime = mem::zeroed();
-            c::GetSystemTimeAsFileTime(&mut t.t);
+            c::GetSystemTimePreciseAsFileTime(&mut t.t);
             t
         }
     }
index 289ee07babfcf297480fd7d3fdd1c863689fc6b2..2c7ba8f8ea1fd97cbba071815a611871a36adb6a 100644 (file)
@@ -70,7 +70,7 @@ unsafe fn _print_fmt(fmt: &mut fmt::Formatter<'_>, print_fmt: PrintFmt) -> fmt::
     let mut print_path = move |fmt: &mut fmt::Formatter<'_>, bows: BytesOrWideString<'_>| {
         output_filename(fmt, bows, print_fmt, cwd.as_ref())
     };
-    write!(fmt, "stack backtrace:\n")?;
+    writeln!(fmt, "stack backtrace:")?;
     let mut bt_fmt = BacktraceFmt::new(fmt, print_fmt, &mut print_path);
     bt_fmt.add_context()?;
     let mut idx = 0;
index 042641852b3e94b639bedb180c0c6e95ff9a7f84..f3a2962098b4d484865a2b687eb6fa6f02a09e42 100644 (file)
@@ -47,7 +47,7 @@ pub fn apply(&self) {
             }
         }
         for (key, maybe_val) in self.vars.iter() {
-            if let &Some(ref val) = maybe_val {
+            if let Some(ref val) = maybe_val {
                 env::set_var(key, val);
             } else {
                 env::remove_var(key);
index 1d96cdfe46042c5617d8826e94f078eff06010b4..498950e68210148756370bf56965385560c2a32e 100644 (file)
@@ -599,24 +599,16 @@ fn next_surrogate(&self, mut pos: usize) -> Option<(usize, u16)> {
 
     #[inline]
     fn final_lead_surrogate(&self) -> Option<u16> {
-        let len = self.len();
-        if len < 3 {
-            return None;
-        }
-        match &self.bytes[(len - 3)..] {
-            &[0xED, b2 @ 0xA0..=0xAF, b3] => Some(decode_surrogate(b2, b3)),
+        match self.bytes {
+            [.., 0xED, b2 @ 0xA0..=0xAF, b3] => Some(decode_surrogate(b2, b3)),
             _ => None,
         }
     }
 
     #[inline]
     fn initial_trail_surrogate(&self) -> Option<u16> {
-        let len = self.len();
-        if len < 3 {
-            return None;
-        }
-        match &self.bytes[..3] {
-            &[0xED, b2 @ 0xB0..=0xBF, b3] => Some(decode_surrogate(b2, b3)),
+        match self.bytes {
+            [0xED, b2 @ 0xB0..=0xBF, b3, ..] => Some(decode_surrogate(b2, b3)),
             _ => None,
         }
     }
index a800bd17c503be5791ed5aeba72eea821de8977b..5317063b80d11fec1a7973fe3ebff215d9366e42 100644 (file)
@@ -283,7 +283,7 @@ fn is_nightly() -> bool {
     bootstrap || !disable_unstable_features
 }
 
-// Gets the CLI options assotiated with `report-time` feature.
+// Gets the CLI options associated with `report-time` feature.
 fn get_time_options(
     matches: &getopts::Matches,
     allow_unstable: bool,
index 149c9202e6e2d9788334dbc582820cb960936d9d..ff741e3bd53bec702ece44826a2ce927c51de46b 100644 (file)
@@ -169,7 +169,7 @@ fn plural(count: u32, s: &str) -> String {
 
     if !quiet {
         if ntest != 0 || nbench != 0 {
-            writeln!(output, "")?;
+            writeln!(output)?;
         }
 
         writeln!(output, "{}, {}", plural(ntest, "test"), plural(nbench, "benchmark"))?;
index a64c0fc263d808fa0a366e497bf96a29f808484d..1fb840520a6567e41d4f3de7a854da7ac6e44d7c 100644 (file)
@@ -36,5 +36,5 @@ pub(crate) fn write_stderr_delimiter(test_output: &mut Vec<u8>, test_name: &Test
         Some(_) => test_output.push(b'\n'),
         None => (),
     }
-    write!(test_output, "---- {} stderr ----\n", test_name).unwrap();
+    writeln!(test_output, "---- {} stderr ----", test_name).unwrap();
 }
index b42e41cbfe6f00735d9ba73347912828030ea86c..55f9df9caafb274a72d0fca8e7541ecabb2f3f10 100644 (file)
@@ -96,7 +96,7 @@ pub mod test {
 // Process exit code to be used to indicate test failures.
 const ERROR_EXIT_CODE: i32 = 101;
 
-const SECONDARY_TEST_INVOKER_VAR: &'static str = "__RUST_TEST_INVOKE";
+const SECONDARY_TEST_INVOKER_VAR: &str = "__RUST_TEST_INVOKE";
 
 // The default console test runner. It accepts the command line
 // arguments and a vector of test_descs.
@@ -158,7 +158,7 @@ pub fn test_main_static_abort(tests: &[&TestDescAndFn]) {
             .filter(|test| test.desc.name.as_slice() == name)
             .map(make_owned_test)
             .next()
-            .expect(&format!("couldn't find a test with the provided name '{}'", name));
+            .unwrap_or_else(|| panic!("couldn't find a test with the provided name '{}'", name));
         let TestDescAndFn { desc, testfn } = test;
         let testfn = match testfn {
             StaticTestFn(f) => f,
index 7db164c269a5e6c0718be2caa7b522a507b28dd3..8e7bd8de924993150917dd9ef7e041411d3b4138 100644 (file)
@@ -41,7 +41,7 @@ pub enum OutputFormat {
     Json,
 }
 
-/// Whether ignored test should be runned or not
+/// Whether ignored test should be run or not
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
 pub enum RunIgnored {
     Yes,
index aab8d012fdf687f584f586cf0ff2d833c921393e..077005371c0cf1c70573a890a510500852aaf9b0 100644 (file)
@@ -204,7 +204,7 @@ fn mean(&self) -> f64 {
     }
 
     fn median(&self) -> f64 {
-        self.percentile(50 as f64)
+        self.percentile(50_f64)
     }
 
     fn var(&self) -> f64 {
@@ -230,7 +230,7 @@ fn std_dev(&self) -> f64 {
     }
 
     fn std_dev_pct(&self) -> f64 {
-        let hundred = 100 as f64;
+        let hundred = 100_f64;
         (self.std_dev() / self.mean()) * hundred
     }
 
@@ -244,7 +244,7 @@ fn median_abs_dev(&self) -> f64 {
     }
 
     fn median_abs_dev_pct(&self) -> f64 {
-        let hundred = 100 as f64;
+        let hundred = 100_f64;
         (self.median_abs_dev() / self.median()) * hundred
     }
 
@@ -257,11 +257,11 @@ fn percentile(&self, pct: f64) -> f64 {
     fn quartiles(&self) -> (f64, f64, f64) {
         let mut tmp = self.to_vec();
         local_sort(&mut tmp);
-        let first = 25f64;
+        let first = 25_f64;
         let a = percentile_of_sorted(&tmp, first);
-        let second = 50f64;
+        let second = 50_f64;
         let b = percentile_of_sorted(&tmp, second);
-        let third = 75f64;
+        let third = 75_f64;
         let c = percentile_of_sorted(&tmp, third);
         (a, b, c)
     }
@@ -281,7 +281,7 @@ fn percentile_of_sorted(sorted_samples: &[f64], pct: f64) -> f64 {
     }
     let zero: f64 = 0.0;
     assert!(zero <= pct);
-    let hundred = 100f64;
+    let hundred = 100_f64;
     assert!(pct <= hundred);
     if pct == hundred {
         return sorted_samples[sorted_samples.len() - 1];
@@ -307,7 +307,7 @@ pub fn winsorize(samples: &mut [f64], pct: f64) {
     let mut tmp = samples.to_vec();
     local_sort(&mut tmp);
     let lo = percentile_of_sorted(&tmp, pct);
-    let hundred = 100 as f64;
+    let hundred = 100_f64;
     let hi = percentile_of_sorted(&tmp, hundred - pct);
     for samp in samples {
         if *samp > hi {
index 5c975c6272b97d99bcc2aa10c002dffbdc978ef2..465f3f8f99427983ded6d70a6f60fe2b9e9d22b8 100644 (file)
@@ -27,7 +27,7 @@ pub enum TestResult {
 unsafe impl Send for TestResult {}
 
 /// Creates a `TestResult` depending on the raw result of test execution
-/// and assotiated data.
+/// and associated data.
 pub fn calc_result<'a>(
     desc: &TestDesc,
     task_result: Result<(), &'a (dyn Any + 'static + Send)>,
index 2619f99592aa9c9af705e19bc4d3e352c4eb8549..5b75d2f367fff3ef09c332e6882c60fbffc4012e 100644 (file)
@@ -59,10 +59,10 @@ pub fn padding(&self) -> NamePadding {
     }
 
     pub fn with_padding(&self, padding: NamePadding) -> TestName {
-        let name = match self {
-            &TestName::StaticTestName(name) => Cow::Borrowed(name),
-            &TestName::DynTestName(ref name) => Cow::Owned(name.clone()),
-            &TestName::AlignedTestName(ref name, _) => name.clone(),
+        let name = match *self {
+            TestName::StaticTestName(name) => Cow::Borrowed(name),
+            TestName::DynTestName(ref name) => Cow::Owned(name.clone()),
+            TestName::AlignedTestName(ref name, _) => name.clone(),
         };
 
         TestName::AlignedTestName(name, padding)
index a24808b32506f7d9511ae64adb170f132e3edb5b..0628e5d2fc03af7737ec617321a14cb65d571e0c 100644 (file)
@@ -33,8 +33,13 @@ fn main() {
     } else if target.contains("dragonfly") {
         println!("cargo:rustc-link-lib=gcc_pic");
     } else if target.contains("pc-windows-gnu") {
-        println!("cargo:rustc-link-lib=static-nobundle=gcc_eh");
-        println!("cargo:rustc-link-lib=static-nobundle=pthread");
+        // This is handled in the target spec with late_link_args_[static|dynamic]
+
+        // cfg!(bootstrap) doesn't work in build scripts
+        if env::var("RUSTC_STAGE").ok() == Some("0".to_string()) {
+            println!("cargo:rustc-link-lib=static-nobundle=gcc_eh");
+            println!("cargo:rustc-link-lib=static-nobundle=pthread");
+        }
     } else if target.contains("uwp-windows-gnu") {
         println!("cargo:rustc-link-lib=unwind");
     } else if target.contains("fuchsia") {
index f92ff9f071a487d5bb4d91c0e58a7b72b7bf7a4f..bd1946133e8afe40708865f1fff3852d5dcfb3a0 100644 (file)
@@ -60,37 +60,36 @@ impl ::Copy for $t {}
     }
 
     // Unwind info registration/deregistration routines.
-    // See the docs of `unwind` module in libstd.
+    // See the docs of libpanic_unwind.
     extern "C" {
         fn rust_eh_register_frames(eh_frame_begin: *const u8, object: *mut u8);
         fn rust_eh_unregister_frames(eh_frame_begin: *const u8, object: *mut u8);
     }
 
-    unsafe fn init() {
+    unsafe extern "C" fn init() {
         // register unwind info on module startup
         rust_eh_register_frames(&__EH_FRAME_BEGIN__ as *const u8, &mut OBJ as *mut _ as *mut u8);
     }
 
-    unsafe fn uninit() {
+    unsafe extern "C" fn uninit() {
         // unregister on shutdown
         rust_eh_unregister_frames(&__EH_FRAME_BEGIN__ as *const u8, &mut OBJ as *mut _ as *mut u8);
     }
 
-    // MSVC-specific init/uninit routine registration
-    pub mod ms_init {
-        // .CRT$X?? sections are roughly analogous to ELF's .init_array and .fini_array,
-        // except that they exploit the fact that linker will sort them alphabitically,
-        // so e.g., sections with names between .CRT$XIA and .CRT$XIZ are guaranteed to be
-        // placed between those two, without requiring any ordering of objects on the linker
-        // command line.
-        // Note that ordering of same-named sections from different objects is not guaranteed.
-        // Since .CRT$XIA contains init array's header symbol, which must always come first,
-        // we place our initialization callback into .CRT$XIB.
+    // MinGW-specific init/uninit routine registration
+    pub mod mingw_init {
+        // MinGW's startup objects (crt0.o / dllcrt0.o) will invoke global constructors in the
+        // .ctors and .dtors sections on startup and exit. In the case of DLLs, this is done when
+        // the DLL is loaded and unloaded.
+        //
+        // The linker will sort the sections, which ensures that our callbacks are located at the
+        // end of the list. Since constructors are run in reverse order, this ensures that our
+        // callbacks are the first and last ones executed.
 
-        #[link_section = ".CRT$XIB"] // .CRT$XI? : C initialization callbacks
-        pub static P_INIT: unsafe fn() = super::init;
+        #[link_section = ".ctors.65535"] // .ctors.* : C initialization callbacks
+        pub static P_INIT: unsafe extern "C" fn() = super::init;
 
-        #[link_section = ".CRT$XTY"] // .CRT$XT? : C termination callbacks
-        pub static P_UNINIT: unsafe fn() = super::uninit;
+        #[link_section = ".dtors.65535"] // .dtors.* : C termination callbacks
+        pub static P_UNINIT: unsafe extern "C" fn() = super::uninit;
     }
 }
index 65071c3ed86e0f1b75057ca1dfb47e3d497737bb..90d24d20737db3b1fb7bafeae97f61acd9b1e70d 100644 (file)
@@ -868,8 +868,10 @@ LLVMRustOptimizeWithNewPassManager(
     } else {
       for (const auto &C : PipelineStartEPCallbacks)
         PB.registerPipelineStartEPCallback(C);
-      for (const auto &C : OptimizerLastEPCallbacks)
-        PB.registerOptimizerLastEPCallback(C);
+      if (OptStage != LLVMRustOptStage::PreLinkThinLTO) {
+        for (const auto &C : OptimizerLastEPCallbacks)
+          PB.registerOptimizerLastEPCallback(C);
+      }
 
       switch (OptStage) {
       case LLVMRustOptStage::PreLinkNoLTO:
@@ -877,6 +879,12 @@ LLVMRustOptimizeWithNewPassManager(
         break;
       case LLVMRustOptStage::PreLinkThinLTO:
         MPM = PB.buildThinLTOPreLinkDefaultPipeline(OptLevel, DebugPassManager);
+        if (!OptimizerLastEPCallbacks.empty()) {
+          FunctionPassManager FPM(DebugPassManager);
+          for (const auto &C : OptimizerLastEPCallbacks)
+            C(FPM, OptLevel);
+          MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
+        }
         break;
       case LLVMRustOptStage::PreLinkFatLTO:
         MPM = PB.buildLTOPreLinkDefaultPipeline(OptLevel, DebugPassManager);
index 49b6e1bfec38d1aa86144af2b3da3a89a777d67f..25cfee3373dc4e5197d99006ed7f199817c4f595 100644 (file)
@@ -112,20 +112,22 @@ extern "C" void LLVMRustPrintPassTimings() {
   TimerGroup::printAll(OS);
 }
 
-extern "C" LLVMValueRef LLVMRustGetNamedValue(LLVMModuleRef M,
-                                              const char *Name) {
-  return wrap(unwrap(M)->getNamedValue(Name));
+extern "C" LLVMValueRef LLVMRustGetNamedValue(LLVMModuleRef M, const char *Name,
+                                              size_t NameLen) {
+  return wrap(unwrap(M)->getNamedValue(StringRef(Name, NameLen)));
 }
 
 extern "C" LLVMValueRef LLVMRustGetOrInsertFunction(LLVMModuleRef M,
                                                     const char *Name,
+                                                    size_t NameLen,
                                                     LLVMTypeRef FunctionTy) {
-  return wrap(
-      unwrap(M)->getOrInsertFunction(Name, unwrap<FunctionType>(FunctionTy))
+  return wrap(unwrap(M)
+                  ->getOrInsertFunction(StringRef(Name, NameLen),
+                                        unwrap<FunctionType>(FunctionTy))
 #if LLVM_VERSION_GE(9, 0)
-      .getCallee()
+                  .getCallee()
 #endif
-      );
+  );
 }
 
 extern "C" LLVMValueRef
@@ -395,22 +397,26 @@ static InlineAsm::AsmDialect fromRust(LLVMRustAsmDialect Dialect) {
   }
 }
 
-extern "C" LLVMValueRef LLVMRustInlineAsm(LLVMTypeRef Ty, char *AsmString,
-                                          char *Constraints,
-                                          LLVMBool HasSideEffects,
-                                          LLVMBool IsAlignStack,
-                                          LLVMRustAsmDialect Dialect) {
-  return wrap(InlineAsm::get(unwrap<FunctionType>(Ty), AsmString, Constraints,
+extern "C" LLVMValueRef
+LLVMRustInlineAsm(LLVMTypeRef Ty, char *AsmString, size_t AsmStringLen,
+                  char *Constraints, size_t ConstraintsLen,
+                  LLVMBool HasSideEffects, LLVMBool IsAlignStack,
+                  LLVMRustAsmDialect Dialect) {
+  return wrap(InlineAsm::get(unwrap<FunctionType>(Ty),
+                             StringRef(AsmString, AsmStringLen),
+                             StringRef(Constraints, ConstraintsLen),
                              HasSideEffects, IsAlignStack, fromRust(Dialect)));
 }
 
-extern "C" bool LLVMRustInlineAsmVerify(LLVMTypeRef Ty,
-                                          char *Constraints) {
-  return InlineAsm::Verify(unwrap<FunctionType>(Ty), Constraints);
+extern "C" bool LLVMRustInlineAsmVerify(LLVMTypeRef Ty, char *Constraints,
+                                        size_t ConstraintsLen) {
+  return InlineAsm::Verify(unwrap<FunctionType>(Ty),
+                           StringRef(Constraints, ConstraintsLen));
 }
 
-extern "C" void LLVMRustAppendModuleInlineAsm(LLVMModuleRef M, const char *Asm) {
-  unwrap(M)->appendModuleInlineAsm(StringRef(Asm));
+extern "C" void LLVMRustAppendModuleInlineAsm(LLVMModuleRef M, const char *Asm,
+                                              size_t AsmLen) {
+  unwrap(M)->appendModuleInlineAsm(StringRef(Asm, AsmLen));
 }
 
 typedef DIBuilder *LLVMRustDIBuilderRef;
@@ -665,20 +671,24 @@ extern "C" void LLVMRustDIBuilderFinalize(LLVMRustDIBuilderRef Builder) {
 
 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateCompileUnit(
     LLVMRustDIBuilderRef Builder, unsigned Lang, LLVMMetadataRef FileRef,
-    const char *Producer, bool isOptimized, const char *Flags,
-    unsigned RuntimeVer, const char *SplitName,
+    const char *Producer, size_t ProducerLen, bool isOptimized,
+    const char *Flags, unsigned RuntimeVer,
+    const char *SplitName, size_t SplitNameLen,
     LLVMRustDebugEmissionKind Kind) {
   auto *File = unwrapDI<DIFile>(FileRef);
 
-  return wrap(Builder->createCompileUnit(Lang, File, Producer, isOptimized,
-                                         Flags, RuntimeVer, SplitName,
+  return wrap(Builder->createCompileUnit(Lang, File, StringRef(Producer, ProducerLen),
+                                         isOptimized, Flags, RuntimeVer,
+                                         StringRef(SplitName, SplitNameLen),
                                          fromRust(Kind)));
 }
 
-extern "C" LLVMMetadataRef
-LLVMRustDIBuilderCreateFile(LLVMRustDIBuilderRef Builder, const char *Filename,
-                            const char *Directory) {
-  return wrap(Builder->createFile(Filename, Directory));
+extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFile(
+    LLVMRustDIBuilderRef Builder,
+    const char *Filename, size_t FilenameLen,
+    const char *Directory, size_t DirectoryLen) {
+  return wrap(Builder->createFile(StringRef(Filename, FilenameLen),
+                                  StringRef(Directory, DirectoryLen)));
 }
 
 extern "C" LLVMMetadataRef
@@ -690,8 +700,10 @@ LLVMRustDIBuilderCreateSubroutineType(LLVMRustDIBuilderRef Builder,
 }
 
 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction(
-    LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
-    const char *LinkageName, LLVMMetadataRef File, unsigned LineNo,
+    LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
+    const char *Name, size_t NameLen,
+    const char *LinkageName, size_t LinkageNameLen,
+    LLVMMetadataRef File, unsigned LineNo,
     LLVMMetadataRef Ty, unsigned ScopeLine, LLVMRustDIFlags Flags,
     LLVMRustDISPFlags SPFlags, LLVMValueRef Fn, LLVMMetadataRef TParam,
     LLVMMetadataRef Decl) {
@@ -705,8 +717,11 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction(
     llvmFlags |= DINode::DIFlags::FlagMainSubprogram;
 #endif
   DISubprogram *Sub = Builder->createFunction(
-      unwrapDI<DIScope>(Scope), Name, LinkageName, unwrapDI<DIFile>(File),
-      LineNo, unwrapDI<DISubroutineType>(Ty), ScopeLine, llvmFlags,
+      unwrapDI<DIScope>(Scope),
+      StringRef(Name, NameLen),
+      StringRef(LinkageName, LinkageNameLen),
+      unwrapDI<DIFile>(File), LineNo,
+      unwrapDI<DISubroutineType>(Ty), ScopeLine, llvmFlags,
       llvmSPFlags, TParams, unwrapDIPtr<DISubprogram>(Decl));
 #else
   bool IsLocalToUnit = isSet(SPFlags & LLVMRustDISPFlags::SPFlagLocalToUnit);
@@ -716,8 +731,11 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction(
   if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagMainSubprogram))
     llvmFlags |= DINode::DIFlags::FlagMainSubprogram;
   DISubprogram *Sub = Builder->createFunction(
-      unwrapDI<DIScope>(Scope), Name, LinkageName, unwrapDI<DIFile>(File),
-      LineNo, unwrapDI<DISubroutineType>(Ty), IsLocalToUnit, IsDefinition,
+      unwrapDI<DIScope>(Scope),
+      StringRef(Name, NameLen),
+      StringRef(LinkageName, LinkageNameLen),
+      unwrapDI<DIFile>(File), LineNo,
+      unwrapDI<DISubroutineType>(Ty), IsLocalToUnit, IsDefinition,
       ScopeLine, llvmFlags, IsOptimized, TParams,
       unwrapDIPtr<DISubprogram>(Decl));
 #endif
@@ -725,53 +743,59 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction(
   return wrap(Sub);
 }
 
-extern "C" LLVMMetadataRef
-LLVMRustDIBuilderCreateBasicType(LLVMRustDIBuilderRef Builder, const char *Name,
-                                 uint64_t SizeInBits, uint32_t AlignInBits,
-                                 unsigned Encoding) {
-  return wrap(Builder->createBasicType(Name, SizeInBits, Encoding));
+extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateBasicType(
+    LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen,
+    uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding) {
+  return wrap(Builder->createBasicType(StringRef(Name, NameLen), SizeInBits, Encoding));
 }
 
 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreatePointerType(
     LLVMRustDIBuilderRef Builder, LLVMMetadataRef PointeeTy,
-    uint64_t SizeInBits, uint32_t AlignInBits, const char *Name) {
+    uint64_t SizeInBits, uint32_t AlignInBits, unsigned AddressSpace,
+    const char *Name, size_t NameLen) {
   return wrap(Builder->createPointerType(unwrapDI<DIType>(PointeeTy),
                                          SizeInBits, AlignInBits,
-                                         /* DWARFAddressSpace */ None,
-                                         Name));
+                                         AddressSpace,
+                                         StringRef(Name, NameLen)));
 }
 
 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStructType(
-    LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
+    LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
+    const char *Name, size_t NameLen,
     LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
     uint32_t AlignInBits, LLVMRustDIFlags Flags,
     LLVMMetadataRef DerivedFrom, LLVMMetadataRef Elements,
     unsigned RunTimeLang, LLVMMetadataRef VTableHolder,
-    const char *UniqueId) {
+    const char *UniqueId, size_t UniqueIdLen) {
   return wrap(Builder->createStructType(
-      unwrapDI<DIDescriptor>(Scope), Name, unwrapDI<DIFile>(File), LineNumber,
+      unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
+      unwrapDI<DIFile>(File), LineNumber,
       SizeInBits, AlignInBits, fromRust(Flags), unwrapDI<DIType>(DerivedFrom),
       DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang,
-      unwrapDI<DIType>(VTableHolder), UniqueId));
+      unwrapDI<DIType>(VTableHolder), StringRef(UniqueId, UniqueIdLen)));
 }
 
 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantPart(
-    LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
+    LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
+    const char *Name, size_t NameLen,
     LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
     uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Discriminator,
-    LLVMMetadataRef Elements, const char *UniqueId) {
+    LLVMMetadataRef Elements, const char *UniqueId, size_t UniqueIdLen) {
   return wrap(Builder->createVariantPart(
-      unwrapDI<DIDescriptor>(Scope), Name, unwrapDI<DIFile>(File), LineNumber,
+      unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
+      unwrapDI<DIFile>(File), LineNumber,
       SizeInBits, AlignInBits, fromRust(Flags), unwrapDI<DIDerivedType>(Discriminator),
-      DINodeArray(unwrapDI<MDTuple>(Elements)), UniqueId));
+      DINodeArray(unwrapDI<MDTuple>(Elements)), StringRef(UniqueId, UniqueIdLen)));
 }
 
 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateMemberType(
-    LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
+    LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
+    const char *Name, size_t NameLen,
     LLVMMetadataRef File, unsigned LineNo, uint64_t SizeInBits,
     uint32_t AlignInBits, uint64_t OffsetInBits, LLVMRustDIFlags Flags,
     LLVMMetadataRef Ty) {
-  return wrap(Builder->createMemberType(unwrapDI<DIDescriptor>(Scope), Name,
+  return wrap(Builder->createMemberType(unwrapDI<DIDescriptor>(Scope),
+                                        StringRef(Name, NameLen),
                                         unwrapDI<DIFile>(File), LineNo,
                                         SizeInBits, AlignInBits, OffsetInBits,
                                         fromRust(Flags), unwrapDI<DIType>(Ty)));
@@ -779,14 +803,15 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateMemberType(
 
 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantMemberType(
     LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
-    const char *Name, LLVMMetadataRef File, unsigned LineNo, uint64_t SizeInBits,
-    uint32_t AlignInBits, uint64_t OffsetInBits, LLVMValueRef Discriminant,
+    const char *Name, size_t NameLen, LLVMMetadataRef File, unsigned LineNo,
+    uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, LLVMValueRef Discriminant,
     LLVMRustDIFlags Flags, LLVMMetadataRef Ty) {
   llvm::ConstantInt* D = nullptr;
   if (Discriminant) {
     D = unwrap<llvm::ConstantInt>(Discriminant);
   }
-  return wrap(Builder->createVariantMemberType(unwrapDI<DIDescriptor>(Scope), Name,
+  return wrap(Builder->createVariantMemberType(unwrapDI<DIDescriptor>(Scope),
+                                               StringRef(Name, NameLen),
                                                unwrapDI<DIFile>(File), LineNo,
                                                SizeInBits, AlignInBits, OffsetInBits, D,
                                                fromRust(Flags), unwrapDI<DIType>(Ty)));
@@ -808,8 +833,10 @@ LLVMRustDIBuilderCreateLexicalBlockFile(LLVMRustDIBuilderRef Builder,
 }
 
 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticVariable(
-    LLVMRustDIBuilderRef Builder, LLVMMetadataRef Context, const char *Name,
-    const char *LinkageName, LLVMMetadataRef File, unsigned LineNo,
+    LLVMRustDIBuilderRef Builder, LLVMMetadataRef Context,
+    const char *Name, size_t NameLen,
+    const char *LinkageName, size_t LinkageNameLen,
+    LLVMMetadataRef File, unsigned LineNo,
     LLVMMetadataRef Ty, bool IsLocalToUnit, LLVMValueRef V,
     LLVMMetadataRef Decl = nullptr, uint32_t AlignInBits = 0) {
   llvm::GlobalVariable *InitVal = cast<llvm::GlobalVariable>(unwrap(V));
@@ -825,7 +852,8 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticVariable(
   }
 
   llvm::DIGlobalVariableExpression *VarExpr = Builder->createGlobalVariableExpression(
-      unwrapDI<DIDescriptor>(Context), Name, LinkageName,
+      unwrapDI<DIDescriptor>(Context), StringRef(Name, NameLen),
+      StringRef(LinkageName, LinkageNameLen),
       unwrapDI<DIFile>(File), LineNo, unwrapDI<DIType>(Ty), IsLocalToUnit,
 #if LLVM_VERSION_GE(10, 0)
       /* isDefined */ true,
@@ -843,17 +871,20 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticVariable(
 
 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariable(
     LLVMRustDIBuilderRef Builder, unsigned Tag, LLVMMetadataRef Scope,
-    const char *Name, LLVMMetadataRef File, unsigned LineNo,
+    const char *Name, size_t NameLen,
+    LLVMMetadataRef File, unsigned LineNo,
     LLVMMetadataRef Ty, bool AlwaysPreserve, LLVMRustDIFlags Flags,
     unsigned ArgNo, uint32_t AlignInBits) {
   if (Tag == 0x100) { // DW_TAG_auto_variable
     return wrap(Builder->createAutoVariable(
-        unwrapDI<DIDescriptor>(Scope), Name, unwrapDI<DIFile>(File), LineNo,
+        unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
+        unwrapDI<DIFile>(File), LineNo,
         unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags), AlignInBits));
   } else {
     return wrap(Builder->createParameterVariable(
-        unwrapDI<DIDescriptor>(Scope), Name, ArgNo, unwrapDI<DIFile>(File),
-        LineNo, unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags)));
+        unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), ArgNo,
+        unwrapDI<DIFile>(File), LineNo,
+        unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags)));
   }
 }
 
@@ -891,50 +922,53 @@ extern "C" LLVMValueRef LLVMRustDIBuilderInsertDeclareAtEnd(
       unwrap(InsertAtEnd)));
 }
 
-extern "C" LLVMMetadataRef
-LLVMRustDIBuilderCreateEnumerator(LLVMRustDIBuilderRef Builder,
-                                  const char *Name, uint64_t Val) {
-  return wrap(Builder->createEnumerator(Name, Val));
+extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerator(
+    LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen,
+    int64_t Value, bool IsUnsigned) {
+  return wrap(Builder->createEnumerator(StringRef(Name, NameLen), Value, IsUnsigned));
 }
 
 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerationType(
-    LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
+    LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
+    const char *Name, size_t NameLen,
     LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
     uint32_t AlignInBits, LLVMMetadataRef Elements,
     LLVMMetadataRef ClassTy, bool IsScoped) {
   return wrap(Builder->createEnumerationType(
-      unwrapDI<DIDescriptor>(Scope), Name, unwrapDI<DIFile>(File), LineNumber,
+      unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
+      unwrapDI<DIFile>(File), LineNumber,
       SizeInBits, AlignInBits, DINodeArray(unwrapDI<MDTuple>(Elements)),
       unwrapDI<DIType>(ClassTy), "", IsScoped));
 }
 
 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateUnionType(
-    LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
+    LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
+    const char *Name, size_t NameLen,
     LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
     uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Elements,
-    unsigned RunTimeLang, const char *UniqueId) {
+    unsigned RunTimeLang, const char *UniqueId, size_t UniqueIdLen) {
   return wrap(Builder->createUnionType(
-      unwrapDI<DIDescriptor>(Scope), Name, unwrapDI<DIFile>(File), LineNumber,
-      SizeInBits, AlignInBits, fromRust(Flags),
-      DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang, UniqueId));
+      unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIFile>(File),
+      LineNumber, SizeInBits, AlignInBits, fromRust(Flags),
+      DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang,
+      StringRef(UniqueId, UniqueIdLen)));
 }
 
 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateTemplateTypeParameter(
-    LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
+    LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
+    const char *Name, size_t NameLen,
     LLVMMetadataRef Ty, LLVMMetadataRef File, unsigned LineNo,
     unsigned ColumnNo) {
   return wrap(Builder->createTemplateTypeParameter(
-      unwrapDI<DIDescriptor>(Scope), Name, unwrapDI<DIType>(Ty)));
+      unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIType>(Ty)));
 }
 
-extern "C" LLVMMetadataRef
-LLVMRustDIBuilderCreateNameSpace(LLVMRustDIBuilderRef Builder,
-                                 LLVMMetadataRef Scope, const char *Name,
-                                 LLVMMetadataRef File, unsigned LineNo) {
+extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateNameSpace(
+    LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
+    const char *Name, size_t NameLen, bool ExportSymbols) {
   return wrap(Builder->createNameSpace(
-      unwrapDI<DIDescriptor>(Scope), Name,
-      false // ExportSymbols (only relevant for C++ anonymous namespaces)
-      ));
+      unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), ExportSymbols
+  ));
 }
 
 extern "C" void
@@ -1254,12 +1288,11 @@ extern "C" void LLVMRustFreeOperandBundleDef(OperandBundleDef *Bundle) {
 
 extern "C" LLVMValueRef LLVMRustBuildCall(LLVMBuilderRef B, LLVMValueRef Fn,
                                           LLVMValueRef *Args, unsigned NumArgs,
-                                          OperandBundleDef *Bundle,
-                                          const char *Name) {
+                                          OperandBundleDef *Bundle) {
   unsigned Len = Bundle ? 1 : 0;
   ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len);
   return wrap(unwrap(B)->CreateCall(
-      unwrap(Fn), makeArrayRef(unwrap(Args), NumArgs), Bundles, Name));
+      unwrap(Fn), makeArrayRef(unwrap(Args), NumArgs), Bundles));
 }
 
 extern "C" LLVMValueRef LLVMRustBuildMemCpy(LLVMBuilderRef B,
index 14bffbadc06423dbf1744ac30c5ad68c27644cdf..4d9a91e38b33c5b551e5585c3342638991b9aecc 100644 (file)
@@ -12,7 +12,7 @@
 # source tarball for a stable release you'll likely see `1.x.0` for rustc and
 # `0.x.0` for Cargo where they were released on `date`.
 
-date: 2020-01-30
+date: 2020-03-12
 rustc: beta
 cargo: beta
 
index 3f47ca834cda6ba37e2f194ff0557a0385766b70..ea540bd0b18a98e7b9bae81b0c9a37d4d6281e19 100644 (file)
@@ -1,4 +1,4 @@
 # Compiler Test Documentation
 
 Documentation for the compiler testing framework can be found in
-[the rustc guide](https://rust-lang.github.io/rustc-guide/tests/intro.html).
+[the rustc dev guide](https://rustc-dev-guide.rust-lang.org/tests/intro.html).
diff --git a/src/test/codegen/catch-unwind.rs b/src/test/codegen/catch-unwind.rs
new file mode 100644 (file)
index 0000000..3c9bc35
--- /dev/null
@@ -0,0 +1,19 @@
+// compile-flags: -O
+
+#![crate_type = "lib"]
+
+extern "C" {
+    fn bar();
+}
+
+// CHECK-LABEL: @foo
+#[no_mangle]
+pub unsafe fn foo() -> i32 {
+    // CHECK: call void @bar
+    // CHECK: ret i32 0
+    std::panic::catch_unwind(|| {
+        bar();
+        0
+    })
+    .unwrap()
+}
index a89ecdfd3a90153f05d20bc01378c8a461d1cd64..e53e75b339beff8795602ec99269d0e427ff57b9 100644 (file)
 // CHECK: @STATIC = {{.*}}, align 4
 
 // This checks the constants from inline_enum_const
-// CHECK: @{{[0-9]+}} = {{.*}}, align 2
+// CHECK: @alloc5 = {{.*}}, align 2
 
 // This checks the constants from {low,high}_align_const, they share the same
 // constant, but the alignment differs, so the higher one should be used
-// CHECK: [[LOW_HIGH:@[0-9]+]] = {{.*}} getelementptr inbounds (<{ [8 x i8] }>, <{ [8 x i8] }>* @2, i32 0, i32 0, i32 0), {{.*}},
+// CHECK: [[LOW_HIGH:@[0-9]+]] = {{.*}} getelementptr inbounds (<{ [8 x i8] }>, <{ [8 x i8] }>* @alloc15, i32 0, i32 0, i32 0), {{.*}}
 
 #[derive(Copy, Clone)]
 // repr(i16) is required for the {low,high}_align_const test
diff --git a/src/test/codegen/debug-column-msvc.rs b/src/test/codegen/debug-column-msvc.rs
new file mode 100644 (file)
index 0000000..aad8b37
--- /dev/null
@@ -0,0 +1,16 @@
+// Verify that no column information is emitted for MSVC targets
+//
+// only-msvc
+// compile-flags: -C debuginfo=2
+
+// CHECK-NOT: !DILexicalBlock({{.*}}column: {{.*}})
+// CHECK-NOT: !DILocation({{.*}}column: {{.*}})
+
+pub fn add(a: u32, b: u32) -> u32 {
+    a + b
+}
+
+fn main() {
+    let c = add(1, 2);
+    println!("{}", c);
+}
diff --git a/src/test/codegen/debug-column.rs b/src/test/codegen/debug-column.rs
new file mode 100644 (file)
index 0000000..f348c48
--- /dev/null
@@ -0,0 +1,24 @@
+// Verify that debuginfo column nubmers are 1-based byte offsets.
+//
+// ignore-windows
+// compile-flags: -C debuginfo=2
+
+fn main() {
+    unsafe {
+        // Column numbers are 1-based. Regression test for #65437.
+        // CHECK: call void @giraffe(), !dbg [[A:!.*]]
+        giraffe();
+
+        // Column numbers use byte offests. Regression test for #67360
+        // CHECK: call void @turtle(), !dbg [[B:!.*]]
+/* ż */ turtle();
+
+        // CHECK: [[A]] = !DILocation(line: 10, column: 9,
+        // CHECK: [[B]] = !DILocation(line: 14, column: 10,
+    }
+}
+
+extern {
+    fn giraffe();
+    fn turtle();
+}
diff --git a/src/test/codegen/enum-discriminant-value.rs b/src/test/codegen/enum-discriminant-value.rs
new file mode 100644 (file)
index 0000000..f9da987
--- /dev/null
@@ -0,0 +1,27 @@
+// Verify that DIEnumerator uses isUnsigned flag when appropriate.
+//
+// compile-flags: -g -C no-prepopulate-passes
+
+#[repr(i64)]
+pub enum I64 {
+    I64Min = std::i64::MIN,
+    I64Max = std::i64::MAX,
+}
+
+#[repr(u64)]
+pub enum U64 {
+    U64Min = std::u64::MIN,
+    U64Max = std::u64::MAX,
+}
+
+fn main() {
+    let _a = I64::I64Min;
+    let _b = I64::I64Max;
+    let _c = U64::U64Min;
+    let _d = U64::U64Max;
+}
+
+// CHECK: !DIEnumerator(name: "I64Min", value: -9223372036854775808)
+// CHECK: !DIEnumerator(name: "I64Max", value: 9223372036854775807)
+// CHECK: !DIEnumerator(name: "U64Min", value: 0, isUnsigned: true)
+// CHECK: !DIEnumerator(name: "U64Max", value: 18446744073709551615, isUnsigned: true)
index 52ffb97a5b221a9454a73fb69f6a9bdaca9d1a55..4724dc3c3e59331f3748f4a2ac94def7823eebd8 100644 (file)
@@ -12,7 +12,7 @@
 include!("aux_mod.rs");
 
 // Here we check that the expansion of the file!() macro is mapped.
-// CHECK: @0 = private unnamed_addr constant <{ [34 x i8] }> <{ [34 x i8] c"/the/src/remap_path_prefix/main.rs" }>, align 1
+// CHECK: @alloc1 = private unnamed_addr constant <{ [34 x i8] }> <{ [34 x i8] c"/the/src/remap_path_prefix/main.rs" }>, align 1
 pub static FILE_PATH: &'static str = file!();
 
 fn main() {
index 8fbe712065bde2e8453bb3cae4a2d08cbd15fbf2..8e08b78ad1eee83a3d44e437d58ae876edd61c5b 100644 (file)
@@ -5,14 +5,9 @@
 
 use std::iter;
 
-// CHECK: @helper([[USIZE:i[0-9]+]] %_1)
-#[no_mangle]
-pub fn helper(_: usize) {
-}
-
 // CHECK-LABEL: @repeat_take_collect
 #[no_mangle]
 pub fn repeat_take_collect() -> Vec<u8> {
-// CHECK: call void @llvm.memset.p0i8.[[USIZE]](i8* {{(nonnull )?}}align 1{{.*}} %{{[0-9]+}}, i8 42, [[USIZE]] 100000, i1 false)
+// CHECK: call void @llvm.memset.p0i8.i{{[0-9]+}}(i8* {{(nonnull )?}}align 1{{.*}} %{{[0-9]+}}, i8 42, i{{[0-9]+}} 100000, i1 false)
     iter::repeat(42).take(100000).collect()
 }
index 9a583725b0bf0c42d81e353341a964cacfbcd101..05b4ab5653cc843e897838430312200385829ccb 100644 (file)
@@ -14,8 +14,8 @@
 //[MSAN-RECOVER-LTO] compile-flags: -Zsanitizer=memory  -Zsanitizer-recover=memory -C lto=fat
 //
 // MSAN-NOT:         @__msan_keep_going
-// MSAN-RECOVER:     @__msan_keep_going = weak_odr {{.*}} constant i32 1
-// MSAN-RECOVER-LTO: @__msan_keep_going = weak_odr {{.*}} constant i32 1
+// MSAN-RECOVER:     @__msan_keep_going = weak_odr {{.*}}constant i32 1
+// MSAN-RECOVER-LTO: @__msan_keep_going = weak_odr {{.*}}constant i32 1
 
 // ASAN-LABEL: define i32 @penguin(
 // ASAN:         call void @__asan_report_load4(i64 %0)
diff --git a/src/test/codegen/try-panic-abort.rs b/src/test/codegen/try-panic-abort.rs
new file mode 100644 (file)
index 0000000..166d2bb
--- /dev/null
@@ -0,0 +1,20 @@
+// compile-flags: -C panic=abort -O
+
+#![crate_type = "lib"]
+#![feature(unwind_attributes, core_intrinsics)]
+
+extern "C" {
+    #[unwind(allow)]
+    fn bar(data: *mut u8);
+}
+extern "Rust" {
+    fn catch(data: *mut u8, exception: *mut u8);
+}
+
+// CHECK-LABEL: @foo
+#[no_mangle]
+pub unsafe fn foo() -> i32 {
+    // CHECK: call void @bar
+    // CHECK: ret i32 0
+    std::intrinsics::r#try(|x| bar(x), 0 as *mut u8, |x, y| catch(x, y))
+}
index abe34a39caf340608cfce82685c0ffffe18f7d4d..3e5cdad7ab936b865fc98b782a5b5d6ff9b22e30 100644 (file)
@@ -11,5 +11,3 @@
 fn panic_impl(info: &PanicInfo) -> ! { loop {} }
 #[lang = "eh_personality"]
 fn eh_personality() {}
-#[lang = "eh_unwind_resume"]
-fn eh_unwind_resume() {}
diff --git a/src/test/compile-fail/chalkify/chalk_initial_program.rs b/src/test/compile-fail/chalkify/chalk_initial_program.rs
deleted file mode 100644 (file)
index df25bad..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// compile-flags: -Z chalk
-
-trait Foo { }
-
-impl Foo for i32 { }
-
-impl Foo for u32 { }
-
-fn gimme<F: Foo>() { }
-
-// Note: this also tests that `std::process::Termination` is implemented for `()`.
-fn main() {
-    gimme::<i32>();
-    gimme::<u32>();
-    gimme::<f32>(); //~ERROR the trait bound `f32: Foo` is not satisfied
-}
diff --git a/src/test/compile-fail/chalkify/generic_impls.rs b/src/test/compile-fail/chalkify/generic_impls.rs
deleted file mode 100644 (file)
index d70c6f8..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-// compile-flags: -Z chalk
-
-trait Foo { }
-
-impl<T> Foo for (T, u32) { }
-
-fn gimme<F: Foo>() { }
-
-fn foo<T>() {
-    gimme::<(T, u32)>();
-    gimme::<(Option<T>, u32)>();
-    gimme::<(Option<T>, f32)>(); //~ ERROR
-}
-
-fn main() {
-    gimme::<(i32, u32)>();
-    gimme::<(i32, f32)>(); //~ ERROR
-}
diff --git a/src/test/compile-fail/chalkify/impl_wf.rs b/src/test/compile-fail/chalkify/impl_wf.rs
deleted file mode 100644 (file)
index 6bb4cf8..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-// compile-flags: -Z chalk
-
-trait Foo: Sized { }
-
-trait Bar {
-    type Item: Foo;
-}
-
-impl Foo for i32 { }
-
-impl Foo for str { }
-//~^ ERROR the size for values of type `str` cannot be known at compilation time
-
-// Implicit `T: Sized` bound.
-impl<T> Foo for Option<T> { }
-
-impl Bar for () {
-    type Item = i32;
-}
-
-impl<T> Bar for Option<T> {
-    type Item = Option<T>;
-}
-
-impl Bar for f32 {
-//~^ ERROR the trait bound `f32: Foo` is not satisfied
-    type Item = f32;
-    //~^ ERROR the trait bound `f32: Foo` is not satisfied
-}
-
-trait Baz<U: ?Sized> where U: Foo { }
-
-impl Baz<i32> for i32 { }
-
-impl Baz<f32> for f32 { }
-//~^ ERROR the trait bound `f32: Foo` is not satisfied
-
-fn main() {
-}
diff --git a/src/test/compile-fail/chalkify/recursive_where_clause_on_type.rs b/src/test/compile-fail/chalkify/recursive_where_clause_on_type.rs
deleted file mode 100644 (file)
index 861f86e..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-// compile-flags: -Z chalk
-
-#![feature(trivial_bounds)]
-
-trait Bar {
-    fn foo();
-}
-trait Foo: Bar { }
-
-struct S where S: Foo;
-
-impl Foo for S {
-}
-
-fn bar<T: Bar>() {
-    T::foo();
-}
-
-fn foo<T: Foo>() {
-    bar::<T>()
-}
-
-fn main() {
-    // For some reason, the error is duplicated...
-
-    foo::<S>() //~ ERROR the type `S` is not well-formed (chalk)
-    //~^ ERROR the type `S` is not well-formed (chalk)
-}
diff --git a/src/test/compile-fail/chalkify/type_wf.rs b/src/test/compile-fail/chalkify/type_wf.rs
deleted file mode 100644 (file)
index d1aa975..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-// compile-flags: -Z chalk
-
-trait Foo { }
-
-struct S<T: Foo> {
-    x: T,
-}
-
-impl Foo for i32 { }
-impl<T> Foo for Option<T> { }
-
-fn main() {
-    let s = S {
-       x: 5,
-    };
-
-    let s = S { //~ ERROR the trait bound `{float}: Foo` is not satisfied
-        x: 5.0,
-    };
-
-    let s = S {
-        x: Some(5.0),
-    };
-}
diff --git a/src/test/debuginfo/no-debug-attribute.rs b/src/test/debuginfo/no-debug-attribute.rs
deleted file mode 100644 (file)
index db9ac4a..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-// ignore-lldb
-
-// compile-flags:-g
-
-// gdb-command:run
-
-// gdb-command:info locals
-// gdb-check:No locals.
-// gdb-command:continue
-
-// gdb-command:info locals
-// gdb-check:abc = 10
-// gdb-command:continue
-
-#![allow(unused_variables)]
-#![feature(no_debug)]
-#![feature(omit_gdb_pretty_printer_section)]
-#![omit_gdb_pretty_printer_section]
-
-#[inline(never)]
-fn id<T>(x: T) -> T {x}
-
-fn function_with_debuginfo() {
-    let abc = 10_usize;
-    id(abc); // #break
-}
-
-#[no_debug]
-fn function_without_debuginfo() {
-    let abc = -57i32;
-    id(abc); // #break
-}
-
-fn main() {
-    function_without_debuginfo();
-    function_with_debuginfo();
-}
index f3de46d99ddc0c422a19df90e675f58b98a4092c..9b3b381d6210ac4f81b73721bc00fa01054c850a 100644 (file)
@@ -2,10 +2,8 @@
 // compile-flags: -Zquery-dep-graph
 
 #![feature(rustc_attrs)]
-#![allow(private_no_mangle_fns)]
-
-#![rustc_partition_codegened(module="change_symbol_export_status-mod1", cfg="rpass2")]
-#![rustc_partition_reused(module="change_symbol_export_status-mod2", cfg="rpass2")]
+#![rustc_partition_codegened(module = "change_symbol_export_status-mod1", cfg = "rpass2")]
+#![rustc_partition_reused(module = "change_symbol_export_status-mod2", cfg = "rpass2")]
 
 // This test case makes sure that a change in symbol visibility is detected by
 // our dependency tracking. We do this by changing a module's visibility to
index 27287d06d54b171b4573b235d1345fb42e6a56c7..03bb5eea765cc2315d5de099f74548125471cfac 100644 (file)
@@ -1,4 +1,4 @@
-// Adapated from rust-lang/rust#58813
+// Adapted from rust-lang/rust#58813
 
 // revisions: rpass1 cfail2
 
index 50d3657d417f38cc1a9549a429fb95501a72a3d5..87f108abadd55869139a5744256b679a35db4e5c 100644 (file)
@@ -25,7 +25,7 @@ pub fn change_callee_function() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir,typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_callee_function() {
     callee2(1, 2)
@@ -40,7 +40,7 @@ pub fn change_argument_function() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_argument_function() {
     callee1(1, 3)
@@ -55,10 +55,10 @@ mod change_callee_indirectly_function {
     #[cfg(not(cfail1))]
     use super::callee2 as callee;
 
-    #[rustc_clean(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_dirty(label="HirBody", cfg="cfail2")]
-    #[rustc_clean(label="HirBody", cfg="cfail3")]
+    #[rustc_clean(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner_items", cfg="cfail3")]
 
 
     pub fn change_callee_indirectly_function() {
@@ -81,7 +81,7 @@ pub fn change_callee_method() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir,typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_callee_method() {
     let s = Struct;
@@ -98,7 +98,7 @@ pub fn change_argument_method() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_argument_method() {
     let s = Struct;
@@ -115,7 +115,7 @@ pub fn change_ufcs_callee_method() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir,typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_ufcs_callee_method() {
     let s = Struct;
@@ -132,7 +132,7 @@ pub fn change_argument_method_ufcs() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_argument_method_ufcs() {
     let s = Struct;
@@ -149,10 +149,10 @@ pub fn change_to_ufcs() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir,typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
-// One might think this would be expanded in the HirBody/Mir, but it actually
-// results in slightly different Hir/Mir.
+// One might think this would be expanded in the hir_owner_items/Mir, but it actually
+// results in slightly different hir_owner/Mir.
 pub fn change_to_ufcs() {
     let s = Struct;
     Struct::method1(&s, 'x', true);
@@ -171,7 +171,7 @@ pub mod change_ufcs_callee_indirectly {
     #[cfg(not(cfail1))]
     use super::Struct2 as Struct;
 
-    #[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir,typeck_tables_of")]
+    #[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir,typeck_tables_of")]
     #[rustc_clean(cfg="cfail3")]
 
 
index 08693560d0b6e7f6d4d2e06b60390785bbe6880a..8edece2c8d361402f4d878f981b64e0e3992ac4b 100644 (file)
@@ -21,7 +21,7 @@ pub fn change_closure_body() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_closure_body() {
     let _ = || 3u32;
@@ -37,7 +37,7 @@ pub fn add_parameter() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir, typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_parameter() {
     let x = 0u32;
@@ -53,7 +53,7 @@ pub fn change_parameter_pattern() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_parameter_pattern() {
     let _ = |(x,): (u32,)| x;
@@ -68,7 +68,7 @@ pub fn add_move() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_move() {
     let _ = move || 1;
@@ -84,8 +84,8 @@ pub fn add_type_ascription_to_parameter() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, typeck_tables_of")]
-#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg = "cfail2", except = "hir_owner_items, typeck_tables_of")]
+#[rustc_clean(cfg = "cfail3")]
 pub fn add_type_ascription_to_parameter() {
     let closure = |x: u32| x + 1u32;
     let _: u32 = closure(1);
@@ -101,7 +101,7 @@ pub fn change_parameter_type() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir, typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_parameter_type() {
     let closure = |x: u16| (x as u64) + 1;
index 3d2eed89636e856243bc6e2171d8b1a8cf2b2f89..8f77bb24f872e42022da29bbc61371f0ae31c4fa 100644 (file)
@@ -19,7 +19,7 @@
 const CONST_VISIBILITY: u8 = 0;
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 pub const CONST_VISIBILITY: u8 = 0;
 
@@ -29,7 +29,7 @@
 const CONST_CHANGE_TYPE_1: i32 = 0;
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")]
 #[rustc_clean(cfg="cfail3")]
 const CONST_CHANGE_TYPE_1: u32 = 0;
 
 const CONST_CHANGE_TYPE_2: Option<u32> = None;
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")]
 #[rustc_clean(cfg="cfail3")]
 const CONST_CHANGE_TYPE_2: Option<u64> = None;
 
 
 // Change value between simple literals
-#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 const CONST_CHANGE_VALUE_1: i16 = {
     #[cfg(cfail1)]
@@ -57,7 +57,7 @@
 
 
 // Change value between expressions
-#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 const CONST_CHANGE_VALUE_2: i16 = {
     #[cfg(cfail1)]
@@ -67,7 +67,7 @@
     { 1 + 2 }
 };
 
-#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 const CONST_CHANGE_VALUE_3: i16 = {
     #[cfg(cfail1)]
@@ -77,7 +77,7 @@
     { 2 * 3 }
 };
 
-#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 const CONST_CHANGE_VALUE_4: i16 = {
     #[cfg(cfail1)]
@@ -99,11 +99,11 @@ mod const_change_type_indirectly {
     #[cfg(not(cfail1))]
     use super::ReferencedType2 as Type;
 
-    #[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
+    #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")]
     #[rustc_clean(cfg="cfail3")]
     const CONST_CHANGE_TYPE_INDIRECTLY_1: Type = Type;
 
-    #[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
+    #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")]
     #[rustc_clean(cfg="cfail3")]
     const CONST_CHANGE_TYPE_INDIRECTLY_2: Option<Type> = None;
 }
index 575b2e92966eab77abee99076670c9c4511a904e..5ad6eeafc7fc3ddee50a0d27f18b4fa7c8cd594a 100644 (file)
@@ -34,7 +34,7 @@ pub fn change_field_value_struct_like() -> Enum {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,optimized_mir,mir_built")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_field_value_struct_like() -> Enum {
     Enum::Struct {
@@ -57,7 +57,7 @@ pub fn change_field_order_struct_like() -> Enum {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 // FIXME(michaelwoerister):Interesting. I would have thought that that changes the MIR. And it
 // would if it were not all constants
@@ -96,7 +96,7 @@ pub fn change_constructor_path_struct_like() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built,typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,optimized_mir,mir_built,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_constructor_path_struct_like() {
     let _ = Enum2::Struct {
@@ -119,7 +119,7 @@ pub fn change_constructor_variant_struct_like() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,optimized_mir,mir_built")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_constructor_variant_struct_like() {
     let _ = Enum2::Struct2 {
@@ -139,7 +139,7 @@ pub mod change_constructor_path_indirectly_struct_like {
 
     #[rustc_clean(
         cfg="cfail2",
-        except="fn_sig,Hir,HirBody,optimized_mir,mir_built,\
+        except="fn_sig,hir_owner,hir_owner_items,optimized_mir,mir_built,\
                 typeck_tables_of"
     )]
     #[rustc_clean(cfg="cfail3")]
@@ -161,7 +161,7 @@ pub mod change_constructor_variant_indirectly_struct_like {
     #[cfg(not(cfail1))]
     use super::Enum2::Struct2 as Variant;
 
-    #[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")]
+    #[rustc_clean(cfg="cfail2", except="hir_owner_items,optimized_mir,mir_built")]
     #[rustc_clean(cfg="cfail3")]
     pub fn function() -> Enum2 {
         Variant {
@@ -180,7 +180,7 @@ pub fn change_field_value_tuple_like() -> Enum {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,optimized_mir,mir_built")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_field_value_tuple_like() -> Enum {
     Enum::Tuple(0, 1, 3)
@@ -197,7 +197,7 @@ pub fn change_constructor_path_tuple_like() {
 #[cfg(not(cfail1))]
 #[rustc_clean(
     cfg="cfail2",
-    except="HirBody,optimized_mir,mir_built,typeck_tables_of"
+    except="hir_owner_items,optimized_mir,mir_built,typeck_tables_of"
 )]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_constructor_path_tuple_like() {
@@ -215,7 +215,7 @@ pub fn change_constructor_variant_tuple_like() {
 #[cfg(not(cfail1))]
 #[rustc_clean(
     cfg="cfail2",
-    except="HirBody,optimized_mir,mir_built,typeck_tables_of"
+    except="hir_owner_items,optimized_mir,mir_built,typeck_tables_of"
 )]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_constructor_variant_tuple_like() {
@@ -232,7 +232,7 @@ pub mod change_constructor_path_indirectly_tuple_like {
 
     #[rustc_clean(
         cfg="cfail2",
-        except="fn_sig,Hir,HirBody,optimized_mir,mir_built,\
+        except="fn_sig,hir_owner,hir_owner_items,optimized_mir,mir_built,\
                 typeck_tables_of"
     )]
     #[rustc_clean(cfg="cfail3")]
@@ -251,7 +251,7 @@ pub mod change_constructor_variant_indirectly_tuple_like {
     #[cfg(not(cfail1))]
     use super::Enum2::Tuple2 as Variant;
 
-    #[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built,typeck_tables_of")]
+    #[rustc_clean(cfg="cfail2", except="hir_owner_items,optimized_mir,mir_built,typeck_tables_of")]
     #[rustc_clean(cfg="cfail3")]
     pub fn function() -> Enum2 {
         Variant(0, 1, 2)
@@ -278,7 +278,7 @@ pub fn change_constructor_path_c_like() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built,typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,optimized_mir,mir_built,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_constructor_path_c_like() {
     let _ = Clike2::B;
@@ -293,7 +293,7 @@ pub fn change_constructor_variant_c_like() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,optimized_mir,mir_built")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_constructor_variant_c_like() {
     let _ = Clike::C;
@@ -309,7 +309,7 @@ pub mod change_constructor_path_indirectly_c_like {
 
     #[rustc_clean(
         cfg="cfail2",
-        except="fn_sig,Hir,HirBody,optimized_mir,mir_built,\
+        except="fn_sig,hir_owner,hir_owner_items,optimized_mir,mir_built,\
                 typeck_tables_of"
     )]
     #[rustc_clean(cfg="cfail3")]
@@ -328,7 +328,7 @@ pub mod change_constructor_variant_indirectly_c_like {
     #[cfg(not(cfail1))]
     use super::Clike::B as Variant;
 
-    #[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")]
+    #[rustc_clean(cfg="cfail2", except="hir_owner_items,optimized_mir,mir_built")]
     #[rustc_clean(cfg="cfail3")]
     pub fn function() -> Clike {
         Variant
index 7256c1aa15326e822deef19f419e778df094dde2..7be15b4bb155f56eb83fdfd6b8136a0ce570b6ef 100644 (file)
@@ -26,7 +26,7 @@
 enum EnumVisibility { A }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 pub enum EnumVisibility {
     A
@@ -42,7 +42,7 @@ enum EnumChangeNameCStyleVariant {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumChangeNameCStyleVariant {
     Variant1,
@@ -59,7 +59,7 @@ enum EnumChangeNameTupleStyleVariant {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumChangeNameTupleStyleVariant {
     Variant1,
@@ -76,7 +76,7 @@ enum EnumChangeNameStructStyleVariant {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumChangeNameStructStyleVariant {
     Variant1,
@@ -93,7 +93,7 @@ enum EnumChangeValueCStyleVariant0 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumChangeValueCStyleVariant0 {
     Variant1,
@@ -109,7 +109,7 @@ enum EnumChangeValueCStyleVariant1 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumChangeValueCStyleVariant1 {
     Variant1,
@@ -125,7 +125,7 @@ enum EnumAddCStyleVariant {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumAddCStyleVariant {
     Variant1,
@@ -142,7 +142,7 @@ enum EnumRemoveCStyleVariant {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumRemoveCStyleVariant {
     Variant1,
@@ -157,7 +157,7 @@ enum EnumAddTupleStyleVariant {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumAddTupleStyleVariant {
     Variant1,
@@ -174,7 +174,7 @@ enum EnumRemoveTupleStyleVariant {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumRemoveTupleStyleVariant {
     Variant1,
@@ -189,7 +189,7 @@ enum EnumAddStructStyleVariant {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumAddStructStyleVariant {
     Variant1,
@@ -206,7 +206,7 @@ enum EnumRemoveStructStyleVariant {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumRemoveStructStyleVariant {
     Variant1,
@@ -221,7 +221,7 @@ enum EnumChangeFieldTypeTupleStyleVariant {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumChangeFieldTypeTupleStyleVariant {
     Variant1(u32,
@@ -238,7 +238,7 @@ enum EnumChangeFieldTypeStructStyleVariant {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumChangeFieldTypeStructStyleVariant {
     Variant1,
@@ -257,7 +257,7 @@ enum EnumChangeFieldNameStructStyleVariant {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumChangeFieldNameStructStyleVariant {
     Variant1 { a: u32, c: u32 },
@@ -272,7 +272,7 @@ enum EnumChangeOrderTupleStyleVariant {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumChangeOrderTupleStyleVariant {
     Variant1(
@@ -289,7 +289,7 @@ enum EnumChangeFieldOrderStructStyleVariant {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumChangeFieldOrderStructStyleVariant {
     Variant1 { b: f32, a: u32 },
@@ -304,7 +304,7 @@ enum EnumAddFieldTupleStyleVariant {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumAddFieldTupleStyleVariant {
     Variant1(u32, u32, u32),
@@ -319,7 +319,7 @@ enum EnumAddFieldStructStyleVariant {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumAddFieldStructStyleVariant {
     Variant1 { a: u32, b: u32, c: u32 },
@@ -335,7 +335,7 @@ enum EnumAddMustUse {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 #[must_use]
 enum EnumAddMustUse {
@@ -353,7 +353,7 @@ enum EnumAddReprC {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")]
 #[rustc_clean(cfg="cfail3")]
 #[repr(C)]
 enum EnumAddReprC {
@@ -531,7 +531,7 @@ enum EnumSwapUsageTypeParameters<A, B> {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumSwapUsageTypeParameters<A, B> {
     Variant1 {
@@ -552,7 +552,7 @@ enum EnumSwapUsageLifetimeParameters<'a, 'b> {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumSwapUsageLifetimeParameters<'a, 'b> {
     Variant1 {
@@ -577,7 +577,7 @@ mod change_field_type_indirectly_tuple_style {
     #[cfg(not(cfail1))]
     use super::ReferencedType2 as FieldType;
 
-    #[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+    #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
     #[rustc_clean(cfg="cfail3")]
     enum TupleStyle {
         Variant1(
@@ -595,7 +595,7 @@ mod change_field_type_indirectly_struct_style {
     #[cfg(not(cfail1))]
     use super::ReferencedType2 as FieldType;
 
-    #[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+    #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
     #[rustc_clean(cfg="cfail3")]
     enum StructStyle {
         Variant1 {
@@ -618,7 +618,7 @@ mod change_trait_bound_indirectly {
     #[cfg(not(cfail1))]
     use super::ReferencedTrait2 as Trait;
 
-    #[rustc_clean(cfg="cfail2", except="Hir,HirBody,predicates_of")]
+    #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,predicates_of")]
     #[rustc_clean(cfg="cfail3")]
     enum Enum<T: Trait> {
         Variant1(T)
@@ -634,7 +634,7 @@ mod change_trait_bound_indirectly_where {
     #[cfg(not(cfail1))]
     use super::ReferencedTrait2 as Trait;
 
-    #[rustc_clean(cfg="cfail2", except="Hir,HirBody,predicates_of")]
+    #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,predicates_of")]
     #[rustc_clean(cfg="cfail3")]
     enum Enum<T> where T: Trait {
         Variant1(T)
index ef275cabeaff991b435a2de86e1a3b3986387547..b546930ea8fcdb44baf8c00aa36e5c849863711e 100644 (file)
@@ -7,8 +7,8 @@
 #![crate_type="rlib"]
 
 // Case 1: The function body is not exported to metadata. If the body changes,
-//         the hash of the HirBody node should change, but not the hash of
-//         either the Hir or the Metadata node.
+//         the hash of the hir_owner_items node should change, but not the hash of
+//         either the hir_owner or the Metadata node.
 
 #[cfg(cfail1)]
 pub fn body_not_exported_to_metadata() -> u32 {
@@ -16,7 +16,7 @@ pub fn body_not_exported_to_metadata() -> u32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn body_not_exported_to_metadata() -> u32 {
     2
@@ -25,7 +25,7 @@ pub fn body_not_exported_to_metadata() -> u32 {
 
 
 // Case 2: The function body *is* exported to metadata because the function is
-//         marked as #[inline]. Only the hash of the Hir depnode should be
+//         marked as #[inline]. Only the hash of the hir_owner depnode should be
 //         unaffected by a change to the body.
 
 #[cfg(cfail1)]
@@ -35,7 +35,7 @@ pub fn body_exported_to_metadata_because_of_inline() -> u32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 #[inline]
 pub fn body_exported_to_metadata_because_of_inline() -> u32 {
@@ -45,7 +45,7 @@ pub fn body_exported_to_metadata_because_of_inline() -> u32 {
 
 
 // Case 2: The function body *is* exported to metadata because the function is
-//         generic. Only the hash of the Hir depnode should be
+//         generic. Only the hash of the hir_owner depnode should be
 //         unaffected by a change to the body.
 
 #[cfg(cfail1)]
@@ -55,7 +55,7 @@ pub fn body_exported_to_metadata_because_of_generic() -> u32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 #[inline]
 pub fn body_exported_to_metadata_because_of_generic() -> u32 {
index 70820dfaea4a033de9c4b9b79f1fca0faace731c..3e54dafd9ac0e5f6d2a32f39f21a5b4d83e69215 100644 (file)
@@ -25,7 +25,7 @@ pub fn change_loop_body() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_loop_body() {
     let mut _x = 0;
@@ -48,7 +48,7 @@ pub fn change_iteration_variable_name() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_iteration_variable_name() {
     let mut _x = 0;
@@ -71,7 +71,7 @@ pub fn change_iteration_variable_pattern() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir, typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_iteration_variable_pattern() {
     let mut _x = 0;
@@ -94,7 +94,7 @@ pub fn change_iterable() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, promoted_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, promoted_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_iterable() {
     let mut _x = 0;
@@ -116,7 +116,7 @@ pub fn add_break() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir, typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_break() {
     let mut _x = 0;
@@ -139,7 +139,7 @@ pub fn add_loop_label() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_loop_label() {
     let mut _x = 0;
@@ -162,7 +162,7 @@ pub fn add_loop_label_to_break() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_loop_label_to_break() {
     let mut _x = 0;
@@ -187,7 +187,7 @@ pub fn change_break_label() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_break_label() {
     let mut _x = 0;
@@ -212,7 +212,7 @@ pub fn add_loop_label_to_continue() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_loop_label_to_continue() {
     let mut _x = 0;
@@ -237,7 +237,7 @@ pub fn change_continue_label() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_continue_label() {
     let mut _x = 0;
@@ -262,7 +262,7 @@ pub fn change_continue_to_break() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_continue_to_break() {
     let mut _x = 0;
index 9cc2d3bcf604575ab5b41f6b1656825a28cc20f4..bfd536284665d2fb150ed12699246939096d2ead 100644 (file)
 // revisions: cfail1 cfail2 cfail3
 // compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
 
-
 #![allow(warnings)]
 #![feature(linkage)]
 #![feature(rustc_attrs)]
 #![crate_type = "rlib"]
 
-
 // Add Parameter ---------------------------------------------------------------
 
 #[cfg(cfail1)]
 pub fn add_parameter() {}
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg = "cfail2",
-              except = "Hir, HirBody, mir_built, optimized_mir, typeck_tables_of, fn_sig")]
+#[rustc_clean(
+    cfg = "cfail2",
+    except = "hir_owner, hir_owner_items, mir_built, optimized_mir, typeck_tables_of, fn_sig"
+)]
 #[rustc_clean(cfg = "cfail3")]
 pub fn add_parameter(p: i32) {}
 
-
 // Add Return Type -------------------------------------------------------------
 
 #[cfg(cfail1)]
 pub fn add_return_type() {}
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody")]
+#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_items")]
 #[rustc_clean(cfg = "cfail3")]
 pub fn add_return_type() -> () {}
 
-
 // Change Parameter Type -------------------------------------------------------
 
 #[cfg(cfail1)]
 pub fn type_of_parameter(p: i32) {}
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg = "cfail2",
-              except = "Hir, HirBody, mir_built, optimized_mir, typeck_tables_of, fn_sig")]
+#[rustc_clean(
+    cfg = "cfail2",
+    except = "hir_owner, hir_owner_items, mir_built, optimized_mir, typeck_tables_of, fn_sig"
+)]
 #[rustc_clean(cfg = "cfail3")]
 pub fn type_of_parameter(p: i64) {}
 
-
 // Change Parameter Type Reference ---------------------------------------------
 
 #[cfg(cfail1)]
 pub fn type_of_parameter_ref(p: &i32) {}
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg = "cfail2",
-              except = "Hir, HirBody, mir_built, optimized_mir, typeck_tables_of, fn_sig")]
+#[rustc_clean(
+    cfg = "cfail2",
+    except = "hir_owner, hir_owner_items, mir_built, optimized_mir, typeck_tables_of, fn_sig"
+)]
 #[rustc_clean(cfg = "cfail3")]
 pub fn type_of_parameter_ref(p: &mut i32) {}
 
-
 // Change Parameter Order ------------------------------------------------------
 
 #[cfg(cfail1)]
 pub fn order_of_parameters(p1: i32, p2: i64) {}
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg = "cfail2",
-              except = "Hir, HirBody, mir_built, optimized_mir, typeck_tables_of, fn_sig")]
+#[rustc_clean(
+    cfg = "cfail2",
+    except = "hir_owner, hir_owner_items, mir_built, optimized_mir, typeck_tables_of, fn_sig"
+)]
 #[rustc_clean(cfg = "cfail3")]
 pub fn order_of_parameters(p2: i64, p1: i32) {}
 
-
 // Unsafe ----------------------------------------------------------------------
 
 #[cfg(cfail1)]
 pub fn make_unsafe() {}
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg = "cfail2",
-              except = "Hir, HirBody, mir_built, optimized_mir, typeck_tables_of, fn_sig")]
+#[rustc_clean(
+    cfg = "cfail2",
+    except = "hir_owner, hir_owner_items, mir_built, optimized_mir, typeck_tables_of, fn_sig"
+)]
 #[rustc_clean(cfg = "cfail3")]
 pub unsafe fn make_unsafe() {}
 
-
 // Extern ----------------------------------------------------------------------
 
 #[cfg(cfail1)]
 pub fn make_extern() {}
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, typeck_tables_of, fn_sig")]
+#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_items, typeck_tables_of, fn_sig")]
 #[rustc_clean(cfg = "cfail3")]
 pub extern "C" fn make_extern() {}
 
-
 // Type Parameter --------------------------------------------------------------
 
 #[cfg(cfail1)]
 pub fn type_parameter() {}
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg = "cfail2",
-              except = "Hir, HirBody, generics_of, type_of, predicates_of")]
+#[rustc_clean(
+    cfg = "cfail2",
+    except = "hir_owner, hir_owner_items, generics_of, type_of, predicates_of"
+)]
 #[rustc_clean(cfg = "cfail3")]
 pub fn type_parameter<T>() {}
 
-
 // Lifetime Parameter ----------------------------------------------------------
 
 #[cfg(cfail1)]
 pub fn lifetime_parameter() {}
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, generics_of")]
+#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_items, generics_of")]
 #[rustc_clean(cfg = "cfail3")]
 pub fn lifetime_parameter<'a>() {}
 
-
 // Trait Bound -----------------------------------------------------------------
 
 #[cfg(cfail1)]
 pub fn trait_bound<T>() {}
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, predicates_of")]
+#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_items, predicates_of")]
 #[rustc_clean(cfg = "cfail3")]
 pub fn trait_bound<T: Eq>() {}
 
-
 // Builtin Bound ---------------------------------------------------------------
 
 #[cfg(cfail1)]
 pub fn builtin_bound<T>() {}
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, predicates_of")]
+#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_items, predicates_of")]
 #[rustc_clean(cfg = "cfail3")]
 pub fn builtin_bound<T: Send>() {}
 
-
 // Lifetime Bound --------------------------------------------------------------
 
 #[cfg(cfail1)]
 pub fn lifetime_bound<'a, T>() {}
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg = "cfail2",
-              except = "Hir, HirBody, generics_of, type_of, predicates_of")]
+#[rustc_clean(
+    cfg = "cfail2",
+    except = "hir_owner, hir_owner_items, generics_of, type_of, predicates_of"
+)]
 #[rustc_clean(cfg = "cfail3")]
 pub fn lifetime_bound<'a, T: 'a>() {}
 
-
 // Second Trait Bound ----------------------------------------------------------
 
 #[cfg(cfail1)]
 pub fn second_trait_bound<T: Eq>() {}
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, predicates_of")]
+#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_items, predicates_of")]
 #[rustc_clean(cfg = "cfail3")]
 pub fn second_trait_bound<T: Eq + Clone>() {}
 
-
 // Second Builtin Bound --------------------------------------------------------
 
 #[cfg(cfail1)]
 pub fn second_builtin_bound<T: Send>() {}
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, predicates_of")]
+#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_items, predicates_of")]
 #[rustc_clean(cfg = "cfail3")]
 pub fn second_builtin_bound<T: Send + Sized>() {}
 
-
 // Second Lifetime Bound -------------------------------------------------------
 
 #[cfg(cfail1)]
 pub fn second_lifetime_bound<'a, 'b, T: 'a>() {}
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg = "cfail2",
-              except = "Hir, HirBody, generics_of, type_of, predicates_of")]
+#[rustc_clean(
+    cfg = "cfail2",
+    except = "hir_owner, hir_owner_items, generics_of, type_of, predicates_of"
+)]
 #[rustc_clean(cfg = "cfail3")]
 pub fn second_lifetime_bound<'a, 'b, T: 'a + 'b>() {}
 
-
 // Inline ----------------------------------------------------------------------
 
 #[cfg(cfail1)]
 pub fn inline() {}
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody")]
+#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_items")]
 #[rustc_clean(cfg = "cfail3")]
 #[inline]
 pub fn inline() {}
 
-
 // Inline Never ----------------------------------------------------------------
 
 #[cfg(cfail1)]
@@ -208,36 +206,33 @@ pub fn inline() {}
 pub fn inline_never() {}
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody")]
+#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_items")]
 #[rustc_clean(cfg = "cfail3")]
 #[inline(never)]
 pub fn inline_never() {}
 
-
 // No Mangle -------------------------------------------------------------------
 
 #[cfg(cfail1)]
 pub fn no_mangle() {}
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody")]
+#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_items")]
 #[rustc_clean(cfg = "cfail3")]
 #[no_mangle]
 pub fn no_mangle() {}
 
-
 // Linkage ---------------------------------------------------------------------
 
 #[cfg(cfail1)]
 pub fn linkage() {}
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody")]
+#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_items")]
 #[rustc_clean(cfg = "cfail3")]
 #[linkage = "weak_odr"]
 pub fn linkage() {}
 
-
 // Return Impl Trait -----------------------------------------------------------
 
 #[cfg(cfail1)]
@@ -246,13 +241,12 @@ pub fn return_impl_trait() -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, typeck_tables_of, fn_sig")]
+#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_items, typeck_tables_of, fn_sig")]
 #[rustc_clean(cfg = "cfail3")]
 pub fn return_impl_trait() -> impl Clone {
     0
 }
 
-
 // Change Return Impl Trait ----------------------------------------------------
 
 #[cfg(cfail1)]
@@ -267,7 +261,6 @@ pub fn change_return_impl_trait() -> impl Copy {
     0u32
 }
 
-
 // Change Return Type Indirectly -----------------------------------------------
 
 pub struct ReferencedType1;
@@ -279,15 +272,16 @@ pub mod change_return_type_indirectly {
     #[cfg(not(cfail1))]
     use super::ReferencedType2 as ReturnType;
 
-    #[rustc_clean(cfg = "cfail2",
-                  except = "Hir, HirBody, mir_built, optimized_mir, typeck_tables_of, fn_sig")]
+    #[rustc_clean(
+        cfg = "cfail2",
+        except = "hir_owner, hir_owner_items, mir_built, optimized_mir, typeck_tables_of, fn_sig"
+    )]
     #[rustc_clean(cfg = "cfail3")]
     pub fn indirect_return_type() -> ReturnType {
         ReturnType {}
     }
 }
 
-
 // Change Parameter Type Indirectly --------------------------------------------
 
 pub mod change_parameter_type_indirectly {
@@ -296,13 +290,14 @@ pub mod change_parameter_type_indirectly {
     #[cfg(not(cfail1))]
     use super::ReferencedType2 as ParameterType;
 
-    #[rustc_clean(cfg = "cfail2",
-                  except = "Hir, HirBody, mir_built, optimized_mir, typeck_tables_of, fn_sig")]
+    #[rustc_clean(
+        cfg = "cfail2",
+        except = "hir_owner, hir_owner_items, mir_built, optimized_mir, typeck_tables_of, fn_sig"
+    )]
     #[rustc_clean(cfg = "cfail3")]
     pub fn indirect_parameter_type(p: ParameterType) {}
 }
 
-
 // Change Trait Bound Indirectly -----------------------------------------------
 
 pub trait ReferencedTrait1 {}
@@ -314,12 +309,11 @@ pub mod change_trait_bound_indirectly {
     #[cfg(not(cfail1))]
     use super::ReferencedTrait2 as Trait;
 
-    #[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, predicates_of")]
+    #[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_items, predicates_of")]
     #[rustc_clean(cfg = "cfail3")]
     pub fn indirect_trait_bound<T: Trait>(p: T) {}
 }
 
-
 // Change Trait Bound Indirectly In Where Clause -------------------------------
 
 pub mod change_trait_bound_indirectly_in_where_clause {
@@ -328,7 +322,7 @@ pub mod change_trait_bound_indirectly_in_where_clause {
     #[cfg(not(cfail1))]
     use super::ReferencedTrait2 as Trait;
 
-    #[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, predicates_of")]
+    #[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_items, predicates_of")]
     #[rustc_clean(cfg = "cfail3")]
     pub fn indirect_trait_bound_where<T>(p: T)
     where
index 4b73f1371f872607ce706e1666bd1d7444d8d235..93bdc0322bb71662b3524e6042c5c3f664523a56 100644 (file)
@@ -25,7 +25,7 @@ pub fn change_condition(x: bool) -> u32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir,typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_condition(x: bool) -> u32 {
     if !x {
@@ -46,7 +46,7 @@ pub fn change_then_branch(x: bool) -> u32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_then_branch(x: bool) -> u32 {
     if x {
@@ -69,7 +69,7 @@ pub fn change_else_branch(x: bool) -> u32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_else_branch(x: bool) -> u32 {
     if x {
@@ -94,7 +94,7 @@ pub fn add_else_branch(x: bool) -> u32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_else_branch(x: bool) -> u32 {
     let mut ret = 1;
@@ -120,7 +120,7 @@ pub fn change_condition_if_let(x: Option<u32>) -> u32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir,typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_condition_if_let(x: Option<u32>) -> u32 {
     if let Some(_) = x {
@@ -143,7 +143,7 @@ pub fn change_then_branch_if_let(x: Option<u32>) -> u32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir,typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_then_branch_if_let(x: Option<u32>) -> u32 {
     if let Some(x) = x {
@@ -166,7 +166,7 @@ pub fn change_else_branch_if_let(x: Option<u32>) -> u32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_else_branch_if_let(x: Option<u32>) -> u32 {
     if let Some(x) = x {
@@ -191,7 +191,7 @@ pub fn add_else_branch_if_let(x: Option<u32>) -> u32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_else_branch_if_let(x: Option<u32>) -> u32 {
     let mut ret = 1;
index 08cf19d7760282b9739fbd60ff38a9039f66c60f..84c0298918e7ef3565f8c338ef1b4bc9e5905c87 100644 (file)
@@ -20,10 +20,10 @@ fn change_simple_index(slice: &[u32]) -> u32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
+#[rustc_clean(label="hir_owner_items", cfg="cfail3")]
 fn change_simple_index(slice: &[u32]) -> u32 {
     slice[4]
 }
@@ -37,10 +37,10 @@ fn change_lower_bound(slice: &[u32]) -> &[u32] {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
+#[rustc_clean(label="hir_owner_items", cfg="cfail3")]
 fn change_lower_bound(slice: &[u32]) -> &[u32] {
     &slice[2..5]
 }
@@ -54,10 +54,10 @@ fn change_upper_bound(slice: &[u32]) -> &[u32] {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
+#[rustc_clean(label="hir_owner_items", cfg="cfail3")]
 fn change_upper_bound(slice: &[u32]) -> &[u32] {
     &slice[3..7]
 }
@@ -71,10 +71,10 @@ fn add_lower_bound(slice: &[u32]) -> &[u32] {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
+#[rustc_clean(label="hir_owner_items", cfg="cfail3")]
 fn add_lower_bound(slice: &[u32]) -> &[u32] {
     &slice[3..4]
 }
@@ -88,10 +88,10 @@ fn add_upper_bound(slice: &[u32]) -> &[u32] {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
+#[rustc_clean(label="hir_owner_items", cfg="cfail3")]
 fn add_upper_bound(slice: &[u32]) -> &[u32] {
     &slice[3..7]
 }
@@ -105,10 +105,10 @@ fn change_mutability(slice: &mut [u32]) -> u32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
+#[rustc_clean(label="hir_owner_items", cfg="cfail3")]
 fn change_mutability(slice: &mut [u32]) -> u32 {
     (&slice[3..5])[0]
 }
@@ -122,10 +122,10 @@ fn exclusive_to_inclusive_range(slice: &[u32]) -> &[u32] {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
+#[rustc_clean(label="hir_owner_items", cfg="cfail3")]
 fn exclusive_to_inclusive_range(slice: &[u32]) -> &[u32] {
     &slice[3..=7]
 }
index 24d436f5f9727c5a82ff82573cd144b98b532017..139c265164bc57d71760e6efd349b4d019c91cca 100644 (file)
@@ -23,7 +23,7 @@ pub fn method_name() { }
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,associated_item_def_ids")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,associated_item_def_ids")]
 #[rustc_clean(cfg="cfail3")]
 impl Foo {
     #[rustc_clean(cfg="cfail3")]
@@ -44,7 +44,7 @@ pub fn method_body() { }
 impl Foo {
     #[rustc_clean(
         cfg="cfail2",
-        except="HirBody,optimized_mir,promoted_mir,mir_built,typeck_tables_of"
+        except="hir_owner_items,optimized_mir,promoted_mir,mir_built,typeck_tables_of"
     )]
     #[rustc_clean(cfg="cfail3")]
     pub fn method_body() {
@@ -68,7 +68,7 @@ pub fn method_body_inlined() { }
 impl Foo {
     #[rustc_clean(
         cfg="cfail2",
-        except="HirBody,optimized_mir,promoted_mir,mir_built,typeck_tables_of"
+        except="hir_owner_items,optimized_mir,promoted_mir,mir_built,typeck_tables_of"
     )]
     #[rustc_clean(cfg="cfail3")]
     #[inline]
@@ -85,10 +85,10 @@ pub fn method_privacy() { }
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 impl Foo {
-    #[rustc_clean(cfg="cfail2", except="associated_item,Hir,HirBody")]
+    #[rustc_clean(cfg="cfail2", except="associated_item,hir_owner,hir_owner_items")]
     #[rustc_clean(cfg="cfail3")]
     fn method_privacy() { }
 }
@@ -100,7 +100,7 @@ pub fn method_selfness() { }
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 impl Foo {
     #[rustc_dirty(cfg="cfail2", except="type_of,predicates_of,promoted_mir")]
@@ -120,7 +120,7 @@ pub fn method_selfmutness(&self) { }
 impl Foo {
     #[rustc_clean(
         cfg="cfail2",
-        except="Hir,HirBody,fn_sig,typeck_tables_of,optimized_mir,mir_built"
+        except="hir_owner,hir_owner_items,fn_sig,typeck_tables_of,optimized_mir,mir_built"
     )]
     #[rustc_clean(cfg="cfail3")]
     pub fn method_selfmutness(&mut self) { }
@@ -135,7 +135,7 @@ pub fn add_method_to_impl1(&self) { }
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,associated_item_def_ids")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,associated_item_def_ids")]
 #[rustc_clean(cfg="cfail3")]
 impl Foo {
     #[rustc_clean(cfg="cfail2")]
@@ -160,7 +160,7 @@ pub fn add_method_parameter(&self) { }
 impl Foo {
     #[rustc_clean(
         cfg="cfail2",
-        except="Hir,HirBody,fn_sig,typeck_tables_of,optimized_mir,mir_built"
+        except="hir_owner,hir_owner_items,fn_sig,typeck_tables_of,optimized_mir,mir_built"
     )]
     #[rustc_clean(cfg="cfail3")]
     pub fn add_method_parameter(&self, _: i32) { }
@@ -178,7 +178,7 @@ pub fn change_method_parameter_name(&self, a: i64) { }
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 impl Foo {
-    #[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")]
+    #[rustc_clean(cfg="cfail2", except="hir_owner_items,optimized_mir,mir_built")]
     #[rustc_clean(cfg="cfail3")]
     pub fn change_method_parameter_name(&self, b: i64) { }
 }
@@ -197,7 +197,7 @@ pub fn change_method_return_type(&self) -> u16 { 0 }
 impl Foo {
     #[rustc_clean(
         cfg="cfail2",
-        except="Hir,HirBody,fn_sig,optimized_mir,mir_built,typeck_tables_of")]
+        except="hir_owner,hir_owner_items,fn_sig,optimized_mir,mir_built,typeck_tables_of")]
     #[rustc_clean(cfg="cfail3")]
     pub fn change_method_return_type(&self) -> u8 { 0 }
 }
@@ -214,7 +214,7 @@ pub fn make_method_inline(&self) -> u8 { 0 }
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 impl Foo {
-    #[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+    #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
     #[rustc_clean(cfg="cfail3")]
     #[inline]
     pub fn make_method_inline(&self) -> u8 { 0 }
@@ -232,7 +232,7 @@ pub fn change_method_parameter_order(&self, a: i64, b: i64) { }
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 impl Foo {
-    #[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")]
+    #[rustc_clean(cfg="cfail2", except="hir_owner_items,optimized_mir,mir_built")]
     #[rustc_clean(cfg="cfail3")]
     pub fn change_method_parameter_order(&self, b: i64, a: i64) { }
 }
@@ -251,7 +251,7 @@ pub fn make_method_unsafe(&self) { }
 impl Foo {
     #[rustc_clean(
         cfg="cfail2",
-        except="Hir,HirBody,fn_sig,typeck_tables_of,optimized_mir,mir_built"
+        except="hir_owner,hir_owner_items,fn_sig,typeck_tables_of,optimized_mir,mir_built"
     )]
     #[rustc_clean(cfg="cfail3")]
     pub unsafe fn make_method_unsafe(&self) { }
@@ -269,7 +269,7 @@ pub fn make_method_extern(&self) { }
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 impl Foo {
-    #[rustc_clean(cfg="cfail2", except="Hir,HirBody,fn_sig,typeck_tables_of")]
+    #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,fn_sig,typeck_tables_of")]
     #[rustc_clean(cfg="cfail3")]
     pub extern fn make_method_extern(&self) { }
 }
@@ -286,7 +286,7 @@ pub extern "C" fn change_method_calling_convention(&self) { }
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 impl Foo {
-    #[rustc_clean(cfg="cfail2", except="Hir,HirBody,fn_sig,typeck_tables_of")]
+    #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,fn_sig,typeck_tables_of")]
     #[rustc_clean(cfg="cfail3")]
     pub extern "system" fn change_method_calling_convention(&self) { }
 }
@@ -312,7 +312,7 @@ impl Foo {
     // if we lower generics before the body, then the `HirId` for
     // things in the body will be affected. So if you start to see
     // `typeck_tables_of` appear dirty, that might be the cause. -nmatsakis
-    #[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+    #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
     #[rustc_clean(cfg="cfail3")]
     pub fn add_lifetime_parameter_to_method<'a>(&self) { }
 }
@@ -340,7 +340,7 @@ impl Foo {
     // appear dirty, that might be the cause. -nmatsakis
     #[rustc_clean(
         cfg="cfail2",
-        except="Hir,HirBody,generics_of,predicates_of,type_of",
+        except="hir_owner,hir_owner_items,generics_of,predicates_of,type_of",
     )]
     #[rustc_clean(cfg="cfail3")]
     pub fn add_type_parameter_to_method<T>(&self) { }
@@ -360,7 +360,7 @@ pub fn add_lifetime_bound_to_lifetime_param_of_method<'a, 'b>(&self) { }
 impl Foo {
     #[rustc_clean(
         cfg="cfail2",
-        except="Hir,HirBody,generics_of,predicates_of,type_of,typeck_tables_of"
+        except="hir_owner,hir_owner_items,generics_of,predicates_of,type_of"
     )]
     #[rustc_clean(cfg="cfail3")]
     pub fn add_lifetime_bound_to_lifetime_param_of_method<'a, 'b: 'a>(&self) { }
@@ -387,7 +387,7 @@ impl Foo {
     // generics before the body, then the `HirId` for things in the
     // body will be affected. So if you start to see `typeck_tables_of`
     // appear dirty, that might be the cause. -nmatsakis
-    #[rustc_clean(cfg="cfail2", except="Hir,HirBody,generics_of,predicates_of,\
+    #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,generics_of,predicates_of,\
                                         type_of")]
     #[rustc_clean(cfg="cfail3")]
     pub fn add_lifetime_bound_to_type_param_of_method<'a, T: 'a>(&self) { }
@@ -414,7 +414,7 @@ impl Foo {
     // generics before the body, then the `HirId` for things in the
     // body will be affected. So if you start to see `typeck_tables_of`
     // appear dirty, that might be the cause. -nmatsakis
-    #[rustc_clean(cfg="cfail2", except="Hir,HirBody,predicates_of")]
+    #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,predicates_of")]
     #[rustc_clean(cfg="cfail3")]
     pub fn add_trait_bound_to_type_param_of_method<T: Clone>(&self) { }
 }
@@ -431,7 +431,7 @@ pub fn add_no_mangle_to_method(&self) { }
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 impl Foo {
-    #[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+    #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
     #[rustc_clean(cfg="cfail3")]
     #[no_mangle]
     pub fn add_no_mangle_to_method(&self) { }
@@ -448,7 +448,7 @@ pub fn add_type_parameter_to_impl(&self) { }
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,generics_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,generics_of")]
 #[rustc_clean(cfg="cfail3")]
 impl<T> Bar<T> {
     #[rustc_clean(
@@ -468,7 +468,7 @@ pub fn change_impl_self_type(&self) { }
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 impl Bar<u64> {
     #[rustc_clean(cfg="cfail2", except="fn_sig,optimized_mir,mir_built,typeck_tables_of")]
@@ -485,7 +485,7 @@ pub fn add_lifetime_bound_to_impl_parameter(&self) { }
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 impl<T: 'static> Bar<T> {
     #[rustc_clean(cfg="cfail2")]
@@ -502,7 +502,7 @@ pub fn add_trait_bound_to_impl_parameter(&self) { }
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 impl<T: Clone> Bar<T> {
     #[rustc_clean(cfg="cfail2")]
index c50ee73d71438c4c16b095ff2fbb80b1362d4220..a77123110aeda8517daeb2d87d8bd7e9304c952f 100644 (file)
@@ -33,7 +33,7 @@ pub fn change_template(a: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 pub fn change_template(a: i32) -> i32 {
@@ -69,7 +69,7 @@ pub fn change_output(a: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 pub fn change_output(a: i32) -> i32 {
@@ -105,7 +105,7 @@ pub fn change_input(_a: i32, _b: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 pub fn change_input(_a: i32, _b: i32) -> i32 {
@@ -140,7 +140,7 @@ pub fn change_input_constraint(_a: i32, _b: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 pub fn change_input_constraint(_a: i32, _b: i32) -> i32 {
@@ -175,7 +175,7 @@ pub fn change_clobber(_a: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 pub fn change_clobber(_a: i32) -> i32 {
@@ -210,7 +210,7 @@ pub fn change_options(_a: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 pub fn change_options(_a: i32) -> i32 {
index 68545b7daaa5cafd70c25ab488f701743a85b611..2d9cf4203dcd378f0cd75d7b45d8e58d1a776cb5 100644 (file)
@@ -22,7 +22,7 @@ pub fn change_name() {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,mir_built,optimized_mir")]
+    except="hir_owner_items,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_name() {
     let _y = 2u64;
@@ -38,7 +38,7 @@ pub fn add_type() {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,typeck_tables_of,mir_built,optimized_mir")]
+    except="hir_owner_items,typeck_tables_of,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_type() {
     let _x: u32 = 2u32;
@@ -54,7 +54,7 @@ pub fn change_type() {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,typeck_tables_of,mir_built,optimized_mir")]
+    except="hir_owner_items,typeck_tables_of,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_type() {
     let _x: u8 = 2;
@@ -70,7 +70,7 @@ pub fn change_mutability_of_reference_type() {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,typeck_tables_of,mir_built,optimized_mir")]
+    except="hir_owner_items,typeck_tables_of,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_mutability_of_reference_type() {
     let _x: &mut u64;
@@ -86,7 +86,7 @@ pub fn change_mutability_of_slot() {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,typeck_tables_of,mir_built,optimized_mir")]
+    except="hir_owner_items,typeck_tables_of,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_mutability_of_slot() {
     let _x: u64 = 0;
@@ -102,7 +102,7 @@ pub fn change_simple_binding_to_pattern() {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,typeck_tables_of,mir_built,optimized_mir")]
+    except="hir_owner_items,typeck_tables_of,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_simple_binding_to_pattern() {
     let (_a, _b) = (0u8, 'x');
@@ -118,7 +118,7 @@ pub fn change_name_in_pattern() {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,mir_built,optimized_mir")]
+    except="hir_owner_items,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_name_in_pattern() {
     let (_a, _c) = (1u8, 'y');
@@ -134,7 +134,7 @@ pub fn add_ref_in_pattern() {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,typeck_tables_of,mir_built,optimized_mir")]
+    except="hir_owner_items,typeck_tables_of,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_ref_in_pattern() {
     let (ref _a, _b) = (1u8, 'y');
@@ -150,7 +150,7 @@ pub fn add_amp_in_pattern() {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,typeck_tables_of,mir_built,optimized_mir")]
+    except="hir_owner_items,typeck_tables_of,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_amp_in_pattern() {
     let (&_a, _b) = (&1u8, 'y');
@@ -166,7 +166,7 @@ pub fn change_mutability_of_binding_in_pattern() {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,typeck_tables_of,mir_built,optimized_mir")]
+    except="hir_owner_items,typeck_tables_of,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_mutability_of_binding_in_pattern() {
     let (mut _a, _b) = (99u8, 'q');
@@ -182,7 +182,7 @@ pub fn add_initializer() {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,typeck_tables_of,mir_built,optimized_mir")]
+    except="hir_owner_items,typeck_tables_of,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_initializer() {
     let _x: i16 = 3i16;
@@ -198,7 +198,7 @@ pub fn change_initializer() {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,mir_built,optimized_mir")]
+    except="hir_owner_items,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_initializer() {
     let _x = 5u16;
index a2222db4c59ad37a57c59ba3a4bad2525a67cee5..7ce43559cfff320ca6f8110fb6310df9711b41ea 100644 (file)
@@ -25,7 +25,7 @@ pub fn change_loop_body() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_loop_body() {
     let mut _x = 0;
@@ -47,7 +47,7 @@ pub fn add_break() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir, typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_break() {
     let mut _x = 0;
@@ -70,7 +70,7 @@ pub fn add_loop_label() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_loop_label() {
     let mut _x = 0;
@@ -93,7 +93,7 @@ pub fn add_loop_label_to_break() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_loop_label_to_break() {
     let mut _x = 0;
@@ -118,7 +118,7 @@ pub fn change_break_label() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir, typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_break_label() {
     let mut _x = 0;
@@ -143,7 +143,7 @@ pub fn add_loop_label_to_continue() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_loop_label_to_continue() {
     let mut _x = 0;
@@ -168,7 +168,7 @@ pub fn change_continue_label() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_continue_label() {
     let mut _x = 0;
@@ -193,7 +193,7 @@ pub fn change_continue_to_break() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir, typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_continue_to_break() {
     let mut _x = 0;
index 840b2222d90a1d2a53dafec68ef9ce0b759a701b..30934c7c1d16a77ae6f6177f994b242e2029e366 100644 (file)
@@ -26,7 +26,7 @@ pub fn add_arm(x: u32) -> u32 {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,mir_built,optimized_mir,typeck_tables_of")]
+    except="hir_owner_items,mir_built,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_arm(x: u32) -> u32 {
     match x {
@@ -51,7 +51,7 @@ pub fn change_order_of_arms(x: u32) -> u32 {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,mir_built,optimized_mir")]
+    except="hir_owner_items,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_order_of_arms(x: u32) -> u32 {
     match x {
@@ -75,7 +75,7 @@ pub fn add_guard_clause(x: u32, y: bool) -> u32 {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,mir_built,optimized_mir,typeck_tables_of")]
+    except="hir_owner_items,mir_built,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_guard_clause(x: u32, y: bool) -> u32 {
     match x {
@@ -99,7 +99,7 @@ pub fn change_guard_clause(x: u32, y: bool) -> u32 {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,mir_built,optimized_mir,typeck_tables_of")]
+    except="hir_owner_items,mir_built,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_guard_clause(x: u32, y: bool) -> u32 {
     match x {
@@ -123,7 +123,7 @@ pub fn add_at_binding(x: u32) -> u32 {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,mir_built,optimized_mir,typeck_tables_of")]
+    except="hir_owner_items,mir_built,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_at_binding(x: u32) -> u32 {
     match x {
@@ -147,7 +147,7 @@ pub fn change_name_of_at_binding(x: u32) -> u32 {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,mir_built,optimized_mir")]
+    except="hir_owner_items,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_name_of_at_binding(x: u32) -> u32 {
     match x {
@@ -170,7 +170,7 @@ pub fn change_simple_name_to_pattern(x: u32) -> u32 {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,mir_built,optimized_mir,typeck_tables_of")]
+    except="hir_owner_items,mir_built,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_simple_name_to_pattern(x: u32) -> u32 {
     match (x, x & 1) {
@@ -193,7 +193,7 @@ pub fn change_name_in_pattern(x: u32) -> u32 {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,mir_built,optimized_mir")]
+    except="hir_owner_items,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_name_in_pattern(x: u32) -> u32 {
     match (x, x & 1) {
@@ -216,7 +216,7 @@ pub fn change_mutability_of_binding_in_pattern(x: u32) -> u32 {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,mir_built,optimized_mir,typeck_tables_of")]
+    except="hir_owner_items,mir_built,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_mutability_of_binding_in_pattern(x: u32) -> u32 {
     match (x, x & 1) {
@@ -238,7 +238,7 @@ pub fn add_ref_to_binding_in_pattern(x: u32) -> u32 {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,mir_built,optimized_mir,typeck_tables_of")]
+    except="hir_owner_items,mir_built,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_ref_to_binding_in_pattern(x: u32) -> u32 {
     match (x, x & 1) {
@@ -260,7 +260,7 @@ pub fn add_amp_to_binding_in_pattern(x: u32) -> u32 {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-except="HirBody,mir_built,optimized_mir,typeck_tables_of")]
+except="hir_owner_items,mir_built,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_amp_to_binding_in_pattern(x: u32) -> u32 {
     match (&x, x & 1) {
@@ -283,7 +283,7 @@ pub fn change_rhs_of_arm(x: u32) -> u32 {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,mir_built,optimized_mir")]
+    except="hir_owner_items,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_rhs_of_arm(x: u32) -> u32 {
     match x {
@@ -307,7 +307,7 @@ pub fn add_alternative_to_arm(x: u32) -> u32 {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,mir_built,optimized_mir,typeck_tables_of")]
+    except="hir_owner_items,mir_built,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_alternative_to_arm(x: u32) -> u32 {
     match x {
index 70b0a5ab78cd7dcfa8b52e80013a0555570c5970..b46d1fac12475034fcc03b40302039e23692d6db 100644 (file)
@@ -18,7 +18,7 @@
 
 
 // Indexing expression
-#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn indexing(slice: &[u8]) -> u8 {
     #[cfg(cfail1)]
@@ -33,7 +33,7 @@ pub fn indexing(slice: &[u8]) -> u8 {
 
 
 // Arithmetic overflow plus
-#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn arithmetic_overflow_plus(val: i32) -> i32 {
     #[cfg(cfail1)]
@@ -48,7 +48,7 @@ pub fn arithmetic_overflow_plus(val: i32) -> i32 {
 
 
 // Arithmetic overflow minus
-#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn arithmetic_overflow_minus(val: i32) -> i32 {
     #[cfg(cfail1)]
@@ -63,7 +63,7 @@ pub fn arithmetic_overflow_minus(val: i32) -> i32 {
 
 
 // Arithmetic overflow mult
-#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn arithmetic_overflow_mult(val: i32) -> i32 {
     #[cfg(cfail1)]
@@ -78,7 +78,7 @@ pub fn arithmetic_overflow_mult(val: i32) -> i32 {
 
 
 // Arithmetic overflow negation
-#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn arithmetic_overflow_negation(val: i32) -> i32 {
     #[cfg(cfail1)]
@@ -93,7 +93,7 @@ pub fn arithmetic_overflow_negation(val: i32) -> i32 {
 
 
 // Division by zero
-#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn division_by_zero(val: i32) -> i32 {
     #[cfg(cfail1)]
@@ -107,7 +107,7 @@ pub fn division_by_zero(val: i32) -> i32 {
 }
 
 // Division by zero
-#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn mod_by_zero(val: i32) -> i32 {
     #[cfg(cfail1)]
@@ -122,7 +122,7 @@ pub fn mod_by_zero(val: i32) -> i32 {
 
 
 // shift left
-#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn shift_left(val: i32, shift: usize) -> i32 {
     #[cfg(cfail1)]
@@ -137,7 +137,7 @@ pub fn shift_left(val: i32, shift: usize) -> i32 {
 
 
 // shift right
-#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn shift_right(val: i32, shift: usize) -> i32 {
     #[cfg(cfail1)]
index d70ebb08b715a74e71820476443772c6a1000515..536b79324734c2aeef5bca6fc7f4fb1769d7a563 100644 (file)
@@ -21,7 +21,7 @@
 static STATIC_VISIBILITY: u8 = 0;
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 pub static STATIC_VISIBILITY: u8 = 0;
 
@@ -31,7 +31,7 @@
 static STATIC_MUTABILITY: u8 = 0;
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 static mut STATIC_MUTABILITY: u8 = 0;
 
@@ -41,7 +41,7 @@
 static STATIC_LINKAGE: u8 = 0;
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 #[linkage="weak_odr"]
 static STATIC_LINKAGE: u8 = 0;
@@ -52,7 +52,7 @@
 static STATIC_NO_MANGLE: u8 = 0;
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 #[no_mangle]
 static STATIC_NO_MANGLE: u8 = 0;
@@ -63,7 +63,7 @@
 static STATIC_THREAD_LOCAL: u8 = 0;
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 #[thread_local]
 static STATIC_THREAD_LOCAL: u8 = 0;
@@ -74,7 +74,7 @@
 static STATIC_CHANGE_TYPE_1: i16 = 0;
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")]
 #[rustc_clean(cfg="cfail3")]
 static STATIC_CHANGE_TYPE_1: u64 = 0;
 
 static STATIC_CHANGE_TYPE_2: Option<i8> = None;
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")]
 #[rustc_clean(cfg="cfail3")]
 static STATIC_CHANGE_TYPE_2: Option<u16> = None;
 
 
 // Change value between simple literals
-#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 static STATIC_CHANGE_VALUE_1: i16 = {
     #[cfg(cfail1)]
 
 
 // Change value between expressions
-#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 static STATIC_CHANGE_VALUE_2: i16 = {
     #[cfg(cfail1)]
     { 1 + 2 }
 };
 
-#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 static STATIC_CHANGE_VALUE_3: i16 = {
     #[cfg(cfail1)]
     { 2 * 3 }
 };
 
-#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 static STATIC_CHANGE_VALUE_4: i16 = {
     #[cfg(cfail1)]
@@ -144,11 +144,11 @@ mod static_change_type_indirectly {
     #[cfg(not(cfail1))]
     use super::ReferencedType2 as Type;
 
-    #[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
+    #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")]
     #[rustc_clean(cfg="cfail3")]
     static STATIC_CHANGE_TYPE_INDIRECTLY_1: Type = Type;
 
-    #[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
+    #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")]
     #[rustc_clean(cfg="cfail3")]
     static STATIC_CHANGE_TYPE_INDIRECTLY_2: Option<Type> = None;
 }
index 7ae1798c7a2e783a1a10fe58d57024159bfd1831..89b18eefd0646c70d89973d12916620a69e3e76b 100644 (file)
@@ -31,7 +31,7 @@ pub fn change_field_value_regular_struct() -> RegularStruct {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,optimized_mir,mir_built")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_field_value_regular_struct() -> RegularStruct {
     RegularStruct {
@@ -54,7 +54,7 @@ pub fn change_field_order_regular_struct() -> RegularStruct {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_field_order_regular_struct() -> RegularStruct {
     RegularStruct {
@@ -82,7 +82,7 @@ pub fn add_field_regular_struct() -> RegularStruct {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built,typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,optimized_mir,mir_built,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_field_regular_struct() -> RegularStruct {
     let struct1 = RegularStruct {
@@ -117,7 +117,7 @@ pub fn change_field_label_regular_struct() -> RegularStruct {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built,typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,optimized_mir,mir_built,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_field_label_regular_struct() -> RegularStruct {
     let struct1 = RegularStruct {
@@ -152,7 +152,7 @@ pub fn change_constructor_path_regular_struct() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_constructor_path_regular_struct() {
     let _ = RegularStruct2 {
@@ -173,7 +173,7 @@ pub mod change_constructor_path_indirectly_regular_struct {
 
     #[rustc_clean(
         cfg="cfail2",
-        except="fn_sig,Hir,HirBody,optimized_mir,mir_built,typeck_tables_of"
+        except="fn_sig,hir_owner,hir_owner_items,optimized_mir,mir_built,typeck_tables_of"
     )]
     #[rustc_clean(cfg="cfail3")]
     pub fn function() -> Struct {
@@ -196,7 +196,7 @@ pub fn change_field_value_tuple_struct() -> TupleStruct {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,optimized_mir,mir_built")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_field_value_tuple_struct() -> TupleStruct {
     TupleStruct(0, 1, 3)
@@ -213,7 +213,7 @@ pub fn change_constructor_path_tuple_struct() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_constructor_path_tuple_struct() {
     let _ = TupleStruct2(0, 1, 2);
@@ -230,7 +230,7 @@ pub mod change_constructor_path_indirectly_tuple_struct {
 
     #[rustc_clean(
         cfg="cfail2",
-        except="fn_sig,Hir,HirBody,optimized_mir,mir_built,typeck_tables_of"
+        except="fn_sig,hir_owner,hir_owner_items,optimized_mir,mir_built,typeck_tables_of"
     )]
     #[rustc_clean(cfg="cfail3")]
     pub fn function() -> Struct {
index e0c5696483158b008794c7b9840637dcda0d400d..fa08b7ec1ed3a93fe0005dc34ff82edcf7f3e1f1 100644 (file)
 pub struct LayoutPacked;
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
 #[rustc_dirty(label="type_of", cfg="cfail2")]
 #[rustc_clean(label="generics_of", cfg="cfail2")]
 #[rustc_clean(label="predicates_of", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(label="hir_owner_items", cfg="cfail3")]
 #[rustc_clean(label="type_of", cfg="cfail3")]
 #[rustc_clean(label="generics_of", cfg="cfail3")]
 #[rustc_clean(label="predicates_of", cfg="cfail3")]
 struct LayoutC;
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
 #[rustc_dirty(label="type_of", cfg="cfail2")]
 #[rustc_clean(label="generics_of", cfg="cfail2")]
 #[rustc_clean(label="predicates_of", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(label="hir_owner_items", cfg="cfail3")]
 #[rustc_clean(label="type_of", cfg="cfail3")]
 #[rustc_clean(label="generics_of", cfg="cfail3")]
 #[rustc_clean(label="predicates_of", cfg="cfail3")]
 struct TupleStructFieldType(i32);
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
 #[rustc_clean(label="type_of", cfg="cfail2")]
 #[rustc_clean(label="generics_of", cfg="cfail2")]
 #[rustc_clean(label="predicates_of", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(label="hir_owner_items", cfg="cfail3")]
 #[rustc_clean(label="type_of", cfg="cfail3")]
 #[rustc_clean(label="generics_of", cfg="cfail3")]
 #[rustc_clean(label="predicates_of", cfg="cfail3")]
@@ -84,13 +84,13 @@ struct TupleStructFieldType(
 struct TupleStructAddField(i32);
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
 #[rustc_dirty(label="type_of", cfg="cfail2")]
 #[rustc_clean(label="generics_of", cfg="cfail2")]
 #[rustc_clean(label="predicates_of", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(label="hir_owner_items", cfg="cfail3")]
 #[rustc_clean(label="type_of", cfg="cfail3")]
 #[rustc_clean(label="generics_of", cfg="cfail3")]
 #[rustc_clean(label="predicates_of", cfg="cfail3")]
@@ -106,13 +106,13 @@ struct TupleStructAddField(
 struct TupleStructFieldVisibility(char);
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
 #[rustc_dirty(label="type_of", cfg="cfail2")]
 #[rustc_clean(label="generics_of", cfg="cfail2")]
 #[rustc_clean(label="predicates_of", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(label="hir_owner_items", cfg="cfail3")]
 #[rustc_clean(label="type_of", cfg="cfail3")]
 #[rustc_clean(label="generics_of", cfg="cfail3")]
 #[rustc_clean(label="predicates_of", cfg="cfail3")]
@@ -125,13 +125,13 @@ struct TupleStructAddField(
 struct RecordStructFieldType { x: f32 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
 #[rustc_clean(label="type_of", cfg="cfail2")]
 #[rustc_clean(label="generics_of", cfg="cfail2")]
 #[rustc_clean(label="predicates_of", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(label="hir_owner_items", cfg="cfail3")]
 #[rustc_clean(label="type_of", cfg="cfail3")]
 #[rustc_clean(label="generics_of", cfg="cfail3")]
 #[rustc_clean(label="predicates_of", cfg="cfail3")]
@@ -148,13 +148,13 @@ struct RecordStructFieldType {
 struct RecordStructFieldName { x: f32 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
 #[rustc_dirty(label="type_of", cfg="cfail2")]
 #[rustc_clean(label="generics_of", cfg="cfail2")]
 #[rustc_clean(label="predicates_of", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(label="hir_owner_items", cfg="cfail3")]
 #[rustc_clean(label="type_of", cfg="cfail3")]
 #[rustc_clean(label="generics_of", cfg="cfail3")]
 #[rustc_clean(label="predicates_of", cfg="cfail3")]
@@ -167,13 +167,13 @@ struct RecordStructFieldName { y: f32 }
 struct RecordStructAddField { x: f32 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
 #[rustc_dirty(label="type_of", cfg="cfail2")]
 #[rustc_clean(label="generics_of", cfg="cfail2")]
 #[rustc_clean(label="predicates_of", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(label="hir_owner_items", cfg="cfail3")]
 #[rustc_clean(label="type_of", cfg="cfail3")]
 #[rustc_clean(label="generics_of", cfg="cfail3")]
 #[rustc_clean(label="predicates_of", cfg="cfail3")]
@@ -188,13 +188,13 @@ struct RecordStructAddField {
 struct RecordStructFieldVisibility { x: f32 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
 #[rustc_dirty(label="type_of", cfg="cfail2")]
 #[rustc_clean(label="generics_of", cfg="cfail2")]
 #[rustc_clean(label="predicates_of", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(label="hir_owner_items", cfg="cfail3")]
 #[rustc_clean(label="type_of", cfg="cfail3")]
 #[rustc_clean(label="generics_of", cfg="cfail3")]
 #[rustc_clean(label="predicates_of", cfg="cfail3")]
@@ -209,13 +209,13 @@ struct RecordStructFieldVisibility {
 struct AddLifetimeParameter<'a>(&'a f32, &'a f64);
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
 #[rustc_dirty(label="type_of", cfg="cfail2")]
 #[rustc_dirty(label="generics_of", cfg="cfail2")]
 #[rustc_clean(label="predicates_of", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(label="hir_owner_items", cfg="cfail3")]
 #[rustc_clean(label="type_of", cfg="cfail3")]
 #[rustc_clean(label="generics_of", cfg="cfail3")]
 #[rustc_clean(label="predicates_of", cfg="cfail3")]
@@ -228,13 +228,13 @@ struct RecordStructFieldVisibility {
 struct AddLifetimeParameterBound<'a, 'b>(&'a f32, &'b f64);
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
 #[rustc_clean(label="type_of", cfg="cfail2")]
 #[rustc_clean(label="generics_of", cfg="cfail2")]
 #[rustc_dirty(label="predicates_of", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(label="hir_owner_items", cfg="cfail3")]
 #[rustc_clean(label="type_of", cfg="cfail3")]
 #[rustc_clean(label="generics_of", cfg="cfail3")]
 #[rustc_clean(label="predicates_of", cfg="cfail3")]
@@ -247,13 +247,13 @@ struct AddLifetimeParameterBound<'a, 'b: 'a>(
 struct AddLifetimeParameterBoundWhereClause<'a, 'b>(&'a f32, &'b f64);
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
 #[rustc_clean(label="type_of", cfg="cfail2")]
 #[rustc_clean(label="generics_of", cfg="cfail2")]
 #[rustc_dirty(label="predicates_of", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(label="hir_owner_items", cfg="cfail3")]
 #[rustc_clean(label="type_of", cfg="cfail3")]
 #[rustc_clean(label="generics_of", cfg="cfail3")]
 #[rustc_clean(label="predicates_of", cfg="cfail3")]
@@ -269,13 +269,13 @@ struct AddLifetimeParameterBoundWhereClause<'a, 'b>(
 struct AddTypeParameter<T1>(T1, T1);
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
 #[rustc_dirty(label="type_of", cfg="cfail2")]
 #[rustc_dirty(label="generics_of", cfg="cfail2")]
 #[rustc_dirty(label="predicates_of", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(label="hir_owner_items", cfg="cfail3")]
 #[rustc_clean(label="type_of", cfg="cfail3")]
 #[rustc_clean(label="generics_of", cfg="cfail3")]
 #[rustc_clean(label="predicates_of", cfg="cfail3")]
@@ -293,13 +293,13 @@ struct AddTypeParameter<T1, T2>(
 struct AddTypeParameterBound<T>(T);
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
 #[rustc_clean(label="type_of", cfg="cfail2")]
 #[rustc_clean(label="generics_of", cfg="cfail2")]
 #[rustc_dirty(label="predicates_of", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(label="hir_owner_items", cfg="cfail3")]
 #[rustc_clean(label="type_of", cfg="cfail3")]
 #[rustc_clean(label="generics_of", cfg="cfail3")]
 #[rustc_clean(label="predicates_of", cfg="cfail3")]
@@ -312,13 +312,13 @@ struct AddTypeParameterBound<T: Send>(
 struct AddTypeParameterBoundWhereClause<T>(T);
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
 #[rustc_clean(label="type_of", cfg="cfail2")]
 #[rustc_clean(label="generics_of", cfg="cfail2")]
 #[rustc_dirty(label="predicates_of", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(label="hir_owner_items", cfg="cfail3")]
 #[rustc_clean(label="type_of", cfg="cfail3")]
 #[rustc_clean(label="generics_of", cfg="cfail3")]
 #[rustc_clean(label="predicates_of", cfg="cfail3")]
@@ -332,13 +332,13 @@ struct AddTypeParameterBoundWhereClause<T>(
 // fingerprint is stable (i.e., that there are no random influences like memory
 // addresses taken into account by the hashing algorithm).
 // Note: there is no #[cfg(...)], so this is ALWAYS compiled
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner_items", cfg="cfail2")]
 #[rustc_clean(label="type_of", cfg="cfail2")]
 #[rustc_clean(label="generics_of", cfg="cfail2")]
 #[rustc_clean(label="predicates_of", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(label="hir_owner_items", cfg="cfail3")]
 #[rustc_clean(label="type_of", cfg="cfail3")]
 #[rustc_clean(label="generics_of", cfg="cfail3")]
 #[rustc_clean(label="predicates_of", cfg="cfail3")]
@@ -351,13 +351,13 @@ struct AddTypeParameterBoundWhereClause<T>(
 struct Visibility;
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
 #[rustc_clean(label="type_of", cfg="cfail2")]
 #[rustc_clean(label="generics_of", cfg="cfail2")]
 #[rustc_clean(label="predicates_of", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(label="hir_owner_items", cfg="cfail3")]
 #[rustc_clean(label="type_of", cfg="cfail3")]
 #[rustc_clean(label="generics_of", cfg="cfail3")]
 #[rustc_clean(label="predicates_of", cfg="cfail3")]
@@ -373,13 +373,13 @@ mod tuple_struct_change_field_type_indirectly {
     #[cfg(not(cfail1))]
     use super::ReferencedType2 as FieldType;
 
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_dirty(label="HirBody", cfg="cfail2")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
     #[rustc_clean(label="type_of", cfg="cfail2")]
     #[rustc_clean(label="generics_of", cfg="cfail2")]
     #[rustc_clean(label="predicates_of", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_clean(label="HirBody", cfg="cfail3")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(label="hir_owner_items", cfg="cfail3")]
     #[rustc_clean(label="type_of", cfg="cfail3")]
     #[rustc_clean(label="generics_of", cfg="cfail3")]
     #[rustc_clean(label="predicates_of", cfg="cfail3")]
@@ -396,13 +396,13 @@ mod record_struct_change_field_type_indirectly {
     #[cfg(not(cfail1))]
     use super::ReferencedType2 as FieldType;
 
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_dirty(label="HirBody", cfg="cfail2")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
     #[rustc_clean(label="type_of", cfg="cfail2")]
     #[rustc_clean(label="generics_of", cfg="cfail2")]
     #[rustc_clean(label="predicates_of", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_clean(label="HirBody", cfg="cfail3")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(label="hir_owner_items", cfg="cfail3")]
     #[rustc_clean(label="type_of", cfg="cfail3")]
     #[rustc_clean(label="generics_of", cfg="cfail3")]
     #[rustc_clean(label="predicates_of", cfg="cfail3")]
@@ -424,13 +424,13 @@ mod change_trait_bound_indirectly {
     #[cfg(not(cfail1))]
     use super::ReferencedTrait2 as Trait;
 
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_dirty(label="HirBody", cfg="cfail2")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
     #[rustc_clean(label="type_of", cfg="cfail2")]
     #[rustc_clean(label="generics_of", cfg="cfail2")]
     #[rustc_dirty(label="predicates_of", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_clean(label="HirBody", cfg="cfail3")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(label="hir_owner_items", cfg="cfail3")]
     #[rustc_clean(label="type_of", cfg="cfail3")]
     #[rustc_clean(label="generics_of", cfg="cfail3")]
     #[rustc_clean(label="predicates_of", cfg="cfail3")]
@@ -444,13 +444,13 @@ mod change_trait_bound_indirectly_in_where_clause {
     #[cfg(not(cfail1))]
     use super::ReferencedTrait2 as Trait;
 
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_dirty(label="HirBody", cfg="cfail2")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
     #[rustc_clean(label="type_of", cfg="cfail2")]
     #[rustc_clean(label="generics_of", cfg="cfail2")]
     #[rustc_dirty(label="predicates_of", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_clean(label="HirBody", cfg="cfail3")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(label="hir_owner_items", cfg="cfail3")]
     #[rustc_clean(label="type_of", cfg="cfail3")]
     #[rustc_clean(label="generics_of", cfg="cfail3")]
     #[rustc_clean(label="predicates_of", cfg="cfail3")]
index 3006cdccfbb55c9df3e5e411a92d3386a03ae8c2..df41b73f92c42ebd6097b172613fc7481ca8a1d6 100644 (file)
@@ -25,8 +25,8 @@
 trait TraitVisibility { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 pub trait TraitVisibility { }
 
 
@@ -36,8 +36,8 @@ pub trait TraitVisibility { }
 trait TraitUnsafety { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 unsafe trait TraitUnsafety { }
 
 
@@ -48,8 +48,8 @@ trait TraitAddMethod {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 pub trait TraitAddMethod {
     fn method();
 }
@@ -63,8 +63,8 @@ trait TraitChangeMethodName {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitChangeMethodName {
     fn methodChanged();
 }
@@ -78,11 +78,11 @@ trait TraitAddReturnType {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddReturnType {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method() -> u32;
 }
 
@@ -95,11 +95,11 @@ trait TraitChangeReturnType {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitChangeReturnType {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method() -> u64;
 }
 
@@ -112,11 +112,11 @@ trait TraitAddParameterToMethod {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddParameterToMethod {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method(a: u32);
 }
 
@@ -130,18 +130,18 @@ fn with_default(x: i32) {}
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitChangeMethodParameterName {
     // FIXME(#38501) This should preferably always be clean.
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method(b: u32);
 
-    #[rustc_clean(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_dirty(label="HirBody", cfg="cfail2")]
-    #[rustc_clean(label="HirBody", cfg="cfail3")]
+    #[rustc_clean(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner_items", cfg="cfail3")]
     fn with_default(y: i32) {}
 }
 
@@ -154,11 +154,11 @@ trait TraitChangeMethodParameterType {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitChangeMethodParameterType {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method(a: i64);
 }
 
@@ -171,11 +171,11 @@ trait TraitChangeMethodParameterTypeRef {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitChangeMethodParameterTypeRef {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method(a: &mut i32);
 }
 
@@ -188,11 +188,11 @@ trait TraitChangeMethodParametersOrder {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitChangeMethodParametersOrder {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method(b: i64, a: i32);
 }
 
@@ -205,11 +205,11 @@ trait TraitAddMethodAutoImplementation {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddMethodAutoImplementation {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method() { }
 }
 
@@ -223,8 +223,8 @@ trait TraitChangeOrderOfMethods {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitChangeOrderOfMethods {
     fn method1();
     fn method0();
@@ -239,11 +239,11 @@ trait TraitChangeModeSelfRefToMut {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitChangeModeSelfRefToMut {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method(&mut self);
 }
 
@@ -255,13 +255,13 @@ fn method(self) {}
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitChangeModeSelfOwnToMut: Sized {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_dirty(label="HirBody", cfg="cfail2")]
-    #[rustc_clean(label="HirBody", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner_items", cfg="cfail3")]
     fn method(mut self) {}
 }
 
@@ -273,11 +273,11 @@ trait TraitChangeModeSelfOwnToRef {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitChangeModeSelfOwnToRef {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method(&self);
 }
 
@@ -290,11 +290,11 @@ trait TraitAddUnsafeModifier {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddUnsafeModifier {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     unsafe fn method();
 }
 
@@ -307,11 +307,11 @@ trait TraitAddExternModifier {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddExternModifier {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     extern fn method();
 }
 
@@ -324,11 +324,11 @@ trait TraitChangeExternCToRustIntrinsic {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitChangeExternCToRustIntrinsic {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     extern "stdcall" fn method();
 }
 
@@ -341,11 +341,11 @@ trait TraitAddTypeParameterToMethod {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddTypeParameterToMethod {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method<T>();
 }
 
@@ -358,11 +358,11 @@ trait TraitAddLifetimeParameterToMethod {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddLifetimeParameterToMethod {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method<'a>();
 }
 
@@ -379,11 +379,11 @@ trait TraitAddTraitBoundToMethodTypeParameter {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddTraitBoundToMethodTypeParameter {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method<T: ReferencedTrait0>();
 }
 
@@ -396,11 +396,11 @@ trait TraitAddBuiltinBoundToMethodTypeParameter {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddBuiltinBoundToMethodTypeParameter {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method<T: Sized>();
 }
 
@@ -413,11 +413,11 @@ trait TraitAddLifetimeBoundToMethodLifetimeParameter {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddLifetimeBoundToMethodLifetimeParameter {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method<'a, 'b: 'a>(a: &'a u32, b: &'b u32);
 }
 
@@ -430,11 +430,11 @@ trait TraitAddSecondTraitBoundToMethodTypeParameter {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddSecondTraitBoundToMethodTypeParameter {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method<T: ReferencedTrait0 + ReferencedTrait1>();
 }
 
@@ -447,11 +447,11 @@ trait TraitAddSecondBuiltinBoundToMethodTypeParameter {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddSecondBuiltinBoundToMethodTypeParameter {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method<T: Sized + Sync>();
 }
 
@@ -464,11 +464,11 @@ trait TraitAddSecondLifetimeBoundToMethodLifetimeParameter {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddSecondLifetimeBoundToMethodLifetimeParameter {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method<'a, 'b, 'c: 'a + 'b>(a: &'a u32, b: &'b u32, c: &'c u32);
 }
 
@@ -478,14 +478,14 @@ trait TraitAddSecondLifetimeBoundToMethodLifetimeParameter {
 #[cfg(cfail1)]
 trait TraitAddAssociatedType {
 
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method();
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddAssociatedType {
     type Associated;
 
@@ -506,11 +506,11 @@ trait TraitAddTraitBoundToAssociatedType {
 // Apparently the type bound contributes to the predicates of the trait, but
 // does not change the associated item itself.
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddTraitBoundToAssociatedType {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     type Associated: ReferencedTrait0;
 
     fn method();
@@ -527,11 +527,11 @@ trait TraitAddLifetimeBoundToAssociatedType<'a> {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddLifetimeBoundToAssociatedType<'a> {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     type Associated: 'a;
 
     fn method();
@@ -548,11 +548,11 @@ trait TraitAddDefaultToAssociatedType {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddDefaultToAssociatedType {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     type Associated = ReferenceType0;
 
     fn method();
@@ -567,8 +567,8 @@ trait TraitAddAssociatedConstant {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddAssociatedConstant {
     const Value: u32;
 
@@ -586,15 +586,15 @@ trait TraitAddInitializerToAssociatedConstant {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddInitializerToAssociatedConstant {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     const Value: u32 = 1;
 
-    #[rustc_clean(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_clean(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method();
 }
 
@@ -609,15 +609,15 @@ trait TraitChangeTypeOfAssociatedConstant {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitChangeTypeOfAssociatedConstant {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     const Value: f64;
 
-    #[rustc_clean(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_clean(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method();
 }
 
@@ -628,8 +628,8 @@ trait TraitChangeTypeOfAssociatedConstant {
 trait TraitAddSuperTrait { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddSuperTrait : ReferencedTrait0 { }
 
 
@@ -639,8 +639,8 @@ trait TraitAddSuperTrait : ReferencedTrait0 { }
 trait TraitAddBuiltiBound { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddBuiltiBound : Send { }
 
 
@@ -650,8 +650,8 @@ trait TraitAddBuiltiBound : Send { }
 trait TraitAddStaticLifetimeBound { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddStaticLifetimeBound : 'static { }
 
 
@@ -661,16 +661,16 @@ trait TraitAddStaticLifetimeBound : 'static { }
 trait TraitAddTraitAsSecondBound : ReferencedTrait0 { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddTraitAsSecondBound : ReferencedTrait0 + ReferencedTrait1 { }
 
 #[cfg(cfail1)]
 trait TraitAddTraitAsSecondBoundFromBuiltin : Send { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddTraitAsSecondBoundFromBuiltin : Send + ReferencedTrait0 { }
 
 
@@ -680,16 +680,16 @@ trait TraitAddTraitAsSecondBoundFromBuiltin : Send + ReferencedTrait0 { }
 trait TraitAddBuiltinBoundAsSecondBound : ReferencedTrait0 { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddBuiltinBoundAsSecondBound : ReferencedTrait0 + Send { }
 
 #[cfg(cfail1)]
 trait TraitAddBuiltinBoundAsSecondBoundFromBuiltin : Send { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddBuiltinBoundAsSecondBoundFromBuiltin: Send + Copy { }
 
 
@@ -699,16 +699,16 @@ trait TraitAddBuiltinBoundAsSecondBoundFromBuiltin: Send + Copy { }
 trait TraitAddStaticBoundAsSecondBound : ReferencedTrait0 { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddStaticBoundAsSecondBound : ReferencedTrait0 + 'static { }
 
 #[cfg(cfail1)]
 trait TraitAddStaticBoundAsSecondBoundFromBuiltin : Send { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddStaticBoundAsSecondBoundFromBuiltin : Send + 'static { }
 
 
@@ -718,8 +718,8 @@ trait TraitAddStaticBoundAsSecondBoundFromBuiltin : Send + 'static { }
 trait TraitAddTypeParameterToTrait { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddTypeParameterToTrait<T> { }
 
 
@@ -729,8 +729,8 @@ trait TraitAddTypeParameterToTrait<T> { }
 trait TraitAddLifetimeParameterToTrait { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddLifetimeParameterToTrait<'a> { }
 
 
@@ -740,8 +740,8 @@ trait TraitAddLifetimeParameterToTrait<'a> { }
 trait TraitAddTraitBoundToTypeParameterOfTrait<T> { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddTraitBoundToTypeParameterOfTrait<T: ReferencedTrait0> { }
 
 
@@ -751,8 +751,8 @@ trait TraitAddTraitBoundToTypeParameterOfTrait<T: ReferencedTrait0> { }
 trait TraitAddLifetimeBoundToTypeParameterOfTrait<'a, T> { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddLifetimeBoundToTypeParameterOfTrait<'a, T: 'a> { }
 
 
@@ -762,8 +762,8 @@ trait TraitAddLifetimeBoundToTypeParameterOfTrait<'a, T: 'a> { }
 trait TraitAddLifetimeBoundToLifetimeParameterOfTrait<'a, 'b> { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddLifetimeBoundToLifetimeParameterOfTrait<'a: 'b, 'b> { }
 
 
@@ -773,8 +773,8 @@ trait TraitAddLifetimeBoundToLifetimeParameterOfTrait<'a: 'b, 'b> { }
 trait TraitAddBuiltinBoundToTypeParameterOfTrait<T> { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddBuiltinBoundToTypeParameterOfTrait<T: Send> { }
 
 
@@ -784,8 +784,8 @@ trait TraitAddBuiltinBoundToTypeParameterOfTrait<T: Send> { }
 trait TraitAddSecondTypeParameterToTrait<T> { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddSecondTypeParameterToTrait<T, S> { }
 
 
@@ -795,8 +795,8 @@ trait TraitAddSecondTypeParameterToTrait<T, S> { }
 trait TraitAddSecondLifetimeParameterToTrait<'a> { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddSecondLifetimeParameterToTrait<'a, 'b> { }
 
 
@@ -806,8 +806,8 @@ trait TraitAddSecondLifetimeParameterToTrait<'a, 'b> { }
 trait TraitAddSecondTraitBoundToTypeParameterOfTrait<T: ReferencedTrait0> { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddSecondTraitBoundToTypeParameterOfTrait<T: ReferencedTrait0 + ReferencedTrait1> { }
 
 
@@ -817,8 +817,8 @@ trait TraitAddSecondTraitBoundToTypeParameterOfTrait<T: ReferencedTrait0 + Refer
 trait TraitAddSecondLifetimeBoundToTypeParameterOfTrait<'a, 'b, T: 'a> { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddSecondLifetimeBoundToTypeParameterOfTrait<'a, 'b, T: 'a + 'b> { }
 
 
@@ -828,8 +828,8 @@ trait TraitAddSecondLifetimeBoundToTypeParameterOfTrait<'a, 'b, T: 'a + 'b> { }
 trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTrait<'a: 'b, 'b, 'c> { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTrait<'a: 'b + 'c, 'b, 'c> { }
 
 
@@ -839,8 +839,8 @@ trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTrait<'a: 'b + 'c, 'b, 'c>
 trait TraitAddSecondBuiltinBoundToTypeParameterOfTrait<T: Send> { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddSecondBuiltinBoundToTypeParameterOfTrait<T: Send + Sync> { }
 
 
@@ -855,8 +855,8 @@ struct ReferenceType1 {}
 trait TraitAddTraitBoundToTypeParameterOfTraitWhere<T> { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddTraitBoundToTypeParameterOfTraitWhere<T> where T: ReferencedTrait0 { }
 
 
@@ -866,8 +866,8 @@ trait TraitAddTraitBoundToTypeParameterOfTraitWhere<T> where T: ReferencedTrait0
 trait TraitAddLifetimeBoundToTypeParameterOfTraitWhere<'a, T> { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddLifetimeBoundToTypeParameterOfTraitWhere<'a, T> where T: 'a { }
 
 
@@ -877,8 +877,8 @@ trait TraitAddLifetimeBoundToTypeParameterOfTraitWhere<'a, T> where T: 'a { }
 trait TraitAddLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b> { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b> where 'a: 'b { }
 
 
@@ -888,8 +888,8 @@ trait TraitAddLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b> where 'a: 'b
 trait TraitAddBuiltinBoundToTypeParameterOfTraitWhere<T> { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddBuiltinBoundToTypeParameterOfTraitWhere<T> where T: Send { }
 
 
@@ -899,8 +899,8 @@ trait TraitAddBuiltinBoundToTypeParameterOfTraitWhere<T> where T: Send { }
 trait TraitAddSecondTraitBoundToTypeParameterOfTraitWhere<T> where T: ReferencedTrait0 { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddSecondTraitBoundToTypeParameterOfTraitWhere<T>
     where T: ReferencedTrait0 + ReferencedTrait1 { }
 
@@ -911,8 +911,8 @@ trait TraitAddSecondTraitBoundToTypeParameterOfTraitWhere<T>
 trait TraitAddSecondLifetimeBoundToTypeParameterOfTraitWhere<'a, 'b, T> where T: 'a { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddSecondLifetimeBoundToTypeParameterOfTraitWhere<'a, 'b, T> where T: 'a + 'b { }
 
 
@@ -922,8 +922,8 @@ trait TraitAddSecondLifetimeBoundToTypeParameterOfTraitWhere<'a, 'b, T> where T:
 trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b, 'c> where 'a: 'b { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b, 'c> where 'a: 'b + 'c { }
 
 
@@ -933,8 +933,8 @@ trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b, 'c> whe
 trait TraitAddSecondBuiltinBoundToTypeParameterOfTraitWhere<T> where T: Send { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddSecondBuiltinBoundToTypeParameterOfTraitWhere<T> where T: Send + Sync { }
 
 
@@ -945,11 +945,11 @@ mod change_return_type_of_method_indirectly_use {
     #[cfg(not(cfail1))]
     use super::ReferenceType1 as ReturnType;
 
-    #[rustc_clean(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_clean(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     trait TraitChangeReturnType {
-        #[rustc_dirty(label="Hir", cfg="cfail2")]
-        #[rustc_clean(label="Hir", cfg="cfail3")]
+        #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+        #[rustc_clean(label="hir_owner", cfg="cfail3")]
         fn method() -> ReturnType;
     }
 }
@@ -963,11 +963,11 @@ mod change_method_parameter_type_indirectly_by_use {
     #[cfg(not(cfail1))]
     use super::ReferenceType1 as ArgType;
 
-    #[rustc_clean(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_clean(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     trait TraitChangeArgType {
-        #[rustc_dirty(label="Hir", cfg="cfail2")]
-        #[rustc_clean(label="Hir", cfg="cfail3")]
+        #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+        #[rustc_clean(label="hir_owner", cfg="cfail3")]
         fn method(a: ArgType);
     }
 }
@@ -981,11 +981,11 @@ mod change_method_parameter_type_bound_indirectly_by_use {
     #[cfg(not(cfail1))]
     use super::ReferencedTrait1 as Bound;
 
-    #[rustc_clean(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_clean(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     trait TraitChangeBoundOfMethodTypeParameter {
-        #[rustc_dirty(label="Hir", cfg="cfail2")]
-        #[rustc_clean(label="Hir", cfg="cfail3")]
+        #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+        #[rustc_clean(label="hir_owner", cfg="cfail3")]
         fn method<T: Bound>(a: T);
     }
 }
@@ -1000,11 +1000,11 @@ mod change_method_parameter_type_bound_indirectly_by_use_where {
     #[cfg(not(cfail1))]
     use super::ReferencedTrait1 as Bound;
 
-    #[rustc_clean(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_clean(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     trait TraitChangeBoundOfMethodTypeParameterWhere {
-        #[rustc_dirty(label="Hir", cfg="cfail2")]
-        #[rustc_clean(label="Hir", cfg="cfail3")]
+        #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+        #[rustc_clean(label="hir_owner", cfg="cfail3")]
         fn method<T>(a: T) where T: Bound;
     }
 }
@@ -1018,8 +1018,8 @@ mod change_method_type_parameter_bound_indirectly {
     #[cfg(not(cfail1))]
     use super::ReferencedTrait1 as Bound;
 
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     trait TraitChangeTraitBound<T: Bound> {
         fn method(a: T);
     }
@@ -1035,8 +1035,8 @@ mod change_method_type_parameter_bound_indirectly_where {
     #[cfg(not(cfail1))]
     use super::ReferencedTrait1 as Bound;
 
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     trait TraitChangeTraitBoundWhere<T> where T: Bound {
         fn method(a: T);
     }
index fa28b2ebedd132aa2a90b9b520edbcbc763832cf..70e066870b6b449f017561707516bf6fa65cfb1d 100644 (file)
@@ -30,18 +30,18 @@ fn method_name() { }
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 pub trait ChangeMethodNameTrait {
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method_name2();
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 impl ChangeMethodNameTrait for Foo {
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method_name2() { }
 }
 
@@ -59,13 +59,13 @@ fn method_name() { }
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 impl ChangeMethodBodyTrait for Foo {
-    #[rustc_clean(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_dirty(label="HirBody", cfg="cfail2")]
-    #[rustc_clean(label="HirBody", cfg="cfail3")]
+    #[rustc_clean(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner_items", cfg="cfail3")]
     fn method_name() {
         ()
     }
@@ -86,13 +86,13 @@ fn method_name() { }
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 impl ChangeMethodBodyTraitInlined for Foo {
-    #[rustc_clean(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_dirty(label="HirBody", cfg="cfail2")]
-    #[rustc_clean(label="HirBody", cfg="cfail3")]
+    #[rustc_clean(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner_items", cfg="cfail3")]
     #[inline]
     fn method_name() {
         panic!()
@@ -117,11 +117,11 @@ pub trait ChangeMethodSelfnessTrait {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 impl ChangeMethodSelfnessTrait for Foo {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method_name(&self) {
         ()
     }
@@ -145,11 +145,11 @@ pub trait RemoveMethodSelfnessTrait {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 impl RemoveMethodSelfnessTrait for Foo {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method_name() {}
 }
 
@@ -171,11 +171,11 @@ pub trait ChangeMethodSelfmutnessTrait {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 impl ChangeMethodSelfmutnessTrait for Foo {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method_name(&mut self) {}
 }
 
@@ -197,8 +197,8 @@ pub trait ChangeItemKindTrait {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 impl ChangeItemKindTrait for Foo {
     type name = ();
 }
@@ -223,8 +223,8 @@ pub trait RemoveItemTrait {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 impl RemoveItemTrait for Foo {
     type TypeName = ();
 }
@@ -248,8 +248,8 @@ pub trait AddItemTrait {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 impl AddItemTrait for Foo {
     type TypeName = ();
     fn method_name() { }
@@ -268,17 +268,17 @@ fn method_name() { }
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 pub trait ChangeHasValueTrait {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method_name() { }
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 impl ChangeHasValueTrait for Foo {
     fn method_name() { }
 }
@@ -295,11 +295,11 @@ fn method_name() { }
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 impl AddDefaultTrait for Foo {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     default fn method_name() { }
 }
 
@@ -321,11 +321,11 @@ pub trait AddArgumentTrait {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 impl AddArgumentTrait for Foo {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method_name(&self, _x: u32) { }
 }
 
@@ -347,11 +347,11 @@ pub trait ChangeArgumentTypeTrait {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 impl ChangeArgumentTypeTrait for Foo {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method_name(&self, _x: char) { }
 }
 
@@ -370,11 +370,11 @@ fn id(t: u32) -> u32 { t }
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 impl<T> AddTypeParameterToImpl<T> for Bar<T> {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn id(t: T) -> T { t }
 }
 
@@ -391,11 +391,11 @@ fn id(self) -> Self { self }
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 impl ChangeSelfTypeOfImpl for u64 {
-    #[rustc_clean(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_clean(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn id(self) -> Self { self }
 }
 
@@ -412,11 +412,11 @@ fn id(self) -> Self { self }
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 impl<T: 'static> AddLifetimeBoundToImplParameter for T {
-    #[rustc_clean(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_clean(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn id(self) -> Self { self }
 }
 
@@ -433,11 +433,11 @@ fn id(self) -> Self { self }
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 impl<T: Clone> AddTraitBoundToImplParameter for T {
-    #[rustc_clean(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_clean(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn id(self) -> Self { self }
 }
 
@@ -454,11 +454,11 @@ fn add_no_mangle_to_method(&self) { }
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 impl AddNoMangleToMethod for Foo {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     #[no_mangle]
     fn add_no_mangle_to_method(&self) { }
 }
@@ -475,11 +475,11 @@ fn make_method_inline(&self) -> u8 { 0 }
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 impl MakeMethodInline for Foo {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     #[inline]
     fn make_method_inline(&self) -> u8 { 0 }
 }
index 264e8f926ffe56ada243411e1f9531eb47387c05..bbe1514ba9fd49f36d360333d246d6f8d5f3da40 100644 (file)
@@ -24,7 +24,7 @@
 type ChangePrimitiveType = i32;
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 type ChangePrimitiveType = i64;
 
@@ -35,7 +35,7 @@
 type ChangeMutability = &'static i32;
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 type ChangeMutability = &'static mut i32;
 
@@ -46,7 +46,7 @@
 type ChangeLifetime<'a> = (&'static i32, &'a i32);
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 type ChangeLifetime<'a> = (&'a i32, &'a i32);
 
@@ -60,7 +60,7 @@
 type ChangeTypeStruct = Struct1;
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 type ChangeTypeStruct = Struct2;
 
@@ -71,7 +71,7 @@
 type ChangeTypeTuple = (u32, u64);
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 type ChangeTypeTuple = (u32, i64);
 
@@ -91,7 +91,7 @@ enum Enum2 {
 type ChangeTypeEnum = Enum1;
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 type ChangeTypeEnum = Enum2;
 
@@ -102,7 +102,7 @@ enum Enum2 {
 type AddTupleField = (i32, i64);
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 type AddTupleField = (i32, i64, i16);
 
@@ -113,7 +113,7 @@ enum Enum2 {
 type ChangeNestedTupleField = (i32, (i64, i16));
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 type ChangeNestedTupleField = (i32, (i64, i8));
 
@@ -124,7 +124,7 @@ enum Enum2 {
 type AddTypeParam<T1> = (T1, T1);
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 type AddTypeParam<T1, T2> = (T1, T2);
 
@@ -135,7 +135,7 @@ enum Enum2 {
 type AddTypeParamBound<T1> = (T1, u32);
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 type AddTypeParamBound<T1: Clone> = (T1, u32);
 
@@ -146,7 +146,7 @@ enum Enum2 {
 type AddTypeParamBoundWhereClause<T1> where T1: Clone = (T1, u32);
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 type AddTypeParamBoundWhereClause<T1> where T1: Clone+Copy = (T1, u32);
 
@@ -157,7 +157,7 @@ enum Enum2 {
 type AddLifetimeParam<'a> = (&'a u32, &'a u32);
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 type AddLifetimeParam<'a, 'b> = (&'a u32, &'b u32);
 
@@ -168,7 +168,7 @@ enum Enum2 {
 type AddLifetimeParamBound<'a, 'b> = (&'a u32, &'b u32);
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 type AddLifetimeParamBound<'a, 'b: 'a> = (&'a u32, &'b u32);
 
@@ -181,7 +181,7 @@ enum Enum2 {
     = (&'a u32, &'b u32, &'c u32);
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 type AddLifetimeParamBoundWhereClause<'a, 'b, 'c>
 where 'b: 'a,
@@ -200,7 +200,7 @@ mod change_trait_bound_indirectly {
     #[cfg(not(cfail1))]
     use super::ReferencedTrait2 as Trait;
 
-    #[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+    #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
     #[rustc_clean(cfg="cfail3")]
     type ChangeTraitBoundIndirectly<T: Trait> = (T, u32);
 }
@@ -214,7 +214,7 @@ mod change_trait_bound_indirectly_in_where_clause {
     #[cfg(not(cfail1))]
     use super::ReferencedTrait2 as Trait;
 
-    #[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+    #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
     #[rustc_clean(cfg="cfail3")]
     type ChangeTraitBoundIndirectly<T> where T : Trait = (T, u32);
 }
index 776a0273ca7b6bf831d1460da85de2bd7051ff48..89aa0b1a58baa9eaa315010aeec03b04ead7555b 100644 (file)
@@ -21,7 +21,7 @@ pub fn const_negation() -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn const_negation() -> i32 {
     -1
@@ -36,7 +36,7 @@ pub fn const_bitwise_not() -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn const_bitwise_not() -> i32 {
     !99
@@ -51,7 +51,7 @@ pub fn var_negation(x: i32, y: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn var_negation(x: i32, y: i32) -> i32 {
     -y
@@ -66,7 +66,7 @@ pub fn var_bitwise_not(x: i32, y: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn var_bitwise_not(x: i32, y: i32) -> i32 {
     !y
@@ -81,7 +81,7 @@ pub fn var_deref(x: &i32, y: &i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built,typeck_tables_of", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn var_deref(x: &i32, y: &i32) -> i32 {
     *y
@@ -96,7 +96,7 @@ pub fn first_const_add() -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn first_const_add() -> i32 {
     2 + 3
@@ -111,7 +111,7 @@ pub fn second_const_add() -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn second_const_add() -> i32 {
     1 + 3
@@ -126,7 +126,7 @@ pub fn first_var_add(a: i32, b: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn first_var_add(a: i32, b: i32) -> i32 {
     b + 2
@@ -141,7 +141,7 @@ pub fn second_var_add(a: i32, b: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn second_var_add(a: i32, b: i32) -> i32 {
     1 + b
@@ -156,7 +156,7 @@ pub fn plus_to_minus(a: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn plus_to_minus(a: i32) -> i32 {
     1 - a
@@ -171,7 +171,7 @@ pub fn plus_to_mult(a: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn plus_to_mult(a: i32) -> i32 {
     1 * a
@@ -186,7 +186,7 @@ pub fn plus_to_div(a: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn plus_to_div(a: i32) -> i32 {
     1 / a
@@ -201,7 +201,7 @@ pub fn plus_to_mod(a: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn plus_to_mod(a: i32) -> i32 {
     1 % a
@@ -216,7 +216,7 @@ pub fn and_to_or(a: bool, b: bool) -> bool {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn and_to_or(a: bool, b: bool) -> bool {
     a || b
@@ -231,7 +231,7 @@ pub fn bitwise_and_to_bitwise_or(a: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn bitwise_and_to_bitwise_or(a: i32) -> i32 {
     1 | a
@@ -246,7 +246,7 @@ pub fn bitwise_and_to_bitwise_xor(a: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn bitwise_and_to_bitwise_xor(a: i32) -> i32 {
     1 ^ a
@@ -261,7 +261,7 @@ pub fn bitwise_and_to_lshift(a: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn bitwise_and_to_lshift(a: i32) -> i32 {
     a << 1
@@ -276,7 +276,7 @@ pub fn bitwise_and_to_rshift(a: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn bitwise_and_to_rshift(a: i32) -> i32 {
     a >> 1
@@ -291,7 +291,7 @@ pub fn eq_to_uneq(a: i32) -> bool {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn eq_to_uneq(a: i32) -> bool {
     a != 1
@@ -306,7 +306,7 @@ pub fn eq_to_lt(a: i32) -> bool {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn eq_to_lt(a: i32) -> bool {
     a < 1
@@ -321,7 +321,7 @@ pub fn eq_to_gt(a: i32) -> bool {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn eq_to_gt(a: i32) -> bool {
     a > 1
@@ -336,7 +336,7 @@ pub fn eq_to_le(a: i32) -> bool {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn eq_to_le(a: i32) -> bool {
     a <= 1
@@ -351,7 +351,7 @@ pub fn eq_to_ge(a: i32) -> bool {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn eq_to_ge(a: i32) -> bool {
     a >= 1
@@ -368,7 +368,7 @@ pub fn type_cast(a: u8) -> u64 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built,typeck_tables_of", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built,typeck_tables_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn type_cast(a: u8) -> u64 {
     let b = a as u32;
@@ -385,7 +385,7 @@ pub fn value_cast(a: u32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn value_cast(a: u32) -> i32 {
     2 as i32
@@ -403,7 +403,7 @@ pub fn place() -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn place() -> i32 {
     let mut x = 10;
@@ -423,7 +423,7 @@ pub fn rvalue() -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn rvalue() -> i32 {
     let mut x = 10;
@@ -440,7 +440,7 @@ pub fn index_to_slice(s: &[u8], i: usize, j: usize) -> u8 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn index_to_slice(s: &[u8], i: usize, j: usize) -> u8 {
     s[j]
index 615f1fe1fd0b888ca79b9b0145884c9ebc062c5e..908f60440fa5b802b63bc00840735c0d90b1c87d 100644 (file)
@@ -25,7 +25,7 @@ pub fn change_loop_body() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_loop_body() {
     let mut _x = 0;
@@ -48,7 +48,7 @@ pub fn change_loop_condition() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_loop_condition() {
     let mut _x = 0;
@@ -70,7 +70,7 @@ pub fn add_break() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_break() {
     let mut _x = 0;
@@ -93,7 +93,7 @@ pub fn add_loop_label() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_loop_label() {
     let mut _x = 0;
@@ -116,7 +116,7 @@ pub fn add_loop_label_to_break() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_loop_label_to_break() {
     let mut _x = 0;
@@ -141,7 +141,7 @@ pub fn change_break_label() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_break_label() {
     let mut _x = 0;
@@ -166,7 +166,7 @@ pub fn add_loop_label_to_continue() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_loop_label_to_continue() {
     let mut _x = 0;
@@ -191,7 +191,7 @@ pub fn change_continue_label() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_continue_label() {
     let mut _x = 0;
@@ -216,7 +216,7 @@ pub fn change_continue_to_break() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_continue_to_break() {
     let mut _x = 0;
index a427ffb96e33982c5c79ad67c80455734ef672ec..365ec5fa567d9e8eb4aad6082281af79b715bffc 100644 (file)
@@ -25,7 +25,7 @@ pub fn change_loop_body() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_loop_body() {
     let mut _x = 0;
@@ -48,7 +48,7 @@ pub fn change_loop_condition() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_loop_condition() {
     let mut _x = 0;
@@ -70,7 +70,7 @@ pub fn add_break() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir, typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_break() {
     let mut _x = 0;
@@ -93,7 +93,7 @@ pub fn add_loop_label() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_loop_label() {
     let mut _x = 0;
@@ -116,7 +116,7 @@ pub fn add_loop_label_to_break() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_loop_label_to_break() {
     let mut _x = 0;
@@ -141,7 +141,7 @@ pub fn change_break_label() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_break_label() {
     let mut _x = 0;
@@ -166,7 +166,7 @@ pub fn add_loop_label_to_continue() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_loop_label_to_continue() {
     let mut _x = 0;
@@ -191,7 +191,7 @@ pub fn change_continue_label() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_continue_label() {
     let mut _x = 0;
@@ -216,7 +216,7 @@ pub fn change_continue_to_break() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_continue_to_break() {
     let mut _x = 0;
index 9dfd2ae2511b15b009f79b3d9552fe3f742ddf30..a9ec66346acb0a15f0604aff57439a184c13ed04 100644 (file)
@@ -26,15 +26,15 @@ mod mod3 {
     #[cfg(rpass2)]
     use Trait2;
 
-    #[rustc_clean(label="Hir", cfg="rpass2")]
-    #[rustc_clean(label="HirBody", cfg="rpass2")]
+    #[rustc_clean(label="hir_owner", cfg="rpass2")]
+    #[rustc_clean(label="hir_owner_items", cfg="rpass2")]
     #[rustc_dirty(label="typeck_tables_of", cfg="rpass2")]
     fn bar() {
         ().method();
     }
 
-    #[rustc_clean(label="Hir", cfg="rpass2")]
-    #[rustc_clean(label="HirBody", cfg="rpass2")]
+    #[rustc_clean(label="hir_owner", cfg="rpass2")]
+    #[rustc_clean(label="hir_owner_items", cfg="rpass2")]
     #[rustc_clean(label="typeck_tables_of", cfg="rpass2")]
     fn baz() {
         22; // no method call, traits in scope don't matter
index b2b7e663151e2630b66e763d1621860036bf2754..a9232190eef48dfc013b7272d5e38b9d6dbaee55 100644 (file)
@@ -7,18 +7,21 @@
 #![crate_type = "rlib"]
 #![feature(rustc_attrs)]
 
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_clean(label = "hir_owner", cfg = "cfail2")]
+#[rustc_dirty(label = "hir_owner_items", cfg = "cfail2")]
 pub fn foo() {
     #[cfg(cfail1)]
-    pub fn baz() { } // order is different...
+    pub fn baz() {} // order is different...
 
-    #[rustc_clean(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="HirBody", cfg="cfail2")]
-    pub fn bar() { } // but that doesn't matter.
+    // FIXME: Make "hir_owner" use `rustc_clean` here. Currently "hir_owner" includes a reference to
+    // the parent node, which is the statement holding this item. Changing the position of
+    // `bar` in `foo` will update that reference and make `hir_owner(bar)` dirty.
+    #[rustc_dirty(label = "hir_owner", cfg = "cfail2")]
+    #[rustc_clean(label = "hir_owner_items", cfg = "cfail2")]
+    pub fn bar() {} // but that doesn't matter.
 
     #[cfg(cfail2)]
-    pub fn baz() { } // order is different...
+    pub fn baz() {} // order is different...
 
-    pub fn bap() { } // neither does adding a new item
+    pub fn bap() {} // neither does adding a new item
 }
index 0e4ab6b78e2d7c72ddb80baf0d7ac87090e60999..c4674faabf5d63494178c223c0c9e0173fc7fd58 100644 (file)
@@ -28,18 +28,18 @@ mod mod3 {
     #[cfg(rpass3)]
     use mod2::Foo;
 
-    #[rustc_clean(label="Hir", cfg="rpass2")]
-    #[rustc_clean(label="HirBody", cfg="rpass2")]
-    #[rustc_clean(label="Hir", cfg="rpass3")]
-    #[rustc_dirty(label="HirBody", cfg="rpass3")]
+    #[rustc_clean(label="hir_owner", cfg="rpass2")]
+    #[rustc_clean(label="hir_owner_items", cfg="rpass2")]
+    #[rustc_clean(label="hir_owner", cfg="rpass3")]
+    #[rustc_dirty(label="hir_owner_items", cfg="rpass3")]
     fn in_expr() {
         Foo(0);
     }
 
-    #[rustc_clean(label="Hir", cfg="rpass2")]
-    #[rustc_clean(label="HirBody", cfg="rpass2")]
-    #[rustc_clean(label="Hir", cfg="rpass3")]
-    #[rustc_dirty(label="HirBody", cfg="rpass3")]
+    #[rustc_clean(label="hir_owner", cfg="rpass2")]
+    #[rustc_clean(label="hir_owner_items", cfg="rpass2")]
+    #[rustc_clean(label="hir_owner", cfg="rpass3")]
+    #[rustc_dirty(label="hir_owner_items", cfg="rpass3")]
     fn in_type() {
         test::<Foo>();
     }
index 819b8434b0839b378e4961df510ce92d469470e9..bb76a0bb8fe868bdc174652c6bfa69f6e1b7e929 100644 (file)
@@ -1,6 +1,6 @@
 // Regression test for #34991: an ICE occurred here because we inline
 // some of the vector routines and give them a local def-id `X`. This
-// got hashed after codegen (`Hir(X)`). When we load back up, we get an
+// got hashed after codegen (`hir_owner(X)`). When we load back up, we get an
 // error because the `X` is remapped to the original def-id (in
 // libstd), and we can't hash a HIR node from std.
 
diff --git a/src/test/incremental/issue-69596.rs b/src/test/incremental/issue-69596.rs
new file mode 100644 (file)
index 0000000..dc587fd
--- /dev/null
@@ -0,0 +1,21 @@
+// revisions: rpass1 rpass2
+
+#![allow(unused_imports)]
+
+#[macro_export]
+macro_rules! a_macro {
+    () => {};
+}
+
+#[cfg(rpass1)]
+use a_macro as same_name;
+
+mod same_name {}
+
+mod needed_mod {
+    fn _crash() {
+        use super::same_name;
+    }
+}
+
+fn main() {}
index 51ea7d6d447e5b43b32f017ba9fd1013256f6b5f..a360a66a64b24afab6c86b5844b3945ced77fd62 100644 (file)
@@ -7,26 +7,26 @@
 
 #![feature(rustc_attrs)]
 
-#[rustc_clean(label="Hir", cfg="rpass2")]
-#[rustc_clean(label="HirBody", cfg="rpass2")]
+#[rustc_clean(label="hir_owner", cfg="rpass2")]
+#[rustc_clean(label="hir_owner_items", cfg="rpass2")]
 fn line_same() {
     let _ = line!();
 }
 
-#[rustc_clean(label="Hir", cfg="rpass2")]
-#[rustc_clean(label="HirBody", cfg="rpass2")]
+#[rustc_clean(label="hir_owner", cfg="rpass2")]
+#[rustc_clean(label="hir_owner_items", cfg="rpass2")]
 fn col_same() {
     let _ = column!();
 }
 
-#[rustc_clean(label="Hir", cfg="rpass2")]
-#[rustc_clean(label="HirBody", cfg="rpass2")]
+#[rustc_clean(label="hir_owner", cfg="rpass2")]
+#[rustc_clean(label="hir_owner_items", cfg="rpass2")]
 fn file_same() {
     let _ = file!();
 }
 
-#[rustc_clean(label="Hir", cfg="rpass2")]
-#[rustc_dirty(label="HirBody", cfg="rpass2")]
+#[rustc_clean(label="hir_owner", cfg="rpass2")]
+#[rustc_dirty(label="hir_owner_items", cfg="rpass2")]
 fn line_different() {
     #[cfg(rpass1)]
     {
@@ -38,8 +38,8 @@ fn line_different() {
     }
 }
 
-#[rustc_clean(label="Hir", cfg="rpass2")]
-#[rustc_dirty(label="HirBody", cfg="rpass2")]
+#[rustc_clean(label="hir_owner", cfg="rpass2")]
+#[rustc_dirty(label="hir_owner_items", cfg="rpass2")]
 fn col_different() {
     #[cfg(rpass1)]
     {
index 54fbe4465e3cf863a4b601f3f0815a08622d171d..2927ddec4e52c324e4afaf0dc3efd8cc267216d2 100644 (file)
@@ -1,4 +1,4 @@
-#[rustc_clean(label="Hir", cfg="rpass2")]
+#[rustc_clean(label="hir_owner", cfg="rpass2")]
 pub struct SomeType {
     pub x: u32,
     pub y: i64,
index 349576168567f75ca49258d9ca7d504d0589b593..aa635077db8ee612db05b964f6a3128095bd10dc 100644 (file)
@@ -1,4 +1,4 @@
-#[rustc_clean(label="Hir", cfg="rpass2")]
+#[rustc_clean(label="hir_owner", cfg="rpass2")]
 pub struct SomeOtherType {
     pub a: i32,
     pub b: u64,
index e6fdc7cb3a0fc24138d3ea1e113fff88757a592e..b87d829132b29e4a3788c904f229094cca0018bd 100644 (file)
@@ -12,6 +12,6 @@
 pub fn main() {}
 
 #[cfg(rpass2)]
-#[rustc_dirty(label="Hir", cfg="rpass2")]
-#[rustc_dirty(label="HirBody", cfg="rpass2")]
+#[rustc_dirty(label="hir_owner", cfg="rpass2")]
+#[rustc_dirty(label="hir_owner_items", cfg="rpass2")]
 pub fn main() {}
index b88acd2af75abf2f93ac9887dc0fc706e9f86a7d..11a42262c16d2012c49e5810df7fd288c7285f87 100644 (file)
@@ -18,7 +18,7 @@ pub fn x() {
     }
 
     #[cfg(cfail2)]
-    #[rustc_dirty(label="HirBody", cfg="cfail2")]
+    #[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
     #[rustc_dirty(label="optimized_mir", cfg="cfail2")]
     pub fn x() {
         println!("{}", "2");
index 42168dd273eff42627997c1be212f2530f734dae..9c17c8745f8caa26461505ab15bc53042beb9553 100644 (file)
@@ -4,7 +4,7 @@
 
 // rust-lang/rust#59535:
 //
-// This is analgous to cgu_invalidated_when_import_removed.rs, but it covers
+// This is analogous to cgu_invalidated_when_import_removed.rs, but it covers
 // the other direction:
 //
 // We start with a call-graph like `[A] -> [B -> D] [C]` (where the letters are
index 19ce7b3e148f73f0388ab80dc21049f9a60120e6..1214e37f982edf101ad8002bc2daf13df6ca114e 100644 (file)
@@ -41,7 +41,7 @@ mod foo {
     // In cfail2, ThinLTO decides that foo() does not get inlined into main, and
     // instead bar() gets inlined into foo(). But faulty logic in our incr.
     // ThinLTO implementation thought that `main()` is unchanged and thus reused
-    // the object file still containing a call to the now non-existant bar().
+    // the object file still containing a call to the now non-existent bar().
     pub fn foo(){
         bar()
     }
index 66bdb670167eda2c90e52961364125be44eb0778..3bc8818aa6f4ca76dbbbc5fb46d205ee3398d619 100644 (file)
 
 fn main() {
 
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
     //[cfail2]~^ ERROR found unchecked `#[rustc_dirty]` / `#[rustc_clean]` attribute
     {
         // empty block
     }
 
-    #[rustc_clean(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail2")]
     //[cfail2]~^ ERROR found unchecked `#[rustc_dirty]` / `#[rustc_clean]` attribute
     {
         // empty block
@@ -24,11 +24,11 @@ fn main() {
 }
 
 struct _Struct {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
     //[cfail2]~^ ERROR found unchecked `#[rustc_dirty]` / `#[rustc_clean]` attribute
     _field1: i32,
 
-    #[rustc_clean(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail2")]
     //[cfail2]~^ ERROR found unchecked `#[rustc_dirty]` / `#[rustc_clean]` attribute
     _field2: i32,
 }
index f6f7d0910911c544e9ca15096dd6e73d9a9811b4..c858a4c5ee7c6cecce7253ae2b0de020c96606b7 100644 (file)
@@ -4,9 +4,9 @@
 
 static Y: i32 = 42;
 
-static mut BAR: *const &'static i32 = [&Y].as_ptr();
+static mut BAR: *const &i32 = [&Y].as_ptr();
 
-static mut FOO: *const &'static i32 = [unsafe { &X }].as_ptr();
+static mut FOO: *const &i32 = [unsafe { &X }].as_ptr();
 
 fn main() {}
 
@@ -14,12 +14,12 @@ fn main() {}
 // START rustc.FOO.PromoteTemps.before.mir
 // bb0: {
 // ...
-//     _5 = const Scalar(alloc1+0) : &i32;
+//     _5 = const {alloc1+0: &i32};
 //     _4 = &(*_5);
 //     _3 = [move _4];
 //     _2 = &_3;
-//     _1 = move _2 as &[&'static i32] (Pointer(Unsize));
-//     _0 = const core::slice::<impl [&'static i32]>::as_ptr(move _1) -> [return: bb2, unwind: bb1];
+//     _1 = move _2 as &[&i32] (Pointer(Unsize));
+//     _0 = const core::slice::<impl [&i32]>::as_ptr(move _1) -> [return: bb2, unwind: bb1];
 // }
 // ...
 // bb2: {
@@ -31,12 +31,12 @@ fn main() {}
 // START rustc.BAR.PromoteTemps.before.mir
 // bb0: {
 // ...
-//     _5 = const Scalar(alloc0+0) : &i32;
+//     _5 = const {alloc0+0: &i32};
 //     _4 = &(*_5);
 //     _3 = [move _4];
 //     _2 = &_3;
-//     _1 = move _2 as &[&'static i32] (Pointer(Unsize));
-//     _0 = const core::slice::<impl [&'static i32]>::as_ptr(move _1) -> [return: bb2, unwind: bb1];
+//     _1 = move _2 as &[&i32] (Pointer(Unsize));
+//     _0 = const core::slice::<impl [&i32]>::as_ptr(move _1) -> [return: bb2, unwind: bb1];
 // }
 // ...
 // bb2: {
@@ -50,8 +50,8 @@ fn main() {}
 // ...
 //     _6 = const BAR::promoted[0];
 //     _2 = &(*_6);
-//     _1 = move _2 as &[&'static i32] (Pointer(Unsize));
-//     _0 = const core::slice::<impl [&'static i32]>::as_ptr(move _1) -> [return: bb2, unwind: bb1];
+//     _1 = move _2 as &[&i32] (Pointer(Unsize));
+//     _0 = const core::slice::<impl [&i32]>::as_ptr(move _1) -> [return: bb2, unwind: bb1];
 // }
 // ...
 // bb2: {
@@ -63,8 +63,8 @@ fn main() {}
 // ...
 //     _6 = const FOO::promoted[0];
 //     _2 = &(*_6);
-//     _1 = move _2 as &[&'static i32] (Pointer(Unsize));
-//     _0 = const core::slice::<impl [&'static i32]>::as_ptr(move _1) -> [return: bb2, unwind: bb1];
+//     _1 = move _2 as &[&i32] (Pointer(Unsize));
+//     _0 = const core::slice::<impl [&i32]>::as_ptr(move _1) -> [return: bb2, unwind: bb1];
 // }
 // ...
 // bb2: {
index 667d21fc14ee4034295e5e7b2a7ccd6bc13afa05..636aa1af6533341513200eb57adda716331d6488 100644 (file)
@@ -31,7 +31,7 @@ fn main() {
 // START rustc.main.ConstProp.after.mir
 //  bb0: {
 //      ...
-//      _3 = const Scalar(0x01) : std::option::Option<bool>;
+//      _3 = const {transmute(0x01): std::option::Option<bool>};
 //      _4 = const 1isize;
 //      switchInt(const 1isize) -> [1isize: bb2, otherwise: bb1];
 //  }
index 30c75303b3e53ccd2973a0929fb70605fc86e6ff..f332bb895095bf276e861b72f1c229454306a7a3 100644 (file)
@@ -29,7 +29,7 @@ fn main() {
 // START rustc.main.ConstProp.after.mir
 //  bb0: {
 //      ...
-//      _3 = const Scalar(<ZST>) : ();
+//      _3 = const ();
 //      _2 = (move _3, const 0u8, const 0u8);
 //      ...
 //      _1 = const encode(move _2) -> bb1;
index 693ef78398558188366fcd845604778e22eeeb9a..d307cebd71539fb3fa37307f6cf27dfcfe59ac8b 100644 (file)
@@ -10,10 +10,10 @@ fn main() {
 // START rustc.main.ConstProp.before.mir
 //  bb0: {
 //      ...
-//      _3 = const Scalar(alloc0+0) : &u8;
+//      _3 = const {alloc0+0: &u8};
 //      _2 = (*_3);
 //      ...
-//      _5 = const Scalar(alloc0+0) : &u8;
+//      _5 = const {alloc0+0: &u8};
 //      _4 = (*_5);
 //      _1 = Add(move _2, move _4);
 //      ...
diff --git a/src/test/mir-opt/generator-tiny.rs b/src/test/mir-opt/generator-tiny.rs
new file mode 100644 (file)
index 0000000..09e943b
--- /dev/null
@@ -0,0 +1,34 @@
+//! Tests that generators that cannot return or unwind don't have unnecessary
+//! panic branches.
+
+// compile-flags: -Zno-landing-pads
+
+#![feature(generators, generator_trait)]
+
+struct HasDrop;
+
+impl Drop for HasDrop {
+    fn drop(&mut self) {}
+}
+
+fn callee() {}
+
+fn main() {
+    let _gen = |_x: u8| {
+        let _d = HasDrop;
+        loop {
+            yield;
+            callee();
+        }
+    };
+}
+
+// END RUST SOURCE
+
+// START rustc.main-{{closure}}.generator_resume.0.mir
+// bb0: {
+//     ...
+//     switchInt(move _11) -> [0u32: bb1, 3u32: bb5, otherwise: bb6];
+// }
+// ...
+// END rustc.main-{{closure}}.generator_resume.0.mir
diff --git a/src/test/mir-opt/no-drop-for-inactive-variant.rs b/src/test/mir-opt/no-drop-for-inactive-variant.rs
new file mode 100644 (file)
index 0000000..74a606a
--- /dev/null
@@ -0,0 +1,43 @@
+// ignore-wasm32-bare compiled with panic=abort by default
+
+// Ensure that there are no drop terminators in `unwrap<T>` (except the one along the cleanup
+// path).
+
+fn unwrap<T>(opt: Option<T>) -> T {
+    match opt {
+        Some(x) => x,
+        None => panic!(),
+    }
+}
+
+fn main() {
+    let _ = unwrap(Some(1i32));
+}
+
+// END RUST SOURCE
+// START rustc.unwrap.SimplifyCfg-elaborate-drops.after.mir
+// fn unwrap(_1: std::option::Option<T>) -> T {
+//     ...
+//     bb0: {
+//         ...
+//         switchInt(move _2) -> [0isize: bb2, 1isize: bb4, otherwise: bb3];
+//     }
+//     bb1 (cleanup): {
+//         resume;
+//     }
+//     bb2: {
+//         ...
+//         const std::rt::begin_panic::<&str>(const "explicit panic") -> bb5;
+//     }
+//     bb3: {
+//         unreachable;
+//     }
+//     bb4: {
+//         ...
+//         return;
+//     }
+//     bb5 (cleanup): {
+//         drop(_1) -> bb1;
+//     }
+// }
+// END rustc.unwrap.SimplifyCfg-elaborate-drops.after.mir
index 294fe247c38be3de5d909f32a8c4f88a0c609252..ea106eaf595292d0d5b28baa180bbe207cfd777e 100644 (file)
@@ -26,16 +26,16 @@ fn main() {
 //     goto -> bb7;
 // }
 // bb2: {
-//     switchInt((*(*((_1 as Some).0: &'<empty> &'<empty> i32)))) -> [0i32: bb3, otherwise: bb1];
+//     switchInt((*(*((_1 as Some).0: &&i32)))) -> [0i32: bb3, otherwise: bb1];
 // }
 // bb3: {
 //     goto -> bb4;
 // }
 // bb4: {
 //     _4 = &shallow _1;
-//     _5 = &shallow ((_1 as Some).0: &'<empty> &'<empty> i32);
-//     _6 = &shallow (*((_1 as Some).0: &'<empty> &'<empty> i32));
-//     _7 = &shallow (*(*((_1 as Some).0: &'<empty> &'<empty> i32)));
+//     _5 = &shallow ((_1 as Some).0: &&i32);
+//     _6 = &shallow (*((_1 as Some).0: &&i32));
+//     _7 = &shallow (*(*((_1 as Some).0: &&i32)));
 //     StorageLive(_8);
 //     _8 = _2;
 //     switchInt(move _8) -> [false: bb6, otherwise: bb5];
@@ -72,7 +72,7 @@ fn main() {
 //     goto -> bb7;
 // }
 // bb2: {
-//     switchInt((*(*((_1 as Some).0: &'<empty> &'<empty> i32)))) -> [0i32: bb3, otherwise: bb1];
+//     switchInt((*(*((_1 as Some).0: &&i32)))) -> [0i32: bb3, otherwise: bb1];
 // }
 // bb3: {
 //     goto -> bb4;
index 6f03438ff723487bbf04ee56297133a0391654df..e427fd55ad6807a82d9e2cb342ad84e50eddd75b 100644 (file)
@@ -1,18 +1,18 @@
 // compile-flags: -C overflow-checks=no
 
-fn use_zst(_: ((), ())) { }
+fn use_zst(_: ((), ())) {}
 
 struct Temp {
-    x: u8
+    x: u8,
 }
 
-fn use_u8(_: u8) { }
+fn use_u8(_: u8) {}
 
 fn main() {
     let ((), ()) = ((), ());
     use_zst(((), ()));
 
-    use_u8((Temp { x : 40 }).x + 2);
+    use_u8((Temp { x: 40 }).x + 2);
 }
 
 // END RUST SOURCE
@@ -35,28 +35,28 @@ fn main() {
 // bb0: {
 //   StorageLive(_1);
 //   StorageLive(_2);
-//   _2 = const Scalar(<ZST>) : ();
+//   _2 = const ();
 //   StorageLive(_3);
-//   _3 = const Scalar(<ZST>) : ();
-//   _1 = const Scalar(<ZST>) : ((), ());
+//   _3 = const ();
+//   _1 = const {transmute(()): ((), ())};
 //   StorageDead(_3);
 //   StorageDead(_2);
 //   StorageDead(_1);
 //   StorageLive(_4);
 //   StorageLive(_6);
-//   _6 = const Scalar(<ZST>) : ();
+//   _6 = const ();
 //   StorageLive(_7);
-//   _7 = const Scalar(<ZST>) : ();
+//   _7 = const ();
 //   StorageDead(_7);
 //   StorageDead(_6);
-//   _4 = const use_zst(const Scalar(<ZST>) : ((), ())) -> bb1;
+//   _4 = const use_zst(const {transmute(()): ((), ())}) -> bb1;
 // }
 // bb1: {
 //   StorageDead(_4);
 //   StorageLive(_8);
 //   StorageLive(_10);
 //   StorageLive(_11);
-//   _11 = const Scalar(0x28) : Temp;
+//   _11 = const {transmute(0x28) : Temp};
 //   _10 = const 40u8;
 //   StorageDead(_10);
 //   _8 = const use_u8(const 42u8) -> bb2;
@@ -75,7 +75,7 @@ fn main() {
 // }
 // bb0: {
 //   StorageLive(_1);
-//   _1 = const use_zst(const Scalar(<ZST>) : ((), ())) -> bb1;
+//   _1 = const use_zst(const {transmute(()): ((), ())}) -> bb1;
 // }
 // bb1: {
 //   StorageDead(_1);
index 5dc15286bab50625cfab315cb5e3b696ae93878c..1c98766b9685c254a4d6f71fe1359c3430e3d574 100644 (file)
@@ -35,12 +35,12 @@ fn main() {
 
 // END RUST SOURCE
 // START rustc.XXX.mir_map.0.mir
-//    let mut _0: &'static Foo;
-//    let _1: &'static Foo;
+//    let mut _0: &Foo;
+//    let _1: &Foo;
 //    let _2: Foo;
-//    let mut _3: &'static [(u32, u32)];
-//    let mut _4: &'static [(u32, u32); 42];
-//    let _5: &'static [(u32, u32); 42];
+//    let mut _3: &[(u32, u32)];
+//    let mut _4: &[(u32, u32); 42];
+//    let _5: &[(u32, u32); 42];
 //    let _6: [(u32, u32); 42];
 //    let mut _7: (u32, u32);
 //    let mut _8: (u32, u32);
@@ -178,7 +178,7 @@ fn main() {
 //        _6 = [move _7, move _8, move _9, move _10, move _11, move _12, move _13, move _14, move _15, move _16, move _17, move _18, move _19, move _20, move _21, move _22, move _23, move _24, move _25, move _26, move _27, move _28, move _29, move _30, move _31, move _32, move _33, move _34, move _35, move _36, move _37, move _38, move _39, move _40, move _41, move _42, move _43, move _44, move _45, move _46, move _47, move _48];
 //        _5 = &_6;
 //        _4 = &(*_5);
-//        _3 = move _4 as &'static [(u32, u32)] (Pointer(Unsize));
+//        _3 = move _4 as &[(u32, u32)] (Pointer(Unsize));
 //        _2 = Foo { tup: const "hi", data: move _3 };
 //        _1 = &_2;
 //        _0 = &(*_1);
index 9db7e27b16103e195eded9d81c95511465321e67..44d2c5db3e668e67fad55215387a9710a4aeb250 100644 (file)
@@ -5,7 +5,7 @@
 #![feature(rustc_attrs)]
 
 fn main() {
-    #![rustc_dummy("hi", 1, 2, 1.012, pi = 3.14, bye, name ("John"))]
+    #![rustc_dummy("hi", 1, 2, 1.012, pi = 3.14, bye, name("John"))]
     #[rustc_dummy = 8]
     fn f() { }
 
index 7bbb7dc911f93a8fe09be4146c28feca05c6ff86..66de0fc6cf7fa85c4487d161182f1314bc6d3792 100644 (file)
@@ -7,7 +7,7 @@ macro_rules! mac { ($ ($ tt : tt) *) => () }
 mac! {
     struct S { field1 : u8, field2 : u16, } impl Clone for S
     {
-        fn clone () -> S
+        fn clone() -> S
         {
             panic ! () ;
 
@@ -16,9 +16,8 @@ fn clone () -> S
 }
 
 mac! {
-    a
-    (aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa
-     aaaaaaaa aaaaaaaa) a
+    a(aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa
+      aaaaaaaa aaaaaaaa) a
     [aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa
      aaaaaaaa aaaaaaaa] a
     {
diff --git a/src/test/pretty/if-attr.rs b/src/test/pretty/if-attr.rs
new file mode 100644 (file)
index 0000000..652604f
--- /dev/null
@@ -0,0 +1,37 @@
+// pp-exact
+
+#[cfg(FALSE)]
+fn simple_attr() {
+
+    #[attr]
+    if true { }
+
+    #[allow_warnings]
+    if true { }
+}
+
+#[cfg(FALSE)]
+fn if_else_chain() {
+
+    #[first_attr]
+    if true { } else if false { } else { }
+}
+
+#[cfg(FALSE)]
+fn if_let() {
+
+    #[attr]
+    if let Some(_) = Some(true) { }
+}
+
+#[cfg(FALSE)]
+fn let_attr_if() {
+    let _ = #[attr] if let _ = 0 { };
+    let _ = #[attr] if true { };
+
+    let _ = #[attr] if let _ = 0 { } else { };
+    let _ = #[attr] if true { } else { };
+}
+
+
+fn main() { }
index 1a9e85c42d8fb95411a06e3fc6a4711cfc2d940f..ca1fef83cffc5fcfa249e8496d39d6c79fd71456 100644 (file)
@@ -1,4 +1,5 @@
 // pp-exact
+// pretty-compare-only
 
 // The next line should not be expanded
 
index 8aa4cdeb5394e4df4b8684e2fe7c74178d1bcf85..ee7586bae820af702cea233269c9cf9e9cdc65de 100644 (file)
@@ -34,29 +34,29 @@ pub fn bar() ({
                            ((::alloc::fmt::format as
                                 for<'r> fn(std::fmt::Arguments<'r>) -> std::string::String {std::fmt::format})(((::core::fmt::Arguments::new_v1
                                                                                                                     as
-                                                                                                                    fn(&[&str], &[std::fmt::ArgumentV1<'_>]) -> std::fmt::Arguments<'_> {std::fmt::Arguments::<'_>::new_v1})((&([("test"
-                                                                                                                                                                                                                                     as
-                                                                                                                                                                                                                                     &'static str)]
-                                                                                                                                                                                                                                   as
-                                                                                                                                                                                                                                   [&str; 1])
-                                                                                                                                                                                                                                 as
-                                                                                                                                                                                                                                 &[&str; 1]),
-                                                                                                                                                                                                                             (&(match (()
-                                                                                                                                                                                                                                          as
-                                                                                                                                                                                                                                          ())
-                                                                                                                                                                                                                                    {
-                                                                                                                                                                                                                                    ()
-                                                                                                                                                                                                                                    =>
-                                                                                                                                                                                                                                    ([]
-                                                                                                                                                                                                                                        as
-                                                                                                                                                                                                                                        [std::fmt::ArgumentV1<'_>; 0]),
-                                                                                                                                                                                                                                }
-                                                                                                                                                                                                                                   as
-                                                                                                                                                                                                                                   [std::fmt::ArgumentV1<'_>; 0])
-                                                                                                                                                                                                                                 as
-                                                                                                                                                                                                                                 &[std::fmt::ArgumentV1<'_>; 0]))
+                                                                                                                    fn(&[&str], &[std::fmt::ArgumentV1]) -> std::fmt::Arguments {std::fmt::Arguments::new_v1})((&([("test"
+                                                                                                                                                                                                                       as
+                                                                                                                                                                                                                       &str)]
+                                                                                                                                                                                                                     as
+                                                                                                                                                                                                                     [&str; 1])
+                                                                                                                                                                                                                   as
+                                                                                                                                                                                                                   &[&str; 1]),
+                                                                                                                                                                                                               (&(match (()
+                                                                                                                                                                                                                            as
+                                                                                                                                                                                                                            ())
+                                                                                                                                                                                                                      {
+                                                                                                                                                                                                                      ()
+                                                                                                                                                                                                                      =>
+                                                                                                                                                                                                                      ([]
+                                                                                                                                                                                                                          as
+                                                                                                                                                                                                                          [std::fmt::ArgumentV1; 0]),
+                                                                                                                                                                                                                  }
+                                                                                                                                                                                                                     as
+                                                                                                                                                                                                                     [std::fmt::ArgumentV1; 0])
+                                                                                                                                                                                                                   as
+                                                                                                                                                                                                                   &[std::fmt::ArgumentV1; 0]))
                                                                                                                    as
-                                                                                                                   std::fmt::Arguments<'_>))
+                                                                                                                   std::fmt::Arguments))
                                as std::string::String);
                        (res as std::string::String)
                    } as std::string::String);
index 643ca761aac32224b87bf8de0356bafe892ca8d9..031a4825959329f11360f13940057b1c8ebcac31 100644 (file)
@@ -12,5 +12,5 @@ struct C {
       #[cfg(debug_assertions)]
       field: 0,
 
-      #[cfg(not (debug_assertions))]
+      #[cfg(not(debug_assertions))]
       field: 1,};
index 07ef2424cc880d2b9549f70f76cb4896b1365426..d975af52f5bb88007d5a61b4628a8f5d236dbb20 100644 (file)
@@ -7,14 +7,12 @@
 extern crate rustc_hir;
 extern crate rustc_target;
 extern crate rustc_driver;
+extern crate rustc_session;
 extern crate rustc_span;
 
 use std::any::Any;
 use std::sync::Arc;
 use std::path::Path;
-use rustc_span::symbol::Symbol;
-use rustc::session::Session;
-use rustc::session::config::OutputFilenames;
 use rustc::ty::TyCtxt;
 use rustc::ty::query::Providers;
 use rustc::middle::cstore::{EncodedMetadata, MetadataLoader, MetadataLoaderDyn};
@@ -23,6 +21,9 @@
 use rustc_codegen_utils::codegen_backend::CodegenBackend;
 use rustc_data_structures::sync::MetadataRef;
 use rustc_data_structures::owning_ref::OwningRef;
+use rustc_session::Session;
+use rustc_session::config::OutputFilenames;
+use rustc_span::symbol::Symbol;
 use rustc_target::spec::Target;
 
 pub struct NoLlvmMetadataLoader;
@@ -89,7 +90,7 @@ fn link(
         outputs: &OutputFilenames,
     ) -> Result<(), ErrorReported> {
         use std::io::Write;
-        use rustc::session::config::CrateType;
+        use rustc_session::config::CrateType;
         use rustc_codegen_utils::link::out_filename;
         let crate_name = codegen_results.downcast::<Symbol>()
             .expect("in link: codegen_results is not a Symbol");
index 12da64fc88f189cfc291d1705db2b75b52f847c8..af84faa7511c61ba9777d853669ac82ab09cce5c 100644 (file)
@@ -1,13 +1,12 @@
 #![feature(rustc_private)]
 
-extern crate rustc;
 extern crate rustc_interface;
 extern crate rustc_driver;
+extern crate rustc_session;
 extern crate rustc_span;
 
-use rustc::session::DiagnosticOutput;
-use rustc::session::config::{Input, Options,
-                             OutputType, OutputTypes};
+use rustc_session::DiagnosticOutput;
+use rustc_session::config::{Input, Options, OutputType, OutputTypes};
 use rustc_interface::interface;
 use rustc_span::source_map::FileName;
 
diff --git a/src/test/run-make-fulldeps/issue-69368/Makefile b/src/test/run-make-fulldeps/issue-69368/Makefile
new file mode 100644 (file)
index 0000000..dbb044d
--- /dev/null
@@ -0,0 +1,18 @@
+-include ../tools.mk
+
+# Test that previously triggered a linker failure with root cause
+# similar to one found in the issue #69368.
+#
+# The crate that provides oom lang item is missing some other lang
+# items. Necessary to prevent the use of start-group / end-group.
+#
+# The weak lang items are defined in a separate compilation units,
+# so that linker could omit them if not used.
+#
+# The crates that need those weak lang items are dependencies of
+# crates that provide them.
+
+all:
+       $(RUSTC) a.rs
+       $(RUSTC) b.rs
+       $(RUSTC) c.rs
diff --git a/src/test/run-make-fulldeps/issue-69368/a.rs b/src/test/run-make-fulldeps/issue-69368/a.rs
new file mode 100644 (file)
index 0000000..726db87
--- /dev/null
@@ -0,0 +1,16 @@
+#![crate_type = "rlib"]
+#![feature(lang_items)]
+#![feature(panic_unwind)]
+#![no_std]
+
+extern crate panic_unwind;
+
+#[panic_handler]
+pub fn panic_handler(_: &core::panic::PanicInfo) -> ! {
+    loop {}
+}
+
+#[no_mangle]
+extern "C" fn __rust_drop_panic() -> ! {
+    loop {}
+}
diff --git a/src/test/run-make-fulldeps/issue-69368/b.rs b/src/test/run-make-fulldeps/issue-69368/b.rs
new file mode 100644 (file)
index 0000000..4d6af02
--- /dev/null
@@ -0,0 +1,8 @@
+#![crate_type = "rlib"]
+#![feature(alloc_error_handler)]
+#![no_std]
+
+#[alloc_error_handler]
+pub fn error_handler(_: core::alloc::Layout) -> ! {
+    panic!();
+}
diff --git a/src/test/run-make-fulldeps/issue-69368/c.rs b/src/test/run-make-fulldeps/issue-69368/c.rs
new file mode 100644 (file)
index 0000000..729c424
--- /dev/null
@@ -0,0 +1,34 @@
+#![crate_type = "bin"]
+#![feature(start)]
+#![no_std]
+
+extern crate alloc;
+extern crate a;
+extern crate b;
+
+use alloc::vec::Vec;
+use core::alloc::*;
+
+struct Allocator;
+
+unsafe impl GlobalAlloc for Allocator {
+    unsafe fn alloc(&self, _: Layout) -> *mut u8 {
+        loop {}
+    }
+
+    unsafe fn dealloc(&self, _: *mut u8, _: Layout) {
+        loop {}
+    }
+}
+
+#[global_allocator]
+static ALLOCATOR: Allocator = Allocator;
+
+#[start]
+fn main(argc: isize, _argv: *const *const u8) -> isize {
+    let mut v = Vec::new();
+    for i in 0..argc {
+        v.push(i);
+    }
+    v.iter().sum()
+}
diff --git a/src/test/rustdoc-js-std/return-specific-literal.js b/src/test/rustdoc-js-std/return-specific-literal.js
new file mode 100644 (file)
index 0000000..c7c3472
--- /dev/null
@@ -0,0 +1,10 @@
+const QUERY = 'struct:"string"';
+
+const EXPECTED = {
+    'in_args': [
+        { 'path': 'std::string::String', 'name': 'ne' },
+    ],
+    'returned': [
+        { 'path': 'std::string::String', 'name': 'add' },
+    ],
+};
diff --git a/src/test/rustdoc-js-std/return-specific.js b/src/test/rustdoc-js-std/return-specific.js
new file mode 100644 (file)
index 0000000..d9a9105
--- /dev/null
@@ -0,0 +1,10 @@
+const QUERY = 'struct:string';
+
+const EXPECTED = {
+    'in_args': [
+        { 'path': 'std::string::String', 'name': 'ne' },
+    ],
+    'returned': [
+        { 'path': 'std::string::String', 'name': 'add' },
+    ],
+};
diff --git a/src/test/rustdoc-ui/coverage/html.rs b/src/test/rustdoc-ui/coverage/html.rs
new file mode 100644 (file)
index 0000000..181cb4c
--- /dev/null
@@ -0,0 +1,4 @@
+// compile-flags:-Z unstable-options --output-format html --show-coverage
+
+/// Foo
+pub struct Xo;
diff --git a/src/test/rustdoc-ui/coverage/html.stderr b/src/test/rustdoc-ui/coverage/html.stderr
new file mode 100644 (file)
index 0000000..adca375
--- /dev/null
@@ -0,0 +1,2 @@
+error: html output format isn't supported for the --show-coverage option
+
diff --git a/src/test/rustdoc-ui/coverage/json.rs b/src/test/rustdoc-ui/coverage/json.rs
new file mode 100644 (file)
index 0000000..b1220b3
--- /dev/null
@@ -0,0 +1,27 @@
+// build-pass
+// compile-flags:-Z unstable-options --output-format json --show-coverage
+
+pub mod foo {
+    /// Hello!
+    pub struct Foo;
+    /// Bar
+    pub enum Bar { A }
+}
+
+/// X
+pub struct X;
+
+/// Bar
+pub mod bar {
+    /// bar
+    pub struct Bar;
+    /// X
+    pub enum X { Y }
+}
+
+/// yolo
+pub enum Yolo { X }
+
+pub struct Xo<T: Clone> {
+    x: T,
+}
diff --git a/src/test/rustdoc-ui/coverage/json.stdout b/src/test/rustdoc-ui/coverage/json.stdout
new file mode 100644 (file)
index 0000000..63b22a7
--- /dev/null
@@ -0,0 +1 @@
+{"$DIR/json.rs":{"total":13,"with_docs":7}}
index d4835c092248e3906987f0540890a85a1f510586..4bd8efeaa3b97514c6573170bbb7540b6c09c4f5 100644 (file)
@@ -1,4 +1,4 @@
 // This previously triggered an ICE.
 
 pub(in crate::r#mod) fn main() {}
-//~^ ERROR expected module, found unresolved item
+//~^ ERROR failed to resolve: maybe a missing crate `r#mod`
index 6c8ba48864df0a7e70377187619d8987c2443e13..8213422491120fd6b410ea2121f0be8a99bf1ff3 100644 (file)
@@ -1,11 +1,11 @@
-error[E0577]: expected module, found unresolved item `crate::r#mod`
-  --> $DIR/issue-61732.rs:3:8
+error[E0433]: failed to resolve: maybe a missing crate `r#mod`?
+  --> $DIR/issue-61732.rs:3:15
    |
 LL | pub(in crate::r#mod) fn main() {}
-   |        ^^^^^^^^^^^^ not a module
+   |               ^^^^^ maybe a missing crate `r#mod`?
 
 error: Compilation failed, aborting rustdoc
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0577`.
+For more information about this error, try `rustc --explain E0433`.
index 6ecdad3ec0000aa04592ec1b0354e132198d5113..e9cd3514a07e21623424b7f1f5648e0379c138de 100644 (file)
@@ -15,3 +15,7 @@ pub extern "C" fn g() {}
 pub enum Foo {
     Bar,
 }
+
+// @has foo/struct.Repr.html '//*[@class="docblock attributes top-attr"]' '#[repr(C, align(8))]'
+#[repr(C, align(8))]
+pub struct Repr;
diff --git a/src/test/rustdoc/crate-version-escape.rs b/src/test/rustdoc/crate-version-escape.rs
new file mode 100644 (file)
index 0000000..2f91eea
--- /dev/null
@@ -0,0 +1,6 @@
+// compile-flags: --crate-version=<script>alert("hi")</script> -Z unstable-options
+
+#![crate_name = "foo"]
+
+// @has 'foo/index.html' '//div[@class="block version"]/p' 'Version <script>alert("hi")</script>'
+// @has 'foo/all.html' '//div[@class="block version"]/p' 'Version <script>alert("hi")</script>'
diff --git a/src/test/rustdoc/doc-spotlight.rs b/src/test/rustdoc/doc-spotlight.rs
deleted file mode 100644 (file)
index ddd46c3..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-#![feature(doc_spotlight)]
-
-pub struct Wrapper<T> {
-    inner: T,
-}
-
-impl<T: SomeTrait> SomeTrait for Wrapper<T> {}
-
-#[doc(spotlight)]
-pub trait SomeTrait {
-    // @has doc_spotlight/trait.SomeTrait.html
-    // @has - '//code[@class="content"]' 'impl<T: SomeTrait> SomeTrait for Wrapper<T>'
-    fn wrap_me(self) -> Wrapper<Self> where Self: Sized {
-        Wrapper {
-            inner: self,
-        }
-    }
-}
-
-pub struct SomeStruct;
-impl SomeTrait for SomeStruct {}
-
-impl SomeStruct {
-    // @has doc_spotlight/struct.SomeStruct.html
-    // @has - '//code[@class="content"]' 'impl SomeTrait for SomeStruct'
-    // @has - '//code[@class="content"]' 'impl<T: SomeTrait> SomeTrait for Wrapper<T>'
-    pub fn new() -> SomeStruct {
-        SomeStruct
-    }
-}
-
-// @has doc_spotlight/fn.bare_fn.html
-// @has - '//code[@class="content"]' 'impl SomeTrait for SomeStruct'
-pub fn bare_fn() -> SomeStruct {
-    SomeStruct
-}
index 6de419ec571df42911d8a4abe15274cbca724945..d2aa4bbbd12511982843df7cd720c9c4f4d7c9c3 100644 (file)
@@ -7,5 +7,5 @@
 extern crate issue_26606_macro;
 
 // @has issue_26606/constant.FOO.html
-// @!has - '//a/@href' '../src/'
+// @has - '//a/@href' '../src/issue_26606/auxiliary/issue-26606-macro.rs.html#3'
 make_item!(FOO);
index 8917693d45eeb4377adaff2752de86872fc9a6cb..837ed1f002fc99b3bb1198397989ad9ffd087a73 100644 (file)
@@ -2,16 +2,14 @@
 
 #![feature(rustc_private)]
 
-// We're testing linkage visibility; the compiler warns us, but we want to
-// do the runtime check that these functions aren't exported.
-#![allow(private_no_mangle_fns)]
-
 extern crate rustc_metadata;
 
 use rustc_metadata::dynamic_lib::DynamicLibrary;
 
 #[no_mangle]
-pub fn foo() { bar(); }
+pub fn foo() {
+    bar();
+}
 
 pub fn foo2<T>() {
     fn bar2() {
@@ -21,11 +19,11 @@ fn bar2() {
 }
 
 #[no_mangle]
-fn bar() { }
+fn bar() {}
 
 #[allow(dead_code)]
 #[no_mangle]
-fn baz() { }
+fn baz() {}
 
 pub fn test() {
     let lib = DynamicLibrary::open(None).unwrap();
index 4936bdb1ece8c715bd963ca9c247b29a2256df84..52620b2464bd667cf41223eec8dc8653244ada23 100644 (file)
@@ -29,10 +29,10 @@ fn name(&self) -> &'static str {
         impl<'a, 'tcx> LateLintPass<'a, 'tcx> for $struct {
             fn check_crate(&mut self, cx: &LateContext, krate: &rustc_hir::Crate) {
                 $(
-                    if !attr::contains_name(&krate.attrs, $attr) {
+                    if !attr::contains_name(&krate.item.attrs, $attr) {
                         cx.lint(CRATE_NOT_OKAY, |lint| {
                              let msg = format!("crate is not marked with #![{}]", $attr);
-                             lint.build(&msg).set_span(krate.span).emit()
+                             lint.build(&msg).set_span(krate.item.span).emit()
                         });
                     }
                 )*
index 32b7ed9dfe2c86c76fa5b3de6ba6d6eb507d2cca..6978d02c09d14f15dcb05741e219f1ba5b52935c 100644 (file)
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
     fn check_crate(&mut self, cx: &LateContext, krate: &rustc_hir::Crate) {
-        if !attr::contains_name(&krate.attrs, Symbol::intern("crate_okay")) {
+        if !attr::contains_name(&krate.item.attrs, Symbol::intern("crate_okay")) {
             cx.lint(CRATE_NOT_OKAY, |lint| {
                 lint.build("crate is not marked with #![crate_okay]")
-                    .set_span(krate.span)
+                    .set_span(krate.item.span)
                     .emit()
             });
         }
index 0b1f6d5a96e56c12fc55dce87caf6eda62acaa70..c275db14b427cfa65c68f8a64ab1cebe1beafffa 100644 (file)
@@ -37,7 +37,7 @@ fn main() {
     unsafe {
         let layout = Layout::from_size_align(4, 2).unwrap();
 
-        let ptr = Global.alloc(layout.clone()).unwrap();
+        let (ptr, _) = Global.alloc(layout.clone()).unwrap();
         helper::work_with(&ptr);
         assert_eq!(HITS.load(Ordering::SeqCst), n + 1);
         Global.dealloc(ptr, layout.clone());
@@ -49,7 +49,7 @@ fn main() {
         drop(s);
         assert_eq!(HITS.load(Ordering::SeqCst), n + 4);
 
-        let ptr = System.alloc(layout.clone()).unwrap();
+        let (ptr, _) = System.alloc(layout.clone()).unwrap();
         assert_eq!(HITS.load(Ordering::SeqCst), n + 4);
         helper::work_with(&ptr);
         System.dealloc(ptr, layout);
index 37b28c195df5bde883c740dae57d8472e5ff55aa..e4746d1a7ec0904e5b7be30d05faf749e9d51b6b 100644 (file)
@@ -20,13 +20,13 @@ fn main() {
         let n = GLOBAL.0.load(Ordering::SeqCst);
         let layout = Layout::from_size_align(4, 2).unwrap();
 
-        let ptr = Global.alloc(layout.clone()).unwrap();
+        let (ptr, _) = Global.alloc(layout.clone()).unwrap();
         helper::work_with(&ptr);
         assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 1);
         Global.dealloc(ptr, layout.clone());
         assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 2);
 
-        let ptr = System.alloc(layout.clone()).unwrap();
+        let (ptr, _) = System.alloc(layout.clone()).unwrap();
         assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 2);
         helper::work_with(&ptr);
         System.dealloc(ptr, layout);
diff --git a/src/test/ui/anon-params-denied-2018.rs b/src/test/ui/anon-params-denied-2018.rs
deleted file mode 100644 (file)
index 5721f5d..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-// Tests that anonymous parameters are a hard error in edition 2018.
-
-// edition:2018
-
-trait T {
-    fn foo(i32); //~ expected one of `:`, `@`, or `|`, found `)`
-
-    fn bar_with_default_impl(String, String) {}
-    //~^ ERROR expected one of `:`
-    //~| ERROR expected one of `:`
-
-    // do not complain about missing `b`
-    fn baz(a:usize, b, c: usize) -> usize { //~ ERROR expected one of `:`
-        a + b + c
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/anon-params-denied-2018.stderr b/src/test/ui/anon-params-denied-2018.stderr
deleted file mode 100644 (file)
index e7a806a..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-error: expected one of `:`, `@`, or `|`, found `)`
-  --> $DIR/anon-params-denied-2018.rs:6:15
-   |
-LL |     fn foo(i32);
-   |               ^ expected one of `:`, `@`, or `|`
-   |
-   = 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 foo(self: i32);
-   |            ^^^^^^^^^
-help: if this was a parameter name, give it a type
-   |
-LL |     fn foo(i32: TypeName);
-   |            ^^^^^^^^^^^^^
-help: if this is a type, explicitly ignore the parameter name
-   |
-LL |     fn foo(_: i32);
-   |            ^^^^^^
-
-error: expected one of `:`, `@`, or `|`, found `,`
-  --> $DIR/anon-params-denied-2018.rs:8:36
-   |
-LL |     fn bar_with_default_impl(String, String) {}
-   |                                    ^ expected one of `:`, `@`, or `|`
-   |
-   = 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_with_default_impl(self: String, String) {}
-   |                              ^^^^^^^^^^^^
-help: if this was a parameter name, give it a type
-   |
-LL |     fn bar_with_default_impl(String: TypeName, String) {}
-   |                              ^^^^^^^^^^^^^^^^
-help: if this is a type, explicitly ignore the parameter name
-   |
-LL |     fn bar_with_default_impl(_: String, String) {}
-   |                              ^^^^^^^^^
-
-error: expected one of `:`, `@`, or `|`, found `)`
-  --> $DIR/anon-params-denied-2018.rs:8:44
-   |
-LL |     fn bar_with_default_impl(String, String) {}
-   |                                            ^ expected one of `:`, `@`, or `|`
-   |
-   = note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
-help: if this was a parameter name, give it a type
-   |
-LL |     fn bar_with_default_impl(String, String: TypeName) {}
-   |                                      ^^^^^^^^^^^^^^^^
-help: if this is a type, explicitly ignore the parameter name
-   |
-LL |     fn bar_with_default_impl(String, _: String) {}
-   |                                      ^^^^^^^^^
-
-error: expected one of `:`, `@`, or `|`, found `,`
-  --> $DIR/anon-params-denied-2018.rs:13:22
-   |
-LL |     fn baz(a:usize, b, c: usize) -> usize {
-   |                      ^ expected one of `:`, `@`, or `|`
-   |
-   = note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
-help: if this was a parameter name, give it a type
-   |
-LL |     fn baz(a:usize, b: TypeName, c: usize) -> usize {
-   |                     ^^^^^^^^^^^
-help: if this is a type, explicitly ignore the parameter name
-   |
-LL |     fn baz(a:usize, _: b, c: usize) -> usize {
-   |                     ^^^^
-
-error: aborting due to 4 previous errors
-
diff --git a/src/test/ui/anon-params-deprecated.fixed b/src/test/ui/anon-params-deprecated.fixed
deleted file mode 100644 (file)
index fe42113..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-#![warn(anonymous_parameters)]
-// Test for the anonymous_parameters deprecation lint (RFC 1685)
-
-// build-pass (FIXME(62277): could be check-pass?)
-// edition:2015
-// run-rustfix
-
-trait T {
-    fn foo(_: i32); //~ WARNING anonymous parameters are deprecated
-                 //~| WARNING hard error
-
-    fn bar_with_default_impl(_: String, _: String) {}
-    //~^ WARNING anonymous parameters are deprecated
-    //~| WARNING hard error
-    //~| WARNING anonymous parameters are deprecated
-    //~| WARNING hard error
-}
-
-fn main() {}
diff --git a/src/test/ui/anon-params-deprecated.rs b/src/test/ui/anon-params-deprecated.rs
deleted file mode 100644 (file)
index dc03577..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-#![warn(anonymous_parameters)]
-// Test for the anonymous_parameters deprecation lint (RFC 1685)
-
-// build-pass (FIXME(62277): could be check-pass?)
-// edition:2015
-// run-rustfix
-
-trait T {
-    fn foo(i32); //~ WARNING anonymous parameters are deprecated
-                 //~| WARNING hard error
-
-    fn bar_with_default_impl(String, String) {}
-    //~^ WARNING anonymous parameters are deprecated
-    //~| WARNING hard error
-    //~| WARNING anonymous parameters are deprecated
-    //~| WARNING hard error
-}
-
-fn main() {}
diff --git a/src/test/ui/anon-params-deprecated.stderr b/src/test/ui/anon-params-deprecated.stderr
deleted file mode 100644 (file)
index 4520559..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-warning: anonymous parameters are deprecated and will be removed in the next edition.
-  --> $DIR/anon-params-deprecated.rs:9:12
-   |
-LL |     fn foo(i32);
-   |            ^^^ help: try naming the parameter or explicitly ignoring it: `_: i32`
-   |
-note: the lint level is defined here
-  --> $DIR/anon-params-deprecated.rs:1:9
-   |
-LL | #![warn(anonymous_parameters)]
-   |         ^^^^^^^^^^^^^^^^^^^^
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
-   = note: for more information, see issue #41686 <https://github.com/rust-lang/rust/issues/41686>
-
-warning: anonymous parameters are deprecated and will be removed in the next edition.
-  --> $DIR/anon-params-deprecated.rs:12:30
-   |
-LL |     fn bar_with_default_impl(String, String) {}
-   |                              ^^^^^^ help: try naming the parameter or explicitly ignoring it: `_: String`
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
-   = note: for more information, see issue #41686 <https://github.com/rust-lang/rust/issues/41686>
-
-warning: anonymous parameters are deprecated and will be removed in the next edition.
-  --> $DIR/anon-params-deprecated.rs:12:38
-   |
-LL |     fn bar_with_default_impl(String, String) {}
-   |                                      ^^^^^^ help: try naming the parameter or explicitly ignoring it: `_: String`
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
-   = note: for more information, see issue #41686 <https://github.com/rust-lang/rust/issues/41686>
-
diff --git a/src/test/ui/anon-params/anon-params-denied-2018.rs b/src/test/ui/anon-params/anon-params-denied-2018.rs
new file mode 100644 (file)
index 0000000..5721f5d
--- /dev/null
@@ -0,0 +1,18 @@
+// Tests that anonymous parameters are a hard error in edition 2018.
+
+// edition:2018
+
+trait T {
+    fn foo(i32); //~ expected one of `:`, `@`, or `|`, found `)`
+
+    fn bar_with_default_impl(String, String) {}
+    //~^ ERROR expected one of `:`
+    //~| ERROR expected one of `:`
+
+    // do not complain about missing `b`
+    fn baz(a:usize, b, c: usize) -> usize { //~ ERROR expected one of `:`
+        a + b + c
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/anon-params/anon-params-denied-2018.stderr b/src/test/ui/anon-params/anon-params-denied-2018.stderr
new file mode 100644 (file)
index 0000000..e7a806a
--- /dev/null
@@ -0,0 +1,74 @@
+error: expected one of `:`, `@`, or `|`, found `)`
+  --> $DIR/anon-params-denied-2018.rs:6:15
+   |
+LL |     fn foo(i32);
+   |               ^ expected one of `:`, `@`, or `|`
+   |
+   = 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 foo(self: i32);
+   |            ^^^^^^^^^
+help: if this was a parameter name, give it a type
+   |
+LL |     fn foo(i32: TypeName);
+   |            ^^^^^^^^^^^^^
+help: if this is a type, explicitly ignore the parameter name
+   |
+LL |     fn foo(_: i32);
+   |            ^^^^^^
+
+error: expected one of `:`, `@`, or `|`, found `,`
+  --> $DIR/anon-params-denied-2018.rs:8:36
+   |
+LL |     fn bar_with_default_impl(String, String) {}
+   |                                    ^ expected one of `:`, `@`, or `|`
+   |
+   = 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_with_default_impl(self: String, String) {}
+   |                              ^^^^^^^^^^^^
+help: if this was a parameter name, give it a type
+   |
+LL |     fn bar_with_default_impl(String: TypeName, String) {}
+   |                              ^^^^^^^^^^^^^^^^
+help: if this is a type, explicitly ignore the parameter name
+   |
+LL |     fn bar_with_default_impl(_: String, String) {}
+   |                              ^^^^^^^^^
+
+error: expected one of `:`, `@`, or `|`, found `)`
+  --> $DIR/anon-params-denied-2018.rs:8:44
+   |
+LL |     fn bar_with_default_impl(String, String) {}
+   |                                            ^ expected one of `:`, `@`, or `|`
+   |
+   = note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
+help: if this was a parameter name, give it a type
+   |
+LL |     fn bar_with_default_impl(String, String: TypeName) {}
+   |                                      ^^^^^^^^^^^^^^^^
+help: if this is a type, explicitly ignore the parameter name
+   |
+LL |     fn bar_with_default_impl(String, _: String) {}
+   |                                      ^^^^^^^^^
+
+error: expected one of `:`, `@`, or `|`, found `,`
+  --> $DIR/anon-params-denied-2018.rs:13:22
+   |
+LL |     fn baz(a:usize, b, c: usize) -> usize {
+   |                      ^ expected one of `:`, `@`, or `|`
+   |
+   = note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
+help: if this was a parameter name, give it a type
+   |
+LL |     fn baz(a:usize, b: TypeName, c: usize) -> usize {
+   |                     ^^^^^^^^^^^
+help: if this is a type, explicitly ignore the parameter name
+   |
+LL |     fn baz(a:usize, _: b, c: usize) -> usize {
+   |                     ^^^^
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/anon-params/anon-params-deprecated.fixed b/src/test/ui/anon-params/anon-params-deprecated.fixed
new file mode 100644 (file)
index 0000000..fe42113
--- /dev/null
@@ -0,0 +1,19 @@
+#![warn(anonymous_parameters)]
+// Test for the anonymous_parameters deprecation lint (RFC 1685)
+
+// build-pass (FIXME(62277): could be check-pass?)
+// edition:2015
+// run-rustfix
+
+trait T {
+    fn foo(_: i32); //~ WARNING anonymous parameters are deprecated
+                 //~| WARNING hard error
+
+    fn bar_with_default_impl(_: String, _: String) {}
+    //~^ WARNING anonymous parameters are deprecated
+    //~| WARNING hard error
+    //~| WARNING anonymous parameters are deprecated
+    //~| WARNING hard error
+}
+
+fn main() {}
diff --git a/src/test/ui/anon-params/anon-params-deprecated.rs b/src/test/ui/anon-params/anon-params-deprecated.rs
new file mode 100644 (file)
index 0000000..dc03577
--- /dev/null
@@ -0,0 +1,19 @@
+#![warn(anonymous_parameters)]
+// Test for the anonymous_parameters deprecation lint (RFC 1685)
+
+// build-pass (FIXME(62277): could be check-pass?)
+// edition:2015
+// run-rustfix
+
+trait T {
+    fn foo(i32); //~ WARNING anonymous parameters are deprecated
+                 //~| WARNING hard error
+
+    fn bar_with_default_impl(String, String) {}
+    //~^ WARNING anonymous parameters are deprecated
+    //~| WARNING hard error
+    //~| WARNING anonymous parameters are deprecated
+    //~| WARNING hard error
+}
+
+fn main() {}
diff --git a/src/test/ui/anon-params/anon-params-deprecated.stderr b/src/test/ui/anon-params/anon-params-deprecated.stderr
new file mode 100644 (file)
index 0000000..4520559
--- /dev/null
@@ -0,0 +1,32 @@
+warning: anonymous parameters are deprecated and will be removed in the next edition.
+  --> $DIR/anon-params-deprecated.rs:9:12
+   |
+LL |     fn foo(i32);
+   |            ^^^ help: try naming the parameter or explicitly ignoring it: `_: i32`
+   |
+note: the lint level is defined here
+  --> $DIR/anon-params-deprecated.rs:1:9
+   |
+LL | #![warn(anonymous_parameters)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #41686 <https://github.com/rust-lang/rust/issues/41686>
+
+warning: anonymous parameters are deprecated and will be removed in the next edition.
+  --> $DIR/anon-params-deprecated.rs:12:30
+   |
+LL |     fn bar_with_default_impl(String, String) {}
+   |                              ^^^^^^ help: try naming the parameter or explicitly ignoring it: `_: String`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #41686 <https://github.com/rust-lang/rust/issues/41686>
+
+warning: anonymous parameters are deprecated and will be removed in the next edition.
+  --> $DIR/anon-params-deprecated.rs:12:38
+   |
+LL |     fn bar_with_default_impl(String, String) {}
+   |                                      ^^^^^^ help: try naming the parameter or explicitly ignoring it: `_: String`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #41686 <https://github.com/rust-lang/rust/issues/41686>
+
diff --git a/src/test/ui/anon-params/anon-params-edition-hygiene.rs b/src/test/ui/anon-params/anon-params-edition-hygiene.rs
new file mode 100644 (file)
index 0000000..14e11c5
--- /dev/null
@@ -0,0 +1,10 @@
+// check-pass
+// edition:2018
+// aux-build:anon-params-edition-hygiene.rs
+
+#[macro_use]
+extern crate anon_params_edition_hygiene;
+
+generate_trait_2015!(u8);
+
+fn main() {}
diff --git a/src/test/ui/anon-params/auxiliary/anon-params-edition-hygiene.rs b/src/test/ui/anon-params/auxiliary/anon-params-edition-hygiene.rs
new file mode 100644 (file)
index 0000000..aa4221b
--- /dev/null
@@ -0,0 +1,12 @@
+// edition:2015
+
+#[macro_export]
+macro_rules! generate_trait_2015 {
+    ($Type: ident) => {
+        trait Trait {
+            fn method($Type) {}
+        }
+    };
+}
+
+fn main() {}
diff --git a/src/test/ui/asm/issue-62046.rs b/src/test/ui/asm/issue-62046.rs
new file mode 100644 (file)
index 0000000..105dadd
--- /dev/null
@@ -0,0 +1,11 @@
+// build-fail
+// ignore-emscripten no asm! support
+
+#![feature(asm)]
+
+fn main() {
+    unsafe {
+        asm!("nop" : "+r"("r15"));
+        //~^ malformed inline assembly
+    }
+}
diff --git a/src/test/ui/asm/issue-62046.stderr b/src/test/ui/asm/issue-62046.stderr
new file mode 100644 (file)
index 0000000..a38a300
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0668]: malformed inline assembly
+  --> $DIR/issue-62046.rs:8:9
+   |
+LL |         asm!("nop" : "+r"("r15"));
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0668`.
diff --git a/src/test/ui/asm/issue-69092.rs b/src/test/ui/asm/issue-69092.rs
new file mode 100644 (file)
index 0000000..caa5c2e
--- /dev/null
@@ -0,0 +1,10 @@
+// build-fail
+// ignore-emscripten no asm! support
+// Regression test for #69092
+
+#![feature(asm)]
+
+fn main() {
+    unsafe { asm!(".ascii \"Xen\0\""); }
+    //~^ ERROR: <inline asm>:1:9: error: expected string in '.ascii' directive
+}
diff --git a/src/test/ui/asm/issue-69092.stderr b/src/test/ui/asm/issue-69092.stderr
new file mode 100644 (file)
index 0000000..5661097
--- /dev/null
@@ -0,0 +1,11 @@
+error: <inline asm>:1:9: error: expected string in '.ascii' directive
+        .ascii "Xen
+               ^
+
+  --> $DIR/issue-69092.rs:8:14
+   |
+LL |     unsafe { asm!(".ascii \"Xen\0\""); }
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/assign-to-method.rs b/src/test/ui/assign-to-method.rs
deleted file mode 100644 (file)
index 95f066c..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-struct Cat {
-  meows : usize,
-
-  how_hungry : isize,
-}
-
-impl Cat {
-    pub fn speak(&self) { self.meows += 1; }
-}
-
-fn cat(in_x : usize, in_y : isize) -> Cat {
-    Cat {
-        meows: in_x,
-        how_hungry: in_y
-    }
-}
-
-fn main() {
-  let nyan : Cat = cat(52, 99);
-  nyan.speak = || println!("meow"); //~ ERROR attempted to take value of method
-  nyan.speak += || println!("meow"); //~ ERROR attempted to take value of method
-}
diff --git a/src/test/ui/assign-to-method.stderr b/src/test/ui/assign-to-method.stderr
deleted file mode 100644 (file)
index feceadb..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-error[E0615]: attempted to take value of method `speak` on type `Cat`
-  --> $DIR/assign-to-method.rs:20:8
-   |
-LL |   nyan.speak = || println!("meow");
-   |        ^^^^^
-   |
-   = help: methods are immutable and cannot be assigned to
-
-error[E0615]: attempted to take value of method `speak` on type `Cat`
-  --> $DIR/assign-to-method.rs:21:8
-   |
-LL |   nyan.speak += || println!("meow");
-   |        ^^^^^
-   |
-   = help: methods are immutable and cannot be assigned to
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0615`.
index 6f89530eac93306b3fe065ffc49999b061c296ba..cadf55454a76ec8bee069592c2ee674d1c6f5f91 100644 (file)
@@ -8,7 +8,7 @@ LL |     Enum::mispellable();
    |           ^^^^^^^^^^^
    |           |
    |           variant or associated item not found in `Enum`
-   |           help: there is a method with a similar name: `misspellable`
+   |           help: there is an associated function with a similar name: `misspellable`
 
 error[E0599]: no variant or associated item named `mispellable_trait` found for enum `Enum` in the current scope
   --> $DIR/associated-item-enum.rs:18:11
index df1151d876c04b17b3e3b7a96195c762f99b7d1d..82b2d32d09d575815b5a4f20d1c1fe93525e3662 100644 (file)
@@ -728,3 +728,4 @@ LL | type TADyn3 = dyn Iterator<Item: 'static, Item: 'static>;
 
 error: aborting due to 96 previous errors
 
+For more information about this error, try `rustc --explain E0719`.
index 4a413381aa30098e0caf68e2720abafacb0da53f..636fafc2bc44a248731973987639c545c49daf4f 100644 (file)
@@ -110,9 +110,9 @@ async fn mixed_sizes() {
 }
 
 fn main() {
-    assert_eq!(1028, std::mem::size_of_val(&single()));
-    assert_eq!(1032, 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!(7188, std::mem::size_of_val(&mixed_sizes()));
+    assert_eq!(1025, std::mem::size_of_val(&single()));
+    assert_eq!(1026, std::mem::size_of_val(&single_with_noop()));
+    assert_eq!(3078, std::mem::size_of_val(&joined()));
+    assert_eq!(3079, std::mem::size_of_val(&joined_with_noop()));
+    assert_eq!(7181, std::mem::size_of_val(&mixed_sizes()));
 }
index 0558084f4f8a31a4a77c8f97d19db1a1f0acd9a5..d5d7b3fc3f0bd10c7438002ba5f0a391f962c929 100644 (file)
@@ -95,9 +95,9 @@ async fn join_retval() -> Joiner {
 }
 
 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()));
+    assert_eq!(2, std::mem::size_of_val(&single()));
+    assert_eq!(3, std::mem::size_of_val(&single_with_noop()));
+    assert_eq!(3078, std::mem::size_of_val(&joined()));
+    assert_eq!(3078, std::mem::size_of_val(&joined_with_noop()));
+    assert_eq!(3074, std::mem::size_of_val(&join_retval()));
 }
index b313992db4ecbc38883d389a3d365735ac0c3dce..0c1f3636446c9ee5b493df779d4d9a23021b6019 100644 (file)
@@ -86,13 +86,13 @@ async fn await3_level5() -> u8 {
 
 fn main() {
     assert_eq!(2, std::mem::size_of_val(&base()));
-    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!(3, std::mem::size_of_val(&await1_level1()));
+    assert_eq!(4, std::mem::size_of_val(&await2_level1()));
+    assert_eq!(5, std::mem::size_of_val(&await3_level1()));
+    assert_eq!(8, std::mem::size_of_val(&await3_level2()));
+    assert_eq!(11, std::mem::size_of_val(&await3_level3()));
+    assert_eq!(14, std::mem::size_of_val(&await3_level4()));
+    assert_eq!(17, std::mem::size_of_val(&await3_level5()));
 
     assert_eq!(1,   wait(base()));
     assert_eq!(1,   wait(await1_level1()));
index 2bf1e77f09b3fb1bf0edcdc46a76906944281533..d80467c7fa88756abf962371b63e457a2c206e99 100644 (file)
@@ -2,10 +2,7 @@ error[E0596]: cannot borrow data in a `&` reference as mutable
   --> $DIR/dont-print-desugared-async.rs:5:20
    |
 LL | async fn async_fn(&ref mut s: &[i32]) {}
-   |                   -^^^^^^^^^
-   |                   ||
-   |                   |cannot borrow as mutable through `&` reference
-   |                   help: consider changing this to be a mutable reference: `&mut ref mut s`
+   |                    ^^^^^^^^^ cannot borrow as mutable through `&` reference
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/async-await/expansion-in-attrs.rs b/src/test/ui/async-await/expansion-in-attrs.rs
new file mode 100644 (file)
index 0000000..af77c34
--- /dev/null
@@ -0,0 +1,13 @@
+// check-pass
+// edition:2018
+
+macro_rules! with_doc {
+    ($doc: expr) => {
+        #[doc = $doc]
+        async fn f() {}
+    };
+}
+
+with_doc!(concat!(""));
+
+fn main() {}
diff --git a/src/test/ui/async-await/issue-54239-private-type-triggers-lint.rs b/src/test/ui/async-await/issue-54239-private-type-triggers-lint.rs
new file mode 100644 (file)
index 0000000..16cf7ad
--- /dev/null
@@ -0,0 +1,17 @@
+// Regression test for #54239, shouldn't trigger lint.
+// check-pass
+// edition:2018
+
+#![deny(missing_debug_implementations)]
+
+struct DontLookAtMe(i32);
+
+async fn secret() -> DontLookAtMe {
+    DontLookAtMe(41)
+}
+
+pub async fn looking() -> i32 { // Shouldn't trigger lint here.
+    secret().await.0
+}
+
+fn main() {}
index cd6670923c2c6ef4f05757cb6b7f295d1ec00783..0624c049048c70896535f2db2a5e58214aeb8719 100644 (file)
@@ -33,10 +33,10 @@ error[E0277]: the trait bound `[closure@$DIR/issue-62009-1.rs:16:5: 16:15]: std:
 LL |     (|_| 2333).await;
    |     ^^^^^^^^^^^^^^^^ the trait `std::future::Future` is not implemented for `[closure@$DIR/issue-62009-1.rs:16:5: 16:15]`
    | 
-  ::: $SRC_DIR/libstd/future.rs:LL:COL
+  ::: $SRC_DIR/libcore/future/mod.rs:LL:COL
    |
 LL |     F: Future,
-   |        ------ required by this bound in `std::future::poll_with_tls_context`
+   |        ------ required by this bound in `std::future::poll_with_context`
 
 error: aborting due to 4 previous errors
 
index f72c645bf8dbf1e0bb99886fa50ba26cffcf8776..2a399540e5296cd779d75219a0ef33b57d1df95b 100644 (file)
@@ -16,13 +16,13 @@ help: to force the closure to take ownership of `self` (and any other referenced
 LL |         foo(move || self.bar()).await;
    |             ^^^^^^^
 
-error[E0521]: borrowed data escapes outside of method
+error[E0521]: borrowed data escapes outside of associated function
   --> $DIR/issue-62097.rs:13:9
    |
 LL |     pub async fn run_dummy_fn(&self) {
-   |                               ----- `self` is a reference that is only valid in the method body
+   |                               ----- `self` is a reference that is only valid in the associated function body
 LL |         foo(|| self.bar()).await;
-   |         ^^^^^^^^^^^^^^^^^^ `self` escapes the method body here
+   |         ^^^^^^^^^^^^^^^^^^ `self` escapes the associated function body here
 
 error: aborting due to 2 previous errors
 
index 696f79ec40f36a5f961903b5f23f7c4182c32ebf..464459d2d61ad095848c32690ad71427c00c3781 100644 (file)
@@ -9,7 +9,7 @@ LL |       ) -> &dyn Foo
 LL | /     {
 LL | |         foo
 LL | |     }
-   | |_____^ method was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1`
+   | |_____^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1`
 
 error: aborting due to previous error
 
index 07559cd240bb6f2fd742ad98b7ff04d9c5eb789a..4e59bb507676f27e5e83a58b2f58075a4e2b37fa 100644 (file)
@@ -1,8 +1,8 @@
 error: functions cannot be both `const` and `async`
-  --> $DIR/no-const-async.rs:4:1
+  --> $DIR/no-const-async.rs:4:5
    |
 LL | pub const async fn x() {}
-   | ^^^^-----^-----^^^^^^^^^^
+   | ----^^^^^-^^^^^----------
    |     |     |
    |     |     `async` because of this
    |     `const` because of this
diff --git a/src/test/ui/async-await/no-std.rs b/src/test/ui/async-await/no-std.rs
new file mode 100644 (file)
index 0000000..63e93cd
--- /dev/null
@@ -0,0 +1,13 @@
+// edition:2018
+// check-pass
+
+#![no_std]
+#![crate_type = "rlib"]
+
+use core::future::Future;
+
+async fn a(f: impl Future) {
+    f.await;
+}
+
+fn main() {}
index 50ca5cad4bc6893d39dcdd3201e9161e73fe80f1..dc7deb8a7c7ac385783878cff2ddf6c0c48762c9 100644 (file)
@@ -2,7 +2,7 @@ error[E0599]: no method named `test_mut` found for struct `std::vec::Vec<{intege
   --> $DIR/auto-ref-slice-plus-ref.rs:7:7
    |
 LL |     a.test_mut();
-   |       ^^^^^^^^ help: there is a method with a similar name: `get_mut`
+   |       ^^^^^^^^ help: there is an associated function with a similar name: `get_mut`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
 note: `MyIter` defines an item `test_mut`, perhaps you need to implement it
index 51422fab81fdaae931ba321bfa5313b415d362ed..4040e66c6af776f65aa5f99e5a0f5fafd9504761 100644 (file)
@@ -1,20 +1,26 @@
 error[E0567]: auto traits cannot have generic parameters
-  --> $DIR/auto-trait-validation.rs:3:1
+  --> $DIR/auto-trait-validation.rs:3:19
    |
 LL | auto trait Generic<T> {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^
+   |            -------^^^ help: remove the parameters
+   |            |
+   |            auto trait cannot have generic parameters
 
 error[E0568]: auto traits cannot have super traits
-  --> $DIR/auto-trait-validation.rs:5:1
+  --> $DIR/auto-trait-validation.rs:5:20
    |
 LL | auto trait Bound : Copy {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |            -----   ^^^^ help: remove the super traits
+   |            |
+   |            auto trait cannot have super traits
 
 error[E0380]: auto traits cannot have methods or associated items
-  --> $DIR/auto-trait-validation.rs:7:1
+  --> $DIR/auto-trait-validation.rs:7:25
    |
 LL | auto trait MyTrait { fn foo() {} }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |            -------      ^^^
+   |            |
+   |            auto trait cannot have items
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/binding/ambiguity-item.rs b/src/test/ui/binding/ambiguity-item.rs
new file mode 100644 (file)
index 0000000..10613cc
--- /dev/null
@@ -0,0 +1,18 @@
+// Identifier pattern referring to an ambiguity item is an error (issue #46079).
+
+mod m {
+    pub fn f() {}
+}
+use m::*;
+
+mod n {
+    pub fn f() {}
+}
+use n::*; // OK, no conflict with `use m::*;`
+
+fn main() {
+    let v = f; //~ ERROR `f` is ambiguous
+    match v {
+        f => {} //~ ERROR `f` is ambiguous
+    }
+}
diff --git a/src/test/ui/binding/ambiguity-item.stderr b/src/test/ui/binding/ambiguity-item.stderr
new file mode 100644 (file)
index 0000000..615193c
--- /dev/null
@@ -0,0 +1,41 @@
+error[E0659]: `f` is ambiguous (glob import vs glob import in the same module)
+  --> $DIR/ambiguity-item.rs:14:13
+   |
+LL |     let v = f;
+   |             ^ ambiguous name
+   |
+note: `f` could refer to the function imported here
+  --> $DIR/ambiguity-item.rs:6:5
+   |
+LL | use m::*;
+   |     ^^^^
+   = help: consider adding an explicit import of `f` to disambiguate
+note: `f` could also refer to the function imported here
+  --> $DIR/ambiguity-item.rs:11:5
+   |
+LL | use n::*; // OK, no conflict with `use m::*;`
+   |     ^^^^
+   = help: consider adding an explicit import of `f` to disambiguate
+
+error[E0659]: `f` is ambiguous (glob import vs glob import in the same module)
+  --> $DIR/ambiguity-item.rs:16:9
+   |
+LL |         f => {}
+   |         ^ ambiguous name
+   |
+note: `f` could refer to the function imported here
+  --> $DIR/ambiguity-item.rs:6:5
+   |
+LL | use m::*;
+   |     ^^^^
+   = help: consider adding an explicit import of `f` to disambiguate
+note: `f` could also refer to the function imported here
+  --> $DIR/ambiguity-item.rs:11:5
+   |
+LL | use n::*; // OK, no conflict with `use m::*;`
+   |     ^^^^
+   = help: consider adding an explicit import of `f` to disambiguate
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0659`.
diff --git a/src/test/ui/binding/const-param.rs b/src/test/ui/binding/const-param.rs
new file mode 100644 (file)
index 0000000..3c7f4d0
--- /dev/null
@@ -0,0 +1,12 @@
+// Identifier pattern referring to a const generic parameter is an error (issue #68853).
+
+#![feature(const_generics)] //~ WARN the feature `const_generics` is incomplete
+
+fn check<const N: usize>() {
+    match 1 {
+        N => {} //~ ERROR const parameters cannot be referenced in patterns
+        _ => {}
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/binding/const-param.stderr b/src/test/ui/binding/const-param.stderr
new file mode 100644 (file)
index 0000000..25b1c75
--- /dev/null
@@ -0,0 +1,17 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/const-param.rs:3:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0158]: const parameters cannot be referenced in patterns
+  --> $DIR/const-param.rs:7:9
+   |
+LL |         N => {}
+   |         ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0158`.
index 264e7fc8e73a212cb17c9943318b97b3afdb074d..d8d15615d7c338ac8f99466d51ce11460dc26d30 100644 (file)
@@ -1,8 +1,15 @@
 error[E0308]: mismatched types
   --> $DIR/blind-item-block-middle.rs:6:9
    |
+LL | mod foo { pub struct bar; }
+   |           --------------- unit struct defined here
+...
 LL |     let bar = 5;
-   |         ^^^ expected integer, found struct `foo::bar`
+   |         ^^^
+   |         |
+   |         expected integer, found struct `foo::bar`
+   |         `bar` is interpreted as a unit struct, not a new binding
+   |         help: introduce a new binding instead: `other_bar`
 
 error: aborting due to previous error
 
index 1307b5d6ddd82a0fbf424c688281201a48f80af3..decee1f2f16291befeef349d7a89bce2bc441a7c 100644 (file)
@@ -4,5 +4,5 @@ warning: unnecessary trailing semicolons
 LL |   if (true) { 12; };;; -num;
    |                     ^^ help: remove these semicolons
    |
-   = note: `#[warn(redundant_semicolon)]` on by default
+   = note: `#[warn(redundant_semicolons)]` on by default
 
index be551f6e889fc63964d44af2f699d84027a373ab..5255e48bee13b86adaada5ab2a17186e5e75459d 100644 (file)
@@ -2,7 +2,7 @@ error[E0599]: no method named `b` found for reference `&Self` in the current sco
   --> $DIR/issue-3563.rs:3:17
    |
 LL |         || self.b()
-   |                 ^ help: there is a method with a similar name: `a`
+   |                 ^ help: there is an associated function with a similar name: `a`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs b/src/test/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs
new file mode 100644 (file)
index 0000000..b67d494
--- /dev/null
@@ -0,0 +1,224 @@
+// Tests using a combination of pattern features has the expected borrow checking behavior
+#![feature(bindings_after_at)]
+#![feature(or_patterns)]
+#![feature(box_patterns)]
+
+#![feature(move_ref_pattern)]
+
+enum Test {
+    Foo,
+    Bar,
+    _Baz,
+}
+
+// bindings_after_at + slice_patterns
+
+fn bindings_after_at_slice_patterns_move_binding(x: [String; 4]) {
+    match x {
+        a @ [.., _] => (),
+        _ => (),
+    };
+
+    &x;
+    //~^ ERROR borrow of moved value
+}
+
+fn bindings_after_at_slice_patterns_borrows_binding_mut(mut x: [String; 4]) {
+    let r = match x {
+        ref mut foo @ [.., _] => Some(foo),
+        _ => None,
+    };
+
+    &x;
+    //~^ ERROR cannot borrow
+
+    drop(r);
+}
+
+fn bindings_after_at_slice_patterns_borrows_slice_mut1(mut x: [String; 4]) {
+    let r = match x {
+        ref foo @ [.., ref mut bar] => (),
+        //~^ ERROR cannot borrow
+        _ => (),
+    };
+
+    drop(r);
+}
+
+fn bindings_after_at_slice_patterns_borrows_slice_mut2(mut x: [String; 4]) {
+    let r = match x {
+        [ref foo @ .., ref bar] => Some(foo),
+        _ => None,
+    };
+
+    &mut x;
+    //~^ ERROR cannot borrow
+
+    drop(r);
+}
+
+fn bindings_after_at_slice_patterns_borrows_both(mut x: [String; 4]) {
+    let r = match x {
+        ref foo @ [.., ref bar] => Some(foo),
+        _ => None,
+    };
+
+    &mut x;
+    //~^ ERROR cannot borrow
+
+    drop(r);
+}
+
+// bindings_after_at + or_patterns
+
+fn bindings_after_at_or_patterns_move(x: Option<Test>) {
+    match x {
+        foo @ Some(Test::Foo | Test::Bar) => (),
+        _ => (),
+    }
+
+    &x;
+    //~^ ERROR borrow of moved value
+}
+
+fn bindings_after_at_or_patterns_borrows(mut x: Option<Test>) {
+    let r = match x {
+        ref foo @ Some(Test::Foo | Test::Bar) => Some(foo),
+        _ => None,
+    };
+
+    &mut x;
+    //~^ ERROR cannot borrow
+
+    drop(r);
+}
+
+fn bindings_after_at_or_patterns_borrows_mut(mut x: Option<Test>) {
+    let r = match x {
+        ref mut foo @ Some(Test::Foo | Test::Bar) => Some(foo),
+        _ => None,
+    };
+
+    &x;
+    //~^ ERROR cannot borrow
+
+    drop(r);
+}
+
+// bindings_after_at + box_patterns
+
+fn bindings_after_at_box_patterns_borrows_both(mut x: Option<Box<String>>) {
+    let r = match x {
+        ref foo @ Some(box ref s) => Some(foo),
+        _ => None,
+    };
+
+    &mut x;
+    //~^ ERROR cannot borrow
+
+    drop(r);
+}
+
+fn bindings_after_at_box_patterns_borrows_mut(mut x: Option<Box<String>>) {
+    match x {
+        ref foo @ Some(box ref mut s) => (),
+        //~^ ERROR cannot borrow
+        _ => (),
+    };
+}
+
+// bindings_after_at + slice_patterns + or_patterns
+
+fn bindings_after_at_slice_patterns_or_patterns_moves(x: [Option<Test>; 4]) {
+    match x {
+        a @ [.., Some(Test::Foo | Test::Bar)] => (),
+        _ => (),
+    };
+
+    &x;
+    //~^ ERROR borrow of moved value
+}
+
+fn bindings_after_at_slice_patterns_or_patterns_borrows_binding(mut x: [Option<Test>; 4]) {
+    let r = match x {
+        ref a @ [ref b @ .., Some(Test::Foo | Test::Bar)] => Some(a),
+        _ => None,
+    };
+
+    &mut x;
+    //~^ ERROR cannot borrow
+
+    drop(r);
+}
+
+fn bindings_after_at_slice_patterns_or_patterns_borrows_slice(mut x: [Option<Test>; 4]) {
+    let r = match x {
+        ref a @ [ref b @ .., Some(Test::Foo | Test::Bar)] => Some(b),
+        _ => None,
+    };
+
+    &mut x;
+    //~^ ERROR cannot borrow
+
+    drop(r);
+}
+
+// bindings_after_at + slice_patterns + box_patterns
+
+fn bindings_after_at_slice_patterns_box_patterns_borrows(mut x: [Option<Box<String>>; 4]) {
+    let r = match x {
+        [_, ref a @ Some(box ref b), ..] => Some(a),
+        _ => None,
+    };
+
+    &mut x;
+    //~^ ERROR cannot borrow
+
+    drop(r);
+}
+
+// bindings_after_at + slice_patterns + or_patterns + box_patterns
+
+fn bindings_after_at_slice_patterns_or_patterns_box_patterns_borrows(
+    mut x: [Option<Box<Test>>; 4]
+) {
+    let r = match x {
+        [_, ref a @ Some(box Test::Foo | box Test::Bar), ..] => Some(a),
+        _ => None,
+    };
+
+    &mut x;
+    //~^ ERROR cannot borrow
+
+    drop(r);
+}
+
+fn bindings_after_at_slice_patterns_or_patterns_box_patterns_borrows_mut(
+    mut x: [Option<Box<Test>>; 4]
+) {
+    let r = match x {
+        [_, ref mut a @ Some(box Test::Foo | box Test::Bar), ..] => Some(a),
+        _ => None,
+    };
+
+    &x;
+    //~^ ERROR cannot borrow
+
+    drop(r);
+}
+
+fn bindings_after_at_slice_patterns_or_patterns_box_patterns_borrows_binding(
+    mut x: [Option<Box<Test>>; 4]
+) {
+    let r = match x {
+        ref a @ [_, ref b @ Some(box Test::Foo | box Test::Bar), ..] => Some(a),
+        _ => None,
+    };
+
+    &mut x;
+    //~^ ERROR cannot borrow
+
+    drop(r);
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.stderr b/src/test/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.stderr
new file mode 100644 (file)
index 0000000..35ed276
--- /dev/null
@@ -0,0 +1,208 @@
+error: cannot borrow value as mutable because it is also borrowed as immutable
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:40:9
+   |
+LL |         ref foo @ [.., ref mut bar] => (),
+   |         -------^^^^^^^^-----------^
+   |         |              |
+   |         |              mutable borrow, by `bar`, occurs here
+   |         immutable borrow, by `foo`, occurs here
+
+error: cannot borrow value as mutable because it is also borrowed as immutable
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:124:9
+   |
+LL |         ref foo @ Some(box ref mut s) => (),
+   |         -------^^^^^^^^^^^^---------^
+   |         |                  |
+   |         |                  mutable borrow, by `s`, occurs here
+   |         immutable borrow, by `foo`, occurs here
+
+error[E0382]: borrow of moved value: `x`
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:22:5
+   |
+LL | fn bindings_after_at_slice_patterns_move_binding(x: [String; 4]) {
+   |                                                  - move occurs because `x` has type `[std::string::String; 4]`, which does not implement the `Copy` trait
+LL |     match x {
+LL |         a @ [.., _] => (),
+   |         ----------- value moved here
+...
+LL |     &x;
+   |     ^^ value borrowed here after move
+
+error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:32:5
+   |
+LL |         ref mut foo @ [.., _] => Some(foo),
+   |         --------------------- mutable borrow occurs here
+...
+LL |     &x;
+   |     ^^ immutable borrow occurs here
+...
+LL |     drop(r);
+   |          - mutable borrow later used here
+
+error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:54:5
+   |
+LL |         [ref foo @ .., ref bar] => Some(foo),
+   |          ------------ immutable borrow occurs here
+...
+LL |     &mut x;
+   |     ^^^^^^ mutable borrow occurs here
+...
+LL |     drop(r);
+   |          - immutable borrow later used here
+
+error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:66:5
+   |
+LL |         ref foo @ [.., ref bar] => Some(foo),
+   |         ----------------------- immutable borrow occurs here
+...
+LL |     &mut x;
+   |     ^^^^^^ mutable borrow occurs here
+...
+LL |     drop(r);
+   |          - immutable borrow later used here
+
+error[E0382]: borrow of moved value: `x`
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:80:5
+   |
+LL | fn bindings_after_at_or_patterns_move(x: Option<Test>) {
+   |                                       - move occurs because `x` has type `std::option::Option<Test>`, which does not implement the `Copy` trait
+LL |     match x {
+LL |         foo @ Some(Test::Foo | Test::Bar) => (),
+   |         ---------------------------------
+   |         |
+   |         value moved here
+   |         value moved here
+...
+LL |     &x;
+   |     ^^ value borrowed here after move
+
+error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:90:5
+   |
+LL |         ref foo @ Some(Test::Foo | Test::Bar) => Some(foo),
+   |         ------------------------------------- immutable borrow occurs here
+...
+LL |     &mut x;
+   |     ^^^^^^ mutable borrow occurs here
+...
+LL |     drop(r);
+   |          - immutable borrow later used here
+
+error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:102:5
+   |
+LL |         ref mut foo @ Some(Test::Foo | Test::Bar) => Some(foo),
+   |         ----------------------------------------- mutable borrow occurs here
+...
+LL |     &x;
+   |     ^^ immutable borrow occurs here
+...
+LL |     drop(r);
+   |          - mutable borrow later used here
+
+error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:116:5
+   |
+LL |         ref foo @ Some(box ref s) => Some(foo),
+   |         ------------------------- immutable borrow occurs here
+...
+LL |     &mut x;
+   |     ^^^^^^ mutable borrow occurs here
+...
+LL |     drop(r);
+   |          - immutable borrow later used here
+
+error[E0382]: borrow of moved value: `x`
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:138:5
+   |
+LL | fn bindings_after_at_slice_patterns_or_patterns_moves(x: [Option<Test>; 4]) {
+   |                                                       - move occurs because `x` has type `[std::option::Option<Test>; 4]`, which does not implement the `Copy` trait
+LL |     match x {
+LL |         a @ [.., Some(Test::Foo | Test::Bar)] => (),
+   |         -------------------------------------
+   |         |
+   |         value moved here
+   |         value moved here
+...
+LL |     &x;
+   |     ^^ value borrowed here after move
+
+error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:148:5
+   |
+LL |         ref a @ [ref b @ .., Some(Test::Foo | Test::Bar)] => Some(a),
+   |         ------------------------------------------------- immutable borrow occurs here
+...
+LL |     &mut x;
+   |     ^^^^^^ mutable borrow occurs here
+...
+LL |     drop(r);
+   |          - immutable borrow later used here
+
+error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:160:5
+   |
+LL |         ref a @ [ref b @ .., Some(Test::Foo | Test::Bar)] => Some(b),
+   |                  ---------- immutable borrow occurs here
+...
+LL |     &mut x;
+   |     ^^^^^^ mutable borrow occurs here
+...
+LL |     drop(r);
+   |          - immutable borrow later used here
+
+error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:174:5
+   |
+LL |         [_, ref a @ Some(box ref b), ..] => Some(a),
+   |             ----------------------- immutable borrow occurs here
+...
+LL |     &mut x;
+   |     ^^^^^^ mutable borrow occurs here
+...
+LL |     drop(r);
+   |          - immutable borrow later used here
+
+error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:190:5
+   |
+LL |         [_, ref a @ Some(box Test::Foo | box Test::Bar), ..] => Some(a),
+   |             ------------------------------------------- immutable borrow occurs here
+...
+LL |     &mut x;
+   |     ^^^^^^ mutable borrow occurs here
+...
+LL |     drop(r);
+   |          - immutable borrow later used here
+
+error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:204:5
+   |
+LL |         [_, ref mut a @ Some(box Test::Foo | box Test::Bar), ..] => Some(a),
+   |             ----------------------------------------------- mutable borrow occurs here
+...
+LL |     &x;
+   |     ^^ immutable borrow occurs here
+...
+LL |     drop(r);
+   |          - mutable borrow later used here
+
+error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:218:5
+   |
+LL |         ref a @ [_, ref b @ Some(box Test::Foo | box Test::Bar), ..] => Some(a),
+   |         ------------------------------------------------------------ immutable borrow occurs here
+...
+LL |     &mut x;
+   |     ^^^^^^ mutable borrow occurs here
+...
+LL |     drop(r);
+   |          - immutable borrow later used here
+
+error: aborting due to 17 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/chalkify/builtin-copy-clone.rs b/src/test/ui/chalkify/builtin-copy-clone.rs
deleted file mode 100644 (file)
index d403514..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-// run-pass
-// compile-flags: -Z chalk
-
-// Test that `Clone` is correctly implemented for builtin types.
-
-#[derive(Copy, Clone)]
-struct S(i32);
-
-fn test_clone<T: Clone>(arg: T) {
-    let _ = arg.clone();
-}
-
-fn test_copy<T: Copy>(arg: T) {
-    let _ = arg;
-    let _ = arg;
-}
-
-fn test_copy_clone<T: Copy + Clone>(arg: T) {
-    test_copy(arg);
-    test_clone(arg);
-}
-
-fn foo() { }
-
-fn main() {
-    test_copy_clone(foo);
-    let f: fn() = foo;
-    test_copy_clone(f);
-    // FIXME: add closures when they're considered WF
-    test_copy_clone([1; 56]);
-    test_copy_clone((1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1));
-    test_copy_clone((1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, true, 'a', 1.1));
-    test_copy_clone(());
-    test_copy_clone(((1, 1), (1, 1, 1), (1.1, 1, 1, 'a'), ()));
-
-    let a = (
-        (S(1), S(0)),
-        (
-            (S(0), S(0), S(1)),
-            S(0)
-        )
-    );
-    test_copy_clone(a);
-}
diff --git a/src/test/ui/chalkify/inherent_impl.rs b/src/test/ui/chalkify/inherent_impl.rs
deleted file mode 100644 (file)
index 44e120c..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-// run-pass
-// compile-flags: -Z chalk
-
-trait Foo { }
-
-impl Foo for i32 { }
-
-struct S<T: Foo> {
-    x: T,
-}
-
-fn only_foo<T: Foo>(_x: &T) { }
-
-impl<T> S<T> {
-    // Test that we have the correct environment inside an inherent method.
-    fn dummy_foo(&self) {
-        only_foo(&self.x)
-    }
-}
-
-trait Bar { }
-impl Bar for u32 { }
-
-fn only_bar<T: Bar>() { }
-
-impl<T> S<T> {
-    // Test that the environment of `dummy_bar` adds up with the environment
-    // of the inherent impl.
-    fn dummy_bar<U: Bar>(&self) {
-        only_foo(&self.x);
-        only_bar::<U>();
-    }
-}
-
-fn main() {
-    let s = S {
-        x: 5,
-    };
-
-    s.dummy_foo();
-    s.dummy_bar::<u32>();
-}
diff --git a/src/test/ui/chalkify/lower_env1.rs b/src/test/ui/chalkify/lower_env1.rs
deleted file mode 100644 (file)
index afb6bdd..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#![feature(rustc_attrs)]
-#![allow(dead_code)]
-
-trait Foo { }
-
-#[rustc_dump_program_clauses] //~ ERROR program clause dump
-trait Bar where Self: Foo { }
-
-#[rustc_dump_env_program_clauses] //~ ERROR program clause dump
-fn bar<T: Bar + ?Sized>() {
-}
-
-fn main() {
-}
diff --git a/src/test/ui/chalkify/lower_env1.stderr b/src/test/ui/chalkify/lower_env1.stderr
deleted file mode 100644 (file)
index bc426e0..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-error: program clause dump
-  --> $DIR/lower_env1.rs:6:1
-   |
-LL | #[rustc_dump_program_clauses]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: forall<Self> { FromEnv(Self: Foo) :- FromEnv(Self: Bar). }
-   = note: forall<Self> { Implemented(Self: Bar) :- FromEnv(Self: Bar). }
-   = note: forall<Self> { WellFormed(Self: Bar) :- Implemented(Self: Bar), WellFormed(Self: Foo). }
-
-error: program clause dump
-  --> $DIR/lower_env1.rs:9:1
-   |
-LL | #[rustc_dump_env_program_clauses]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: forall<Self> { FromEnv(Self: Foo) :- FromEnv(Self: Bar). }
-   = note: forall<Self> { Implemented(Self: Bar) :- FromEnv(Self: Bar). }
-   = note: forall<Self> { Implemented(Self: Foo) :- FromEnv(Self: Foo). }
-
-error: aborting due to 2 previous errors
-
diff --git a/src/test/ui/chalkify/lower_env2.rs b/src/test/ui/chalkify/lower_env2.rs
deleted file mode 100644 (file)
index a067575..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-#![feature(rustc_attrs)]
-#![allow(dead_code)]
-
-trait Foo { }
-
-#[rustc_dump_program_clauses] //~ ERROR program clause dump
-struct S<'a, T: ?Sized> where T: Foo {
-    data: &'a T,
-}
-
-#[rustc_dump_env_program_clauses] //~ ERROR program clause dump
-fn bar<T: Foo>(_x: S<'_, T>) { // note that we have an implicit `T: Sized` bound
-}
-
-fn main() {
-}
diff --git a/src/test/ui/chalkify/lower_env2.stderr b/src/test/ui/chalkify/lower_env2.stderr
deleted file mode 100644 (file)
index 613a568..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-error: program clause dump
-  --> $DIR/lower_env2.rs:6:1
-   |
-LL | #[rustc_dump_program_clauses]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: forall<'a, T> { FromEnv(T: Foo) :- FromEnv(S<'a, T>). }
-   = note: forall<'a, T> { TypeOutlives(T: 'a) :- FromEnv(S<'a, T>). }
-   = note: forall<'a, T> { WellFormed(S<'a, T>) :- WellFormed(T: Foo), TypeOutlives(T: 'a). }
-
-error: program clause dump
-  --> $DIR/lower_env2.rs:11:1
-   |
-LL | #[rustc_dump_env_program_clauses]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: forall<'a, T> { FromEnv(T: Foo) :- FromEnv(S<'a, T>). }
-   = note: forall<'a, T> { TypeOutlives(T: 'a) :- FromEnv(S<'a, T>). }
-   = note: forall<Self> { Implemented(Self: Foo) :- FromEnv(Self: Foo). }
-   = note: forall<Self> { Implemented(Self: std::marker::Sized) :- FromEnv(Self: std::marker::Sized). }
-
-error: aborting due to 2 previous errors
-
diff --git a/src/test/ui/chalkify/lower_env3.rs b/src/test/ui/chalkify/lower_env3.rs
deleted file mode 100644 (file)
index 61ed3cb..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-#![feature(rustc_attrs)]
-#![allow(dead_code)]
-
-trait Foo {
-    #[rustc_dump_env_program_clauses] //~ ERROR program clause dump
-    fn foo(&self);
-}
-
-impl<T> Foo for T where T: Clone {
-    #[rustc_dump_env_program_clauses] //~ ERROR program clause dump
-    fn foo(&self) {
-    }
-}
-
-fn main() {
-}
diff --git a/src/test/ui/chalkify/lower_env3.stderr b/src/test/ui/chalkify/lower_env3.stderr
deleted file mode 100644 (file)
index a1fc83b..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-error: program clause dump
-  --> $DIR/lower_env3.rs:5:5
-   |
-LL |     #[rustc_dump_env_program_clauses]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: forall<Self> { Implemented(Self: Foo) :- FromEnv(Self: Foo). }
-
-error: program clause dump
-  --> $DIR/lower_env3.rs:10:5
-   |
-LL |     #[rustc_dump_env_program_clauses]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: forall<Self> { FromEnv(Self: std::marker::Sized) :- FromEnv(Self: std::clone::Clone). }
-   = note: forall<Self> { Implemented(Self: std::clone::Clone) :- FromEnv(Self: std::clone::Clone). }
-   = note: forall<Self> { Implemented(Self: std::marker::Sized) :- FromEnv(Self: std::marker::Sized). }
-
-error: aborting due to 2 previous errors
-
diff --git a/src/test/ui/chalkify/lower_impl.rs b/src/test/ui/chalkify/lower_impl.rs
deleted file mode 100644 (file)
index 1bd44a9..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-#![feature(rustc_attrs)]
-
-trait Foo { }
-
-#[rustc_dump_program_clauses] //~ ERROR program clause dump
-impl<T: 'static> Foo for T where T: Iterator<Item = i32> { }
-
-trait Bar {
-    type Assoc;
-}
-
-impl<T> Bar for T where T: Iterator<Item = i32> {
-    #[rustc_dump_program_clauses] //~ ERROR program clause dump
-    type Assoc = Vec<T>;
-}
-
-fn main() {
-    println!("hello");
-}
diff --git a/src/test/ui/chalkify/lower_impl.stderr b/src/test/ui/chalkify/lower_impl.stderr
deleted file mode 100644 (file)
index d6827fb..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-error: program clause dump
-  --> $DIR/lower_impl.rs:5:1
-   |
-LL | #[rustc_dump_program_clauses]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: forall<T> { Implemented(T: Foo) :- ProjectionEq(<T as std::iter::Iterator>::Item == i32), TypeOutlives(T: 'static), Implemented(T: std::iter::Iterator), Implemented(T: std::marker::Sized). }
-
-error: program clause dump
-  --> $DIR/lower_impl.rs:13:5
-   |
-LL |     #[rustc_dump_program_clauses]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: forall<T> { Normalize(<T as Bar>::Assoc -> std::vec::Vec<T>) :- Implemented(T: Bar). }
-
-error: aborting due to 2 previous errors
-
diff --git a/src/test/ui/chalkify/lower_struct.rs b/src/test/ui/chalkify/lower_struct.rs
deleted file mode 100644 (file)
index aecccea..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#![feature(rustc_attrs)]
-
-#[rustc_dump_program_clauses] //~ ERROR program clause dump
-struct Foo<'a, T> where Box<T>: Clone {
-    _x: std::marker::PhantomData<&'a T>,
-}
-
-fn main() { }
diff --git a/src/test/ui/chalkify/lower_struct.stderr b/src/test/ui/chalkify/lower_struct.stderr
deleted file mode 100644 (file)
index 0331c2f..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-error: program clause dump
-  --> $DIR/lower_struct.rs:3:1
-   |
-LL | #[rustc_dump_program_clauses]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: forall<'a, T> { FromEnv(T: std::marker::Sized) :- FromEnv(Foo<'a, T>). }
-   = note: forall<'a, T> { FromEnv(std::boxed::Box<T>: std::clone::Clone) :- FromEnv(Foo<'a, T>). }
-   = note: forall<'a, T> { TypeOutlives(T: 'a) :- FromEnv(Foo<'a, T>). }
-   = note: forall<'a, T> { WellFormed(Foo<'a, T>) :- WellFormed(T: std::marker::Sized), WellFormed(std::boxed::Box<T>: std::clone::Clone), TypeOutlives(T: 'a). }
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/chalkify/lower_trait.rs b/src/test/ui/chalkify/lower_trait.rs
deleted file mode 100644 (file)
index 0e19560..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-#![feature(rustc_attrs)]
-
-trait Bar { }
-
-#[rustc_dump_program_clauses] //~ ERROR program clause dump
-trait Foo<S, T: ?Sized> {
-    #[rustc_dump_program_clauses] //~ ERROR program clause dump
-    type Assoc: Bar + ?Sized;
-}
-
-fn main() {
-    println!("hello");
-}
diff --git a/src/test/ui/chalkify/lower_trait.stderr b/src/test/ui/chalkify/lower_trait.stderr
deleted file mode 100644 (file)
index ed3bded..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-error: program clause dump
-  --> $DIR/lower_trait.rs:5:1
-   |
-LL | #[rustc_dump_program_clauses]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: forall<Self, S, T> { FromEnv(<Self as Foo<S, T>>::Assoc: Bar) :- FromEnv(Self: Foo<S, T>). }
-   = note: forall<Self, S, T> { FromEnv(S: std::marker::Sized) :- FromEnv(Self: Foo<S, T>). }
-   = note: forall<Self, S, T> { Implemented(Self: Foo<S, T>) :- FromEnv(Self: Foo<S, T>). }
-   = note: forall<Self, S, T> { WellFormed(Self: Foo<S, T>) :- Implemented(Self: Foo<S, T>), WellFormed(S: std::marker::Sized), WellFormed(<Self as Foo<S, T>>::Assoc: Bar). }
-
-error: program clause dump
-  --> $DIR/lower_trait.rs:7:5
-   |
-LL |     #[rustc_dump_program_clauses]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: forall<Self, S, T, ^3> { ProjectionEq(<Self as Foo<S, T>>::Assoc == ^3) :- Normalize(<Self as Foo<S, T>>::Assoc -> ^3). }
-   = note: forall<Self, S, T> { FromEnv(Self: Foo<S, T>) :- FromEnv(Unnormalized(<Self as Foo<S, T>>::Assoc)). }
-   = note: forall<Self, S, T> { ProjectionEq(<Self as Foo<S, T>>::Assoc == Unnormalized(<Self as Foo<S, T>>::Assoc)). }
-   = note: forall<Self, S, T> { WellFormed(Unnormalized(<Self as Foo<S, T>>::Assoc)) :- WellFormed(Self: Foo<S, T>). }
-
-error: aborting due to 2 previous errors
-
diff --git a/src/test/ui/chalkify/lower_trait_higher_rank.rs b/src/test/ui/chalkify/lower_trait_higher_rank.rs
deleted file mode 100644 (file)
index 715f096..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#![feature(rustc_attrs)]
-
-#[rustc_dump_program_clauses] //~ ERROR program clause dump
-trait Foo<F: ?Sized> where for<'a> F: Fn(&'a (u8, u16)) -> &'a u8
-{
-}
-
-fn main() {
-    println!("hello");
-}
diff --git a/src/test/ui/chalkify/lower_trait_higher_rank.stderr b/src/test/ui/chalkify/lower_trait_higher_rank.stderr
deleted file mode 100644 (file)
index 79bbc9f..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-error: program clause dump
-  --> $DIR/lower_trait_higher_rank.rs:3:1
-   |
-LL | #[rustc_dump_program_clauses]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: forall<'a, Self, F> { FromEnv(F: std::ops::Fn<(&'a (u8, u16),)>) :- FromEnv(Self: Foo<F>). }
-   = note: forall<'a, Self, F> { ProjectionEq(<F as std::ops::FnOnce<(&'a (u8, u16),)>>::Output == &'a u8) :- FromEnv(Self: Foo<F>). }
-   = note: forall<Self, F> { Implemented(Self: Foo<F>) :- FromEnv(Self: Foo<F>). }
-   = note: forall<Self, F> { WellFormed(Self: Foo<F>) :- Implemented(Self: Foo<F>), forall<'a> { WellFormed(F: std::ops::Fn<(&'a (u8, u16),)>) }, forall<'a> { ProjectionEq(<F as std::ops::FnOnce<(&'a (u8, u16),)>>::Output == &'a u8) }. }
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/chalkify/lower_trait_where_clause.rs b/src/test/ui/chalkify/lower_trait_where_clause.rs
deleted file mode 100644 (file)
index 78fa39f..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-#![feature(rustc_attrs)]
-
-use std::borrow::Borrow;
-
-#[rustc_dump_program_clauses] //~ ERROR program clause dump
-trait Foo<'a, 'b, T, U>
-where
-    T: Borrow<U> + ?Sized,
-    U: ?Sized + 'b,
-    'a: 'b,
-    Box<T>:, // NOTE(#53696) this checks an empty list of bounds.
-{
-}
-
-fn main() {
-    println!("hello");
-}
diff --git a/src/test/ui/chalkify/lower_trait_where_clause.stderr b/src/test/ui/chalkify/lower_trait_where_clause.stderr
deleted file mode 100644 (file)
index 408f371..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-error: program clause dump
-  --> $DIR/lower_trait_where_clause.rs:5:1
-   |
-LL | #[rustc_dump_program_clauses]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: forall<'a, 'b, Self, T, U> { FromEnv(T: std::borrow::Borrow<U>) :- FromEnv(Self: Foo<'a, 'b, T, U>). }
-   = note: forall<'a, 'b, Self, T, U> { Implemented(Self: Foo<'a, 'b, T, U>) :- FromEnv(Self: Foo<'a, 'b, T, U>). }
-   = note: forall<'a, 'b, Self, T, U> { RegionOutlives('a: 'b) :- FromEnv(Self: Foo<'a, 'b, T, U>). }
-   = note: forall<'a, 'b, Self, T, U> { TypeOutlives(U: 'b) :- FromEnv(Self: Foo<'a, 'b, T, U>). }
-   = note: forall<'a, 'b, Self, T, U> { TypeOutlives(std::boxed::Box<T>: '<empty>) :- FromEnv(Self: Foo<'a, 'b, T, U>). }
-   = note: forall<'a, 'b, Self, T, U> { WellFormed(Self: Foo<'a, 'b, T, U>) :- Implemented(Self: Foo<'a, 'b, T, U>), WellFormed(T: std::borrow::Borrow<U>), TypeOutlives(U: 'b), RegionOutlives('a: 'b), TypeOutlives(std::boxed::Box<T>: '<empty>). }
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/chalkify/projection.rs b/src/test/ui/chalkify/projection.rs
deleted file mode 100644 (file)
index d6a8dd7..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-// run-pass
-// compile-flags: -Z chalk
-
-trait Foo { }
-
-trait Bar {
-    type Item: Foo;
-}
-
-impl Foo for i32 { }
-impl Bar for i32 {
-    type Item = i32;
-}
-
-fn only_foo<T: Foo>() { }
-
-fn only_bar<T: Bar>() {
-    // `T` implements `Bar` hence `<T as Bar>::Item` must also implement `Bar`
-    only_foo::<T::Item>()
-}
-
-fn main() {
-    only_bar::<i32>();
-    only_foo::<<i32 as Bar>::Item>();
-}
diff --git a/src/test/ui/chalkify/super_trait.rs b/src/test/ui/chalkify/super_trait.rs
deleted file mode 100644 (file)
index eeff9fd..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-// run-pass
-// compile-flags: -Z chalk
-
-trait Foo { }
-trait Bar: Foo { }
-
-impl Foo for i32 { }
-impl Bar for i32 { }
-
-fn only_foo<T: Foo>() { }
-
-fn only_bar<T: Bar>() {
-    // `T` implements `Bar` hence `T` must also implement `Foo`
-    only_foo::<T>()
-}
-
-fn main() {
-    only_bar::<i32>()
-}
diff --git a/src/test/ui/chalkify/trait_implied_bound.rs b/src/test/ui/chalkify/trait_implied_bound.rs
deleted file mode 100644 (file)
index 8a2e1cf..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-// run-pass
-// compile-flags: -Z chalk
-
-trait Foo { }
-trait Bar<U> where U: Foo { }
-
-impl Foo for i32 { }
-impl Bar<i32> for i32 { }
-
-fn only_foo<T: Foo>() { }
-
-fn only_bar<U, T: Bar<U>>() {
-    only_foo::<U>()
-}
-
-fn main() {
-    only_bar::<i32, i32>()
-}
diff --git a/src/test/ui/chalkify/type_implied_bound.rs b/src/test/ui/chalkify/type_implied_bound.rs
deleted file mode 100644 (file)
index 8673f53..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-// run-pass
-// compile-flags: -Z chalk
-
-trait Eq { }
-trait Hash: Eq { }
-
-impl Eq for i32 { }
-impl Hash for i32 { }
-
-struct Set<T: Hash> {
-    _x: T,
-}
-
-fn only_eq<T: Eq>() { }
-
-fn take_a_set<T>(_: &Set<T>) {
-    // `Set<T>` is an input type of `take_a_set`, hence we know that
-    // `T` must implement `Hash`, and we know in turn that `T` must
-    // implement `Eq`.
-    only_eq::<T>()
-}
-
-fn main() {
-    let set = Set {
-        _x: 5,
-    };
-
-    take_a_set(&set);
-}
diff --git a/src/test/ui/chalkify/type_inference.rs b/src/test/ui/chalkify/type_inference.rs
deleted file mode 100644 (file)
index 62a53ec..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-// compile-flags: -Z chalk
-
-trait Foo { }
-impl Foo for i32 { }
-
-trait Bar { }
-impl Bar for i32 { }
-impl Bar for u32 { }
-
-fn only_foo<T: Foo>(_x: T) { }
-
-fn only_bar<T: Bar>(_x: T) { }
-
-fn main() {
-    let x = 5.0;
-
-    // The only type which implements `Foo` is `i32`, so the chalk trait solver
-    // is expecting a variable of type `i32`. This behavior differs from the
-    // old-style trait solver. I guess this will change, that's why I'm
-    // adding that test.
-    only_foo(x); //~ ERROR mismatched types
-
-    // Here we have two solutions so we get back the behavior of the old-style
-    // trait solver.
-    only_bar(x); //~ ERROR the trait bound `{float}: Bar` is not satisfied
-}
diff --git a/src/test/ui/chalkify/type_inference.stderr b/src/test/ui/chalkify/type_inference.stderr
deleted file mode 100644 (file)
index b8152ca..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/type_inference.rs:21:14
-   |
-LL |     only_foo(x);
-   |              ^ expected `i32`, found floating-point number
-
-error[E0277]: the trait bound `{float}: Bar` is not satisfied
-  --> $DIR/type_inference.rs:25:5
-   |
-LL | fn only_bar<T: Bar>(_x: T) { }
-   |    --------    --- required by this bound in `only_bar`
-...
-LL |     only_bar(x);
-   |     ^^^^^^^^ the trait `Bar` is not implemented for `{float}`
-   |
-   = help: the following implementations were found:
-             <i32 as Bar>
-             <u32 as Bar>
-
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0277, E0308.
-For more information about an error, try `rustc --explain E0277`.
index 4db66af6783cae505a82b474ccc742baee4ce3af..1bd37f395902a287e532460cf11a3409fce3cfcd 100644 (file)
@@ -1,9 +1,10 @@
 error[E0198]: negative impls cannot be unsafe
-  --> $DIR/coherence-negative-impls-safe.rs:7:1
+  --> $DIR/coherence-negative-impls-safe.rs:7:13
    |
 LL | unsafe impl !Send for TestType {}
-   | ------^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   | |
+   | ------      -^^^^
+   | |           |
+   | |           negative because of this
    | unsafe because of this
 
 error: aborting due to previous error
diff --git a/src/test/ui/conditional-compilation/cfg_accessible-input-validation.rs b/src/test/ui/conditional-compilation/cfg_accessible-input-validation.rs
new file mode 100644 (file)
index 0000000..c51c908
--- /dev/null
@@ -0,0 +1,24 @@
+#![feature(cfg_accessible)]
+
+#[cfg_accessible] //~ ERROR malformed `cfg_accessible` attribute input
+struct S1;
+
+#[cfg_accessible = "value"] //~ ERROR malformed `cfg_accessible` attribute input
+struct S2;
+
+#[cfg_accessible()] //~ ERROR `cfg_accessible` path is not specified
+struct S3;
+
+#[cfg_accessible(std, core)] //~ ERROR multiple `cfg_accessible` paths are specified
+struct S4;
+
+#[cfg_accessible("std")] //~ ERROR `cfg_accessible` path cannot be a literal
+struct S5;
+
+#[cfg_accessible(std = "value")] //~ ERROR `cfg_accessible` path cannot accept arguments
+struct S6;
+
+#[cfg_accessible(std(value))] //~ ERROR `cfg_accessible` path cannot accept arguments
+struct S7;
+
+fn main() {}
diff --git a/src/test/ui/conditional-compilation/cfg_accessible-input-validation.stderr b/src/test/ui/conditional-compilation/cfg_accessible-input-validation.stderr
new file mode 100644 (file)
index 0000000..86706c7
--- /dev/null
@@ -0,0 +1,44 @@
+error: malformed `cfg_accessible` attribute input
+  --> $DIR/cfg_accessible-input-validation.rs:3:1
+   |
+LL | #[cfg_accessible]
+   | ^^^^^^^^^^^^^^^^^ help: must be of the form: `#[cfg_accessible(path)]`
+
+error: malformed `cfg_accessible` attribute input
+  --> $DIR/cfg_accessible-input-validation.rs:6:1
+   |
+LL | #[cfg_accessible = "value"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[cfg_accessible(path)]`
+
+error: `cfg_accessible` path is not specified
+  --> $DIR/cfg_accessible-input-validation.rs:9:1
+   |
+LL | #[cfg_accessible()]
+   | ^^^^^^^^^^^^^^^^^^^
+
+error: multiple `cfg_accessible` paths are specified
+  --> $DIR/cfg_accessible-input-validation.rs:12:23
+   |
+LL | #[cfg_accessible(std, core)]
+   |                       ^^^^
+
+error: `cfg_accessible` path cannot be a literal
+  --> $DIR/cfg_accessible-input-validation.rs:15:18
+   |
+LL | #[cfg_accessible("std")]
+   |                  ^^^^^
+
+error: `cfg_accessible` path cannot accept arguments
+  --> $DIR/cfg_accessible-input-validation.rs:18:18
+   |
+LL | #[cfg_accessible(std = "value")]
+   |                  ^^^^^^^^^^^^^
+
+error: `cfg_accessible` path cannot accept arguments
+  --> $DIR/cfg_accessible-input-validation.rs:21:18
+   |
+LL | #[cfg_accessible(std(value))]
+   |                  ^^^^^^^^^^
+
+error: aborting due to 7 previous errors
+
diff --git a/src/test/ui/conditional-compilation/cfg_accessible-stuck.rs b/src/test/ui/conditional-compilation/cfg_accessible-stuck.rs
new file mode 100644 (file)
index 0000000..8bc93fa
--- /dev/null
@@ -0,0 +1,9 @@
+#![feature(cfg_accessible)]
+
+#[cfg_accessible(Z)] //~ ERROR cannot determine whether the path is accessible or not
+struct S;
+
+#[cfg_accessible(S)] //~ ERROR cannot determine whether the path is accessible or not
+struct Z;
+
+fn main() {}
diff --git a/src/test/ui/conditional-compilation/cfg_accessible-stuck.stderr b/src/test/ui/conditional-compilation/cfg_accessible-stuck.stderr
new file mode 100644 (file)
index 0000000..9641441
--- /dev/null
@@ -0,0 +1,14 @@
+error: cannot determine whether the path is accessible or not
+  --> $DIR/cfg_accessible-stuck.rs:6:1
+   |
+LL | #[cfg_accessible(S)]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: cannot determine whether the path is accessible or not
+  --> $DIR/cfg_accessible-stuck.rs:3:1
+   |
+LL | #[cfg_accessible(Z)]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/conditional-compilation/cfg_accessible-unstable.rs b/src/test/ui/conditional-compilation/cfg_accessible-unstable.rs
new file mode 100644 (file)
index 0000000..e9247e6
--- /dev/null
@@ -0,0 +1,2 @@
+#[cfg_accessible(std)] //~ ERROR use of unstable library feature 'cfg_accessible'
+fn main() {}
diff --git a/src/test/ui/conditional-compilation/cfg_accessible-unstable.stderr b/src/test/ui/conditional-compilation/cfg_accessible-unstable.stderr
new file mode 100644 (file)
index 0000000..2f55b95
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0658]: use of unstable library feature 'cfg_accessible': `cfg_accessible` is not fully implemented
+  --> $DIR/cfg_accessible-unstable.rs:1:3
+   |
+LL | #[cfg_accessible(std)]
+   |   ^^^^^^^^^^^^^^
+   |
+   = note: see issue #64797 <https://github.com/rust-lang/rust/issues/64797> for more information
+   = help: add `#![feature(cfg_accessible)]` 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/conditional-compilation/cfg_accessible.rs b/src/test/ui/conditional-compilation/cfg_accessible.rs
new file mode 100644 (file)
index 0000000..07b0be5
--- /dev/null
@@ -0,0 +1,43 @@
+#![feature(cfg_accessible)]
+
+mod m {
+    pub struct ExistingPublic;
+    struct ExistingPrivate;
+}
+
+#[cfg_accessible(m::ExistingPublic)]
+struct ExistingPublic;
+
+// FIXME: Not implemented yet.
+#[cfg_accessible(m::ExistingPrivate)] //~ ERROR not sure whether the path is accessible or not
+struct ExistingPrivate;
+
+// FIXME: Not implemented yet.
+#[cfg_accessible(m::NonExistent)] //~ ERROR not sure whether the path is accessible or not
+struct ExistingPrivate;
+
+#[cfg_accessible(n::AccessibleExpanded)] // OK, `cfg_accessible` can wait and retry.
+struct AccessibleExpanded;
+
+macro_rules! generate_accessible_expanded {
+    () => {
+        mod n {
+            pub struct AccessibleExpanded;
+        }
+    };
+}
+
+generate_accessible_expanded!();
+
+struct S {
+    field: u8,
+}
+
+// FIXME: Not implemented yet.
+#[cfg_accessible(S::field)] //~ ERROR not sure whether the path is accessible or not
+struct Field;
+
+fn main() {
+    ExistingPublic;
+    AccessibleExpanded;
+}
diff --git a/src/test/ui/conditional-compilation/cfg_accessible.stderr b/src/test/ui/conditional-compilation/cfg_accessible.stderr
new file mode 100644 (file)
index 0000000..167765c
--- /dev/null
@@ -0,0 +1,38 @@
+error: not sure whether the path is accessible or not
+  --> $DIR/cfg_accessible.rs:12:18
+   |
+LL | #[cfg_accessible(m::ExistingPrivate)]
+   |                  ^^^^^^^^^^^^^^^^^^
+   |
+note: `cfg_accessible` is not fully implemented
+  --> $DIR/cfg_accessible.rs:12:18
+   |
+LL | #[cfg_accessible(m::ExistingPrivate)]
+   |                  ^^^^^^^^^^^^^^^^^^
+
+error: not sure whether the path is accessible or not
+  --> $DIR/cfg_accessible.rs:16:18
+   |
+LL | #[cfg_accessible(m::NonExistent)]
+   |                  ^^^^^^^^^^^^^^
+   |
+note: `cfg_accessible` is not fully implemented
+  --> $DIR/cfg_accessible.rs:16:18
+   |
+LL | #[cfg_accessible(m::NonExistent)]
+   |                  ^^^^^^^^^^^^^^
+
+error: not sure whether the path is accessible or not
+  --> $DIR/cfg_accessible.rs:37:18
+   |
+LL | #[cfg_accessible(S::field)]
+   |                  ^^^^^^^^
+   |
+note: `cfg_accessible` is not fully implemented
+  --> $DIR/cfg_accessible.rs:37:18
+   |
+LL | #[cfg_accessible(S::field)]
+   |                  ^^^^^^^^
+
+error: aborting due to 3 previous errors
+
index 43b76bf649778ec84706635c4796ca4caac24ed9..0b78532c73751fbf9298b29445e88a643ad508a3 100644 (file)
@@ -76,5 +76,5 @@ LL | | }
 
 error: aborting due to 10 previous errors
 
-Some errors have detailed explanations: E0566, E0587.
+Some errors have detailed explanations: E0566, E0587, E0634.
 For more information about an error, try `rustc --explain E0566`.
index 4869f48363447db0fc0bbbb4aecc566a91860d86..b39a160b5298785940b5658298f7e4e3c48583a9 100644 (file)
@@ -1,8 +1,8 @@
 error[E0277]: arrays only have std trait implementations for lengths 0..=32
-  --> $DIR/into-iter-no-impls-length-33.rs:12:5
+  --> $DIR/into-iter-no-impls-length-33.rs:12:19
    |
 LL |     IntoIter::new([0i32; 33])
-   |     ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
+   |                   ^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
    |
    = note: required by `std::array::IntoIter::<T, N>::new`
 
@@ -19,10 +19,10 @@ LL |     IntoIter::new([0i32; 33])
    = 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
+  --> $DIR/into-iter-no-impls-length-33.rs:18:19
    |
 LL |     IntoIter::new([0i32; 33])
-   |     ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
+   |                   ^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
    |
    = note: required by `std::array::IntoIter::<T, N>::new`
 
@@ -39,10 +39,10 @@ LL |     IntoIter::new([0i32; 33])
    = 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
+  --> $DIR/into-iter-no-impls-length-33.rs:24:19
    |
 LL |     IntoIter::new([0i32; 33])
-   |     ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
+   |                   ^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
    |
    = note: required by `std::array::IntoIter::<T, N>::new`
 
@@ -59,10 +59,10 @@ LL |     IntoIter::new([0i32; 33])
    = 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
+  --> $DIR/into-iter-no-impls-length-33.rs:30:19
    |
 LL |     IntoIter::new([0i32; 33])
-   |     ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
+   |                   ^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
    |
    = note: required by `std::array::IntoIter::<T, N>::new`
 
@@ -79,10 +79,10 @@ LL |     IntoIter::new([0i32; 33])
    = 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
+  --> $DIR/into-iter-no-impls-length-33.rs:36:19
    |
 LL |     IntoIter::new([0i32; 33])
-   |     ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
+   |                   ^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
    |
    = note: required by `std::array::IntoIter::<T, N>::new`
 
@@ -99,10 +99,10 @@ LL |     IntoIter::new([0i32; 33])
    = 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
+  --> $DIR/into-iter-no-impls-length-33.rs:42:19
    |
 LL |     IntoIter::new([0i32; 33])
-   |     ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
+   |                   ^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
    |
    = note: required by `std::array::IntoIter::<T, N>::new`
 
@@ -119,10 +119,10 @@ LL |     IntoIter::new([0i32; 33])
    = 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
+  --> $DIR/into-iter-no-impls-length-33.rs:48:19
    |
 LL |     IntoIter::new([0i32; 33])
-   |     ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
+   |                   ^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
    |
    = note: required by `std::array::IntoIter::<T, N>::new`
 
index 8379cbd4908e95fa51f7bf81f674ad999695813f..c1d7022d56b5f848d92e718162cb9fd4808ac301 100644 (file)
@@ -10,7 +10,7 @@ error[E0282]: type annotations needed
   --> $DIR/cannot-infer-const-args.rs:9:5
    |
 LL |     foo();
-   |     ^^^ cannot infer type for fn item `fn() -> usize {foo::<_: usize>}`
+   |     ^^^ cannot infer type for fn item `fn() -> usize {foo::<{_: usize}>}`
 
 error: aborting due to previous error
 
index 28586426b44e9f736951a6dc297774ef81b4f6a8..469843d6aae1ef5a971531d7f44329eff8b7612f 100644 (file)
@@ -7,5 +7,5 @@
 struct S<const N: usize>;
 
 fn main() {
-    assert_eq!(std::any::type_name::<S<3>>(), "const_generic_type_name::S<3usize>");
+    assert_eq!(std::any::type_name::<S<3>>(), "const_generic_type_name::S<3>");
 }
index 44eab8baa40a6571651cac2887f64ab8ab214ecd..05d2dff8e986816a9a355b25b6876a8eab7e7fe0 100644 (file)
@@ -10,12 +10,12 @@ error[E0308]: mismatched types
   --> $DIR/fn-const-param-infer.rs:16:31
    |
 LL |     let _: Checked<not_one> = Checked::<not_two>;
-   |            ----------------   ^^^^^^^^^^^^^^^^^^ expected `not_one`, found `not_two`
+   |            ----------------   ^^^^^^^^^^^^^^^^^^ expected `{not_one as fn(usize) -> bool}`, found `{not_two as fn(usize) -> bool}`
    |            |
    |            expected due to this
    |
-   = note: expected struct `Checked<not_one>`
-              found struct `Checked<not_two>`
+   = note: expected struct `Checked<{not_one as fn(usize) -> bool}>`
+              found struct `Checked<{not_two as fn(usize) -> bool}>`
 
 error[E0308]: mismatched types
   --> $DIR/fn-const-param-infer.rs:20:24
@@ -36,12 +36,12 @@ error[E0308]: mismatched types
   --> $DIR/fn-const-param-infer.rs:25:40
    |
 LL |     let _: Checked<{generic::<u32>}> = Checked::<{generic::<u16>}>;
-   |            -------------------------   ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `generic::<u32>`, found `generic::<u16>`
+   |            -------------------------   ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{generic::<u32> as fn(usize) -> bool}`, found `{generic::<u16> as fn(usize) -> bool}`
    |            |
    |            expected due to this
    |
-   = note: expected struct `Checked<generic::<u32>>`
-              found struct `Checked<generic::<u16>>`
+   = note: expected struct `Checked<{generic::<u32> as fn(usize) -> bool}>`
+              found struct `Checked<{generic::<u16> as fn(usize) -> bool}>`
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/const-generics/issues/issue-62456.rs b/src/test/ui/const-generics/issues/issue-62456.rs
new file mode 100644 (file)
index 0000000..c5e6fe9
--- /dev/null
@@ -0,0 +1,9 @@
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+fn foo<const N: usize>() {
+    let _ = [0u64; N + 1];
+    //~^ ERROR array lengths can't depend on generic parameters
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-62456.stderr b/src/test/ui/const-generics/issues/issue-62456.stderr
new file mode 100644 (file)
index 0000000..9cdccf8
--- /dev/null
@@ -0,0 +1,16 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/issue-62456.rs:1:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+
+error: array lengths can't depend on generic parameters
+  --> $DIR/issue-62456.rs:5:20
+   |
+LL |     let _ = [0u64; N + 1];
+   |                    ^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/const-generics/issues/issue-62504.rs b/src/test/ui/const-generics/issues/issue-62504.rs
new file mode 100644 (file)
index 0000000..74ed3d3
--- /dev/null
@@ -0,0 +1,25 @@
+// Regression test for #62504
+
+#![feature(const_generics)]
+#![allow(incomplete_features)]
+
+trait HasSize {
+    const SIZE: usize;
+}
+
+impl<const X: usize> HasSize for ArrayHolder<{ X }> {
+    const SIZE: usize = X;
+}
+
+struct ArrayHolder<const X: usize>([u32; X]);
+
+impl<const X: usize> ArrayHolder<{ X }> {
+    pub const fn new() -> Self {
+        ArrayHolder([0; Self::SIZE])
+        //~^ ERROR: array lengths can't depend on generic parameters
+    }
+}
+
+fn main() {
+    let mut array = ArrayHolder::new();
+}
diff --git a/src/test/ui/const-generics/issues/issue-62504.stderr b/src/test/ui/const-generics/issues/issue-62504.stderr
new file mode 100644 (file)
index 0000000..c2a752e
--- /dev/null
@@ -0,0 +1,8 @@
+error: array lengths can't depend on generic parameters
+  --> $DIR/issue-62504.rs:18:25
+   |
+LL |         ArrayHolder([0; Self::SIZE])
+   |                         ^^^^^^^^^^
+
+error: aborting due to previous error
+
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 (file)
index 3ca5273..0000000
+++ /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, const N: usize>([T; N]);
-impl<T, const N: usize> Foo<T, {N}> {}
-
-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 (file)
index 60b388e..0000000
+++ /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/issues/issue-67739.rs b/src/test/ui/const-generics/issues/issue-67739.rs
new file mode 100644 (file)
index 0000000..79c5ac9
--- /dev/null
@@ -0,0 +1,18 @@
+// Regression test for #67739
+
+#![allow(incomplete_features)]
+#![feature(const_generics)]
+
+use std::mem;
+
+pub trait Trait {
+    type Associated: Sized;
+
+    fn associated_size(&self) -> usize {
+        [0u8; mem::size_of::<Self::Associated>()];
+        //~^ ERROR: array lengths can't depend on generic parameters
+        0
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-67739.stderr b/src/test/ui/const-generics/issues/issue-67739.stderr
new file mode 100644 (file)
index 0000000..a31b556
--- /dev/null
@@ -0,0 +1,8 @@
+error: array lengths can't depend on generic parameters
+  --> $DIR/issue-67739.rs:12:15
+   |
+LL |         [0u8; mem::size_of::<Self::Associated>()];
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
index f69c37fbb8f3d0e7be0b40c5ea6cf25fcb79de70..f0349f469626f971884526e77420700385f9c306 100644 (file)
@@ -4,6 +4,6 @@
 struct Const<const P: *const u32>;
 
 fn main() {
-    let _: Const<{15 as *const _}> = Const::<{10 as *const _}>; //~ mismatched types
-    let _: Const<{10 as *const _}> = Const::<{10 as *const _}>;
+    let _: Const<{ 15 as *const _ }> = Const::<{ 10 as *const _ }>; //~ mismatched types
+    let _: Const<{ 10 as *const _ }> = Const::<{ 10 as *const _ }>;
 }
index 9cd39b61dc9367accff286bf3b9ef31cfb0f7444..d9794f60a19ceb2bd648bf1709a7d909d66a501a 100644 (file)
@@ -7,15 +7,15 @@ 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
+  --> $DIR/raw-ptr-const-param.rs:7:40
    |
-LL |     let _: Const<{15 as *const _}> = Const::<{10 as *const _}>;
-   |            -----------------------   ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{pointer}`, found `{pointer}`
+LL |     let _: Const<{ 15 as *const _ }> = Const::<{ 10 as *const _ }>;
+   |            -------------------------   ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{0xf as *const u32}`, found `{0xa as *const u32}`
    |            |
    |            expected due to this
    |
-   = note: expected struct `Const<{pointer}>`
-              found struct `Const<{pointer}>`
+   = note: expected struct `Const<{0xf as *const u32}>`
+              found struct `Const<{0xa as *const u32}>`
 
 error: aborting due to previous error
 
index e0df787f80a4415c076ec0cbbc7a881314e1e934..305f259eac22dc38832040e15a79ede2a75ca89d 100644 (file)
@@ -12,7 +12,7 @@ error: any use of this value will cause an error
 LL |     const I32_REF_U8_UNION: u8 = unsafe { Nonsense { int_32_ref: &3 }.uint_8 };
    |     --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                           |
-   |                                           a raw memory access tried to access part of a pointer value as raw bytes
+   |                                           unable to turn pointer into raw bytes
    |
    = note: `#[deny(const_err)]` on by default
 
@@ -22,7 +22,7 @@ error: any use of this value will cause an error
 LL |     const I32_REF_U16_UNION: u16 = unsafe { Nonsense { int_32_ref: &3 }.uint_16 };
    |     ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                             |
-   |                                             a raw memory access tried to access part of a pointer value as raw bytes
+   |                                             unable to turn pointer into raw bytes
 
 error: any use of this value will cause an error
   --> $DIR/const-pointer-values-in-various-types.rs:34:45
@@ -30,7 +30,7 @@ error: any use of this value will cause an error
 LL |     const I32_REF_U32_UNION: u32 = unsafe { Nonsense { int_32_ref: &3 }.uint_32 };
    |     ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                             |
-   |                                             a raw memory access tried to access part of a pointer value as raw bytes
+   |                                             unable to turn pointer into raw bytes
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/const-pointer-values-in-various-types.rs:37:5
@@ -54,7 +54,7 @@ error: any use of this value will cause an error
 LL |     const I32_REF_I8_UNION: i8 = unsafe { Nonsense { int_32_ref: &3 }.int_8 };
    |     --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                           |
-   |                                           a raw memory access tried to access part of a pointer value as raw bytes
+   |                                           unable to turn pointer into raw bytes
 
 error: any use of this value will cause an error
   --> $DIR/const-pointer-values-in-various-types.rs:46:45
@@ -62,7 +62,7 @@ error: any use of this value will cause an error
 LL |     const I32_REF_I16_UNION: i16 = unsafe { Nonsense { int_32_ref: &3 }.int_16 };
    |     ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                             |
-   |                                             a raw memory access tried to access part of a pointer value as raw bytes
+   |                                             unable to turn pointer into raw bytes
 
 error: any use of this value will cause an error
   --> $DIR/const-pointer-values-in-various-types.rs:49:45
@@ -70,7 +70,7 @@ error: any use of this value will cause an error
 LL |     const I32_REF_I32_UNION: i32 = unsafe { Nonsense { int_32_ref: &3 }.int_32 };
    |     ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                             |
-   |                                             a raw memory access tried to access part of a pointer value as raw bytes
+   |                                             unable to turn pointer into raw bytes
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/const-pointer-values-in-various-types.rs:52:5
@@ -94,7 +94,7 @@ error: any use of this value will cause an error
 LL |     const I32_REF_F32_UNION: f32 = unsafe { Nonsense { int_32_ref: &3 }.float_32 };
    |     ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                             |
-   |                                             a raw memory access tried to access part of a pointer value as raw bytes
+   |                                             unable to turn pointer into raw bytes
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/const-pointer-values-in-various-types.rs:61:5
@@ -110,7 +110,7 @@ error: any use of this value will cause an error
 LL |     const I32_REF_BOOL_UNION: bool = unsafe { Nonsense { int_32_ref: &3 }.truthy_falsey };
    |     ------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                               |
-   |                                               a raw memory access tried to access part of a pointer value as raw bytes
+   |                                               unable to turn pointer into raw bytes
 
 error: any use of this value will cause an error
   --> $DIR/const-pointer-values-in-various-types.rs:67:47
@@ -118,7 +118,7 @@ error: any use of this value will cause an error
 LL |     const I32_REF_CHAR_UNION: char = unsafe { Nonsense { int_32_ref: &3 }.character };
    |     ------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                               |
-   |                                               a raw memory access tried to access part of a pointer value as raw bytes
+   |                                               unable to turn pointer into raw bytes
 
 error: any use of this value will cause an error
   --> $DIR/const-pointer-values-in-various-types.rs:70:39
@@ -126,7 +126,7 @@ error: any use of this value will cause an error
 LL |     const STR_U8_UNION: u8 = unsafe { Nonsense { stringy: "3" }.uint_8 };
    |     ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                       |
-   |                                       a raw memory access tried to access part of a pointer value as raw bytes
+   |                                       unable to turn pointer into raw bytes
 
 error: any use of this value will cause an error
   --> $DIR/const-pointer-values-in-various-types.rs:73:41
@@ -134,7 +134,7 @@ error: any use of this value will cause an error
 LL |     const STR_U16_UNION: u16 = unsafe { Nonsense { stringy: "3" }.uint_16 };
    |     ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                         |
-   |                                         a raw memory access tried to access part of a pointer value as raw bytes
+   |                                         unable to turn pointer into raw bytes
 
 error: any use of this value will cause an error
   --> $DIR/const-pointer-values-in-various-types.rs:76:41
@@ -142,7 +142,7 @@ error: any use of this value will cause an error
 LL |     const STR_U32_UNION: u32 = unsafe { Nonsense { stringy: "3" }.uint_32 };
    |     ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                         |
-   |                                         a raw memory access tried to access part of a pointer value as raw bytes
+   |                                         unable to turn pointer into raw bytes
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/const-pointer-values-in-various-types.rs:79:5
@@ -158,7 +158,7 @@ error: any use of this value will cause an error
 LL |     const STR_U128_UNION: u128 = unsafe { Nonsense { stringy: "3" }.uint_128 };
    |     --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                           |
-   |                                           a raw memory access tried to access part of a pointer value as raw bytes
+   |                                           unable to turn pointer into raw bytes
 
 error: any use of this value will cause an error
   --> $DIR/const-pointer-values-in-various-types.rs:85:39
@@ -166,7 +166,7 @@ error: any use of this value will cause an error
 LL |     const STR_I8_UNION: i8 = unsafe { Nonsense { stringy: "3" }.int_8 };
    |     ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                       |
-   |                                       a raw memory access tried to access part of a pointer value as raw bytes
+   |                                       unable to turn pointer into raw bytes
 
 error: any use of this value will cause an error
   --> $DIR/const-pointer-values-in-various-types.rs:88:41
@@ -174,7 +174,7 @@ error: any use of this value will cause an error
 LL |     const STR_I16_UNION: i16 = unsafe { Nonsense { stringy: "3" }.int_16 };
    |     ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                         |
-   |                                         a raw memory access tried to access part of a pointer value as raw bytes
+   |                                         unable to turn pointer into raw bytes
 
 error: any use of this value will cause an error
   --> $DIR/const-pointer-values-in-various-types.rs:91:41
@@ -182,7 +182,7 @@ error: any use of this value will cause an error
 LL |     const STR_I32_UNION: i32 = unsafe { Nonsense { stringy: "3" }.int_32 };
    |     ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                         |
-   |                                         a raw memory access tried to access part of a pointer value as raw bytes
+   |                                         unable to turn pointer into raw bytes
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/const-pointer-values-in-various-types.rs:94:5
@@ -198,7 +198,7 @@ error: any use of this value will cause an error
 LL |     const STR_I128_UNION: i128 = unsafe { Nonsense { stringy: "3" }.int_128 };
    |     --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                           |
-   |                                           a raw memory access tried to access part of a pointer value as raw bytes
+   |                                           unable to turn pointer into raw bytes
 
 error: any use of this value will cause an error
   --> $DIR/const-pointer-values-in-various-types.rs:100:41
@@ -206,7 +206,7 @@ error: any use of this value will cause an error
 LL |     const STR_F32_UNION: f32 = unsafe { Nonsense { stringy: "3" }.float_32 };
    |     ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                         |
-   |                                         a raw memory access tried to access part of a pointer value as raw bytes
+   |                                         unable to turn pointer into raw bytes
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/const-pointer-values-in-various-types.rs:103:5
@@ -222,7 +222,7 @@ error: any use of this value will cause an error
 LL |     const STR_BOOL_UNION: bool = unsafe { Nonsense { stringy: "3" }.truthy_falsey };
    |     --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                           |
-   |                                           a raw memory access tried to access part of a pointer value as raw bytes
+   |                                           unable to turn pointer into raw bytes
 
 error: any use of this value will cause an error
   --> $DIR/const-pointer-values-in-various-types.rs:109:43
@@ -230,7 +230,7 @@ error: any use of this value will cause an error
 LL |     const STR_CHAR_UNION: char = unsafe { Nonsense { stringy: "3" }.character };
    |     --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                           |
-   |                                           a raw memory access tried to access part of a pointer value as raw bytes
+   |                                           unable to turn pointer into raw bytes
 
 error: aborting due to 29 previous errors
 
index 9afcdf77610f28caa45ed009c860118070aa45c6..6b86feb5921a1d04a64972ad763f07654d8c53aa 100644 (file)
@@ -17,8 +17,6 @@
 
 #[lang = "eh_personality"]
 fn eh() {}
-#[lang = "eh_unwind_resume"]
-fn eh_unwind_resume() {}
 
 #[panic_handler]
 fn panic(_info: &PanicInfo) -> ! {
index 48cfea82bd65e338ae84f81cccb16fa7cd20ce31..f9a36d37943f301c2538f4220a1b8f0c6f311352 100644 (file)
@@ -1,4 +1,4 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 pub trait Foo {
     fn foo(self) -> u32;
index 2cba833a74896ad1f128a5a1fa5f69b50ce47f54..cc40728e6b574afa577f8f59cead2455a48782ee 100644 (file)
@@ -30,7 +30,7 @@ error: any use of this value will cause an error
 LL | const Z2: i32 = unsafe { *(42 as *const i32) };
    | -------------------------^^^^^^^^^^^^^^^^^^^---
    |                          |
-   |                          a memory access tried to interpret some bytes as a pointer
+   |                          unable to turn bytes into a pointer
 
 error: any use of this value will cause an error
   --> $DIR/const_raw_ptr_ops.rs:17:26
@@ -38,7 +38,7 @@ error: any use of this value will cause an error
 LL | const Z3: i32 = unsafe { *(44 as *const i32) };
    | -------------------------^^^^^^^^^^^^^^^^^^^---
    |                          |
-   |                          a memory access tried to interpret some bytes as a pointer
+   |                          unable to turn bytes into a pointer
 
 error: aborting due to 5 previous errors
 
index d209e604486873a8b9a451f354fa58ef4c2ef119..c61239bb677e8841e9f4d10d9e7176644b240085 100644 (file)
@@ -1,4 +1,4 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 fn main() {
     const MIN: i8 = -5;
index b5d72d46f2861a5e95d42126edc93940a303f46d..c6b8e8eb611819a10c9af6cb0da142ca8a246158 100644 (file)
@@ -6,7 +6,7 @@
 const TEST: () = { unsafe { //~ NOTE
     let slice: *const [u8] = mem::transmute((1usize, usize::MAX));
     let _val = &*slice; //~ ERROR: any use of this value will cause an error
-    //~^ NOTE: total size is bigger than largest supported object
+    //~^ NOTE: slice is bigger than largest supported object
     //~^^ on by default
 } };
 
index 286de0800975473bc3799b7769926f511364ed90..b9ddc93b03b84e942dfc318b09c2d48b275743fd 100644 (file)
@@ -4,7 +4,7 @@ error: any use of this value will cause an error
 LL | / const TEST: () = { unsafe {
 LL | |     let slice: *const [u8] = mem::transmute((1usize, usize::MAX));
 LL | |     let _val = &*slice;
-   | |                ^^^^^^^ invalid slice: total size is bigger than largest supported object
+   | |                ^^^^^^^ invalid metadata in wide pointer: slice is bigger than largest supported object
 LL | |
 LL | |
 LL | | } };
index ff2fff7fb790eca482646e3e210c6d9dd31847a0..f156d259abb202bcf6b5e858e343e2d6cda882b5 100644 (file)
@@ -1,4 +1,4 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 enum Foo {
     A = 5,
index a9a3f071bf89fca25a13869cb7724cb8a22b5450..48f4426d9cff48671fe89dac60d0d78b359704f5 100644 (file)
@@ -1,4 +1,4 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 #![feature(const_fn, rustc_attrs)]
 
index 029d4e5e3732edc5865025b90fa536ecfffed2dd..87b12937dd4f230f282c3b8dbcedf29e879739af 100644 (file)
@@ -1,4 +1,4 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 use std::time::Duration;
 
index e2b3bc83c3f01ddff63579b7bec595ec2975dc35..f210d1a0a90c59acf3b3c9e5e829d3ad4a83347a 100644 (file)
@@ -1,4 +1,4 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 #![feature(extern_types)]
 
index ce0e11f29f44220616eb4e20307d5d80dca22f8e..4444cdfcda9c7ae27383ae140b6ef8a91cfaba85 100644 (file)
@@ -1,4 +1,4 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 pub trait Nullable {
     const NULL: Self;
index 250bf954e9ac2f3938601ff7becd92dc32c9984f..4758a5a9d561c2232809224347735dea563adef9 100644 (file)
@@ -1,4 +1,7 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// Regression test for #50356: Compiler panic when using repr(packed)
+// associated constant in a match arm
+
+// check-pass
 #[derive(Copy, Clone, PartialEq, Eq)]
 #[repr(packed)]
 pub struct Num(u64);
index 9de150bd0528d618174510ebba17d61ea734c0a7..b98e76031d4f300434acd1500144e6d5edae2fdb 100644 (file)
@@ -1,4 +1,4 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 struct S(pub &'static u32, pub u32);
 
index 48809e0ae649ca01f98c17ebe04022fc9c73dd9f..798f130a4baf6fb1bfa2c39afd888d2da3afcad3 100644 (file)
@@ -4,7 +4,7 @@ error: any use of this value will cause an error
 LL | const X: u64 = *wat(42);
    | ---------------^^^^^^^^-
    |                |
-   |                dangling pointer was dereferenced
+   |                pointer to alloc2 was dereferenced after this allocation got freed
    |
    = note: `#[deny(const_err)]` on by default
 
index bf69bc28da41a910112e1ebd35dc8a9e42057039..a13c27f2e780269c61a2a9993829c1a4740625d6 100644 (file)
@@ -1,4 +1,4 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 pub struct Stats;
 
index 4753bf0f7b174ecccdfa8c52e4edc2d662273756..8e68e8c911785bb0b99b2784d12fa0091d326e95 100644 (file)
@@ -1,4 +1,4 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 // https://github.com/rust-lang/rust/issues/51300
 
 #[derive(PartialEq, Eq, Clone, Copy)]
index ac0940b33e47a82444599687b289ae0099f19a18..850338625bc0136387fc88a282a8d3d9f69a37e9 100644 (file)
@@ -1,4 +1,4 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 macro_rules! m {
     () => {{
index d300e0b5125dae283885b48e66bb0d56938b952b..31c946c3cb7613a2dd07234a9080c88b4744ab5c 100644 (file)
@@ -1,4 +1,4 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 pub const STATIC_TRAIT: &dyn Test = &();
 
index d04570c67ff2ebcb75c2eaf1e76b4561b915bc1f..4c9e10d9cbe16503eb82481c2d74d57be036d538 100644 (file)
@@ -1,4 +1,4 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 // Test that we can handle newtypes wrapping extern types
 
index cea367528c975aa90370a636817b166eac3ac7d5..910ca3c4bcbb601ad768722c22ea1a9e7b5d1cbf 100644 (file)
@@ -1,4 +1,4 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 // if `X` were used instead of `x`, `X - 10` would result in a lint.
 // This file should never produce a lint, no matter how the const
index ca75d65a39a924160c0399e46afdaa7770493028..edda10e6e82e97535027f53d6dc36641189ff0f7 100644 (file)
@@ -1,4 +1,4 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 pub fn main() {
     let y: &'static mut [u8; 0] = &mut [];
index 4ff140fee7a71643f2548b2ca0c010624fb8793b..ad165d40a76f27b8e45ee6a88a12f70d24cb8676 100644 (file)
@@ -1,4 +1,4 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 #![warn(const_err)]
 
 #![crate_type = "lib"]
index 7f1586336e72192f74ca2091c3f0a4cb9e6921c8..078e4c896df80ec3e257d61d7f548e556770c81b 100644 (file)
@@ -1,4 +1,4 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 #![warn(const_err)]
 
 pub const Z: u32 = 0 - 1;
index 8a9f3fe974d918c30abe1c7246e730b59abce426..1a416dd460d684cc9ea8054aed9fa47f99cb00f5 100644 (file)
@@ -1,4 +1,4 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 const PARSE_BOOL: Option<&'static str> = None;
 static FOO: (Option<&str>, u32) = (PARSE_BOOL, 42);
index 47f89fccf7a817d5ddec729338607f46d33e1aec..e93a6887ba8f7c06fdb4cf415d342e4738aae6cb 100644 (file)
@@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/transmute-const.rs:5:1
    |
 LL | static FOO: bool = unsafe { mem::transmute(3u8) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3, but expected something less or equal to 1
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3, but expected a boolean
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
index 483285aa4e12342b8a2b2aa6e50956c211b1c4e6..1922d59891f1e1ea3ef2631eba97f97b598993cc 100644 (file)
@@ -1,34 +1,36 @@
+#![feature(const_transmute, never_type)]
 #![allow(const_err)] // make sure we cannot allow away the errors tested here
 
+use std::mem;
 
 #[repr(transparent)]
 #[derive(Copy, Clone)]
 struct Wrap<T>(T);
 
+#[derive(Copy, Clone)]
+enum Never {}
+
+// # simple enum with discriminant 0
+
 #[repr(usize)]
 #[derive(Copy, Clone)]
 enum Enum {
     A = 0,
 }
-#[repr(C)]
-union TransmuteEnum {
-    in1: &'static u8,
-    in2: usize,
-    out1: Enum,
-    out2: Wrap<Enum>,
-}
 
-const GOOD_ENUM: Enum = unsafe { TransmuteEnum { in2: 0 }.out1 };
+const GOOD_ENUM: Enum = unsafe { mem::transmute(0usize) };
 
-const BAD_ENUM: Enum = unsafe { TransmuteEnum { in2: 1 }.out1 };
+const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) };
 //~^ ERROR is undefined behavior
 
-const BAD_ENUM_PTR: Enum = unsafe { TransmuteEnum { in1: &1 }.out1 };
+const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) };
 //~^ ERROR is undefined behavior
 
-const BAD_ENUM_WRAPPED: Wrap<Enum> = unsafe { TransmuteEnum { in1: &1 }.out2 };
+const BAD_ENUM_WRAPPED: Wrap<Enum> = unsafe { mem::transmute(&1) };
 //~^ ERROR is undefined behavior
 
+// # simple enum with discriminant 2
+
 // (Potentially) invalid enum discriminant
 #[repr(usize)]
 #[derive(Copy, Clone)]
@@ -36,39 +38,58 @@ enum Enum2 {
     A = 2,
 }
 
-#[repr(C)]
-union TransmuteEnum2 {
-    in1: usize,
-    in2: &'static u8,
-    in3: (),
-    out1: Enum2,
-    out2: Wrap<Enum2>, // something wrapping the enum so that we test layout first, not enum
-    out3: Option<Enum2>,
-}
-const BAD_ENUM2: Enum2 = unsafe { TransmuteEnum2 { in1: 0 }.out1 };
+const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) };
 //~^ ERROR is undefined behavior
-const BAD_ENUM2_PTR: Enum2 = unsafe { TransmuteEnum2 { in2: &0 }.out1 };
+const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) };
 //~^ ERROR is undefined behavior
-const BAD_ENUM2_WRAPPED: Wrap<Enum2> = unsafe { TransmuteEnum2 { in2: &0 }.out2 };
+// something wrapping the enum so that we test layout first, not enum
+const BAD_ENUM2_WRAPPED: Wrap<Enum2> = unsafe { mem::transmute(&0) };
 //~^ ERROR is undefined behavior
 
 // Undef enum discriminant.
-const BAD_ENUM2_UNDEF : Enum2 = unsafe { TransmuteEnum2 { in3: () }.out1 };
+#[repr(C)]
+union MaybeUninit<T: Copy> {
+    uninit: (),
+    init: T,
+}
+const BAD_ENUM2_UNDEF : Enum2 = unsafe { MaybeUninit { uninit: () }.init };
 //~^ ERROR is undefined behavior
 
 // Pointer value in an enum with a niche that is not just 0.
-const BAD_ENUM2_OPTION_PTR: Option<Enum2> = unsafe { TransmuteEnum2 { in2: &0 }.out3 };
+const BAD_ENUM2_OPTION_PTR: Option<Enum2> = unsafe { mem::transmute(&0) };
 //~^ ERROR is undefined behavior
 
+// # valid discriminant for uninhabited variant
+
+// An enum with 3 variants of which some are uninhabited -- so the uninhabited variants *do*
+// have a discriminant.
+enum UninhDiscriminant {
+    A,
+    B(!),
+    C,
+    D(Never),
+}
+
+const GOOD_INHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(0u8) }; // variant A
+const GOOD_INHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(2u8) }; // variant C
+
+const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(1u8) };
+//~^ ERROR is undefined behavior
+const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8) };
+//~^ ERROR is undefined behavior
+
+// # other
+
 // Invalid enum field content (mostly to test printing of paths for enum tuple
 // variants and tuples).
-#[repr(C)]
-union TransmuteChar {
-    a: u32,
-    b: char,
-}
 // Need to create something which does not clash with enum layout optimizations.
-const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { TransmuteChar { a: !0 }.b }));
+const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute(!0u32) }));
+//~^ ERROR is undefined behavior
+
+// All variants are uninhabited but also have data.
+const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { mem::transmute(1u64) };
+//~^ ERROR is undefined behavior
+const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe { mem::transmute(1u64) };
 //~^ ERROR is undefined behavior
 
 fn main() {
index 8ebc9dbec8ab2d1f9c5e6c05ca68fbf8d8ca4147..10a3d2fa1ab9995efb1d879a7090fd6591a140c0 100644 (file)
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-enum.rs:23:1
    |
-LL | const BAD_ENUM: Enum = unsafe { TransmuteEnum { in2: 1 }.out1 };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 1, but expected a valid enum discriminant
+LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 1, but expected a valid enum discriminant
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-enum.rs:26:1
    |
-LL | const BAD_ENUM_PTR: Enum = unsafe { TransmuteEnum { in1: &1 }.out1 };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected a valid enum discriminant
+LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .<enum-tag>, but expected initialized plain (non-pointer) bytes
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-enum.rs:29:1
    |
-LL | const BAD_ENUM_WRAPPED: Wrap<Enum> = unsafe { TransmuteEnum { in1: &1 }.out2 };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected something that cannot possibly fail to be equal to 0
+LL | const BAD_ENUM_WRAPPED: Wrap<Enum> = unsafe { mem::transmute(&1) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .0.<enum-tag>, but expected initialized plain (non-pointer) bytes
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-enum.rs:48:1
+  --> $DIR/ub-enum.rs:41:1
    |
-LL | const BAD_ENUM2: Enum2 = unsafe { TransmuteEnum2 { in1: 0 }.out1 };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected a valid enum discriminant
+LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected a valid enum discriminant
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-enum.rs:50:1
+  --> $DIR/ub-enum.rs:43:1
    |
-LL | const BAD_ENUM2_PTR: Enum2 = unsafe { TransmuteEnum2 { in2: &0 }.out1 };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected a valid enum discriminant
+LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .<enum-tag>, but expected initialized plain (non-pointer) bytes
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-enum.rs:52:1
+  --> $DIR/ub-enum.rs:46:1
    |
-LL | const BAD_ENUM2_WRAPPED: Wrap<Enum2> = unsafe { TransmuteEnum2 { in2: &0 }.out2 };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected something that cannot possibly fail to be equal to 2
+LL | const BAD_ENUM2_WRAPPED: Wrap<Enum2> = unsafe { mem::transmute(&0) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .0.<enum-tag>, but expected initialized plain (non-pointer) bytes
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-enum.rs:56:1
+  --> $DIR/ub-enum.rs:55:1
    |
-LL | const BAD_ENUM2_UNDEF : Enum2 = unsafe { TransmuteEnum2 { in3: () }.out1 };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected a valid enum discriminant
+LL | const BAD_ENUM2_UNDEF : Enum2 = unsafe { MaybeUninit { uninit: () }.init };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes at .<enum-tag>, but expected initialized plain (non-pointer) bytes
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-enum.rs:60:1
+  --> $DIR/ub-enum.rs:59:1
    |
-LL | const BAD_ENUM2_OPTION_PTR: Option<Enum2> = unsafe { TransmuteEnum2 { in2: &0 }.out3 };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected a valid enum discriminant
+LL | const BAD_ENUM2_OPTION_PTR: Option<Enum2> = unsafe { mem::transmute(&0) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .<enum-tag>, but expected initialized plain (non-pointer) bytes
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-enum.rs:71:1
+  --> $DIR/ub-enum.rs:76:1
    |
-LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { TransmuteChar { a: !0 }.b }));
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 4294967295 at .<downcast-variant(Some)>.0.1, but expected something less or equal to 1114111
+LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(1u8) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of the never type `!` at .<enum-variant(B)>.0
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
-error: aborting due to 9 previous errors
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ub-enum.rs:78:1
+   |
+LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Never at .<enum-variant(D)>.0
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ub-enum.rs:86:1
+   |
+LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute(!0u32) }));
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 4294967295 at .<enum-variant(Some)>.0.1, but expected a valid unicode codepoint
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ub-enum.rs:90:1
+   |
+LL | const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { mem::transmute(1u64) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of the never type `!` at .<enum-variant(Err)>.0.1
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ub-enum.rs:92:1
+   |
+LL | const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe { mem::transmute(1u64) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Never at .<enum-variant(Err)>.0.1
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+
+error: aborting due to 13 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
index 8ce64ced7dff4c02b004fb6d8637e94d82e2086a..1f46b6c98ad2fad012095465feb98417bdf193f2 100644 (file)
 //~^ ERROR it is undefined behavior to use this value
 
 #[repr(C)]
-union Transmute {
+union MaybeUninit<T: Copy> {
     uninit: (),
-    out: NonZeroU8,
+    init: T,
 }
-const UNINIT: NonZeroU8 = unsafe { Transmute { uninit: () }.out };
+const UNINIT: NonZeroU8 = unsafe { MaybeUninit { uninit: () }.init };
 //~^ ERROR it is undefined behavior to use this value
 
 // Also test other uses of rustc_layout_scalar_valid_range_start
index 4d9d258f80890a23afa695528fc0a3fe5b72c34d..adad1b4f7fafe3006be2b5a38a7c446f0d20983d 100644 (file)
@@ -13,7 +13,7 @@ LL | / const OUT_OF_BOUNDS_PTR: NonNull<u8> = { unsafe {
 LL | |     let ptr: &[u8; 256] = mem::transmute(&0u8); // &0 gets promoted so it does not dangle
 LL | |     // Use address-of-element for pointer arithmetic. This could wrap around to NULL!
 LL | |     let out_of_bounds_ptr = &ptr[255];
-   | |                             ^^^^^^^^^ Memory access failed: pointer must be in-bounds at offset 256, but is outside bounds of allocation 8 which has size 1
+   | |                             ^^^^^^^^^ Memory access failed: pointer must be in-bounds at offset 256, but is outside bounds of alloc8 which has size 1
 LL | |     mem::transmute(out_of_bounds_ptr)
 LL | | } };
    | |____-
@@ -43,8 +43,8 @@ LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) };
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-nonnull.rs:32:1
    |
-LL | const UNINIT: NonZeroU8 = unsafe { Transmute { uninit: () }.out };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected something greater or equal to 1
+LL | const UNINIT: NonZeroU8 = unsafe { MaybeUninit { uninit: () }.init };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes at .0, but expected initialized plain (non-pointer) bytes
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
index 03ac12c8b1ac152f059e7e08b0199144ccb90e5e..562ec99111b69f56b13b4a6bc49bcc145aad5b7c 100644 (file)
@@ -6,11 +6,18 @@
 
 const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) };
 //~^ ERROR it is undefined behavior to use this value
-//~^^ type validation failed: encountered unaligned reference (required 2 byte alignment but found 1)
+//~^^ type validation failed: encountered an unaligned reference (required 2 byte alignment but found 1)
+
+const UNALIGNED_BOX: Box<u16> = unsafe { mem::transmute(&[0u8; 4]) };
+//~^ ERROR it is undefined behavior to use this value
+//~^^ type validation failed: encountered an unaligned box (required 2 byte alignment but found 1)
 
 const NULL: &u16 = unsafe { mem::transmute(0usize) };
 //~^ ERROR it is undefined behavior to use this value
 
+const NULL_BOX: Box<u16> = unsafe { mem::transmute(0usize) };
+//~^ ERROR it is undefined behavior to use this value
+
 // It is very important that we reject this: We do promote `&(4 * REF_AS_USIZE)`,
 // but that would fail to compile; so we ended up breaking user code that would
 // have worked fine had we not promoted.
 const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
 //~^ ERROR it is undefined behavior to use this value
 
+const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) };
+//~^ ERROR it is undefined behavior to use this value
+
 const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) };
 //~^ ERROR it is undefined behavior to use this value
 
+const USIZE_AS_BOX: Box<u8> = unsafe { mem::transmute(1337usize) };
+//~^ ERROR it is undefined behavior to use this value
+
 fn main() {}
index 01bde413c0d9cc18188833da85b51213084f6342..fb3df8ace4e153983717275357b378d87bd12a95 100644 (file)
@@ -2,20 +2,36 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-ref.rs:7:1
    |
 LL | const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered unaligned reference (required 2 byte alignment but found 1)
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered an unaligned reference (required 2 byte alignment but found 1)
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-ref.rs:11:1
    |
+LL | const UNALIGNED_BOX: Box<u16> = unsafe { mem::transmute(&[0u8; 4]) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered an unaligned box (required 2 byte alignment but found 1)
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ub-ref.rs:15:1
+   |
 LL | const NULL: &u16 = unsafe { mem::transmute(0usize) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a NULL reference
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ub-ref.rs:18:1
+   |
+LL | const NULL_BOX: Box<u16> = unsafe { mem::transmute(0usize) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a NULL box
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref.rs:17:1
+  --> $DIR/ub-ref.rs:24:1
    |
 LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes
@@ -23,7 +39,7 @@ LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) };
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref.rs:20:1
+  --> $DIR/ub-ref.rs:27:1
    |
 LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .<deref>, but expected plain (non-pointer) bytes
@@ -31,13 +47,29 @@ LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref.rs:23:1
+  --> $DIR/ub-ref.rs:30:1
+   |
+LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .<deref>, but expected plain (non-pointer) bytes
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ub-ref.rs:33:1
    |
 LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling reference (created from integer)
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (created from integer)
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ub-ref.rs:36:1
+   |
+LL | const USIZE_AS_BOX: Box<u8> = unsafe { mem::transmute(1337usize) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling box (created from integer)
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
-error: aborting due to 5 previous errors
+error: aborting due to 9 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
index d2745d71bdb2f74b693d1d8c0d6e617798057ac2..e7350ae271673778b5656a3815ecf5ab9f727a9b 100644 (file)
@@ -7,18 +7,18 @@
 enum Bar {}
 
 #[repr(C)]
-union TransmuteUnion<A: Clone + Copy, B: Clone + Copy> {
-    a: A,
-    b: B,
+union MaybeUninit<T: Copy> {
+    uninit: (),
+    init: T,
 }
 
-const BAD_BAD_BAD: Bar = unsafe { (TransmuteUnion::<(), Bar> { a: () }).b };
+const BAD_BAD_BAD: Bar = unsafe { MaybeUninit { uninit: () }.init };
 //~^ ERROR it is undefined behavior to use this value
 
 const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) };
 //~^ ERROR it is undefined behavior to use this value
 
-const BAD_BAD_ARRAY: [Bar; 1] = unsafe { (TransmuteUnion::<(), [Bar; 1]> { a: () }).b };
+const BAD_BAD_ARRAY: [Bar; 1] = unsafe { MaybeUninit { uninit: () }.init };
 //~^ ERROR it is undefined behavior to use this value
 
 fn main() {}
index 3877f3cab6d44b2f38a43a0014b8791a970a0577..8ce4279a8b7dd7db11c0cec64c62e24332a3e04e 100644 (file)
@@ -1,8 +1,8 @@
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-uninhabit.rs:15:1
    |
-LL | const BAD_BAD_BAD: Bar = unsafe { (TransmuteUnion::<(), Bar> { a: () }).b };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type
+LL | const BAD_BAD_BAD: Bar = unsafe { MaybeUninit { uninit: () }.init };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Bar
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
@@ -10,15 +10,15 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-uninhabit.rs:18:1
    |
 LL | const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type at .<deref>
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Bar at .<deref>
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-uninhabit.rs:21:1
    |
-LL | const BAD_BAD_ARRAY: [Bar; 1] = unsafe { (TransmuteUnion::<(), [Bar; 1]> { a: () }).b };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type
+LL | const BAD_BAD_ARRAY: [Bar; 1] = unsafe { MaybeUninit { uninit: () }.init };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Bar at [0]
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
index ea6ab3ae5b5baf5d9a3c9ddcffaa0de581d26a77..972c9eb38c81e1626197bd22856ad1ea17906c75 100644 (file)
@@ -6,7 +6,7 @@ LL | |     let bad_ref: &'static u16 = unsafe { mem::transmute(0usize) };
 LL | |     let another_var = 13;
 LL | |     move || { let _ = bad_ref; let _ = another_var; }
 LL | | };
-   | |__^ type validation failed: encountered 0 at .<deref>.<dyn-downcast>.<closure-var(bad_ref)>, but expected something greater or equal to 1
+   | |__^ type validation failed: encountered a NULL reference at .<deref>.<dyn-downcast>.<captured-var(bad_ref)>
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
index a5c2a57c6c886c051a0553d91be34ef570a24263..0200bfe9f08f870f1fbdf43431ec9d25b8f16408 100644 (file)
@@ -1,72 +1,18 @@
 // ignore-tidy-linelength
+#![feature(const_transmute)]
 #![allow(unused)]
 #![allow(const_err)] // make sure we cannot allow away the errors tested here
 
+use std::mem;
+
 // normalize-stderr-test "offset \d+" -> "offset N"
-// normalize-stderr-test "allocation \d+" -> "allocation N"
+// normalize-stderr-test "alloc\d+" -> "allocN"
 // normalize-stderr-test "size \d+" -> "size N"
 
 #[repr(C)]
-union BoolTransmute {
-  val: u8,
-  bl: bool,
-}
-
-#[repr(C)]
-#[derive(Copy, Clone)]
-struct SliceRepr {
-    ptr: *const u8,
-    len: usize,
-}
-
-#[repr(C)]
-#[derive(Copy, Clone)]
-struct BadSliceRepr {
-    ptr: *const u8,
-    len: &'static u8,
-}
-
-#[repr(C)]
-union SliceTransmute {
-    repr: SliceRepr,
-    bad: BadSliceRepr,
-    addr: usize,
-    slice: &'static [u8],
-    raw_slice: *const [u8],
-    str: &'static str,
-    my_str: &'static MyStr,
-    my_slice: &'static MySliceBool,
-}
-
-#[repr(C)]
-#[derive(Copy, Clone)]
-struct DynRepr {
-    ptr: *const u8,
-    vtable: *const u8,
-}
-
-#[repr(C)]
-#[derive(Copy, Clone)]
-struct DynRepr2 {
-    ptr: *const u8,
-    vtable: *const u64,
-}
-
-#[repr(C)]
-#[derive(Copy, Clone)]
-struct BadDynRepr {
-    ptr: *const u8,
-    vtable: usize,
-}
-
-#[repr(C)]
-union DynTransmute {
-    repr: DynRepr,
-    repr2: DynRepr2,
-    bad: BadDynRepr,
-    addr: usize,
-    rust: &'static dyn Trait,
-    raw_rust: *const dyn Trait,
+union MaybeUninit<T: Copy> {
+    uninit: (),
+    init: T,
 }
 
 trait Trait {}
@@ -81,90 +27,103 @@ impl Trait for bool {}
 
 // # str
 // OK
-const STR_VALID: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 1 } }.str};
+const STR_VALID: &str = unsafe { mem::transmute((&42u8, 1usize)) };
 // bad str
-const STR_TOO_LONG: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.str};
+const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) };
+//~^ ERROR it is undefined behavior to use this value
+const NESTED_STR_MUCH_TOO_LONG: (&str,) = (unsafe { mem::transmute((&42, usize::MAX)) },);
 //~^ ERROR it is undefined behavior to use this value
 // bad str
-const STR_LENGTH_PTR: &str = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.str};
+const STR_LENGTH_PTR: &str = unsafe { mem::transmute((&42u8, &3)) };
 //~^ ERROR it is undefined behavior to use this value
 // bad str in user-defined unsized type
-const MY_STR_LENGTH_PTR: &MyStr = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.my_str};
+const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) };
+//~^ ERROR it is undefined behavior to use this value
+const MY_STR_MUCH_TOO_LONG: &MyStr = unsafe { mem::transmute((&42u8, usize::MAX)) };
 //~^ ERROR it is undefined behavior to use this value
 
 // invalid UTF-8
-const STR_NO_UTF8: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str };
+const STR_NO_UTF8: &str = unsafe { mem::transmute::<&[u8], _>(&[0xFF]) };
 //~^ ERROR it is undefined behavior to use this value
 // invalid UTF-8 in user-defined str-like
-const MYSTR_NO_UTF8: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my_str };
+const MYSTR_NO_UTF8: &MyStr = unsafe { mem::transmute::<&[u8], _>(&[0xFF]) };
 //~^ ERROR it is undefined behavior to use this value
 
 // # slice
 // OK
-const SLICE_VALID: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 1 } }.slice};
+const SLICE_VALID: &[u8] = unsafe { mem::transmute((&42u8, 1usize)) };
 // bad slice: length uninit
-const SLICE_LENGTH_UNINIT: &[u8] = unsafe { SliceTransmute { addr: 42 }.slice};
+const SLICE_LENGTH_UNINIT: &[u8] = unsafe {
 //~^ ERROR it is undefined behavior to use this value
+    let uninit_len = MaybeUninit::<usize> { uninit: () };
+    mem::transmute((42, uninit_len))
+};
 // bad slice: length too big
-const SLICE_TOO_LONG: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.slice};
+const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) };
 //~^ ERROR it is undefined behavior to use this value
 // bad slice: length not an int
-const SLICE_LENGTH_PTR: &[u8] = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.slice};
+const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) };
+//~^ ERROR it is undefined behavior to use this value
+// bad slice box: length too big
+const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999usize)) };
+//~^ ERROR it is undefined behavior to use this value
+// bad slice box: length not an int
+const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3)) };
 //~^ ERROR it is undefined behavior to use this value
 
 // bad data *inside* the slice
-const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { BoolTransmute { val: 3 }.bl }];
+const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
 //~^ ERROR it is undefined behavior to use this value
 
 // good MySliceBool
 const MYSLICE_GOOD: &MySliceBool = &MySlice(true, [false]);
 // bad: sized field is not okay
-const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { BoolTransmute { val: 3 }.bl }, [false]);
+const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]);
 //~^ ERROR it is undefined behavior to use this value
 // bad: unsized part is not okay
-const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { BoolTransmute { val: 3 }.bl }]);
+const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]);
 //~^ ERROR it is undefined behavior to use this value
 
 // # raw slice
-const RAW_SLICE_VALID: *const [u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 1 } }.raw_slice}; // ok
-const RAW_SLICE_TOO_LONG: *const [u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.raw_slice}; // ok because raw
-const RAW_SLICE_MUCH_TOO_LONG: *const [u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: usize::max_value() } }.raw_slice}; // ok because raw
-const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { SliceTransmute { addr: 42 }.raw_slice};
+const RAW_SLICE_VALID: *const [u8] = unsafe { mem::transmute((&42u8, 1usize)) }; // ok
+const RAW_SLICE_TOO_LONG: *const [u8] = unsafe { mem::transmute((&42u8, 999usize)) }; // ok because raw
+const RAW_SLICE_MUCH_TOO_LONG: *const [u8] = unsafe { mem::transmute((&42u8, usize::MAX)) }; // ok because raw
+const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe {
 //~^ ERROR it is undefined behavior to use this value
+    let uninit_len = MaybeUninit::<usize> { uninit: () };
+    mem::transmute((42, uninit_len))
+};
 
 // # trait object
 // bad trait object
-const TRAIT_OBJ_SHORT_VTABLE_1: &dyn Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust};
+const TRAIT_OBJ_SHORT_VTABLE_1: &dyn Trait = unsafe { mem::transmute((&92u8, &3u8)) };
 //~^ ERROR it is undefined behavior to use this value
 // bad trait object
-const TRAIT_OBJ_SHORT_VTABLE_2: &dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust};
+const TRAIT_OBJ_SHORT_VTABLE_2: &dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) };
 //~^ ERROR it is undefined behavior to use this value
 // bad trait object
-const TRAIT_OBJ_INT_VTABLE: &dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust};
+const TRAIT_OBJ_INT_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, 4usize)) };
 //~^ ERROR it is undefined behavior to use this value
 
 // bad data *inside* the trait object
-const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl };
+const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) };
 //~^ ERROR it is undefined behavior to use this value
 
 // # raw trait object
-const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.raw_rust};
+const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) };
 //~^ ERROR it is undefined behavior to use this value
-const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.raw_rust};
+const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) };
 //~^ ERROR it is undefined behavior to use this value
-const RAW_TRAIT_OBJ_CONTENT_INVALID: *const dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl } as *const _; // ok because raw
+const RAW_TRAIT_OBJ_CONTENT_INVALID: *const dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) } as *const dyn Trait; // ok because raw
 
 // Const eval fails for these, so they need to be statics to error.
 static mut RAW_TRAIT_OBJ_VTABLE_NULL_THROUGH_REF: *const dyn Trait = unsafe {
-    DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.rust
+    mem::transmute::<_, &dyn Trait>((&92u8, 0usize))
     //~^ ERROR could not evaluate static initializer
 };
 static mut RAW_TRAIT_OBJ_VTABLE_INVALID_THROUGH_REF: *const dyn Trait = unsafe {
-    DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust
+    mem::transmute::<_, &dyn Trait>((&92u8, &3u64))
     //~^ ERROR could not evaluate static initializer
 };
 
-fn main() {
-    let _ = RAW_TRAIT_OBJ_VTABLE_NULL;
-    let _ = RAW_TRAIT_OBJ_VTABLE_INVALID;
-}
+fn main() {}
index ce57d680dc95d6ece189594614af354e04b823f7..80e60dbb58a5d6adf5f74cc191158f2a3b218c36 100644 (file)
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:86:1
+  --> $DIR/ub-wide-ptr.rs:32:1
    |
-LL | const STR_TOO_LONG: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.str};
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling reference (not entirely in bounds)
+LL | const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (going beyond the bounds of its allocation)
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:89:1
+  --> $DIR/ub-wide-ptr.rs:34:1
    |
-LL | const STR_LENGTH_PTR: &str = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.str};
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer
+LL | const NESTED_STR_MUCH_TOO_LONG: (&str,) = (unsafe { mem::transmute((&42, usize::MAX)) },);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid reference metadata: slice is bigger than largest supported object at .0
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:92:1
+  --> $DIR/ub-wide-ptr.rs:37:1
    |
-LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.my_str};
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer
+LL | const STR_LENGTH_PTR: &str = unsafe { mem::transmute((&42u8, &3)) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:96:1
+  --> $DIR/ub-wide-ptr.rs:40:1
    |
-LL | const STR_NO_UTF8: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at .<deref>
+LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:99:1
+  --> $DIR/ub-wide-ptr.rs:42:1
    |
-LL | const MYSTR_NO_UTF8: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my_str };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at .<deref>.0
+LL | const MY_STR_MUCH_TOO_LONG: &MyStr = unsafe { mem::transmute((&42u8, usize::MAX)) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid reference metadata: slice is bigger than largest supported object
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:106:1
+  --> $DIR/ub-wide-ptr.rs:46:1
    |
-LL | const SLICE_LENGTH_UNINIT: &[u8] = unsafe { SliceTransmute { addr: 42 }.slice};
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered undefined pointer
+LL | const STR_NO_UTF8: &str = unsafe { mem::transmute::<&[u8], _>(&[0xFF]) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at .<deref>
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:109:1
+  --> $DIR/ub-wide-ptr.rs:49:1
+   |
+LL | const MYSTR_NO_UTF8: &MyStr = unsafe { mem::transmute::<&[u8], _>(&[0xFF]) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at .<deref>.0
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ub-wide-ptr.rs:56:1
+   |
+LL | / const SLICE_LENGTH_UNINIT: &[u8] = unsafe {
+LL | |
+LL | |     let uninit_len = MaybeUninit::<usize> { uninit: () };
+LL | |     mem::transmute((42, uninit_len))
+LL | | };
+   | |__^ type validation failed: encountered undefined pointer
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ub-wide-ptr.rs:62:1
    |
-LL | const SLICE_TOO_LONG: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.slice};
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling reference (not entirely in bounds)
+LL | const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (going beyond the bounds of its allocation)
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:112:1
+  --> $DIR/ub-wide-ptr.rs:65:1
    |
-LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.slice};
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer
+LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:116:1
+  --> $DIR/ub-wide-ptr.rs:68:1
    |
-LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { BoolTransmute { val: 3 }.bl }];
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>[0], but expected something less or equal to 1
+LL | const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999usize)) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling box (going beyond the bounds of its allocation)
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:122:1
+  --> $DIR/ub-wide-ptr.rs:71:1
    |
-LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { BoolTransmute { val: 3 }.bl }, [false]);
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>.0, but expected something less or equal to 1
+LL | const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3)) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:125:1
+  --> $DIR/ub-wide-ptr.rs:75:1
    |
-LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { BoolTransmute { val: 3 }.bl }]);
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>.1[0], but expected something less or equal to 1
+LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>[0], but expected a boolean
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:132:1
+  --> $DIR/ub-wide-ptr.rs:81:1
    |
-LL | const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { SliceTransmute { addr: 42 }.raw_slice};
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered undefined pointer
+LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>.0, but expected a boolean
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:137:1
+  --> $DIR/ub-wide-ptr.rs:84:1
    |
-LL | const TRAIT_OBJ_SHORT_VTABLE_1: &dyn Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust};
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable
+LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>.1[0], but expected a boolean
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:140:1
+  --> $DIR/ub-wide-ptr.rs:91:1
    |
-LL | const TRAIT_OBJ_SHORT_VTABLE_2: &dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust};
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable
+LL | / const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe {
+LL | |
+LL | |     let uninit_len = MaybeUninit::<usize> { uninit: () };
+LL | |     mem::transmute((42, uninit_len))
+LL | | };
+   | |__^ type validation failed: encountered undefined pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:143:1
+  --> $DIR/ub-wide-ptr.rs:99:1
+   |
+LL | const TRAIT_OBJ_SHORT_VTABLE_1: &dyn Trait = unsafe { mem::transmute((&92u8, &3u8)) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ub-wide-ptr.rs:102:1
    |
-LL | const TRAIT_OBJ_INT_VTABLE: &dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust};
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable
+LL | const TRAIT_OBJ_SHORT_VTABLE_2: &dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:147:1
+  --> $DIR/ub-wide-ptr.rs:105:1
+   |
+LL | const TRAIT_OBJ_INT_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, 4usize)) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ub-wide-ptr.rs:109:1
    |
-LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>.<dyn-downcast>, but expected something less or equal to 1
+LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>.<dyn-downcast>, but expected a boolean
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:151:1
+  --> $DIR/ub-wide-ptr.rs:113:1
    |
-LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.raw_rust};
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable
+LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:153:1
+  --> $DIR/ub-wide-ptr.rs:115:1
    |
-LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.raw_rust};
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable
+LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: could not evaluate static initializer
-  --> $DIR/ub-wide-ptr.rs:159:5
+  --> $DIR/ub-wide-ptr.rs:121:5
    |
-LL |     DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.rust
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid use of NULL pointer
+LL |     mem::transmute::<_, &dyn Trait>((&92u8, 0usize))
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid use of NULL pointer
 
 error[E0080]: could not evaluate static initializer
-  --> $DIR/ub-wide-ptr.rs:163:5
+  --> $DIR/ub-wide-ptr.rs:125:5
    |
-LL |     DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Memory access failed: pointer must be in-bounds at offset N, but is outside bounds of allocation N which has size N
+LL |     mem::transmute::<_, &dyn Trait>((&92u8, &3u64))
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Memory access failed: pointer must be in-bounds at offset N, but is outside bounds of allocN which has size N
 
-error: aborting due to 20 previous errors
+error: aborting due to 24 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
index fa67bc0d8e7b55ddc9f97941268d27f331be41c0..9d90d6e8548d886ead73763fca4ebfed9887c684 100644 (file)
@@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/union-ub.rs:31:1
    |
 LL | const BAD_BOOL: bool = unsafe { DummyUnion { u8: 42 }.bool};
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 42, but expected something less or equal to 1
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 42, but expected a boolean
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
index c98e206e88c240c8c7a45106274200cb6856eb71..cede356a6b8a190ba48585677ee7b83174b45575 100644 (file)
@@ -4,7 +4,7 @@ warning: any use of this value will cause an error
 LL |     unsafe { std::mem::transmute(()) }
    |              ^^^^^^^^^^^^^^^^^^^^^^^
    |              |
-   |              entering unreachable code
+   |              transmuting to uninhabited type
    |              inside call to `foo` at $DIR/validate_uninhabited_zsts.rs:14:26
 ...
 LL | const FOO: [Empty; 3] = [foo(); 3];
@@ -20,7 +20,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/validate_uninhabited_zsts.rs:17:1
    |
 LL | const BAR: [Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Empty at [0]
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
index 7edb6bd03dabf2f3ca3f882a35d7cb15ba075035..5f7ddf7f758e0b50eae396d63f2a4faa37e7eec7 100644 (file)
@@ -1,4 +1,4 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 static ASSERT: () = [()][!(std::mem::size_of::<u32>() == 4) as usize];
 
index 75dac812f1e3a749e1ecb7786965fc9be1633742..99bbeaafda5c47f51b3563da6b74f84033649d56 100644 (file)
@@ -8,7 +8,7 @@
 const fn add(x: i8, y: i8) -> i8 { x+y }
 const fn sub(x: i8, y: i8) -> i8 { x-y }
 const fn mul(x: i8, y: i8) -> i8 { x*y }
-// div and rem are always checked, so we cannot test their result in case of oveflow.
+// div and rem are always checked, so we cannot test their result in case of overflow.
 const fn neg(x: i8) -> i8 { -x }
 
 fn main() {
index d52dbbae1e7b5359e9ae8895131e45fcaac43a39..6484169dd9ae12e4e6ef7013741105c595770d53 100644 (file)
@@ -1,7 +1,5 @@
 // run-pass
 
-#![feature(const_int_conversion)]
-
 const REVERSE: u32 = 0x12345678_u32.reverse_bits();
 const FROM_BE_BYTES: i32 = i32::from_be_bytes([0x12, 0x34, 0x56, 0x78]);
 const FROM_LE_BYTES: i32 = i32::from_le_bytes([0x12, 0x34, 0x56, 0x78]);
index bf31e0b0732d8be34880cb26b0e17b4faccaa862..cf70454b6bf9eb28399144cf5fa761b4f4d9c135 100644 (file)
@@ -4,7 +4,7 @@ error: any use of this value will cause an error
 LL | const SHL_U8: u8 = unsafe { intrinsics::unchecked_shl(5_u8, 8) };
    | ----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                             |
-   |                             Overflowing shift by 8 in `unchecked_shl`
+   |                             overflowing shift by 8 in `unchecked_shl`
    |
    = note: `#[deny(const_err)]` on by default
 
@@ -14,7 +14,7 @@ error: any use of this value will cause an error
 LL | const SHL_U16: u16 = unsafe { intrinsics::unchecked_shl(5_u16, 16) };
    | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                               |
-   |                               Overflowing shift by 16 in `unchecked_shl`
+   |                               overflowing shift by 16 in `unchecked_shl`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:19:31
@@ -22,7 +22,7 @@ error: any use of this value will cause an error
 LL | const SHL_U32: u32 = unsafe { intrinsics::unchecked_shl(5_u32, 32) };
    | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                               |
-   |                               Overflowing shift by 32 in `unchecked_shl`
+   |                               overflowing shift by 32 in `unchecked_shl`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:21:31
@@ -30,7 +30,7 @@ error: any use of this value will cause an error
 LL | const SHL_U64: u64 = unsafe { intrinsics::unchecked_shl(5_u64, 64) };
    | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                               |
-   |                               Overflowing shift by 64 in `unchecked_shl`
+   |                               overflowing shift by 64 in `unchecked_shl`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:23:33
@@ -38,7 +38,7 @@ error: any use of this value will cause an error
 LL | const SHL_U128: u128 = unsafe { intrinsics::unchecked_shl(5_u128, 128) };
    | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                 |
-   |                                 Overflowing shift by 128 in `unchecked_shl`
+   |                                 overflowing shift by 128 in `unchecked_shl`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:28:29
@@ -46,7 +46,7 @@ error: any use of this value will cause an error
 LL | const SHL_I8: i8 = unsafe { intrinsics::unchecked_shl(5_i8, 8) };
    | ----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                             |
-   |                             Overflowing shift by 8 in `unchecked_shl`
+   |                             overflowing shift by 8 in `unchecked_shl`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:30:31
@@ -54,7 +54,7 @@ error: any use of this value will cause an error
 LL | const SHL_I16: i16 = unsafe { intrinsics::unchecked_shl(5_16, 16) };
    | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                               |
-   |                               Overflowing shift by 16 in `unchecked_shl`
+   |                               overflowing shift by 16 in `unchecked_shl`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:32:31
@@ -62,7 +62,7 @@ error: any use of this value will cause an error
 LL | const SHL_I32: i32 = unsafe { intrinsics::unchecked_shl(5_i32, 32) };
    | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                               |
-   |                               Overflowing shift by 32 in `unchecked_shl`
+   |                               overflowing shift by 32 in `unchecked_shl`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:34:31
@@ -70,7 +70,7 @@ error: any use of this value will cause an error
 LL | const SHL_I64: i64 = unsafe { intrinsics::unchecked_shl(5_i64, 64) };
    | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                               |
-   |                               Overflowing shift by 64 in `unchecked_shl`
+   |                               overflowing shift by 64 in `unchecked_shl`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:36:33
@@ -78,7 +78,7 @@ error: any use of this value will cause an error
 LL | const SHL_I128: i128 = unsafe { intrinsics::unchecked_shl(5_i128, 128) };
    | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                 |
-   |                                 Overflowing shift by 128 in `unchecked_shl`
+   |                                 overflowing shift by 128 in `unchecked_shl`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:41:33
@@ -86,7 +86,7 @@ error: any use of this value will cause an error
 LL | const SHL_I8_NEG: i8 = unsafe { intrinsics::unchecked_shl(5_i8, -1) };
    | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                 |
-   |                                 Overflowing shift by 255 in `unchecked_shl`
+   |                                 overflowing shift by 255 in `unchecked_shl`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:43:35
@@ -94,7 +94,7 @@ error: any use of this value will cause an error
 LL | const SHL_I16_NEG: i16 = unsafe { intrinsics::unchecked_shl(5_16, -1) };
    | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                   |
-   |                                   Overflowing shift by 65535 in `unchecked_shl`
+   |                                   overflowing shift by 65535 in `unchecked_shl`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:45:35
@@ -102,7 +102,7 @@ error: any use of this value will cause an error
 LL | const SHL_I32_NEG: i32 = unsafe { intrinsics::unchecked_shl(5_i32, -1) };
    | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                   |
-   |                                   Overflowing shift by 4294967295 in `unchecked_shl`
+   |                                   overflowing shift by 4294967295 in `unchecked_shl`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:47:35
@@ -110,7 +110,7 @@ error: any use of this value will cause an error
 LL | const SHL_I64_NEG: i64 = unsafe { intrinsics::unchecked_shl(5_i64, -1) };
    | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                   |
-   |                                   Overflowing shift by 18446744073709551615 in `unchecked_shl`
+   |                                   overflowing shift by 18446744073709551615 in `unchecked_shl`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:49:37
@@ -118,7 +118,7 @@ error: any use of this value will cause an error
 LL | const SHL_I128_NEG: i128 = unsafe { intrinsics::unchecked_shl(5_i128, -1) };
    | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                     |
-   |                                     Overflowing shift by 340282366920938463463374607431768211455 in `unchecked_shl`
+   |                                     overflowing shift by 340282366920938463463374607431768211455 in `unchecked_shl`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:55:40
@@ -126,7 +126,7 @@ error: any use of this value will cause an error
 LL | const SHL_I8_NEG_RANDOM: i8 = unsafe { intrinsics::unchecked_shl(5_i8, -6) };
    | ---------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                        |
-   |                                        Overflowing shift by 250 in `unchecked_shl`
+   |                                        overflowing shift by 250 in `unchecked_shl`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:57:42
@@ -134,7 +134,7 @@ error: any use of this value will cause an error
 LL | const SHL_I16_NEG_RANDOM: i16 = unsafe { intrinsics::unchecked_shl(5_16, -13) };
    | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                          |
-   |                                          Overflowing shift by 65523 in `unchecked_shl`
+   |                                          overflowing shift by 65523 in `unchecked_shl`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:59:42
@@ -142,7 +142,7 @@ error: any use of this value will cause an error
 LL | const SHL_I32_NEG_RANDOM: i32 = unsafe { intrinsics::unchecked_shl(5_i32, -25) };
    | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                          |
-   |                                          Overflowing shift by 4294967271 in `unchecked_shl`
+   |                                          overflowing shift by 4294967271 in `unchecked_shl`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:61:42
@@ -150,7 +150,7 @@ error: any use of this value will cause an error
 LL | const SHL_I64_NEG_RANDOM: i64 = unsafe { intrinsics::unchecked_shl(5_i64, -30) };
    | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                          |
-   |                                          Overflowing shift by 18446744073709551586 in `unchecked_shl`
+   |                                          overflowing shift by 18446744073709551586 in `unchecked_shl`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:63:44
@@ -158,7 +158,7 @@ error: any use of this value will cause an error
 LL | const SHL_I128_NEG_RANDOM: i128 = unsafe { intrinsics::unchecked_shl(5_i128, -93) };
    | -------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                            |
-   |                                            Overflowing shift by 340282366920938463463374607431768211363 in `unchecked_shl`
+   |                                            overflowing shift by 340282366920938463463374607431768211363 in `unchecked_shl`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:70:29
@@ -166,7 +166,7 @@ error: any use of this value will cause an error
 LL | const SHR_U8: u8 = unsafe { intrinsics::unchecked_shr(5_u8, 8) };
    | ----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                             |
-   |                             Overflowing shift by 8 in `unchecked_shr`
+   |                             overflowing shift by 8 in `unchecked_shr`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:72:31
@@ -174,7 +174,7 @@ error: any use of this value will cause an error
 LL | const SHR_U16: u16 = unsafe { intrinsics::unchecked_shr(5_u16, 16) };
    | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                               |
-   |                               Overflowing shift by 16 in `unchecked_shr`
+   |                               overflowing shift by 16 in `unchecked_shr`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:74:31
@@ -182,7 +182,7 @@ error: any use of this value will cause an error
 LL | const SHR_U32: u32 = unsafe { intrinsics::unchecked_shr(5_u32, 32) };
    | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                               |
-   |                               Overflowing shift by 32 in `unchecked_shr`
+   |                               overflowing shift by 32 in `unchecked_shr`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:76:31
@@ -190,7 +190,7 @@ error: any use of this value will cause an error
 LL | const SHR_U64: u64 = unsafe { intrinsics::unchecked_shr(5_u64, 64) };
    | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                               |
-   |                               Overflowing shift by 64 in `unchecked_shr`
+   |                               overflowing shift by 64 in `unchecked_shr`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:78:33
@@ -198,7 +198,7 @@ error: any use of this value will cause an error
 LL | const SHR_U128: u128 = unsafe { intrinsics::unchecked_shr(5_u128, 128) };
    | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                 |
-   |                                 Overflowing shift by 128 in `unchecked_shr`
+   |                                 overflowing shift by 128 in `unchecked_shr`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:83:29
@@ -206,7 +206,7 @@ error: any use of this value will cause an error
 LL | const SHR_I8: i8 = unsafe { intrinsics::unchecked_shr(5_i8, 8) };
    | ----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                             |
-   |                             Overflowing shift by 8 in `unchecked_shr`
+   |                             overflowing shift by 8 in `unchecked_shr`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:85:31
@@ -214,7 +214,7 @@ error: any use of this value will cause an error
 LL | const SHR_I16: i16 = unsafe { intrinsics::unchecked_shr(5_16, 16) };
    | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                               |
-   |                               Overflowing shift by 16 in `unchecked_shr`
+   |                               overflowing shift by 16 in `unchecked_shr`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:87:31
@@ -222,7 +222,7 @@ error: any use of this value will cause an error
 LL | const SHR_I32: i32 = unsafe { intrinsics::unchecked_shr(5_i32, 32) };
    | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                               |
-   |                               Overflowing shift by 32 in `unchecked_shr`
+   |                               overflowing shift by 32 in `unchecked_shr`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:89:31
@@ -230,7 +230,7 @@ error: any use of this value will cause an error
 LL | const SHR_I64: i64 = unsafe { intrinsics::unchecked_shr(5_i64, 64) };
    | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                               |
-   |                               Overflowing shift by 64 in `unchecked_shr`
+   |                               overflowing shift by 64 in `unchecked_shr`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:91:33
@@ -238,7 +238,7 @@ error: any use of this value will cause an error
 LL | const SHR_I128: i128 = unsafe { intrinsics::unchecked_shr(5_i128, 128) };
    | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                 |
-   |                                 Overflowing shift by 128 in `unchecked_shr`
+   |                                 overflowing shift by 128 in `unchecked_shr`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:96:33
@@ -246,7 +246,7 @@ error: any use of this value will cause an error
 LL | const SHR_I8_NEG: i8 = unsafe { intrinsics::unchecked_shr(5_i8, -1) };
    | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                 |
-   |                                 Overflowing shift by 255 in `unchecked_shr`
+   |                                 overflowing shift by 255 in `unchecked_shr`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:98:35
@@ -254,7 +254,7 @@ error: any use of this value will cause an error
 LL | const SHR_I16_NEG: i16 = unsafe { intrinsics::unchecked_shr(5_16, -1) };
    | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                   |
-   |                                   Overflowing shift by 65535 in `unchecked_shr`
+   |                                   overflowing shift by 65535 in `unchecked_shr`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:100:35
@@ -262,7 +262,7 @@ error: any use of this value will cause an error
 LL | const SHR_I32_NEG: i32 = unsafe { intrinsics::unchecked_shr(5_i32, -1) };
    | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                   |
-   |                                   Overflowing shift by 4294967295 in `unchecked_shr`
+   |                                   overflowing shift by 4294967295 in `unchecked_shr`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:102:35
@@ -270,7 +270,7 @@ error: any use of this value will cause an error
 LL | const SHR_I64_NEG: i64 = unsafe { intrinsics::unchecked_shr(5_i64, -1) };
    | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                   |
-   |                                   Overflowing shift by 18446744073709551615 in `unchecked_shr`
+   |                                   overflowing shift by 18446744073709551615 in `unchecked_shr`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:104:37
@@ -278,7 +278,7 @@ error: any use of this value will cause an error
 LL | const SHR_I128_NEG: i128 = unsafe { intrinsics::unchecked_shr(5_i128, -1) };
    | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                     |
-   |                                     Overflowing shift by 340282366920938463463374607431768211455 in `unchecked_shr`
+   |                                     overflowing shift by 340282366920938463463374607431768211455 in `unchecked_shr`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:110:40
@@ -286,7 +286,7 @@ error: any use of this value will cause an error
 LL | const SHR_I8_NEG_RANDOM: i8 = unsafe { intrinsics::unchecked_shr(5_i8, -6) };
    | ---------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                        |
-   |                                        Overflowing shift by 250 in `unchecked_shr`
+   |                                        overflowing shift by 250 in `unchecked_shr`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:112:42
@@ -294,7 +294,7 @@ error: any use of this value will cause an error
 LL | const SHR_I16_NEG_RANDOM: i16 = unsafe { intrinsics::unchecked_shr(5_16, -13) };
    | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                          |
-   |                                          Overflowing shift by 65523 in `unchecked_shr`
+   |                                          overflowing shift by 65523 in `unchecked_shr`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:114:42
@@ -302,7 +302,7 @@ error: any use of this value will cause an error
 LL | const SHR_I32_NEG_RANDOM: i32 = unsafe { intrinsics::unchecked_shr(5_i32, -25) };
    | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                          |
-   |                                          Overflowing shift by 4294967271 in `unchecked_shr`
+   |                                          overflowing shift by 4294967271 in `unchecked_shr`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:116:42
@@ -310,7 +310,7 @@ error: any use of this value will cause an error
 LL | const SHR_I64_NEG_RANDOM: i64 = unsafe { intrinsics::unchecked_shr(5_i64, -30) };
    | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                          |
-   |                                          Overflowing shift by 18446744073709551586 in `unchecked_shr`
+   |                                          overflowing shift by 18446744073709551586 in `unchecked_shr`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:118:44
@@ -318,7 +318,7 @@ error: any use of this value will cause an error
 LL | const SHR_I128_NEG_RANDOM: i128 = unsafe { intrinsics::unchecked_shr(5_i128, -93) };
    | -------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                            |
-   |                                            Overflowing shift by 340282366920938463463374607431768211363 in `unchecked_shr`
+   |                                            overflowing shift by 340282366920938463463374607431768211363 in `unchecked_shr`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:123:25
@@ -326,7 +326,7 @@ error: any use of this value will cause an error
 LL | const _: u16 = unsafe { std::intrinsics::unchecked_add(40000u16, 30000) };
    | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                         |
-   |                         Overflow executing `unchecked_add`
+   |                         overflow executing `unchecked_add`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:126:25
@@ -334,7 +334,7 @@ error: any use of this value will cause an error
 LL | const _: u32 = unsafe { std::intrinsics::unchecked_sub(14u32, 22) };
    | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                         |
-   |                         Overflow executing `unchecked_sub`
+   |                         overflow executing `unchecked_sub`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:129:25
@@ -342,7 +342,7 @@ error: any use of this value will cause an error
 LL | const _: u16 = unsafe { std::intrinsics::unchecked_mul(300u16, 250u16) };
    | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                         |
-   |                         Overflow executing `unchecked_mul`
+   |                         overflow executing `unchecked_mul`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:132:25
@@ -358,7 +358,7 @@ error: any use of this value will cause an error
 LL | const _: i32 = unsafe { std::intrinsics::unchecked_div(i32::min_value(), -1) };
    | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                         |
-   |                         Overflow executing `unchecked_div`
+   |                         overflow executing `unchecked_div`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:137:25
@@ -374,7 +374,7 @@ error: any use of this value will cause an error
 LL | const _: i32 = unsafe { std::intrinsics::unchecked_rem(i32::min_value(), -1) };
    | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                         |
-   |                         Overflow executing `unchecked_rem`
+   |                         overflow executing `unchecked_rem`
 
 error: aborting due to 47 previous errors
 
index 8949358e2933338ed8797a7ef6caf08ca5f686f9..f2ca7ff782591d0b45d8e9598f708a2c2a1ddf5e 100644 (file)
@@ -8,7 +8,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/const-points-to-static.rs:5:1
    |
 LL | const TEST: &u8 = &MY_STATIC;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a reference pointing to a static variable
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
diff --git a/src/test/ui/consts/const_discriminant.rs b/src/test/ui/consts/const_discriminant.rs
new file mode 100644 (file)
index 0000000..1ad5134
--- /dev/null
@@ -0,0 +1,40 @@
+// run-pass
+#![feature(const_discriminant)]
+#![allow(dead_code)]
+
+use std::mem::{discriminant, Discriminant};
+
+// `discriminant(const_expr)` may get const-propagated.
+// As we want to check that const-eval is equal to ordinary exection,
+// we wrap `const_expr` with a function which is not const to prevent this.
+#[inline(never)]
+fn identity<T>(x: T) -> T { x }
+
+enum Test {
+    A(u8),
+    B,
+    C { a: u8, b: u8 },
+}
+
+const TEST_A: Discriminant<Test> = discriminant(&Test::A(5));
+const TEST_A_OTHER: Discriminant<Test> = discriminant(&Test::A(17));
+const TEST_B: Discriminant<Test> = discriminant(&Test::B);
+
+enum Void {}
+
+enum SingleVariant {
+    V,
+    Never(Void),
+}
+
+const TEST_V: Discriminant<SingleVariant> = discriminant(&SingleVariant::V);
+
+fn main() {
+    assert_eq!(TEST_A, TEST_A_OTHER);
+    assert_eq!(TEST_A, discriminant(identity(&Test::A(17))));
+    assert_eq!(TEST_B, discriminant(identity(&Test::B)));
+    assert_ne!(TEST_A, TEST_B);
+    assert_ne!(TEST_B, discriminant(identity(&Test::C { a: 42, b: 7 })));
+
+    assert_eq!(TEST_V, discriminant(identity(&SingleVariant::V)));
+}
index a2364c392f26bd945bf232a315f343d498197bdf..818819f9ff67a53f6dacf8cebb17001163fd16a4 100644 (file)
@@ -5,6 +5,7 @@ struct Bar<T> { x: T }
 struct W(u32);
 struct A { a: u32 }
 
+#[allow(redundant_semicolons)]
 const fn basics((a,): (u32,)) -> u32 {
     // Deferred assignment:
     let b: u32;
index 0c927a0484d9d15ce704fddd9a8bc9622d50eb3d..bc0ef26eb2fe525fa40afd77a91f5e59c82e3c1b 100644 (file)
@@ -7,6 +7,7 @@ struct Bar<T> { x: T }
 struct W(f32);
 struct A { a: f32 }
 
+#[allow(redundant_semicolons)]
 const fn basics((a,): (f32,)) -> f32 {
     // Deferred assignment:
     let b: f32;
diff --git a/src/test/ui/consts/const_limit/const_eval_limit_not_reached.rs b/src/test/ui/consts/const_limit/const_eval_limit_not_reached.rs
new file mode 100644 (file)
index 0000000..4ed9083
--- /dev/null
@@ -0,0 +1,15 @@
+// check-pass
+#![feature(const_eval_limit)]
+#![const_eval_limit="1000"]
+
+const CONSTANT: usize = limit();
+
+fn main() {
+    assert_eq!(CONSTANT, 1764);
+}
+
+const fn limit() -> usize {
+    let x = 42;
+
+    x * 42
+}
diff --git a/src/test/ui/consts/const_limit/const_eval_limit_overflow.rs b/src/test/ui/consts/const_limit/const_eval_limit_overflow.rs
new file mode 100644 (file)
index 0000000..1c49593
--- /dev/null
@@ -0,0 +1,15 @@
+#![feature(const_eval_limit)]
+#![const_eval_limit="18_446_744_073_709_551_615"]
+//~^ ERROR `limit` must be a non-negative integer
+
+const CONSTANT: usize = limit();
+
+fn main() {
+    assert_eq!(CONSTANT, 1764);
+}
+
+const fn limit() -> usize {
+    let x = 42;
+
+    x * 42
+}
diff --git a/src/test/ui/consts/const_limit/const_eval_limit_overflow.stderr b/src/test/ui/consts/const_limit/const_eval_limit_overflow.stderr
new file mode 100644 (file)
index 0000000..7f5d5e6
--- /dev/null
@@ -0,0 +1,10 @@
+error: `limit` must be a non-negative integer
+  --> $DIR/const_eval_limit_overflow.rs:2:1
+   |
+LL | #![const_eval_limit="18_446_744_073_709_551_615"]
+   | ^^^^^^^^^^^^^^^^^^^^----------------------------^
+   |                     |
+   |                     not a valid integer
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/consts/const_limit/const_eval_limit_reached.rs b/src/test/ui/consts/const_limit/const_eval_limit_reached.rs
new file mode 100644 (file)
index 0000000..d962398
--- /dev/null
@@ -0,0 +1,21 @@
+// ignore-tidy-linelength
+// only-x86_64
+// check-pass
+// NOTE: We always compile this test with -Copt-level=0 because higher opt-levels
+//       optimize away the const function
+// compile-flags:-Copt-level=0
+#![feature(const_eval_limit)]
+#![const_eval_limit="2"]
+
+const CONSTANT: usize = limit();
+//~^ WARNING Constant evaluating a complex constant, this might take some time
+
+fn main() {
+    assert_eq!(CONSTANT, 1764);
+}
+
+const fn limit() -> usize { //~ WARNING Constant evaluating a complex constant, this might take some time
+    let x = 42;
+
+    x * 42
+}
diff --git a/src/test/ui/consts/const_limit/const_eval_limit_reached.stderr b/src/test/ui/consts/const_limit/const_eval_limit_reached.stderr
new file mode 100644 (file)
index 0000000..e0871ff
--- /dev/null
@@ -0,0 +1,16 @@
+warning: Constant evaluating a complex constant, this might take some time
+  --> $DIR/const_eval_limit_reached.rs:17:1
+   |
+LL | / const fn limit() -> usize {
+LL | |     let x = 42;
+LL | |
+LL | |     x * 42
+LL | | }
+   | |_^
+
+warning: Constant evaluating a complex constant, this might take some time
+  --> $DIR/const_eval_limit_reached.rs:10:1
+   |
+LL | const CONSTANT: usize = limit();
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
diff --git a/src/test/ui/consts/const_limit/feature-gate-const_eval_limit.rs b/src/test/ui/consts/const_limit/feature-gate-const_eval_limit.rs
new file mode 100644 (file)
index 0000000..61119d7
--- /dev/null
@@ -0,0 +1,14 @@
+#![const_eval_limit="42"]
+//~^ ERROR the `#[const_eval_limit]` attribute is an experimental feature [E0658]
+
+const CONSTANT: usize = limit();
+
+fn main() {
+    assert_eq!(CONSTANT, 1764);
+}
+
+const fn limit() -> usize {
+    let x = 42;
+
+    x * 42
+}
diff --git a/src/test/ui/consts/const_limit/feature-gate-const_eval_limit.stderr b/src/test/ui/consts/const_limit/feature-gate-const_eval_limit.stderr
new file mode 100644 (file)
index 0000000..5bd29c7
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0658]: the `#[const_eval_limit]` attribute is an experimental feature
+  --> $DIR/feature-gate-const_eval_limit.rs:1:1
+   |
+LL | #![const_eval_limit="42"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #67217 <https://github.com/rust-lang/rust/issues/67217> for more information
+   = help: add `#![feature(const_eval_limit)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
index bac9f555d271bdd4c2ace1c970aa1c506f0a6754..0e213555052c85f683416846a706c2754b3185f3 100644 (file)
@@ -5,7 +5,7 @@ LL | / const FOO: &() = {
 LL | |     let y = ();
 LL | |     unsafe { Foo { y: &y }.long_live_the_unit }
 LL | | };
-   | |__^ type validation failed: encountered dangling pointer in final constant
+   | |__^ encountered dangling pointer in final constant
    |
    = note: `#[deny(const_err)]` on by default
 
index 4748be37dffcfe2332ee771522dfff66ba9155b2..4d4c2876c4598afad2d7ddd75fa4853c1ca724c1 100644 (file)
@@ -5,7 +5,7 @@ LL | / const FOO: *const u32 = {
 LL | |     let x = 42;
 LL | |     &x
 LL | | };
-   | |__^ type validation failed: encountered dangling pointer in final constant
+   | |__^ encountered dangling pointer in final constant
    |
    = note: `#[deny(const_err)]` on by default
 
index d5ed970fc3533d09ca7283f74d2e3487057dead4..5e85be45b164711a54c96d36519996e76263d345 100644 (file)
@@ -8,7 +8,7 @@ LL | |             ptr: &42,
 ...  |
 LL | |     .slice
 LL | | };
-   | |__^ invalid slice: total size is bigger than largest supported object
+   | |__^ type validation failed: encountered invalid reference metadata: slice is bigger than largest supported object
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
diff --git a/src/test/ui/consts/issue-69191-ice-on-uninhabited-enum-field.rs b/src/test/ui/consts/issue-69191-ice-on-uninhabited-enum-field.rs
new file mode 100644 (file)
index 0000000..5b7c7be
--- /dev/null
@@ -0,0 +1,91 @@
+// build-pass
+//
+// (this is deliberately *not* check-pass; I have confirmed that the bug in
+// question does not replicate when one uses `cargo check` alone.)
+
+pub enum Void {}
+
+enum UninhabitedUnivariant {
+    _Variant(Void),
+}
+
+enum UninhabitedMultivariant2 {
+    _Variant(Void),
+    _Warriont(Void),
+}
+
+enum UninhabitedMultivariant3 {
+    _Variant(Void),
+    _Warriont(Void),
+    _Worrynot(Void),
+}
+
+#[repr(C)]
+enum UninhabitedUnivariantC {
+    _Variant(Void),
+}
+
+#[repr(i32)]
+enum UninhabitedUnivariant32 {
+    _Variant(Void),
+}
+
+fn main() {
+    let _seed: UninhabitedUnivariant = None.unwrap();
+    match _seed {
+        UninhabitedUnivariant::_Variant(_x) => {}
+    }
+
+    let _seed: UninhabitedMultivariant2 = None.unwrap();
+    match _seed {
+        UninhabitedMultivariant2::_Variant(_x) => {}
+        UninhabitedMultivariant2::_Warriont(_x) => {}
+    }
+
+    let _seed: UninhabitedMultivariant2 = None.unwrap();
+    match _seed {
+        UninhabitedMultivariant2::_Variant(_x) => {}
+        _ => {}
+    }
+
+    let _seed: UninhabitedMultivariant2 = None.unwrap();
+    match _seed {
+        UninhabitedMultivariant2::_Warriont(_x) => {}
+        _ => {}
+    }
+
+    let _seed: UninhabitedMultivariant3 = None.unwrap();
+    match _seed {
+        UninhabitedMultivariant3::_Variant(_x) => {}
+        UninhabitedMultivariant3::_Warriont(_x) => {}
+        UninhabitedMultivariant3::_Worrynot(_x) => {}
+    }
+
+    let _seed: UninhabitedMultivariant3 = None.unwrap();
+    match _seed {
+        UninhabitedMultivariant3::_Variant(_x) => {}
+        _ => {}
+    }
+
+    let _seed: UninhabitedMultivariant3 = None.unwrap();
+    match _seed {
+        UninhabitedMultivariant3::_Warriont(_x) => {}
+        _ => {}
+    }
+
+    let _seed: UninhabitedMultivariant3 = None.unwrap();
+    match _seed {
+        UninhabitedMultivariant3::_Worrynot(_x) => {}
+        _ => {}
+    }
+
+    let _seed: UninhabitedUnivariantC = None.unwrap();
+    match _seed {
+        UninhabitedUnivariantC::_Variant(_x) => {}
+    }
+
+    let _seed: UninhabitedUnivariant32 = None.unwrap();
+    match _seed {
+        UninhabitedUnivariant32::_Variant(_x) => {}
+    }
+}
index c8d060f5cdcfe5fc78057264e825288d810c7b7b..7794cc7583dfcefa8cdaf753b016e8276fa95a47 100644 (file)
@@ -4,7 +4,6 @@ error[E0658]: internal implementation detail
 LL | #[rustc_allow_const_fn_ptr]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: see issue #29642 <https://github.com/rust-lang/rust/issues/29642> for more information
    = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable
 
 error: aborting due to previous error
index da00c49963eec2778231a36c93a9491e2f403df4..c7e902132e91ad5a3d29d4c3f7378ab194383b2d 100644 (file)
@@ -16,7 +16,7 @@ error: any use of this value will cause an error
 LL |     my_fn();
    |     ^^^^^^^
    |     |
-   |     tried to call a function with ABI C using caller ABI Rust
+   |     calling a function with ABI C using caller ABI Rust
    |     inside call to `call_rust_fn` at $DIR/abi-mismatch.rs:13:17
 ...
 LL | const VAL: () = call_rust_fn(unsafe { std::mem::transmute(c_fn as extern "C" fn()) });
index 15e13942481c970723ab35e99f73e6c1ad732b7e..ad777cfe8ea4bcb2d52a6a4b393e620a825bd4c0 100644 (file)
@@ -48,7 +48,7 @@ LL | |     static FOO: AtomicUsize = AtomicUsize::new(0);
 LL | |     unsafe { &*(&FOO as *const _ as *const usize) }
 LL | |
 LL | | };
-   | |__^ constant accesses static
+   | |__^ type validation failed: encountered a reference pointing to a static variable
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
@@ -97,7 +97,7 @@ LL | |     static FOO: usize = 0;
 LL | |     &FOO
 LL | |
 LL | | };
-   | |__^ constant accesses static
+   | |__^ type validation failed: encountered a reference pointing to a static variable
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
index 86f27784701c6a81c707b941aa5d965160509115..8456e8ec6870dcd4c0d2204b8e8ac737bfb662d7 100644 (file)
@@ -11,7 +11,7 @@ LL | / const MUTATING_BEHIND_RAW: () = {
 LL | |     // Test that `MUTABLE_BEHIND_RAW` is actually immutable, by doing this at const time.
 LL | |     unsafe {
 LL | |         *MUTABLE_BEHIND_RAW = 99
-   | |         ^^^^^^^^^^^^^^^^^^^^^^^^ tried to modify constant memory
+   | |         ^^^^^^^^^^^^^^^^^^^^^^^^ writing to alloc1 which is read-only
 LL | |     }
 LL | | };
    | |__-
index 3eb8e0ec182881c4cbaace481293ae85f1a5a82b..dda9ddf1f487f3faf715b326f96b50d0a0712f9f 100644 (file)
@@ -10,7 +10,7 @@ error: internal compiler error: mutable allocation in constant
 LL | const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-thread 'rustc' panicked at 'no errors encountered even though `delay_span_bug` issued', src/librustc_errors/lib.rs:355:17
+thread 'rustc' panicked at 'no errors encountered even though `delay_span_bug` issued', src/librustc_errors/lib.rs:360:17
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
 
 error: internal compiler error: unexpected panic
index 24da983cf0868088db004d9d7b8f894b38bb202b..217530740079f2c6af474bab77fe2d0d908056ce 100644 (file)
@@ -26,7 +26,7 @@ error: any use of this value will cause an error
 LL |           intrinsics::ptr_offset_from(self, origin)
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |           |
-   |           a memory access tried to interpret some bytes as a pointer
+   |           unable to turn bytes into a pointer
    |           inside call to `std::ptr::const_ptr::<impl *const u8>::offset_from` at $DIR/offset_from_ub.rs:28:14
    | 
   ::: $DIR/offset_from_ub.rs:26:1
@@ -43,7 +43,7 @@ error: any use of this value will cause an error
 LL |           intrinsics::ptr_offset_from(self, origin)
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |           |
-   |           exact_div: 1 cannot be divided by 2 without remainder
+   |           exact_div: 1isize cannot be divided by 2isize without remainder
    |           inside call to `std::ptr::const_ptr::<impl *const u16>::offset_from` at $DIR/offset_from_ub.rs:36:14
    | 
   ::: $DIR/offset_from_ub.rs:31:1
@@ -81,7 +81,7 @@ error: any use of this value will cause an error
 LL |           intrinsics::ptr_offset_from(self, origin)
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |           |
-   |           a memory access tried to interpret some bytes as a pointer
+   |           unable to turn bytes into a pointer
    |           inside call to `std::ptr::const_ptr::<impl *const u8>::offset_from` at $DIR/offset_from_ub.rs:49:14
    | 
   ::: $DIR/offset_from_ub.rs:45:1
index 296a55ef16076c9ef5e4d59a251f3f7aa6d6cf64..5a4777145962584d625b2f0067e8511e92630b9a 100644 (file)
@@ -21,7 +21,7 @@ LL | const ZST: &[u8] = unsafe { std::mem::transmute(1usize) };
    |                             ^^^^^^^^^^^^^^^^^^^
    |
    = note: source type: `usize` (word size)
-   = note: target type: `&'static [u8]` (2 * word size)
+   = note: target type: `&[u8]` (2 * word size)
 
 error: could not evaluate constant pattern
   --> $DIR/transmute-size-mismatch-before-typeck.rs:10:9
index cb995b8216f4ec154662d90a6241c0b7edbd7443..77f0a2ebd4021721434ab61aff16a7f11b7d25e0 100644 (file)
@@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/validate_never_arrays.rs:3:1
    |
 LL | const _: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type at .<deref>
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of the never type `!` at .<deref>[0]
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
@@ -10,7 +10,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/validate_never_arrays.rs:6:1
    |
 LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 1]) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type at .<deref>[0]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of the never type `!` at .<deref>[0]
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
@@ -18,7 +18,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/validate_never_arrays.rs:7:1
    |
 LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 42]) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type at .<deref>[0]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of the never type `!` at .<deref>[0]
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
index b596ba8936a4391142680f3aceccd3970f9819ee..b665b049f32f9750fe8cc8eaf467fedbde1ff350 100644 (file)
@@ -1,4 +1,4 @@
-// Check that functions visible to macros through paths with >2 segements are
+// Check that functions visible to macros through paths with >2 segments are
 // considered reachable
 
 // aux-build:field-method-macro.rs
index 613d7eee59480869cfa38bb5600ba90d7a68d566..76e87a3749c33a5b8f2849c41707741b14b78dc6 100644 (file)
@@ -32,11 +32,11 @@ LL |     X() {}
 LL | }
    | - the item list ends here
 
-error: expected `[`, found `#`
+error: expected one of `!` or `[`, found `#`
   --> $DIR/issue-40006.rs:19:17
    |
 LL |     fn xxx() { ### }
-   |                 ^ expected `[`
+   |                 ^ expected one of `!` or `[`
 
 error: expected one of `!` or `::`, found `=`
   --> $DIR/issue-40006.rs:22:7
index 376c1a9cd66277f94a5936af6559aac8bc0a305e..9cb159603a8c561c1ce76152d2475ab59269782e 100644 (file)
@@ -1,7 +1,9 @@
 // Test that macro-expanded non-inline modules behave correctly
 
 macro_rules! mod_decl {
-    ($i:ident) => { mod $i; } //~ ERROR Cannot declare a non-inline module inside a block
+    ($i:ident) => {
+        mod $i; //~ ERROR Cannot declare a non-inline module inside a block
+    };
 }
 
 mod macro_expanded_mod_helper {
index c7780c869d635c55c9800240145e52c2502b2cf9..f90419247c92badae27794bd1690ebbdf6ef3164 100644 (file)
@@ -1,8 +1,8 @@
 error: Cannot declare a non-inline module inside a block unless it has a path attribute
-  --> $DIR/macro-expanded-mod.rs:4:25
+  --> $DIR/macro-expanded-mod.rs:5:9
    |
-LL |     ($i:ident) => { mod $i; }
-   |                         ^^
+LL |         mod $i;
+   |         ^^^^^^^
 ...
 LL |     mod_decl!(foo);
    |     --------------- in this macro invocation
index 46acc7e66d8b821fbab899dbfdc7f8f8f84e1b52..d034942ca5d4cc7a50ab020eeecadca5ad3a5878 100644 (file)
@@ -1,8 +1,8 @@
 error: Cannot declare a non-inline module inside a block unless it has a path attribute
-  --> $DIR/non-inline-mod-restriction.rs:4:9
+  --> $DIR/non-inline-mod-restriction.rs:4:5
    |
 LL |     mod foo;
-   |         ^^^
+   |     ^^^^^^^^
 
 error: aborting due to previous error
 
index 451686d9ae21ccf3d218dd582e2ae0b7319be58d..d31736f142c3f45394d12e29ae6a9367136377e3 100644 (file)
@@ -3,6 +3,7 @@
 
 #![feature(generators, generator_trait, untagged_unions)]
 #![feature(move_ref_pattern)]
+#![feature(bindings_after_at)]
 
 #![allow(unused_assignments)]
 #![allow(unused_variables)]
@@ -291,6 +292,44 @@ fn subslice_mixed_min_lengths(a: &Allocator, c: i32) {
     }
 }
 
+fn bindings_after_at_dynamic_init_move(a: &Allocator, c: bool) {
+    let foo = if c { Some(a.alloc()) } else { None };
+    let _x;
+
+    if let bar @ Some(_) = foo {
+        _x = bar;
+    }
+}
+
+fn bindings_after_at_dynamic_init_ref(a: &Allocator, c: bool) {
+    let foo = if c { Some(a.alloc()) } else { None };
+    let _x;
+
+    if let bar @ Some(_baz) = &foo {
+        _x = bar;
+    }
+}
+
+fn bindings_after_at_dynamic_drop_move(a: &Allocator, c: bool) {
+    let foo = if c { Some(a.alloc()) } else { None };
+
+    if let bar @ Some(_) = foo {
+        bar
+    } else {
+        None
+    };
+}
+
+fn bindings_after_at_dynamic_drop_ref(a: &Allocator, c: bool) {
+    let foo = if c { Some(a.alloc()) } else { None };
+
+    if let bar @ Some(_baz) = &foo {
+        bar
+    } else {
+        &None
+    };
+}
+
 fn move_ref_pattern(a: &Allocator) {
     let mut tup = (a.alloc(), a.alloc(), a.alloc(), a.alloc());
     let (ref _a, ref mut _b, _c, mut _d) = tup;
@@ -471,5 +510,14 @@ fn main() {
     run_test(|a| panic_after_init_temp(a));
     run_test(|a| panic_after_init_by_loop(a));
 
+    run_test(|a| bindings_after_at_dynamic_init_move(a, true));
+    run_test(|a| bindings_after_at_dynamic_init_move(a, false));
+    run_test(|a| bindings_after_at_dynamic_init_ref(a, true));
+    run_test(|a| bindings_after_at_dynamic_init_ref(a, false));
+    run_test(|a| bindings_after_at_dynamic_drop_move(a, true));
+    run_test(|a| bindings_after_at_dynamic_drop_move(a, false));
+    run_test(|a| bindings_after_at_dynamic_drop_ref(a, true));
+    run_test(|a| bindings_after_at_dynamic_drop_ref(a, false));
+
     run_test_nopanic(|a| union1(a));
 }
index f44f81fce7134c3434092146d6bbd8d0877e260b..88a1f5dc6736d96efb6bebf20eb43fdd57fcd467 100644 (file)
@@ -7,8 +7,8 @@ LL |     produces_async! {}
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 help: you can escape reserved keywords to use them as identifiers
    |
-LL | () => (pub fn r#async () { })
-   |               ^^^^^^^
+LL |     () => (pub fn r#async() {})
+   |                   ^^^^^^^
 
 error: aborting due to previous error
 
index 22a7495ca234a31a1b95c532fb6b914fd00c92fc..e12d1a48463d73aa392a73273fc369d150d3aaa6 100644 (file)
@@ -33,10 +33,10 @@ LL |     r#async = consumes_async_raw!(async);
    |                                   ^^^^^ no rules expected this token in macro call
 
 error: macro expansion ends with an incomplete expression: expected one of `move`, `|`, or `||`
-  --> <::edition_kw_macro_2015::passes_ident macros>:1:22
+  --> $DIR/auxiliary/edition-kw-macro-2015.rs:27:23
    |
-LL | ($ i : ident) => ($ i)
-   |                      ^ expected one of `move`, `|`, or `||`
+LL |     ($i: ident) => ($i)
+   |                       ^ expected one of `move`, `|`, or `||`
    | 
   ::: $DIR/edition-keywords-2018-2015-parsing.rs:16:8
    |
index a8fc58fc0cb8d927a6836b2f86205f58b21a246c..5eaa1d03a4a5f491dfe2d5bd3b5f8089f61d1d34 100644 (file)
@@ -7,8 +7,8 @@ LL |     produces_async! {}
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 help: you can escape reserved keywords to use them as identifiers
    |
-LL | () => (pub fn r#async () { })
-   |               ^^^^^^^
+LL |     () => (pub fn r#async() {})
+   |                   ^^^^^^^
 
 error: aborting due to previous error
 
index 7488fcc2e584e624d40722610a48bf89888a3a17..110165fc077ca54711b7659be84dd9e12089f24f 100644 (file)
@@ -33,10 +33,10 @@ LL |     r#async = consumes_async_raw!(async);
    |                                   ^^^^^ no rules expected this token in macro call
 
 error: macro expansion ends with an incomplete expression: expected one of `move`, `|`, or `||`
-  --> <::edition_kw_macro_2018::passes_ident macros>:1:22
+  --> $DIR/auxiliary/edition-kw-macro-2018.rs:27:23
    |
-LL | ($ i : ident) => ($ i)
-   |                      ^ expected one of `move`, `|`, or `||`
+LL |     ($i: ident) => ($i)
+   |                       ^ expected one of `move`, `|`, or `||`
    | 
   ::: $DIR/edition-keywords-2018-2018-parsing.rs:16:8
    |
index 3aa88df29f11b2652472bd7e18751fcce1b9d24c..fadf6ab86b43e0f49934377e3eec5820a120a10e 100644 (file)
@@ -9,24 +9,31 @@ note: the lint level is defined here
    |
 LL | #![deny(overflowing_literals)]
    |         ^^^^^^^^^^^^^^^^^^^^
+   = note: the literal `223` does not fit into the type `i8` whose range is `-128..=127`
 
 error: literal out of range for `i16`
   --> $DIR/enum-discrim-too-small2.rs:15:12
    |
 LL |     Ci16 = 55555,
    |            ^^^^^
+   |
+   = note: the literal `55555` does not fit into the type `i16` whose range is `-32768..=32767`
 
 error: literal out of range for `i32`
   --> $DIR/enum-discrim-too-small2.rs:22:12
    |
 LL |     Ci32 = 3_000_000_000,
    |            ^^^^^^^^^^^^^
+   |
+   = note: the literal `3_000_000_000` does not fit into the type `i32` whose range is `-2147483648..=2147483647`
 
 error: literal out of range for `i64`
   --> $DIR/enum-discrim-too-small2.rs:29:12
    |
 LL |     Ci64 = 9223372036854775809,
    |            ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the literal `9223372036854775809` does not fit into the type `i64` whose range is `-9223372036854775808..=9223372036854775807`
 
 error: aborting due to 4 previous errors
 
index 5a5c6b40c5afecbcc7303459e13ff528d3ed23ba..ad854837ae5bd678985e7f483a2fd97019929755 100644 (file)
@@ -14,7 +14,7 @@ LL | static BAR: _ = "test";
    |             ^
    |             |
    |             not allowed in type signatures
-   |             help: replace `_` with the correct type: `&'static str`
+   |             help: replace `_` with the correct type: `&str`
 
 error: aborting due to 2 previous errors
 
index 51ed9c83bc99924447a7359921d16b015daa1beb..35e1042649ef9e382e40b324b5e71d158a9e172d 100644 (file)
@@ -1,8 +1,8 @@
 error[E0197]: inherent impls cannot be unsafe
-  --> $DIR/E0197.rs:3:1
+  --> $DIR/E0197.rs:3:13
    |
 LL | unsafe impl Foo { }
-   | ------^^^^^^^^^^^^^
+   | ------      ^^^ inherent impl for this type
    | |
    | unsafe because of this
 
index 90e8b4abd1296dfad3286306e1863e25c76af464..bb2efefb427bad08dff28f7c81b1450fb58b7179 100644 (file)
@@ -1,9 +1,10 @@
 error[E0198]: negative impls cannot be unsafe
-  --> $DIR/E0198.rs:5:1
+  --> $DIR/E0198.rs:5:13
    |
 LL | unsafe impl !Send for Foo { }
-   | ------^^^^^^^^^^^^^^^^^^^^^^^
-   | |
+   | ------      -^^^^
+   | |           |
+   | |           negative because of this
    | unsafe because of this
 
 error: aborting due to previous error
index 7222f87da248f32732f3b206a2c103b43b545751..685055525627ee7a8436e0d2301cb988f59fc8ae 100644 (file)
@@ -4,7 +4,7 @@ error: any use of this value will cause an error
 LL | const VALUE: u8 = unsafe { *REG_ADDR };
    | ---------------------------^^^^^^^^^---
    |                            |
-   |                            a memory access tried to interpret some bytes as a pointer
+   |                            unable to turn bytes into a pointer
    |
    = note: `#[deny(const_err)]` on by default
 
index ef7a48bc8a48f3805c9cd72fa5e3562b4f45e609..dbe700355957b1ebe76edff13adb9d7108211fca 100644 (file)
@@ -1,10 +1,10 @@
 error[E0583]: file not found for module `module_that_doesnt_exist`
-  --> $DIR/E0583.rs:1:5
+  --> $DIR/E0583.rs:1:1
    |
 LL | mod module_that_doesnt_exist;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: name the file either module_that_doesnt_exist.rs or module_that_doesnt_exist/mod.rs inside the directory "$DIR"
+   = help: to create the module `module_that_doesnt_exist`, create file "$DIR/module_that_doesnt_exist.rs"
 
 error: aborting due to previous error
 
index 45f72a565ca1bc53adfc3130d0e769ea4e030404..4c68b70fb165afe0295e13ae1839d6e93e7c25de 100644 (file)
@@ -8,5 +8,5 @@ fn method(&self) {}
 
 fn main() {
     let foo = inner::Foo;
-    foo.method(); //~ ERROR method `method` is private [E0624]
+    foo.method(); //~ ERROR associated function `method` is private [E0624]
 }
index 01ac24cfbbe122b4318b6efb4c1987b71b8d7093..65256c8dd2dd6f3b2b0f661fc4fb06355de877a3 100644 (file)
@@ -1,4 +1,4 @@
-error[E0624]: method `method` is private
+error[E0624]: associated function `method` is private
   --> $DIR/E0624.rs:11:9
    |
 LL |     foo.method();
index a046fbfc3d04a0fd4d0c930eafe66ed3d8ecd553..0e4bbf083baf326c04a6f940aa9a66761b97d92c 100644 (file)
@@ -16,3 +16,4 @@ LL | fn test() -> Box<dyn Iterator<Item = (), Item = Unit>> {
 
 error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0719`.
index 9ea56271f593fa244dc88a57907b90e9f4a97b62..c50c46ee5641665e2978ffe6d1e3aacae934db5c 100644 (file)
@@ -46,7 +46,7 @@ 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:
+- cast the fn item of a fn pointer before calling transmute, as shown here:
 
     ```
     let f: extern "C" fn(*mut i32) = transmute(foo as extern "C" fn(_));
index 4c80989951abc79d9cfd6b816e75e1359de1e2ed..94a2cfe013d190778b696ab943611b3365f63fbc 100644 (file)
@@ -79,19 +79,19 @@ LL |     r.unstable_undeclared();
    = note: see issue #38412 <https://github.com/rust-lang/rust/issues/38412> for more information
    = help: add `#![feature(unstable_undeclared)]` to the crate attributes to enable
 
-error[E0624]: method `pub_crate` is private
+error[E0624]: associated function `pub_crate` is private
   --> $DIR/explore-issue-38412.rs:50:7
    |
 LL |     r.pub_crate();
    |       ^^^^^^^^^
 
-error[E0624]: method `pub_mod` is private
+error[E0624]: associated function `pub_mod` is private
   --> $DIR/explore-issue-38412.rs:51:7
    |
 LL |     r.pub_mod();
    |       ^^^^^^^
 
-error[E0624]: method `private` is private
+error[E0624]: associated function `private` is private
   --> $DIR/explore-issue-38412.rs:52:7
    |
 LL |     r.private();
@@ -115,19 +115,19 @@ LL |     t.unstable_undeclared();
    = note: see issue #38412 <https://github.com/rust-lang/rust/issues/38412> for more information
    = help: add `#![feature(unstable_undeclared)]` to the crate attributes to enable
 
-error[E0624]: method `pub_crate` is private
+error[E0624]: associated function `pub_crate` is private
   --> $DIR/explore-issue-38412.rs:63:7
    |
 LL |     t.pub_crate();
    |       ^^^^^^^^^
 
-error[E0624]: method `pub_mod` is private
+error[E0624]: associated function `pub_mod` is private
   --> $DIR/explore-issue-38412.rs:64:7
    |
 LL |     t.pub_mod();
    |       ^^^^^^^
 
-error[E0624]: method `private` is private
+error[E0624]: associated function `private` is private
   --> $DIR/explore-issue-38412.rs:65:7
    |
 LL |     t.private();
diff --git a/src/test/ui/feature-gates/feature-gate-doc_spotlight.rs b/src/test/ui/feature-gates/feature-gate-doc_spotlight.rs
deleted file mode 100644 (file)
index 452b45b..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-#[doc(spotlight)] //~ ERROR: `#[doc(spotlight)]` is experimental
-trait SomeTrait {}
-
-fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-doc_spotlight.stderr b/src/test/ui/feature-gates/feature-gate-doc_spotlight.stderr
deleted file mode 100644 (file)
index 010d740..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0658]: `#[doc(spotlight)]` is experimental
-  --> $DIR/feature-gate-doc_spotlight.rs:1:1
-   |
-LL | #[doc(spotlight)]
-   | ^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #45040 <https://github.com/rust-lang/rust/issues/45040> for more information
-   = help: add `#![feature(doc_spotlight)]` 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-no-debug-2.rs b/src/test/ui/feature-gates/feature-gate-no-debug-2.rs
deleted file mode 100644 (file)
index b399bd2..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-#![deny(deprecated)]
-#![feature(no_debug)]
-
-#[no_debug] //~ ERROR use of deprecated attribute `no_debug`
-fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-no-debug-2.stderr b/src/test/ui/feature-gates/feature-gate-no-debug-2.stderr
deleted file mode 100644 (file)
index 9a6f898..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-error: use of deprecated attribute `no_debug`: the `#[no_debug]` attribute was an experimental feature that has been deprecated due to lack of demand. See https://github.com/rust-lang/rust/issues/29721
-  --> $DIR/feature-gate-no-debug-2.rs:4:1
-   |
-LL | #[no_debug]
-   | ^^^^^^^^^^^ help: remove this attribute
-   |
-note: the lint level is defined here
-  --> $DIR/feature-gate-no-debug-2.rs:1:9
-   |
-LL | #![deny(deprecated)]
-   |         ^^^^^^^^^^
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/feature-gates/feature-gate-no-debug.rs b/src/test/ui/feature-gates/feature-gate-no-debug.rs
deleted file mode 100644 (file)
index a472c4c..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-#![allow(deprecated)]
-
-#[no_debug] //~ ERROR the `#[no_debug]` attribute was
-fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-no-debug.stderr b/src/test/ui/feature-gates/feature-gate-no-debug.stderr
deleted file mode 100644 (file)
index e146d64..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0658]: the `#[no_debug]` attribute was an experimental feature that has been deprecated due to lack of demand
-  --> $DIR/feature-gate-no-debug.rs:3:1
-   |
-LL | #[no_debug]
-   | ^^^^^^^^^^^
-   |
-   = note: see issue #29721 <https://github.com/rust-lang/rust/issues/29721> for more information
-   = help: add `#![feature(no_debug)]` to the crate attributes to enable
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0658`.
index d29c373a33c95f9bc92f38aa6fe8cd1284b0f16e..490d29ad8a35f33eef20f9ffde326f6b0a3b404b 100644 (file)
@@ -8,10 +8,10 @@ LL | auto trait AutoDummyTrait {}
    = help: add `#![feature(optin_builtin_traits)]` to the crate attributes to enable
 
 error[E0658]: negative trait bounds are not yet fully implemented; use marker types for now
-  --> $DIR/feature-gate-optin-builtin-traits.rs:9:1
+  --> $DIR/feature-gate-optin-builtin-traits.rs:9:6
    |
 LL | impl !AutoDummyTrait for DummyStruct {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |      ^^^^^^^^^^^^^^^
    |
    = note: see issue #13231 <https://github.com/rust-lang/rust/issues/13231> for more information
    = help: add `#![feature(optin_builtin_traits)]` to the crate attributes to enable
index 082d897c01dc1c6f7555f55e939262f5be0e9c90..82dec1fd4cf21f74ba75da84fc99bc84d6c7f552 100644 (file)
@@ -4,7 +4,6 @@ error[E0658]: the `#[rustc_variance]` attribute is just used for rustc unit test
 LL | #[rustc_variance]
    | ^^^^^^^^^^^^^^^^^
    |
-   = note: see issue #29642 <https://github.com/rust-lang/rust/issues/29642> for more information
    = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable
 
 error[E0658]: the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable
@@ -13,7 +12,6 @@ error[E0658]: the `#[rustc_error]` attribute is just used for rustc unit tests a
 LL | #[rustc_error]
    | ^^^^^^^^^^^^^^
    |
-   = note: see issue #29642 <https://github.com/rust-lang/rust/issues/29642> for more information
    = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable
 
 error[E0658]: the `#[rustc_nonnull_optimization_guaranteed]` attribute is just used to enable niche optimizations in libcore and will never be stable
@@ -22,7 +20,6 @@ error[E0658]: the `#[rustc_nonnull_optimization_guaranteed]` attribute is just u
 LL | #[rustc_nonnull_optimization_guaranteed]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: see issue #29642 <https://github.com/rust-lang/rust/issues/29642> for more information
    = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable
 
 error: aborting due to 3 previous errors
index 58f8b4e7035134a89a11a2ba972b899dcdd31db9..1e039f17a0d115f3b080805791d3b600908633c9 100644 (file)
@@ -4,7 +4,6 @@ error[E0658]: attributes starting with `rustc` are reserved for use by the `rust
 LL | #[rustc::unknown]
    |   ^^^^^
    |
-   = note: see issue #29642 <https://github.com/rust-lang/rust/issues/29642> for more information
    = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable
 
 error: expected attribute, found macro `rustc::unknown`
@@ -19,7 +18,6 @@ error[E0658]: attributes starting with `rustc` are reserved for use by the `rust
 LL | #[unknown::rustc]
    |            ^^^^^
    |
-   = note: see issue #29642 <https://github.com/rust-lang/rust/issues/29642> for more information
    = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable
 
 error: expected attribute, found macro `unknown::rustc`
@@ -34,7 +32,6 @@ error[E0658]: attributes starting with `rustc` are reserved for use by the `rust
 LL | #[rustc_unknown]
    |   ^^^^^^^^^^^^^
    |
-   = note: see issue #29642 <https://github.com/rust-lang/rust/issues/29642> for more information
    = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable
 
 error: cannot find attribute `rustc_unknown` in this scope
@@ -49,7 +46,6 @@ error[E0658]: the `#[rustc_dummy]` attribute is just used for rustc unit tests a
 LL | #[rustc_dummy]
    | ^^^^^^^^^^^^^^
    |
-   = note: see issue #29642 <https://github.com/rust-lang/rust/issues/29642> for more information
    = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable
 
 error: aborting due to 7 previous errors
index b83252012b8f8bfd1572e0e8f5023e0d523d45ba..2d7c86b8666f855347402710f07e3758d9b0d1f8 100644 (file)
@@ -8,7 +8,7 @@ fn hof<F>(_: F) where F: FnMut(()) {}
 
 fn ice() {
     hof(|c| match c {
-        A::new() => (), //~ ERROR expected tuple struct or tuple variant, found method
+        A::new() => (), //~ ERROR expected tuple struct or tuple variant, found associated function
         _ => ()
     })
 }
index 5d6632f2fc2ec96d78aa7f3f7abeef316e96250a..2482d632695cce2d0a72aab2db5b04fe229ea7d6 100644 (file)
@@ -1,4 +1,4 @@
-error[E0164]: expected tuple struct or tuple variant, found method `A::new`
+error[E0164]: expected tuple struct or tuple variant, found associated function `A::new`
   --> $DIR/fn-in-pat.rs:11:9
    |
 LL |         A::new() => (),
diff --git a/src/test/ui/generator-yielding-or-returning-itself.rs b/src/test/ui/generator-yielding-or-returning-itself.rs
deleted file mode 100644 (file)
index 30788e3..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-#![feature(generator_trait)]
-#![feature(generators)]
-
-// Test that we cannot create a generator that returns a value of its
-// own type.
-
-use std::ops::Generator;
-
-pub fn want_cyclic_generator_return<T>(_: T)
-    where T: Generator<Yield = (), Return = T>
-{
-}
-
-fn supply_cyclic_generator_return() {
-    want_cyclic_generator_return(|| {
-        //~^ ERROR type mismatch
-        if false { yield None.unwrap(); }
-        None.unwrap()
-    })
-}
-
-pub fn want_cyclic_generator_yield<T>(_: T)
-    where T: Generator<Yield = T, Return = ()>
-{
-}
-
-fn supply_cyclic_generator_yield() {
-    want_cyclic_generator_yield(|| {
-        //~^ ERROR type mismatch
-        if false { yield None.unwrap(); }
-        None.unwrap()
-    })
-}
-
-fn main() { }
diff --git a/src/test/ui/generator-yielding-or-returning-itself.stderr b/src/test/ui/generator-yielding-or-returning-itself.stderr
deleted file mode 100644 (file)
index fc8064d..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-error[E0271]: type mismatch resolving `<[generator@$DIR/generator-yielding-or-returning-itself.rs:15:34: 19:6 _] as std::ops::Generator>::Return == [generator@$DIR/generator-yielding-or-returning-itself.rs:15:34: 19:6 _]`
-  --> $DIR/generator-yielding-or-returning-itself.rs:15:5
-   |
-LL | pub fn want_cyclic_generator_return<T>(_: T)
-   |        ----------------------------
-LL |     where T: Generator<Yield = (), Return = T>
-   |                                    ---------- required by this bound in `want_cyclic_generator_return`
-...
-LL |     want_cyclic_generator_return(|| {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size
-   |
-   = note: closures cannot capture themselves or take themselves as argument;
-           this error may be the result of a recent compiler bug-fix,
-           see issue #46062 <https://github.com/rust-lang/rust/issues/46062>
-           for more information
-
-error[E0271]: type mismatch resolving `<[generator@$DIR/generator-yielding-or-returning-itself.rs:28:33: 32:6 _] as std::ops::Generator>::Yield == [generator@$DIR/generator-yielding-or-returning-itself.rs:28:33: 32:6 _]`
-  --> $DIR/generator-yielding-or-returning-itself.rs:28:5
-   |
-LL | pub fn want_cyclic_generator_yield<T>(_: T)
-   |        ---------------------------
-LL |     where T: Generator<Yield = T, Return = ()>
-   |                        --------- required by this bound in `want_cyclic_generator_yield`
-...
-LL |     want_cyclic_generator_yield(|| {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size
-   |
-   = note: closures cannot capture themselves or take themselves as argument;
-           this error may be the result of a recent compiler bug-fix,
-           see issue #46062 <https://github.com/rust-lang/rust/issues/46062>
-           for more information
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0271`.
diff --git a/src/test/ui/generator/discriminant.rs b/src/test/ui/generator/discriminant.rs
new file mode 100644 (file)
index 0000000..8a0f8a3
--- /dev/null
@@ -0,0 +1,134 @@
+//! Tests that generator discriminant sizes and ranges are chosen optimally and that they are
+//! reflected in the output of `mem::discriminant`.
+
+// run-pass
+
+#![feature(generators, generator_trait, core_intrinsics)]
+
+use std::intrinsics::discriminant_value;
+use std::marker::Unpin;
+use std::mem::size_of_val;
+use std::{cmp, ops::*};
+
+macro_rules! yield25 {
+    ($e:expr) => {
+        yield $e;
+        yield $e;
+        yield $e;
+        yield $e;
+        yield $e;
+
+        yield $e;
+        yield $e;
+        yield $e;
+        yield $e;
+        yield $e;
+
+        yield $e;
+        yield $e;
+        yield $e;
+        yield $e;
+        yield $e;
+
+        yield $e;
+        yield $e;
+        yield $e;
+        yield $e;
+        yield $e;
+
+        yield $e;
+        yield $e;
+        yield $e;
+        yield $e;
+        yield $e;
+    };
+}
+
+/// Yields 250 times.
+macro_rules! yield250 {
+    () => {
+        yield250!(())
+    };
+
+    ($e:expr) => {
+        yield25!($e);
+        yield25!($e);
+        yield25!($e);
+        yield25!($e);
+        yield25!($e);
+
+        yield25!($e);
+        yield25!($e);
+        yield25!($e);
+        yield25!($e);
+        yield25!($e);
+    };
+}
+
+fn cycle(gen: impl Generator<()> + Unpin, expected_max_discr: u64) {
+    let mut gen = Box::pin(gen);
+    let mut max_discr = 0;
+    loop {
+        max_discr = cmp::max(max_discr, discriminant_value(gen.as_mut().get_mut()));
+        match gen.as_mut().resume(()) {
+            GeneratorState::Yielded(_) => {}
+            GeneratorState::Complete(_) => {
+                assert_eq!(max_discr, expected_max_discr);
+                return;
+            }
+        }
+    }
+}
+
+fn main() {
+    // Has only one invalid discr. value.
+    let gen_u8_tiny_niche = || {
+        || {
+            // 3 reserved variants
+
+            yield250!(); // 253 variants
+
+            yield; // 254
+            yield; // 255
+        }
+    };
+
+    // Uses all values in the u8 discriminant.
+    let gen_u8_full = || {
+        || {
+            // 3 reserved variants
+
+            yield250!(); // 253 variants
+
+            yield; // 254
+            yield; // 255
+            yield; // 256
+        }
+    };
+
+    // Barely needs a u16 discriminant.
+    let gen_u16 = || {
+        || {
+            // 3 reserved variants
+
+            yield250!(); // 253 variants
+
+            yield; // 254
+            yield; // 255
+            yield; // 256
+            yield; // 257
+        }
+    };
+
+    assert_eq!(size_of_val(&gen_u8_tiny_niche()), 1);
+    assert_eq!(size_of_val(&Some(gen_u8_tiny_niche())), 1); // uses niche
+    assert_eq!(size_of_val(&Some(Some(gen_u8_tiny_niche()))), 2); // cannot use niche anymore
+    assert_eq!(size_of_val(&gen_u8_full()), 1);
+    assert_eq!(size_of_val(&Some(gen_u8_full())), 2); // cannot use niche
+    assert_eq!(size_of_val(&gen_u16()), 2);
+    assert_eq!(size_of_val(&Some(gen_u16())), 2); // uses niche
+
+    cycle(gen_u8_tiny_niche(), 254);
+    cycle(gen_u8_full(), 255);
+    cycle(gen_u16(), 256);
+}
diff --git a/src/test/ui/generator/generator-yielding-or-returning-itself.rs b/src/test/ui/generator/generator-yielding-or-returning-itself.rs
new file mode 100644 (file)
index 0000000..30788e3
--- /dev/null
@@ -0,0 +1,35 @@
+#![feature(generator_trait)]
+#![feature(generators)]
+
+// Test that we cannot create a generator that returns a value of its
+// own type.
+
+use std::ops::Generator;
+
+pub fn want_cyclic_generator_return<T>(_: T)
+    where T: Generator<Yield = (), Return = T>
+{
+}
+
+fn supply_cyclic_generator_return() {
+    want_cyclic_generator_return(|| {
+        //~^ ERROR type mismatch
+        if false { yield None.unwrap(); }
+        None.unwrap()
+    })
+}
+
+pub fn want_cyclic_generator_yield<T>(_: T)
+    where T: Generator<Yield = T, Return = ()>
+{
+}
+
+fn supply_cyclic_generator_yield() {
+    want_cyclic_generator_yield(|| {
+        //~^ ERROR type mismatch
+        if false { yield None.unwrap(); }
+        None.unwrap()
+    })
+}
+
+fn main() { }
diff --git a/src/test/ui/generator/generator-yielding-or-returning-itself.stderr b/src/test/ui/generator/generator-yielding-or-returning-itself.stderr
new file mode 100644 (file)
index 0000000..fc8064d
--- /dev/null
@@ -0,0 +1,35 @@
+error[E0271]: type mismatch resolving `<[generator@$DIR/generator-yielding-or-returning-itself.rs:15:34: 19:6 _] as std::ops::Generator>::Return == [generator@$DIR/generator-yielding-or-returning-itself.rs:15:34: 19:6 _]`
+  --> $DIR/generator-yielding-or-returning-itself.rs:15:5
+   |
+LL | pub fn want_cyclic_generator_return<T>(_: T)
+   |        ----------------------------
+LL |     where T: Generator<Yield = (), Return = T>
+   |                                    ---------- required by this bound in `want_cyclic_generator_return`
+...
+LL |     want_cyclic_generator_return(|| {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size
+   |
+   = note: closures cannot capture themselves or take themselves as argument;
+           this error may be the result of a recent compiler bug-fix,
+           see issue #46062 <https://github.com/rust-lang/rust/issues/46062>
+           for more information
+
+error[E0271]: type mismatch resolving `<[generator@$DIR/generator-yielding-or-returning-itself.rs:28:33: 32:6 _] as std::ops::Generator>::Yield == [generator@$DIR/generator-yielding-or-returning-itself.rs:28:33: 32:6 _]`
+  --> $DIR/generator-yielding-or-returning-itself.rs:28:5
+   |
+LL | pub fn want_cyclic_generator_yield<T>(_: T)
+   |        ---------------------------
+LL |     where T: Generator<Yield = T, Return = ()>
+   |                        --------- required by this bound in `want_cyclic_generator_yield`
+...
+LL |     want_cyclic_generator_yield(|| {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size
+   |
+   = note: closures cannot capture themselves or take themselves as argument;
+           this error may be the result of a recent compiler bug-fix,
+           see issue #46062 <https://github.com/rust-lang/rust/issues/46062>
+           for more information
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/src/test/ui/generator/issue-64620-yield-array-element.rs b/src/test/ui/generator/issue-64620-yield-array-element.rs
new file mode 100644 (file)
index 0000000..2cbe8f5
--- /dev/null
@@ -0,0 +1,9 @@
+// Regression test for #64620
+
+#![feature(generators)]
+
+pub fn crash(arr: [usize; 1]) {
+    yield arr[0]; //~ ERROR: yield expression outside of generator literal
+}
+
+fn main() {}
diff --git a/src/test/ui/generator/issue-64620-yield-array-element.stderr b/src/test/ui/generator/issue-64620-yield-array-element.stderr
new file mode 100644 (file)
index 0000000..48383c2
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0627]: yield expression outside of generator literal
+  --> $DIR/issue-64620-yield-array-element.rs:6:5
+   |
+LL |     yield arr[0];
+   |     ^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0627`.
index 60004f3b0aeee59529d1d6b6993844a8087ce8f4..ccc141860aa5f908683fb4d3ada63de8a96c1ff6 100644 (file)
@@ -4,11 +4,15 @@
 
 use std::ops::{Generator, GeneratorState};
 
+fn mkstr(my_name: String, my_mood: String) -> String {
+    format!("{} is {}", my_name.trim(), my_mood.trim())
+}
+
 fn my_scenario() -> impl Generator<String, Yield = &'static str, Return = String> {
     |_arg: String| {
         let my_name = yield "What is your name?";
         let my_mood = yield "How are you feeling?";
-        format!("{} is {}", my_name.trim(), my_mood.trim())
+        mkstr(my_name, my_mood)
     }
 }
 
diff --git a/src/test/ui/generator/resume-arg-size.rs b/src/test/ui/generator/resume-arg-size.rs
new file mode 100644 (file)
index 0000000..4f08ac0
--- /dev/null
@@ -0,0 +1,28 @@
+#![feature(generators)]
+
+// run-pass
+
+use std::mem::size_of_val;
+
+fn main() {
+    // Generator taking a `Copy`able resume arg.
+    let gen_copy = |mut x: usize| {
+        loop {
+            drop(x);
+            x = yield;
+        }
+    };
+
+    // Generator taking a non-`Copy` resume arg.
+    let gen_move = |mut x: Box<usize>| {
+        loop {
+            drop(x);
+            x = yield;
+        }
+    };
+
+    // Neither of these generators have the resume arg live across the `yield`, so they should be
+    // 4 Bytes in size (only storing the discriminant)
+    assert_eq!(size_of_val(&gen_copy), 1);
+    assert_eq!(size_of_val(&gen_move), 1);
+}
index 2864fbb2f3c8d4dcfe565f9b0e4df00586a5caa1..74c60d98154dd3da107bb7672c5d40afa5129c65 100644 (file)
@@ -58,7 +58,7 @@ fn overlap_move_points() -> impl Generator<Yield = (), Return = ()> {
     }
 }
 
-fn overlap_x_and_y() -> impl Generator<Yield = (), Return = ()>{
+fn overlap_x_and_y() -> impl Generator<Yield = (), Return = ()> {
     static || {
         let x = Foo([0; FOO_SIZE]);
         yield;
@@ -70,8 +70,8 @@ fn overlap_x_and_y() -> impl Generator<Yield = (), Return = ()>{
 }
 
 fn main() {
-    assert_eq!(1028, std::mem::size_of_val(&move_before_yield()));
-    assert_eq!(1032, std::mem::size_of_val(&move_before_yield_with_noop()));
-    assert_eq!(2056, std::mem::size_of_val(&overlap_move_points()));
-    assert_eq!(1032, std::mem::size_of_val(&overlap_x_and_y()));
+    assert_eq!(1025, std::mem::size_of_val(&move_before_yield()));
+    assert_eq!(1026, std::mem::size_of_val(&move_before_yield_with_noop()));
+    assert_eq!(2051, std::mem::size_of_val(&overlap_move_points()));
+    assert_eq!(1026, std::mem::size_of_val(&overlap_x_and_y()));
 }
index a297ee43de9695dc0e7a5c7e32de0126b1130eba..22d40db3f2678e248ae13d11b9351d0a6a900cad 100644 (file)
@@ -6,3 +6,4 @@ LL |     |(), ()| {
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0628`.
index 522e23ca43d78f8d8f30ba8f8e749f4f82e4587d..6eb25a92f34133587558e8196be83835d03d9a88 100644 (file)
@@ -3,7 +3,7 @@
 
 trait Foo {
     type Bar<,>;
-    //~^ ERROR expected one of `>`, `const`, identifier, or lifetime, found `,`
+    //~^ ERROR expected one of `#`, `>`, `const`, identifier, or lifetime, found `,`
 }
 
 fn main() {}
index bd5708d81403776643aeeb4f416c30cff3ef8fe3..1599d683ad6dd7dc078b9e9b01d0c80a446cd9c8 100644 (file)
@@ -1,10 +1,10 @@
-error: expected one of `>`, `const`, identifier, or lifetime, found `,`
+error: expected one of `#`, `>`, `const`, identifier, or lifetime, found `,`
   --> $DIR/empty_generics.rs:5:14
    |
 LL | trait Foo {
    |           - while parsing this item list starting here
 LL |     type Bar<,>;
-   |              ^ expected one of `>`, `const`, identifier, or lifetime
+   |              ^ expected one of `#`, `>`, `const`, identifier, or lifetime
 LL |
 LL | }
    | - the item list ends here
diff --git a/src/test/ui/hygiene/macro-metavars-legacy.rs b/src/test/ui/hygiene/macro-metavars-legacy.rs
new file mode 100644 (file)
index 0000000..09070f0
--- /dev/null
@@ -0,0 +1,29 @@
+// Ensure macro metavariables are compared with legacy hygiene
+
+#![feature(rustc_attrs)]
+
+// run-pass
+
+macro_rules! make_mac {
+    ( $($dollar:tt $arg:ident),+ ) => {
+        macro_rules! mac {
+            ( $($dollar $arg : ident),+ ) => {
+                $( $dollar $arg )-+
+            }
+        }
+    }
+}
+
+macro_rules! show_hygiene {
+    ( $dollar:tt $arg:ident ) => {
+        make_mac!($dollar $arg, $dollar arg);
+    }
+}
+
+show_hygiene!( $arg );
+
+fn main() {
+    let x = 5;
+    let y = 3;
+    assert_eq!(2, mac!(x, y));
+}
diff --git a/src/test/ui/hygiene/macro-metavars-transparent.rs b/src/test/ui/hygiene/macro-metavars-transparent.rs
new file mode 100644 (file)
index 0000000..e475b57
--- /dev/null
@@ -0,0 +1,24 @@
+// Ensure macro metavariables are not compared without removing transparent
+// marks.
+
+#![feature(rustc_attrs)]
+
+// run-pass
+
+#[rustc_macro_transparency = "transparent"]
+macro_rules! k {
+    ($($s:tt)*) => {
+        macro_rules! m {
+            ($y:tt) => {
+                $($s)*
+            }
+        }
+    }
+}
+
+k!(1 + $y);
+
+fn main() {
+    let x = 2;
+    assert_eq!(3, m!(x));
+}
diff --git a/src/test/ui/if-attrs/bad-cfg.rs b/src/test/ui/if-attrs/bad-cfg.rs
new file mode 100644 (file)
index 0000000..3f84929
--- /dev/null
@@ -0,0 +1,5 @@
+#![feature(stmt_expr_attributes)]
+
+fn main() {
+    let _ = #[cfg(FALSE)] if true {}; //~ ERROR removing an expression
+}
diff --git a/src/test/ui/if-attrs/bad-cfg.stderr b/src/test/ui/if-attrs/bad-cfg.stderr
new file mode 100644 (file)
index 0000000..8a28908
--- /dev/null
@@ -0,0 +1,8 @@
+error: removing an expression is not supported in this position
+  --> $DIR/bad-cfg.rs:4:13
+   |
+LL |     let _ = #[cfg(FALSE)] if true {};
+   |             ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/if-attrs/builtin-if-attr.rs b/src/test/ui/if-attrs/builtin-if-attr.rs
new file mode 100644 (file)
index 0000000..7e29066
--- /dev/null
@@ -0,0 +1,12 @@
+// check-pass
+
+fn main() {
+    #[allow(unused_variables)]
+    if true {
+        let a = 1;
+    } else if false {
+        let b = 1;
+    } else {
+        let c = 1;
+    }
+}
diff --git a/src/test/ui/if-attrs/cfg-false-if-attr.rs b/src/test/ui/if-attrs/cfg-false-if-attr.rs
new file mode 100644 (file)
index 0000000..1f77a1b
--- /dev/null
@@ -0,0 +1,43 @@
+// check-pass
+
+#[cfg(FALSE)]
+fn simple_attr() {
+    #[attr] if true {}
+    #[allow_warnings] if true {}
+}
+
+#[cfg(FALSE)]
+fn if_else_chain() {
+    #[first_attr] if true {
+    } else if false {
+    } else {
+    }
+}
+
+#[cfg(FALSE)]
+fn if_let() {
+    #[attr] if let Some(_) = Some(true) {}
+}
+
+fn bar() {
+    #[cfg(FALSE)]
+    if true {
+        let x: () = true; // Should not error due to the #[cfg(FALSE)]
+    }
+
+    #[cfg_attr(not(unset_attr), cfg(FALSE))]
+    if true {
+        let a: () = true; // Should not error due to the applied #[cfg(FALSE)]
+    }
+}
+
+macro_rules! custom_macro {
+    ($expr:expr) => {}
+}
+
+custom_macro! {
+    #[attr] if true {}
+}
+
+
+fn main() {}
diff --git a/src/test/ui/if-attrs/else-attrs.rs b/src/test/ui/if-attrs/else-attrs.rs
new file mode 100644 (file)
index 0000000..85da7cf
--- /dev/null
@@ -0,0 +1,25 @@
+#[cfg(FALSE)]
+fn if_else_parse_error() {
+    if true {
+    } #[attr] else if false { //~ ERROR expected
+    }
+}
+
+#[cfg(FALSE)]
+fn else_attr_ifparse_error() {
+    if true {
+    } else #[attr] if false { //~ ERROR outer attributes are not allowed
+    } else {
+    }
+}
+
+#[cfg(FALSE)]
+fn else_parse_error() {
+    if true {
+    } else if false {
+    } #[attr] else { //~ ERROR expected
+    }
+}
+
+fn main() {
+}
diff --git a/src/test/ui/if-attrs/else-attrs.stderr b/src/test/ui/if-attrs/else-attrs.stderr
new file mode 100644 (file)
index 0000000..2733377
--- /dev/null
@@ -0,0 +1,26 @@
+error: expected expression, found keyword `else`
+  --> $DIR/else-attrs.rs:4:15
+   |
+LL |     } #[attr] else if false {
+   |               ^^^^ expected expression
+
+error: outer attributes are not allowed on `if` and `else` branches
+  --> $DIR/else-attrs.rs:11:12
+   |
+LL |       } else #[attr] if false {
+   |  _______----_^^^^^^^_-
+   | |       |    |
+   | |       |    help: remove the attributes
+   | |       the branch belongs to this `else`
+LL | |     } else {
+LL | |     }
+   | |_____- the attributes are attached to this branch
+
+error: expected expression, found keyword `else`
+  --> $DIR/else-attrs.rs:20:15
+   |
+LL |     } #[attr] else {
+   |               ^^^^ expected expression
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/if-attrs/gate-whole-expr.rs b/src/test/ui/if-attrs/gate-whole-expr.rs
new file mode 100644 (file)
index 0000000..63772d5
--- /dev/null
@@ -0,0 +1,15 @@
+// run-pass
+
+fn main() {
+    let x = 1;
+
+    #[cfg(FALSE)]
+    if false {
+        x = 2;
+    } else if true {
+        x = 3;
+    } else {
+        x = 4;
+    }
+    assert_eq!(x, 1);
+}
diff --git a/src/test/ui/if-attrs/let-chains-attr.rs b/src/test/ui/if-attrs/let-chains-attr.rs
new file mode 100644 (file)
index 0000000..5237a9f
--- /dev/null
@@ -0,0 +1,13 @@
+// check-pass
+
+#![feature(let_chains)] //~ WARN the feature `let_chains` is incomplete
+
+#[cfg(FALSE)]
+fn foo() {
+    #[attr]
+    if let Some(_) = Some(true) && let Ok(_) = Ok(1) {
+    } else if let Some(false) = Some(true) {
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/if-attrs/let-chains-attr.stderr b/src/test/ui/if-attrs/let-chains-attr.stderr
new file mode 100644 (file)
index 0000000..a6c91bb
--- /dev/null
@@ -0,0 +1,8 @@
+warning: the feature `let_chains` is incomplete and may cause the compiler to crash
+  --> $DIR/let-chains-attr.rs:3:12
+   |
+LL | #![feature(let_chains)]
+   |            ^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+
diff --git a/src/test/ui/if-attrs/stmt-expr-gated.rs b/src/test/ui/if-attrs/stmt-expr-gated.rs
new file mode 100644 (file)
index 0000000..38599c8
--- /dev/null
@@ -0,0 +1,6 @@
+fn main() {
+    let _ = #[deny(warnings)] if true { //~ ERROR attributes on expressions
+    } else if false {
+    } else {
+    };
+}
diff --git a/src/test/ui/if-attrs/stmt-expr-gated.stderr b/src/test/ui/if-attrs/stmt-expr-gated.stderr
new file mode 100644 (file)
index 0000000..47dac39
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0658]: attributes on expressions are experimental
+  --> $DIR/stmt-expr-gated.rs:2:13
+   |
+LL |     let _ = #[deny(warnings)] if true {
+   |             ^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
+   = help: add `#![feature(stmt_expr_attributes)]` 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/impl-trait/issue-57200.rs b/src/test/ui/impl-trait/issue-57200.rs
new file mode 100644 (file)
index 0000000..e0c71d1
--- /dev/null
@@ -0,0 +1,15 @@
+// Regression test for #57200
+// FIXME: The error is temporary hack, we'll revisit here at some point.
+
+#![feature(impl_trait_in_bindings)]
+#![allow(incomplete_features)]
+
+fn bug<'a, 'b, T>()
+where
+    'a: 'b,
+{
+    let f: impl Fn(&'a T) -> &'b T = |x| x;
+    //~^ ERROR: lifetimes in impl Trait types in bindings are not currently supported
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/issue-57200.stderr b/src/test/ui/impl-trait/issue-57200.stderr
new file mode 100644 (file)
index 0000000..b44f332
--- /dev/null
@@ -0,0 +1,8 @@
+error: lifetimes in impl Trait types in bindings are not currently supported
+  --> $DIR/issue-57200.rs:11:12
+   |
+LL |     let f: impl Fn(&'a T) -> &'b T = |x| x;
+   |            ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/impl-trait/issue-57201.rs b/src/test/ui/impl-trait/issue-57201.rs
new file mode 100644 (file)
index 0000000..c1a98d8
--- /dev/null
@@ -0,0 +1,15 @@
+// Regression test for #57201
+// FIXME: The error is temporary hack, we'll revisit here at some point.
+
+#![feature(impl_trait_in_bindings)]
+#![allow(incomplete_features)]
+
+fn bug<'a, 'b, T>()
+where
+    'a: 'b,
+{
+    let f: &impl Fn(&'a T) -> &'b T = &|x| x;
+    //~^ ERROR: lifetimes in impl Trait types in bindings are not currently supported
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/issue-57201.stderr b/src/test/ui/impl-trait/issue-57201.stderr
new file mode 100644 (file)
index 0000000..462b17b
--- /dev/null
@@ -0,0 +1,8 @@
+error: lifetimes in impl Trait types in bindings are not currently supported
+  --> $DIR/issue-57201.rs:11:13
+   |
+LL |     let f: &impl Fn(&'a T) -> &'b T = &|x| x;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/impl-trait/issue-60473.rs b/src/test/ui/impl-trait/issue-60473.rs
new file mode 100644 (file)
index 0000000..50cf0c8
--- /dev/null
@@ -0,0 +1,17 @@
+// Regression test for #60473
+
+#![feature(impl_trait_in_bindings)]
+#![allow(incomplete_features)]
+
+struct A<'a>(&'a ());
+
+trait Trait<T> {
+}
+
+impl<T> Trait<T> for () {
+}
+
+fn main() {
+    let x: impl Trait<A> = (); // FIXME: The error doesn't seem correct.
+    //~^ ERROR: opaque type expands to a recursive type
+}
diff --git a/src/test/ui/impl-trait/issue-60473.stderr b/src/test/ui/impl-trait/issue-60473.stderr
new file mode 100644 (file)
index 0000000..2d95be4
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0720]: opaque type expands to a recursive type
+  --> $DIR/issue-60473.rs:15:12
+   |
+LL |     let x: impl Trait<A> = (); // FIXME: The error doesn't seem correct.
+   |            ^^^^^^^^^^^^^ expands to a recursive type
+   |
+   = note: type resolves to itself
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0720`.
diff --git a/src/test/ui/impl-trait/issue-67166.rs b/src/test/ui/impl-trait/issue-67166.rs
new file mode 100644 (file)
index 0000000..de7433a
--- /dev/null
@@ -0,0 +1,11 @@
+// Regression test for #67166
+
+#![feature(impl_trait_in_bindings)]
+#![allow(incomplete_features)]
+
+pub fn run() {
+    let _foo: Box<impl Copy + '_> = Box::new(()); // FIXME: The error doesn't much make sense.
+    //~^ ERROR: opaque type expands to a recursive type
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/issue-67166.stderr b/src/test/ui/impl-trait/issue-67166.stderr
new file mode 100644 (file)
index 0000000..56cba3c
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0720]: opaque type expands to a recursive type
+  --> $DIR/issue-67166.rs:7:19
+   |
+LL |     let _foo: Box<impl Copy + '_> = Box::new(()); // FIXME: The error doesn't much make sense.
+   |                   ^^^^^^^^^^^^^^ expands to a recursive type
+   |
+   = note: type resolves to itself
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0720`.
index 1c3b5ac76138f2eb56f25c2effda0fb28a494d14..00f3490991b5235771fb2362207cb00f53f09fa8 100644 (file)
@@ -12,7 +12,7 @@ impl<'a> LifetimeTrait<'a> for &'a i32 {}
 fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
 //~^ ERROR cannot infer an appropriate lifetime
 
-// Tests that a closure type contianing 'b cannot be returned from a type where
+// Tests that a closure type containing 'b cannot be returned from a type where
 // only 'a was expected.
 fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) {
     //~^ ERROR lifetime mismatch
index f16d2adb3656e9f155437d852d43ef8d68adf179..490c08446b5a800d8d4ec4416d09b39f88466fcd 100644 (file)
@@ -4,11 +4,26 @@ error[E0603]: struct import `ParseOptions` is private
 LL | pub use parser::ParseOptions;
    |                 ^^^^^^^^^^^^ this struct import is private
    |
-note: the struct import `ParseOptions` is defined here
+note: the struct import `ParseOptions` is defined here...
   --> $DIR/issue-55884-2.rs:9:9
    |
 LL |     use ParseOptions;
    |         ^^^^^^^^^^^^
+note: ...and refers to the struct import `ParseOptions` which is defined here...
+  --> $DIR/issue-55884-2.rs:12:9
+   |
+LL | pub use parser::ParseOptions;
+   |         ^^^^^^^^^^^^^^^^^^^^ consider importing it directly
+note: ...and refers to the struct import `ParseOptions` which is defined here...
+  --> $DIR/issue-55884-2.rs:6:13
+   |
+LL |     pub use options::*;
+   |             ^^^^^^^^^^ consider importing it directly
+note: ...and refers to the struct `ParseOptions` which is defined here
+  --> $DIR/issue-55884-2.rs:2:5
+   |
+LL |     pub struct ParseOptions {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ consider importing it directly
 
 error: aborting due to previous error
 
index 7b0d63574ec8e8c4d6d2442a65e3de359f8bb38c..d63fbc7ec6781d6c378f7e6e6a60d7dc31c734f9 100644 (file)
@@ -16,11 +16,16 @@ error[E0603]: module import `foo` is private
 LL |     use b::a::foo::S;
    |               ^^^ this module import is private
    |
-note: the module import `foo` is defined here
+note: the module import `foo` is defined here...
   --> $DIR/reexports.rs:21:17
    |
 LL |         pub use super::foo; // This is OK since the value `foo` is visible enough.
    |                 ^^^^^^^^^^
+note: ...and refers to the module `foo` which is defined here
+  --> $DIR/reexports.rs:16:5
+   |
+LL |     mod foo {
+   |     ^^^^^^^
 
 error[E0603]: module import `foo` is private
   --> $DIR/reexports.rs:34:15
@@ -28,11 +33,16 @@ error[E0603]: module import `foo` is private
 LL |     use b::b::foo::S as T;
    |               ^^^ this module import is private
    |
-note: the module import `foo` is defined here
+note: the module import `foo` is defined here...
   --> $DIR/reexports.rs:26:17
    |
 LL |         pub use super::*; // This is also OK since the value `foo` is visible enough.
    |                 ^^^^^^^^
+note: ...and refers to the module `foo` which is defined here
+  --> $DIR/reexports.rs:16:5
+   |
+LL |     mod foo {
+   |     ^^^^^^^
 
 warning: glob import doesn't reexport anything because no candidate is public enough
   --> $DIR/reexports.rs:9:17
index a304fc9356b510fdf4f5fdec972f095aa8215e77..ce905572f2a8cee736a5e33f3e30514097e5bb50 100644 (file)
@@ -1,3 +1,4 @@
+// compile-flags: -O
 // run-pass
 
 #![allow(unused_must_use)]
 
 #![feature(intrinsics)]
 
-use std::thread;
-
-extern "rust-intrinsic" {
-    pub fn init<T>() -> T;
-}
+use std::{mem, thread};
 
 const SIZE: usize = 1024 * 1024;
 
 fn main() {
     // do the test in a new thread to avoid (spurious?) stack overflows
     thread::spawn(|| {
-        let _memory: [u8; SIZE] = unsafe { init() };
+        let _memory: [u8; SIZE] = unsafe { mem::zeroed() };
     }).join();
 }
diff --git a/src/test/ui/init-unsafe.rs b/src/test/ui/init-unsafe.rs
deleted file mode 100644 (file)
index 3d65cfc..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#![allow(deprecated)]
-#![feature(core_intrinsics)]
-
-use std::intrinsics::{init};
-
-// Test that the `init` intrinsic is really unsafe
-pub fn main() {
-    let stuff = init::<isize>(); //~ ERROR call to unsafe function is unsafe
-}
diff --git a/src/test/ui/init-unsafe.stderr b/src/test/ui/init-unsafe.stderr
deleted file mode 100644 (file)
index e112631..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
-  --> $DIR/init-unsafe.rs:8:17
-   |
-LL |     let stuff = init::<isize>();
-   |                 ^^^^^^^^^^^^^^^ call to unsafe function
-   |
-   = note: consult the function's documentation for information on how to avoid undefined behavior
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0133`.
index 75b4ec365fe03af67be7ba03ecd505218115639a..b672f1ed26e8d8d1dfdd81f57fa2cf929fa5f42b 100644 (file)
@@ -5,7 +5,6 @@
 
 mod rusti {
     extern "rust-intrinsic" {
-        pub fn init<T>() -> T;
         pub fn move_val_init<T>(dst: *mut T, src: T);
     }
 }
@@ -15,17 +14,17 @@ pub fn main() {
         // sanity check
         check_drops_state(0, None);
 
-        let mut x: Box<D> = box D(1);
-        assert_eq!(x.0, 1);
+        let mut x: Option<Box<D>> = Some(box D(1));
+        assert_eq!(x.as_ref().unwrap().0, 1);
 
         // A normal overwrite, to demonstrate `check_drops_state`.
-        x = box D(2);
+        x = Some(box D(2));
 
         // At this point, one destructor has run, because the
         // overwrite of `x` drops its initial value.
         check_drops_state(1, Some(1));
 
-        let mut y: Box<D> = rusti::init();
+        let mut y: Option<Box<D>> = std::mem::zeroed();
 
         // An initial binding does not overwrite anything.
         check_drops_state(1, Some(1));
@@ -51,9 +50,9 @@ pub fn main() {
         // during such a destructor call. We do so after the end of
         // this scope.
 
-        assert_eq!(y.0, 2);
-        y.0 = 3;
-        assert_eq!(y.0, 3);
+        assert_eq!(y.as_ref().unwrap().0, 2);
+        y.as_mut().unwrap().0 = 3;
+        assert_eq!(y.as_ref().unwrap().0, 3);
 
         check_drops_state(1, Some(1));
     }
diff --git a/src/test/ui/intrinsics/intrinsic-uninit.rs b/src/test/ui/intrinsics/intrinsic-uninit.rs
deleted file mode 100644 (file)
index 9555efb..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-// run-pass
-// pretty-expanded FIXME #23616
-
-#![feature(intrinsics)]
-
-mod rusti {
-    extern "rust-intrinsic" {
-        pub fn uninit<T>() -> T;
-    }
-}
-pub fn main() {
-    let _a : isize = unsafe {rusti::uninit()};
-}
diff --git a/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs b/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs
new file mode 100644 (file)
index 0000000..02f8eca
--- /dev/null
@@ -0,0 +1,170 @@
+// run-pass
+// ignore-wasm32-bare compiled with panic=abort by default
+
+// This test checks panic emitted from `mem::{uninitialized,zeroed}`.
+
+#![feature(never_type)]
+#![allow(deprecated, invalid_value)]
+
+use std::{
+    mem::{self, MaybeUninit, ManuallyDrop},
+    panic,
+    ptr::NonNull,
+    num,
+};
+
+#[allow(dead_code)]
+struct Foo {
+    x: u8,
+    y: !,
+}
+
+enum Bar {}
+
+#[allow(dead_code)]
+enum OneVariant { Variant(i32) }
+
+// An enum with ScalarPair layout
+#[allow(dead_code)]
+enum LR {
+    Left(i64),
+    Right(i64),
+}
+#[allow(dead_code, non_camel_case_types)]
+enum LR_NonZero {
+    Left(num::NonZeroI64),
+    Right(num::NonZeroI64),
+}
+
+fn test_panic_msg<T>(op: impl (FnOnce() -> T) + panic::UnwindSafe, msg: &str) {
+    let err = panic::catch_unwind(op).err();
+    assert_eq!(
+        err.as_ref().and_then(|a| a.downcast_ref::<String>()).map(|s| &**s),
+        Some(msg)
+    );
+}
+
+fn main() {
+    unsafe {
+        // Uninhabited types
+        test_panic_msg(
+            || mem::uninitialized::<!>(),
+            "attempted to instantiate uninhabited type `!`"
+        );
+        test_panic_msg(
+            || mem::zeroed::<!>(),
+            "attempted to instantiate uninhabited type `!`"
+        );
+        test_panic_msg(
+            || MaybeUninit::<!>::uninit().assume_init(),
+            "attempted to instantiate uninhabited type `!`"
+        );
+
+        test_panic_msg(
+            || mem::uninitialized::<Foo>(),
+            "attempted to instantiate uninhabited type `Foo`"
+        );
+        test_panic_msg(
+            || mem::zeroed::<Foo>(),
+            "attempted to instantiate uninhabited type `Foo`"
+        );
+        test_panic_msg(
+            || MaybeUninit::<Foo>::uninit().assume_init(),
+            "attempted to instantiate uninhabited type `Foo`"
+        );
+
+        test_panic_msg(
+            || mem::uninitialized::<Bar>(),
+            "attempted to instantiate uninhabited type `Bar`"
+        );
+        test_panic_msg(
+            || mem::zeroed::<Bar>(),
+            "attempted to instantiate uninhabited type `Bar`"
+        );
+        test_panic_msg(
+            || MaybeUninit::<Bar>::uninit().assume_init(),
+            "attempted to instantiate uninhabited type `Bar`"
+        );
+
+        // Types that do not like zero-initialziation
+        test_panic_msg(
+            || mem::uninitialized::<fn()>(),
+            "attempted to leave type `fn()` uninitialized, which is invalid"
+        );
+        test_panic_msg(
+            || mem::zeroed::<fn()>(),
+            "attempted to zero-initialize type `fn()`, which is invalid"
+        );
+
+        test_panic_msg(
+            || mem::uninitialized::<*const dyn Send>(),
+            "attempted to leave type `*const dyn std::marker::Send` uninitialized, which is invalid"
+        );
+        test_panic_msg(
+            || mem::zeroed::<*const dyn Send>(),
+            "attempted to zero-initialize type `*const dyn std::marker::Send`, which is invalid"
+        );
+
+        /* FIXME(#66151) we conservatively do not error here yet.
+        test_panic_msg(
+            || mem::uninitialized::<LR_NonZero>(),
+            "attempted to leave type `LR_NonZero` uninitialized, which is invalid"
+        );
+        test_panic_msg(
+            || mem::zeroed::<LR_NonZero>(),
+            "attempted to zero-initialize type `LR_NonZero`, which is invalid"
+        );
+
+        test_panic_msg(
+            || mem::uninitialized::<ManuallyDrop<LR_NonZero>>(),
+            "attempted to leave type `std::mem::ManuallyDrop<LR_NonZero>` uninitialized, \
+             which is invalid"
+        );
+        test_panic_msg(
+            || mem::zeroed::<ManuallyDrop<LR_NonZero>>(),
+            "attempted to zero-initialize type `std::mem::ManuallyDrop<LR_NonZero>`, \
+             which is invalid"
+        );
+
+        test_panic_msg(
+            || mem::uninitialized::<(NonNull<u32>, u32, u32)>(),
+            "attempted to leave type `(std::ptr::NonNull<u32>, u32, u32)` uninitialized, \
+                which is invalid"
+        );
+        test_panic_msg(
+            || mem::zeroed::<(NonNull<u32>, u32, u32)>(),
+            "attempted to zero-initialize type `(std::ptr::NonNull<u32>, u32, u32)`, \
+                which is invalid"
+        );
+        */
+
+        // Types that can be zero, but not uninit.
+        test_panic_msg(
+            || mem::uninitialized::<bool>(),
+            "attempted to leave type `bool` uninitialized, which is invalid"
+        );
+        test_panic_msg(
+            || mem::uninitialized::<LR>(),
+            "attempted to leave type `LR` uninitialized, which is invalid"
+        );
+        test_panic_msg(
+            || mem::uninitialized::<ManuallyDrop<LR>>(),
+            "attempted to leave type `std::mem::ManuallyDrop<LR>` uninitialized, which is invalid"
+        );
+
+        // Some things that should work.
+        let _val = mem::zeroed::<bool>();
+        let _val = mem::zeroed::<LR>();
+        let _val = mem::zeroed::<ManuallyDrop<LR>>();
+        let _val = mem::zeroed::<OneVariant>();
+        let _val = mem::zeroed::<Option<&'static i32>>();
+        let _val = mem::zeroed::<MaybeUninit<NonNull<u32>>>();
+        let _val = mem::uninitialized::<MaybeUninit<bool>>();
+
+        // These are UB because they have not been officially blessed, but we await the resolution
+        // of <https://github.com/rust-lang/unsafe-code-guidelines/issues/71> before doing
+        // anything about that.
+        let _val = mem::uninitialized::<i32>();
+        let _val = mem::uninitialized::<*const ()>();
+    }
+}
index c95df5b4534c11ce337d4b2c7c29d67a95301f20..52296042eb4a73b80b129fdda944822d3ee7e1cd 100644 (file)
@@ -1,10 +1,10 @@
 error[E0583]: file not found for module `baz`
-  --> $DIR/auxiliary/foo/bar.rs:1:9
+  --> $DIR/auxiliary/foo/bar.rs:1:1
    |
 LL | pub mod baz;
-   |         ^^^
+   | ^^^^^^^^^^^^
    |
-   = help: name the file either bar/baz.rs or bar/baz/mod.rs inside the directory "$DIR/auxiliary/foo"
+   = help: to create the module `baz`, create file "$DIR/auxiliary/foo/bar/baz.rs"
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/auxiliary/issue-69725.rs b/src/test/ui/issues/auxiliary/issue-69725.rs
new file mode 100644 (file)
index 0000000..13606e4
--- /dev/null
@@ -0,0 +1,8 @@
+#[derive(Clone)]
+pub struct Struct<A>(A);
+
+impl<A> Struct<A> {
+    pub fn new() -> Self {
+        todo!()
+    }
+}
index f76e7a4e44fd73af119bbe34629d54b005748752..b82b0b552e2dd6e15950b44356077a2f20e0ee24 100644 (file)
@@ -1,10 +1,10 @@
-error[E0521]: borrowed data escapes outside of method
+error[E0521]: borrowed data escapes outside of associated function
   --> $DIR/issue-16683.rs:4:9
    |
 LL |     fn b(&self) {
-   |          ----- `self` is a reference that is only valid in the method body
+   |          ----- `self` is a reference that is only valid in the associated function body
 LL |         self.a();
-   |         ^^^^^^^^ `self` escapes the method body here
+   |         ^^^^^^^^ `self` escapes the associated function body here
 
 error: aborting due to previous error
 
index 92e21f4dc1769fa22dcaec0c62285b43ac6451ab..23557b4d956aa642ba76e155e43566b15dd12c96 100644 (file)
@@ -1,10 +1,10 @@
-error[E0521]: borrowed data escapes outside of method
+error[E0521]: borrowed data escapes outside of associated function
   --> $DIR/issue-17758.rs:7:9
    |
 LL |     fn bar(&self) {
-   |            ----- `self` is a reference that is only valid in the method body
+   |            ----- `self` is a reference that is only valid in the associated function body
 LL |         self.foo();
-   |         ^^^^^^^^^^ `self` escapes the method body here
+   |         ^^^^^^^^^^ `self` escapes the associated function body here
 
 error: aborting due to previous error
 
index c9e8b61e50b5280269bd5c23fb9c9cac91ab5b54..3ceb58d1252d315c67e63d44b318aace5d719b31 100644 (file)
@@ -29,7 +29,7 @@
 
 
 type Type_8<'a,,> = &'a ();
-//~^ error: expected one of `>`, `const`, identifier, or lifetime, found `,`
+//~^ error: expected one of `#`, `>`, `const`, identifier, or lifetime, found `,`
 
 
 //type Type_9<T,,> = Box<T>; // error: expected identifier, found `,`
index 479469634c523b9847a4d3bfc875204a763defe6..e9f37e50fffec7e02ce674346c82b42f5f932c45 100644 (file)
@@ -1,8 +1,8 @@
-error: expected one of `>`, `const`, identifier, or lifetime, found `,`
+error: expected one of `#`, `>`, `const`, identifier, or lifetime, found `,`
   --> $DIR/issue-20616-8.rs:31:16
    |
 LL | type Type_8<'a,,> = &'a ();
-   |                ^ expected one of `>`, `const`, identifier, or lifetime
+   |                ^ expected one of `#`, `>`, `const`, identifier, or lifetime
 
 error: aborting due to previous error
 
index 1c509f26fd63aa8c90b1c02b2e996c8c007678ba..7f84284481e2f02e07fc82788163d6e01bf1d98d 100644 (file)
@@ -32,4 +32,4 @@
 
 
 type Type_9<T,,> = Box<T>;
-//~^ error: expected one of `>`, `const`, identifier, or lifetime, found `,`
+//~^ error: expected one of `#`, `>`, `const`, identifier, or lifetime, found `,`
index b7e3322b7aa9207dd393f9df4124882cf86e25a7..dc309d1bce1586c12e35eb3fae926ca6a246edf8 100644 (file)
@@ -1,8 +1,8 @@
-error: expected one of `>`, `const`, identifier, or lifetime, found `,`
+error: expected one of `#`, `>`, `const`, identifier, or lifetime, found `,`
   --> $DIR/issue-20616-9.rs:34:15
    |
 LL | type Type_9<T,,> = Box<T>;
-   |               ^ expected one of `>`, `const`, identifier, or lifetime
+   |               ^ expected one of `#`, `>`, `const`, identifier, or lifetime
 
 error: aborting due to previous error
 
index 5ac5a8665bc69e41c2c05fe84648abdc82d01558..09402c3d814101610a67760d90df1148e9abe146 100644 (file)
@@ -4,8 +4,8 @@ error[E0512]: cannot transmute between types of different sizes, or dependently-
 LL |     let new: T::B = unsafe { std::mem::transmute(value) };
    |                              ^^^^^^^^^^^^^^^^^^^
    |
-   = note: source type: `<T as Trait<'a>>::A` (size can vary because of <T as Trait>::A)
-   = note: target type: `<T as Trait<'a>>::B` (size can vary because of <T as Trait>::B)
+   = note: source type: `<T as Trait>::A` (this type does not have a fixed size)
+   = note: target type: `<T as Trait>::B` (this type does not have a fixed size)
 
 error: aborting due to previous error
 
index 2c5f1394449b46c7dbc0203103afe0cd1116c8f2..f62de7ce7dbe7651794abdf755b66b2d3494cb34 100644 (file)
@@ -8,7 +8,7 @@ mod B {
     use crate1::A::Foo;
     fn bar(f: Foo) {
         Foo::foo(&f);
-        //~^ ERROR: method `foo` is private
+        //~^ ERROR: associated function `foo` is private
     }
 }
 
index d19e42d8d9cadebe1b4681b309f3c445454a5c7c..18669add20551fd7d70be53dea61f981ed9c2c26 100644 (file)
@@ -1,4 +1,4 @@
-error[E0624]: method `foo` is private
+error[E0624]: associated function `foo` is private
   --> $DIR/issue-21202.rs:10:9
    |
 LL |         Foo::foo(&f);
index 319aa2a5cce9eb50ce24795ab30b3fca2a0c9c23..d20bb4bd90726f66d6cf2ce15c6221a5197e4ee2 100644 (file)
@@ -3,8 +3,7 @@
 #![feature(optin_builtin_traits)]
 
 unsafe auto trait Trait {
-//~^ ERROR E0380
-    type Output;
+    type Output; //~ ERROR E0380
 }
 
 fn call_method<T: Trait>(x: T) {}
index 1103de0d91043802d61b4674962c2b7eb135d342..fcd1ecfa98288ff1d43db80a2e7d50b50ce2ed15 100644 (file)
@@ -1,11 +1,10 @@
 error[E0380]: auto traits cannot have methods or associated items
-  --> $DIR/issue-23080-2.rs:5:1
+  --> $DIR/issue-23080-2.rs:6:10
    |
-LL | / unsafe auto trait Trait {
-LL | |
-LL | |     type Output;
-LL | | }
-   | |_^
+LL | unsafe auto trait Trait {
+   |                   ----- auto trait cannot have items
+LL |     type Output;
+   |          ^^^^^^
 
 error[E0275]: overflow evaluating the requirement `<() as Trait>::Output`
    |
index fdfee6981447df330673cc00b57766fe273a40c2..fa5c35316bc28d4853fe4868586a435c1fc6d395 100644 (file)
@@ -1,8 +1,7 @@
 #![feature(optin_builtin_traits)]
 
 unsafe auto trait Trait {
-//~^ ERROR E0380
-    fn method(&self) {
+    fn method(&self) { //~ ERROR E0380
         println!("Hello");
     }
 }
index 91c27217324269672ab0f74ff7ff419ec69e0b5b..dbb9861b5784a8669a26114a3a13b7113c3c0017 100644 (file)
@@ -1,13 +1,10 @@
 error[E0380]: auto traits cannot have methods or associated items
-  --> $DIR/issue-23080.rs:3:1
+  --> $DIR/issue-23080.rs:4:8
    |
-LL | / unsafe auto trait Trait {
-LL | |
-LL | |     fn method(&self) {
-LL | |         println!("Hello");
-LL | |     }
-LL | | }
-   | |_^
+LL | unsafe auto trait Trait {
+   |                   ----- auto trait cannot have items
+LL |     fn method(&self) {
+   |        ^^^^^^
 
 error: aborting due to previous error
 
index 77bc829209440b40bf68151c9e369fdeef41cc86..e34ac45e69db6b9940663f27b4853c416eb10e47 100644 (file)
@@ -11,7 +11,7 @@ LL |     let x: u8 = BitXor::bitor(0 as u8, 0 as u8);
    |                         ^^^^^
    |                         |
    |                         function or associated item not found in `dyn std::ops::BitXor<_>`
-   |                         help: there is a method with a similar name: `bitxor`
+   |                         help: there is an associated function with a similar name: `bitxor`
 
 error[E0191]: the value of the associated type `Output` (from trait `std::ops::BitXor`) must be specified
   --> $DIR/issue-28344.rs:8:13
@@ -26,7 +26,7 @@ LL |     let g = BitXor::bitor;
    |                     ^^^^^
    |                     |
    |                     function or associated item not found in `dyn std::ops::BitXor<_>`
-   |                     help: there is a method with a similar name: `bitxor`
+   |                     help: there is an associated function with a similar name: `bitxor`
 
 error: aborting due to 4 previous errors
 
index 522df6a07c2c6a521911f0cceb15b89b1b5e6089..1e61178f42edbca6727c7e20d382f088a3c806d8 100644 (file)
@@ -1,8 +1,15 @@
 error[E0308]: mismatched types
   --> $DIR/issue-33504.rs:7:13
    |
+LL | struct Test;
+   | ------------ unit struct defined here
+...
 LL |         let Test = 1;
-   |             ^^^^ expected integer, found struct `Test`
+   |             ^^^^
+   |             |
+   |             expected integer, found struct `Test`
+   |             `Test` is interpreted as a unit struct, not a new binding
+   |             help: introduce a new binding instead: `other_test`
 
 error: aborting due to previous error
 
index 5d17a30ab3624af2149e6d815bf860fc679c6070..451321c55035d37a748bf38f47b707b0c341f04c 100644 (file)
@@ -1,3 +1,6 @@
+// compile-flags: -Zsave-analysis
+// Also regression test for #69416
+
 mod my_mod {
     pub struct MyStruct {
         priv_field: isize
@@ -18,9 +21,9 @@ fn main() {
     let _woohoo = (Box::new(my_struct)).priv_field;
     //~^ ERROR field `priv_field` of struct `my_mod::MyStruct` is private
 
-    (&my_struct).happyfun();               //~ ERROR method `happyfun` is private
+    (&my_struct).happyfun();               //~ ERROR associated function `happyfun` is private
 
-    (Box::new(my_struct)).happyfun();          //~ ERROR method `happyfun` is private
+    (Box::new(my_struct)).happyfun();          //~ ERROR associated function `happyfun` is private
     let nope = my_struct.priv_field;
     //~^ ERROR field `priv_field` of struct `my_mod::MyStruct` is private
 }
index 50169286b1ceb1a8f8148d8457d08a173eb36a1d..d548477a88ff80d1b1f585ce65771065704d4931 100644 (file)
@@ -1,29 +1,29 @@
 error[E0616]: field `priv_field` of struct `my_mod::MyStruct` is private
-  --> $DIR/issue-3763.rs:15:19
+  --> $DIR/issue-3763.rs:18:19
    |
 LL |     let _woohoo = (&my_struct).priv_field;
    |                   ^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0616]: field `priv_field` of struct `my_mod::MyStruct` is private
-  --> $DIR/issue-3763.rs:18:19
+  --> $DIR/issue-3763.rs:21:19
    |
 LL |     let _woohoo = (Box::new(my_struct)).priv_field;
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0624]: method `happyfun` is private
-  --> $DIR/issue-3763.rs:21:18
+error[E0624]: associated function `happyfun` is private
+  --> $DIR/issue-3763.rs:24:18
    |
 LL |     (&my_struct).happyfun();
    |                  ^^^^^^^^
 
-error[E0624]: method `happyfun` is private
-  --> $DIR/issue-3763.rs:23:27
+error[E0624]: associated function `happyfun` is private
+  --> $DIR/issue-3763.rs:26:27
    |
 LL |     (Box::new(my_struct)).happyfun();
    |                           ^^^^^^^^
 
 error[E0616]: field `priv_field` of struct `my_mod::MyStruct` is private
-  --> $DIR/issue-3763.rs:24:16
+  --> $DIR/issue-3763.rs:27:16
    |
 LL |     let nope = my_struct.priv_field;
    |                ^^^^^^^^^^^^^^^^^^^^
index 37e61b1b0e603655d300347e8136b9b3c0a51f16..8a4aef46dd5145bc93d0c3e9c12ba14234165cf0 100644 (file)
@@ -71,15 +71,16 @@ pub fn supersize_me(out: &mut Vec<Big>) {
 
 #[inline(never)]
 fn verify_stack_usage(before_ptr: *mut Vec<Big>) {
-    // to check stack usage, create locals before and after
+    // To check stack usage, create locals before and after
     // and check the difference in addresses between them.
     let mut stack_var: Vec<Big> = vec![];
     test::black_box(&mut stack_var);
     let stack_usage = isize::abs(
         (&mut stack_var as *mut _ as isize) -
             (before_ptr as isize)) as usize;
-    // give space for 2 copies of `Big` + 128 "misc" bytes.
-    if stack_usage > mem::size_of::<Big>() * 2 + 128 {
+    // Give space for 2 copies of `Big` + 272 "misc" bytes
+    // (value observed on x86_64-pc-windows-gnu).
+    if stack_usage > mem::size_of::<Big>() * 2 + 272 {
         panic!("used {} bytes of stack, but `struct Big` is only {} bytes",
                stack_usage, mem::size_of::<Big>());
     }
index 35435d0e618196a25d255d929d680b404b0ed17a..5451cf423559ed14d681785ac1f503ac07b81a4d 100644 (file)
@@ -1,8 +1,15 @@
 error[E0308]: mismatched types
   --> $DIR/issue-4968.rs:5:16
    |
+LL | const A: (isize,isize) = (4,2);
+   | ------------------------------- constant defined here
+LL | fn main() {
 LL |     match 42 { A => () }
-   |                ^ expected integer, found tuple
+   |                ^
+   |                |
+   |                expected integer, found tuple
+   |                `A` is interpreted as a constant, not a new binding
+   |                help: introduce a new binding instead: `other_a`
    |
    = note: expected type `{integer}`
              found tuple `(isize, isize)`
index 5db521536a804058def4aacb43b05f362045c534..b97131a199227822d399b0481f5d3f189ad7170d 100644 (file)
@@ -2,7 +2,7 @@ error[E0599]: no method named `as_deref` found for enum `std::option::Option<{in
   --> $DIR/option-as_deref.rs:2:29
    |
 LL |     let _result = &Some(42).as_deref();
-   |                             ^^^^^^^^ help: there is a method with a similar name: `as_ref`
+   |                             ^^^^^^^^ help: there is an associated function with a similar name: `as_ref`
    |
    = note: the method `as_deref` exists but the following trait bounds were not satisfied:
            `{integer}: std::ops::Deref`
index 2dfc6d53750e703fc12d98cea40f71b8b0a2947b..f33e9c7823ee4fbd8e955a74e189fa8559910b8d 100644 (file)
@@ -2,7 +2,7 @@ error[E0599]: no method named `as_deref` found for enum `std::result::Result<{in
   --> $DIR/result-as_deref.rs:4:27
    |
 LL |     let _result = &Ok(42).as_deref();
-   |                           ^^^^^^^^ help: there is a method with a similar name: `as_ref`
+   |                           ^^^^^^^^ help: there is an associated function with a similar name: `as_ref`
    |
    = note: the method `as_deref` exists but the following trait bounds were not satisfied:
            `{integer}: std::ops::Deref`
index 1d65c57e5e9ec182321a49156864111310ca2d70..68ebfab95c47e79fddfd6632558ff62aad0e225e 100644 (file)
@@ -2,7 +2,7 @@ error[E0599]: no method named `as_deref_err` found for enum `std::result::Result
   --> $DIR/result-as_deref_err.rs:4:28
    |
 LL |     let _result = &Err(41).as_deref_err();
-   |                            ^^^^^^^^^^^^ help: there is a method with a similar name: `as_deref_mut`
+   |                            ^^^^^^^^^^^^ help: there is an associated function with a similar name: `as_deref_mut`
    |
    = note: the method `as_deref_err` exists but the following trait bounds were not satisfied:
            `{integer}: std::ops::Deref`
index 2f4bf0c94b5cb038a20d0be493dfe82fb6f01887..d2ba1049b76ba0736ebd9982fa5eb135f7277d3d 100644 (file)
@@ -2,7 +2,7 @@ error[E0599]: no method named `as_deref_mut` found for enum `std::result::Result
   --> $DIR/result-as_deref_mut.rs:4:31
    |
 LL |     let _result = &mut Ok(42).as_deref_mut();
-   |                               ^^^^^^^^^^^^ help: there is a method with a similar name: `as_deref_err`
+   |                               ^^^^^^^^^^^^ help: there is an associated function with a similar name: `as_deref_err`
    |
    = note: the method `as_deref_mut` exists but the following trait bounds were not satisfied:
            `{integer}: std::ops::DerefMut`
index b76d36c804e5f522fcba291b5946ecac68b9f67c..d724ae5c74bdefbc7ea94435c381d0db709e8f35 100644 (file)
@@ -2,7 +2,7 @@ error[E0599]: no method named `as_deref_mut_err` found for enum `std::result::Re
   --> $DIR/result-as_deref_mut_err.rs:4:32
    |
 LL |     let _result = &mut Err(41).as_deref_mut_err();
-   |                                ^^^^^^^^^^^^^^^^ help: there is a method with a similar name: `as_deref_mut`
+   |                                ^^^^^^^^^^^^^^^^ help: there is an associated function with a similar name: `as_deref_mut`
    |
    = note: the method `as_deref_mut_err` exists but the following trait bounds were not satisfied:
            `{integer}: std::ops::DerefMut`
index c81d6dcaf02173df0c0cfec556685c5da3b4cf7b..a89980964ca0ab56afe3cbbd9fb77b1d82b811e8 100644 (file)
@@ -1,6 +1,9 @@
 error[E0308]: mismatched types
   --> $DIR/issue-5100.rs:8:9
    |
+LL | enum A { B, C }
+   |          - unit variant defined here
+...
 LL |     match (true, false) {
    |           ------------- this expression has type `(bool, bool)`
 LL |         A::B => (),
index c87d423649233b20431af9bd6732995bf9ff3339..9e0437c46f4bdd826f7f79373826837ed542bef5 100644 (file)
@@ -13,5 +13,5 @@ fn foo() {}
 }
 
 fn main() {
-    test::Foo::<test::B>::foo(); //~ ERROR method `foo` is private
+    test::Foo::<test::B>::foo(); //~ ERROR associated function `foo` is private
 }
index 3fd48233daeb49e5c82a79a95771ae036d7912d4..042848c27bbdc083c1d8338a6ef106184d039b68 100644 (file)
@@ -1,4 +1,4 @@
-error[E0624]: method `foo` is private
+error[E0624]: associated function `foo` is private
   --> $DIR/issue-53498.rs:16:5
    |
 LL |     test::Foo::<test::B>::foo();
index bb0d15a23d60536f4451b53c54b60eaa13fc86be..faf78cfe8d9f88c461299c626ed543927d64fc18 100644 (file)
@@ -1,4 +1,4 @@
-error[E0164]: expected tuple struct or tuple variant, found method `Path::new`
+error[E0164]: expected tuple struct or tuple variant, found associated function `Path::new`
   --> $DIR/issue-55587.rs:4:9
    |
 LL |     let Path::new();
index 60ff318f35a1c1abb09a4da9c5cbe75405a4e4af..0375359aeaba619c3320df95d240ed6070dc2485 100644 (file)
@@ -5,6 +5,7 @@ LL |     for n in 100_000.. {
    |              ^^^^^^^
    |
    = note: `#[deny(overflowing_literals)]` on by default
+   = note: the literal `100_000` does not fit into the type `u16` whose range is `0..=65535`
 
 error: aborting due to previous error
 
index cc298a28b97e5bc6e683fe5faee36d95d64720bf..9db4521bb423926b5dba771279e0e245581d51be 100644 (file)
Binary files a/src/test/ui/issues/issue-66473.rs and b/src/test/ui/issues/issue-66473.rs differ
index dbeef44bad0ec68b68ce3c3c06768df43587855c..b370b125cfefda4f82cbb4866fec528b1465a2ef 100644 (file)
Binary files a/src/test/ui/issues/issue-66473.stderr and b/src/test/ui/issues/issue-66473.stderr differ
diff --git a/src/test/ui/issues/issue-69396-const-no-type-in-macro.rs b/src/test/ui/issues/issue-69396-const-no-type-in-macro.rs
new file mode 100644 (file)
index 0000000..69fc0c1
--- /dev/null
@@ -0,0 +1,17 @@
+macro_rules! suite {
+    ( $( $fn:ident; )* ) => {
+        $(
+            const A = "A".$fn();
+            //~^ ERROR the name `A` is defined multiple times
+            //~| ERROR missing type for `const` item
+            //~| ERROR the type placeholder `_` is not allowed within types
+        )*
+    }
+}
+
+suite! {
+    len;
+    is_empty;
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-69396-const-no-type-in-macro.stderr b/src/test/ui/issues/issue-69396-const-no-type-in-macro.stderr
new file mode 100644 (file)
index 0000000..1af5368
--- /dev/null
@@ -0,0 +1,53 @@
+error[E0428]: the name `A` is defined multiple times
+  --> $DIR/issue-69396-const-no-type-in-macro.rs:4:13
+   |
+LL |               const A = "A".$fn();
+   |               ^^^^^^^^^^^^^^^^^^^^
+   |               |
+   |               `A` redefined here
+   |               previous definition of the value `A` here
+...
+LL | / suite! {
+LL | |     len;
+LL | |     is_empty;
+LL | | }
+   | |_- in this macro invocation
+   |
+   = note: `A` must be defined only once in the value namespace of this module
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: missing type for `const` item
+  --> $DIR/issue-69396-const-no-type-in-macro.rs:4:19
+   |
+LL |               const A = "A".$fn();
+   |                     ^ help: provide a type for the item: `A: usize`
+...
+LL | / suite! {
+LL | |     len;
+LL | |     is_empty;
+LL | | }
+   | |_- in this macro invocation
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/issue-69396-const-no-type-in-macro.rs:4:19
+   |
+LL |               const A = "A".$fn();
+   |                     ^
+   |                     |
+   |                     not allowed in type signatures
+   |                     help: replace `_` with the correct type: `bool`
+...
+LL | / suite! {
+LL | |     len;
+LL | |     is_empty;
+LL | | }
+   | |_- in this macro invocation
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0121, E0428.
+For more information about an error, try `rustc --explain E0121`.
diff --git a/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.rs b/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.rs
new file mode 100644 (file)
index 0000000..d060f26
--- /dev/null
@@ -0,0 +1,23 @@
+trait TraitA {
+    const VALUE: usize;
+}
+
+struct A;
+impl TraitA for A {
+  const VALUE: usize = 0;
+}
+
+trait TraitB {
+    type MyA: TraitA;
+    const VALUE: usize = Self::MyA::VALUE;
+}
+
+struct B;
+impl TraitB for B { //~ ERROR not all trait items implemented, missing: `MyA`
+    type M   = A; //~ ERROR type `M` is not a member of trait `TraitB`
+}
+
+fn main() {
+    let _ = [0; B::VALUE];
+    //~^ ERROR array lengths can't depend on generic parameters
+}
diff --git a/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.stderr b/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.stderr
new file mode 100644 (file)
index 0000000..c6b2b4d
--- /dev/null
@@ -0,0 +1,25 @@
+error[E0437]: type `M` is not a member of trait `TraitB`
+  --> $DIR/issue-69602-type-err-during-codegen-ice.rs:17:5
+   |
+LL |     type M   = A;
+   |     ^^^^^^^^^^^^^ not a member of trait `TraitB`
+
+error[E0046]: not all trait items implemented, missing: `MyA`
+  --> $DIR/issue-69602-type-err-during-codegen-ice.rs:16:1
+   |
+LL |     type MyA: TraitA;
+   |     ----------------- `MyA` from trait
+...
+LL | impl TraitB for B {
+   | ^^^^^^^^^^^^^^^^^ missing `MyA` in implementation
+
+error: array lengths can't depend on generic parameters
+  --> $DIR/issue-69602-type-err-during-codegen-ice.rs:21:17
+   |
+LL |     let _ = [0; B::VALUE];
+   |                 ^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0046, E0437.
+For more information about an error, try `rustc --explain E0046`.
diff --git a/src/test/ui/issues/issue-69725.rs b/src/test/ui/issues/issue-69725.rs
new file mode 100644 (file)
index 0000000..b8130b4
--- /dev/null
@@ -0,0 +1,11 @@
+// aux-build:issue-69725.rs
+
+extern crate issue_69725;
+use issue_69725::Struct;
+
+fn crash<A>() {
+    let _ = Struct::<A>::new().clone();
+    //~^ ERROR: no method named `clone` found
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-69725.stderr b/src/test/ui/issues/issue-69725.stderr
new file mode 100644 (file)
index 0000000..667383e
--- /dev/null
@@ -0,0 +1,18 @@
+error[E0599]: no method named `clone` found for struct `issue_69725::Struct<A>` in the current scope
+  --> $DIR/issue-69725.rs:7:32
+   |
+LL |     let _ = Struct::<A>::new().clone();
+   |                                ^^^^^ method not found in `issue_69725::Struct<A>`
+   | 
+  ::: $DIR/auxiliary/issue-69725.rs:2:1
+   |
+LL | pub struct Struct<A>(A);
+   | ------------------------ doesn't satisfy `issue_69725::Struct<A>: std::clone::Clone`
+   |
+   = note: the method `clone` exists but the following trait bounds were not satisfied:
+           `A: std::clone::Clone`
+           which is required by `issue_69725::Struct<A>: std::clone::Clone`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
index 4a29464aebd2b6ee7c7ffb0ff5c6b61a4fdcdbf2..0d3121d60455d95c6df8c9602f338e26aca8701b 100644 (file)
@@ -1,6 +1,9 @@
 error[E0308]: mismatched types
   --> $DIR/issue-7867.rs:7:9
    |
+LL | enum A { B, C }
+   |          - unit variant defined here
+...
 LL |     match (true, false) {
    |           ------------- this expression has type `(bool, bool)`
 LL |         A::B => (),
index ab0feb3c451adb4b0497b7f51705213c99017188..026943669f82892617f9414f7437597664fbe6a4 100644 (file)
@@ -1,10 +1,6 @@
-{"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.
+{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type.
 
-For example:
+Erroneous code example:
 
 ```compile_fail,E0308
 let x: i32 = \"I am not a number!\";
@@ -15,15 +11,17 @@ let x: i32 = \"I am not a number!\";
 //      |
 //    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},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":612,"byte_end":618,"line_start":17,"line_end":17,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":"    let s : String = 1;  // Error in the middle of line.","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"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
+
+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.
+"},"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},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":612,"byte_end":618,"line_start":17,"line_end":17,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":"    let s : String = 1;  // Error in the middle of line.","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"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":"Expected type did not match the received type.
 
-For example:
+Erroneous code example:
 
 ```compile_fail,E0308
 let x: i32 = \"I am not a number!\";
@@ -34,15 +32,17 @@ let x: i32 = \"I am not a number!\";
 //      |
 //    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},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":672,"byte_end":678,"line_start":19,"line_end":19,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":"    let s : String = 1","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"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
+
+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.
+"},"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},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":672,"byte_end":678,"line_start":19,"line_end":19,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":"    let s : String = 1","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"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":"Expected type did not match the received type.
 
-For example:
+Erroneous code example:
 
 ```compile_fail,E0308
 let x: i32 = \"I am not a number!\";
@@ -53,15 +53,17 @@ let x: i32 = \"I am not a number!\";
 //      |
 //    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},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":735,"byte_end":741,"line_start":22,"line_end":22,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":"    let s : String =","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"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
+
+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.
+"},"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},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":735,"byte_end":741,"line_start":22,"line_end":22,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":"    let s : String =","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"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":"Expected type did not match the received type.
 
-For example:
+Erroneous code example:
 
 ```compile_fail,E0308
 let x: i32 = \"I am not a number!\";
@@ -72,6 +74,12 @@ let x: i32 = \"I am not a number!\";
 //      |
 //    type `i32` assigned to variable `x`
 ```
+
+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.
 "},"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},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":792,"byte_end":798,"line_start":25,"line_end":25,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":"    let s : String = (","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"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
index 1dd898db3ad8c0bbc83d8fb87c6ac0b372b14512..735a46b8c875a2736c06928e11647e0a02066df1 100644 (file)
@@ -1,10 +1,6 @@
-{"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.
+{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type.
 
-For example:
+Erroneous code example:
 
 ```compile_fail,E0308
 let x: i32 = \"I am not a number!\";
@@ -15,15 +11,17 @@ let x: i32 = \"I am not a number!\";
 //      |
 //    type `i32` assigned to variable `x`
 ```
-"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":606,"byte_end":607,"line_start":16,"line_end":16,"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},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":597,"byte_end":603,"line_start":16,"line_end":16,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":"    let s : String = 1;  // Error in the middle of line.","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":606,"byte_end":607,"line_start":16,"line_end":16,"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:16: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
+
+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.
+"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":606,"byte_end":607,"line_start":16,"line_end":16,"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},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":597,"byte_end":603,"line_start":16,"line_end":16,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":"    let s : String = 1;  // Error in the middle of line.","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":606,"byte_end":607,"line_start":16,"line_end":16,"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:16:22: error[E0308]: mismatched types
+"}
+{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type.
 
-For example:
+Erroneous code example:
 
 ```compile_fail,E0308
 let x: i32 = \"I am not a number!\";
@@ -34,15 +32,17 @@ let x: i32 = \"I am not a number!\";
 //      |
 //    type `i32` assigned to variable `x`
 ```
-"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":666,"byte_end":667,"line_start":18,"line_end":18,"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},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":657,"byte_end":663,"line_start":18,"line_end":18,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":"    let s : String = 1","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":666,"byte_end":667,"line_start":18,"line_end":18,"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:18: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
+
+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.
+"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":666,"byte_end":667,"line_start":18,"line_end":18,"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},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":657,"byte_end":663,"line_start":18,"line_end":18,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":"    let s : String = 1","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":666,"byte_end":667,"line_start":18,"line_end":18,"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:18:22: error[E0308]: mismatched types
+"}
+{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type.
 
-For example:
+Erroneous code example:
 
 ```compile_fail,E0308
 let x: i32 = \"I am not a number!\";
@@ -53,15 +53,17 @@ let x: i32 = \"I am not a number!\";
 //      |
 //    type `i32` assigned to variable `x`
 ```
-"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":730,"byte_end":731,"line_start":22,"line_end":22,"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},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":720,"byte_end":726,"line_start":21,"line_end":21,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":"    let s : String =","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":730,"byte_end":731,"line_start":22,"line_end":22,"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:22: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
+
+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.
+"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":730,"byte_end":731,"line_start":22,"line_end":22,"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},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":720,"byte_end":726,"line_start":21,"line_end":21,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":"    let s : String =","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":730,"byte_end":731,"line_start":22,"line_end":22,"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:22:1: error[E0308]: mismatched types
+"}
+{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type.
 
-For example:
+Erroneous code example:
 
 ```compile_fail,E0308
 let x: i32 = \"I am not a number!\";
@@ -72,6 +74,12 @@ let x: i32 = \"I am not a number!\";
 //      |
 //    type `i32` assigned to variable `x`
 ```
+
+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.
 "},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":786,"byte_end":794,"line_start":24,"line_end":25,"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},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":777,"byte_end":783,"line_start":24,"line_end":24,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":"    let s : String = (","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"$DIR/json-bom-plus-crlf.rs:24: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
index b07de3e341c41b486184b3c8827f51affc4dd8a3..a46ce67d40d5a709d60fbba06c2e7a3adc612286 100644 (file)
@@ -1,3 +1,4 @@
 use extern::foo; //~ ERROR expected identifier, found keyword `extern`
+                 //~| ERROR unresolved import `r#extern`
 
 fn main() {}
index 05802f2d36710a42a4c670d2e601cd9f82f483f1..edbb36452b6ce0139ff8239a8f962323af289e68 100644 (file)
@@ -9,5 +9,12 @@ help: you can escape reserved keywords to use them as identifiers
 LL | use r#extern::foo;
    |     ^^^^^^^^
 
-error: aborting due to previous error
+error[E0432]: unresolved import `r#extern`
+  --> $DIR/keyword-extern-as-identifier-use.rs:1:5
+   |
+LL | use extern::foo;
+   |     ^^^^^^ maybe a missing crate `r#extern`?
+
+error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0432`.
index fd8850dd8dab255a8a374efffb12ac2f5eec3d60..a2c75882be0ca3d76d19efb4f9edfb46a5ad08ba 100644 (file)
@@ -2,7 +2,10 @@ error: expected `{`, found `'b`
   --> $DIR/label_break_value_illegal_uses.rs:6:12
    |
 LL |     unsafe 'b: {}
-   |            ^^ expected `{`
+   |            ^^----
+   |            |
+   |            expected `{`
+   |            help: try placing this code inside a block: `{ 'b: {} }`
 
 error: expected `{`, found `'b`
   --> $DIR/label_break_value_illegal_uses.rs:10:13
index 291edc505cd1e28a5ff307ebdd1222fb5031a69b..4c78821157670e33099ddba363cbec96a8548b32 100644 (file)
@@ -7,7 +7,7 @@ LL |     fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 {
    |            lifetime `'a` defined here
 LL | 
 LL |         if x > y { x } else { y }
-   |                    ^ method was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1`
+   |                    ^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1`
 
 error: aborting due to previous error
 
index 15ee58574ecaa375c1d45421e162b1a5d8e09592..11e7fa96d7ee947b5f329dde7bb5ffef96b6b620 100644 (file)
@@ -7,7 +7,7 @@ LL |   fn foo<'a>(&self, x: &'a i32) -> &i32 {
    |          lifetime `'a` defined here
 LL | 
 LL |     x
-   |     ^ method was supposed to return data with lifetime `'1` but it is returning data with lifetime `'a`
+   |     ^ associated function was supposed to return data with lifetime `'1` but it is returning data with lifetime `'a`
 
 error: aborting due to previous error
 
index a27a91e38f1e4d37d1b737db7559458ec3c95d73..c41f08e691ac2f0c6723f5cd3157ea74ad1ae840 100644 (file)
@@ -7,7 +7,7 @@ LL |     fn foo<'a>(&self, x: &'a Foo) -> &'a Foo {
    |            lifetime `'a` defined here
 LL | 
 LL |         if true { x } else { self }
-   |                              ^^^^ method was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1`
+   |                              ^^^^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1`
 
 error: aborting due to previous error
 
index 5f922d8560b2ad0e8aadf4eb38be2d8873d54da9..1a19e81f235ba5c984e9eb62d1aae52c11b2c08b 100644 (file)
@@ -6,7 +6,7 @@ LL |   fn foo<'a>(&self, x: &i32) -> &i32 {
    |              |
    |              let's call the lifetime of this reference `'2`
 LL |     x
-   |     ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |     ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: aborting due to previous error
 
index 91d7597c87feafc58980e3d004c18178f53a9dc7..87b13dc15914bf7dedf86d39bd37b6493add6a5f 100644 (file)
@@ -6,7 +6,7 @@ LL |     fn foo<'a>(&self, x: &Foo) -> &Foo {
    |                |
    |                let's call the lifetime of this reference `'2`
 LL |         if true { x } else { self }
-   |                   ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |                   ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: aborting due to previous error
 
index 7f59495023e260ad5f1ddf444b2f457e5fb174b2..127dd4127c261999435c2c9a53b0eb2f769c1e7e 100644 (file)
@@ -5,6 +5,7 @@ LL |     let x: u8 = 256;
    |                 ^^^
    |
    = note: `#[deny(overflowing_literals)]` on by default
+   = note: the literal `256` does not fit into the type `u8` whose range is `0..=255`
 
 error: range endpoint is out of range for `u8`
   --> $DIR/deny-overflowing-literals.rs:5:14
diff --git a/src/test/ui/lint/issue-69485-var-size-diffs-too-large.rs b/src/test/ui/lint/issue-69485-var-size-diffs-too-large.rs
new file mode 100644 (file)
index 0000000..49d489d
--- /dev/null
@@ -0,0 +1,10 @@
+// build-fail
+// only-x86_64
+
+fn main() {
+    Bug::V([0; !0]); //~ ERROR is too big for the current
+}
+
+enum Bug {
+    V([u8; !0]),
+}
diff --git a/src/test/ui/lint/issue-69485-var-size-diffs-too-large.stderr b/src/test/ui/lint/issue-69485-var-size-diffs-too-large.stderr
new file mode 100644 (file)
index 0000000..d31ce9c
--- /dev/null
@@ -0,0 +1,8 @@
+error: the type `[u8; 18446744073709551615]` is too big for the current architecture
+  --> $DIR/issue-69485-var-size-diffs-too-large.rs:5:12
+   |
+LL |     Bug::V([0; !0]);
+   |            ^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lint/lint-pre-expansion-extern-module.rs b/src/test/ui/lint/lint-pre-expansion-extern-module.rs
new file mode 100644 (file)
index 0000000..30e2ed8
--- /dev/null
@@ -0,0 +1,7 @@
+// check-pass
+// compile-flags: -W rust-2018-compatibility
+// error-pattern: `try` is a keyword in the 2018 edition
+
+fn main() {}
+
+mod lint_pre_expansion_extern_module_aux;
diff --git a/src/test/ui/lint/lint-pre-expansion-extern-module.stderr b/src/test/ui/lint/lint-pre-expansion-extern-module.stderr
new file mode 100644 (file)
index 0000000..c683a3f
--- /dev/null
@@ -0,0 +1,10 @@
+warning: `try` is a keyword in the 2018 edition
+  --> $DIR/lint_pre_expansion_extern_module_aux.rs:3:8
+   |
+LL | pub fn try() {}
+   |        ^^^ help: you can use a raw identifier to stay compatible: `r#try`
+   |
+   = note: `-W keyword-idents` implied by `-W rust-2018-compatibility`
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
index dff61e022ebb87724b6fbb9cf5dc85da50cc524f..d2df73727412fb5f400825d11725456861775329 100644 (file)
@@ -15,18 +15,24 @@ error: literal out of range for `u8`
    |
 LL |     let range_c = 0..=256;
    |                       ^^^
+   |
+   = note: the literal `256` does not fit into the type `u8` whose range is `0..=255`
 
 error: literal out of range for `u8`
   --> $DIR/lint-range-endpoint-overflow.rs:7:19
    |
 LL |     let range_d = 256..5;
    |                   ^^^
+   |
+   = note: the literal `256` does not fit into the type `u8` whose range is `0..=255`
 
 error: literal out of range for `u8`
   --> $DIR/lint-range-endpoint-overflow.rs:8:22
    |
 LL |     let range_e = 0..257;
    |                      ^^^
+   |
+   = note: the literal `257` does not fit into the type `u8` whose range is `0..=255`
 
 error: range endpoint is out of range for `u8`
   --> $DIR/lint-range-endpoint-overflow.rs:9:20
index bf510823b568f9bd4b6880de2ec8adfca1cfc04d..1e3c88dfc469c52541abfdfcdc7eebce570bfbd1 100644 (file)
@@ -17,6 +17,7 @@ note: the lint level is defined here
    |
 LL | #![warn(overflowing_literals)]
    |         ^^^^^^^^^^^^^^^^^^^^
+   = note: the literal `128` does not fit into the type `i8` whose range is `-128..=127`
 
 error: aborting due to previous error
 
index 00441f99e60d9163b54c1062cc52738c3a90b0d0..150e9a2aa47921ac2486cba9efa31f621f29f356 100644 (file)
@@ -17,6 +17,7 @@ note: the lint level is defined here
    |
 LL | #![warn(overflowing_literals)]
    |         ^^^^^^^^^^^^^^^^^^^^
+   = note: the literal `200` does not fit into the type `i8` whose range is `-128..=127`
 
 error: aborting due to previous error
 
index ec15313158d5b8a5e4ae726bfbf37916386e19be..7715c0d3a4db93d8e1a1754bbb2dd2b860dba032 100644 (file)
@@ -9,108 +9,143 @@ note: the lint level is defined here
    |
 LL | #![deny(overflowing_literals)]
    |         ^^^^^^^^^^^^^^^^^^^^
+   = note: the literal `256` does not fit into the type `u8` whose range is `0..=255`
 
 error: literal out of range for `u8`
   --> $DIR/lint-type-overflow.rs:13:14
    |
 LL |     let x1 = 256_u8;
    |              ^^^^^^
+   |
+   = note: the literal `256_u8` does not fit into the type `u8` whose range is `0..=255`
 
 error: literal out of range for `i8`
   --> $DIR/lint-type-overflow.rs:16:18
    |
 LL |     let x1: i8 = 128;
    |                  ^^^
+   |
+   = note: the literal `128` does not fit into the type `i8` whose range is `-128..=127`
 
 error: literal out of range for `i8`
   --> $DIR/lint-type-overflow.rs:18:19
    |
 LL |     let x3: i8 = -129;
    |                   ^^^
+   |
+   = note: the literal `129` does not fit into the type `i8` whose range is `-128..=127`
 
 error: literal out of range for `i8`
   --> $DIR/lint-type-overflow.rs:19:19
    |
 LL |     let x3: i8 = -(129);
    |                   ^^^^^
+   |
+   = note: the literal `129` does not fit into the type `i8` whose range is `-128..=127`
 
 error: literal out of range for `i8`
   --> $DIR/lint-type-overflow.rs:20:20
    |
 LL |     let x3: i8 = -{129};
    |                    ^^^
+   |
+   = note: the literal `129` does not fit into the type `i8` whose range is `-128..=127`
 
 error: literal out of range for `i8`
   --> $DIR/lint-type-overflow.rs:22:10
    |
 LL |     test(1000);
    |          ^^^^
+   |
+   = note: the literal `1000` does not fit into the type `i8` whose range is `-128..=127`
 
 error: literal out of range for `i8`
   --> $DIR/lint-type-overflow.rs:24:13
    |
 LL |     let x = 128_i8;
    |             ^^^^^^
+   |
+   = note: the literal `128_i8` does not fit into the type `i8` whose range is `-128..=127`
 
 error: literal out of range for `i8`
   --> $DIR/lint-type-overflow.rs:28:14
    |
 LL |     let x = -129_i8;
    |              ^^^^^^
+   |
+   = note: the literal `129_i8` does not fit into the type `i8` whose range is `-128..=127`
 
 error: literal out of range for `i32`
   --> $DIR/lint-type-overflow.rs:32:18
    |
 LL |     let x: i32 = 2147483648;
    |                  ^^^^^^^^^^
+   |
+   = note: the literal `2147483648` does not fit into the type `i32` whose range is `-2147483648..=2147483647`
 
 error: literal out of range for `i32`
   --> $DIR/lint-type-overflow.rs:33:13
    |
 LL |     let x = 2147483648_i32;
    |             ^^^^^^^^^^^^^^
+   |
+   = note: the literal `2147483648_i32` does not fit into the type `i32` whose range is `-2147483648..=2147483647`
 
 error: literal out of range for `i32`
   --> $DIR/lint-type-overflow.rs:36:19
    |
 LL |     let x: i32 = -2147483649;
    |                   ^^^^^^^^^^
+   |
+   = note: the literal `2147483649` does not fit into the type `i32` whose range is `-2147483648..=2147483647`
 
 error: literal out of range for `i32`
   --> $DIR/lint-type-overflow.rs:37:14
    |
 LL |     let x = -2147483649_i32;
    |              ^^^^^^^^^^^^^^
+   |
+   = note: the literal `2147483649_i32` does not fit into the type `i32` whose range is `-2147483648..=2147483647`
 
 error: literal out of range for `i32`
   --> $DIR/lint-type-overflow.rs:38:13
    |
 LL |     let x = 2147483648;
    |             ^^^^^^^^^^
+   |
+   = note: the literal `2147483648` does not fit into the type `i32` whose range is `-2147483648..=2147483647`
 
 error: literal out of range for `i64`
   --> $DIR/lint-type-overflow.rs:40:13
    |
 LL |     let x = 9223372036854775808_i64;
    |             ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the literal `9223372036854775808_i64` does not fit into the type `i64` whose range is `-9223372036854775808..=9223372036854775807`
 
 error: literal out of range for `i64`
   --> $DIR/lint-type-overflow.rs:42:13
    |
 LL |     let x = 18446744073709551615_i64;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the literal `18446744073709551615_i64` does not fit into the type `i64` whose range is `-9223372036854775808..=9223372036854775807`
 
 error: literal out of range for `i64`
   --> $DIR/lint-type-overflow.rs:43:19
    |
 LL |     let x: i64 = -9223372036854775809;
    |                   ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the literal `9223372036854775809` does not fit into the type `i64` whose range is `-9223372036854775808..=9223372036854775807`
 
 error: literal out of range for `i64`
   --> $DIR/lint-type-overflow.rs:44:14
    |
 LL |     let x = -9223372036854775809_i64;
    |              ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the literal `9223372036854775809_i64` does not fit into the type `i64` whose range is `-9223372036854775808..=9223372036854775807`
 
 error: aborting due to 18 previous errors
 
index dfc691ab910432f92b7f5e335f9a5967c968226b..61e33b7a260c96a2d4ee37426bb0645b9af00911 100644 (file)
@@ -9,30 +9,39 @@ note: the lint level is defined here
    |
 LL | #![deny(overflowing_literals)]
    |         ^^^^^^^^^^^^^^^^^^^^
+   = note: the literal `128` does not fit into the type `i8` whose range is `-128..=127`
 
 error: literal out of range for `f32`
   --> $DIR/lint-type-overflow2.rs:9:14
    |
 LL |     let x = -3.40282357e+38_f32;
    |              ^^^^^^^^^^^^^^^^^^
+   |
+   = note: the literal `3.40282357e+38_f32` does not fit into the type `f32` and will be converted to `std::f32::INFINITY`
 
 error: literal out of range for `f32`
   --> $DIR/lint-type-overflow2.rs:10:14
    |
 LL |     let x =  3.40282357e+38_f32;
    |              ^^^^^^^^^^^^^^^^^^
+   |
+   = note: the literal `3.40282357e+38_f32` does not fit into the type `f32` and will be converted to `std::f32::INFINITY`
 
 error: literal out of range for `f64`
   --> $DIR/lint-type-overflow2.rs:11:14
    |
 LL |     let x = -1.7976931348623159e+308_f64;
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the literal `1.7976931348623159e+308_f64` does not fit into the type `f64` and will be converted to `std::f64::INFINITY`
 
 error: literal out of range for `f64`
   --> $DIR/lint-type-overflow2.rs:12:14
    |
 LL |     let x =  1.7976931348623159e+308_f64;
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the literal `1.7976931348623159e+308_f64` does not fit into the type `f64` and will be converted to `std::f64::INFINITY`
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/lint/lint_pre_expansion_extern_module_aux.rs b/src/test/ui/lint/lint_pre_expansion_extern_module_aux.rs
new file mode 100644 (file)
index 0000000..71dec40
--- /dev/null
@@ -0,0 +1,3 @@
+// ignore-test: not a test
+
+pub fn try() {}
index f207b235735feae397fc3b89799930caf7f4fc02..08a5c6c2b634a3ddb73c6b31ab8d430da96aaa6a 100644 (file)
@@ -1,6 +1,6 @@
 // aux-build:redundant-semi-proc-macro-def.rs
 
-#![deny(redundant_semicolon)]
+#![deny(redundant_semicolons)]
 extern crate redundant_semi_proc_macro;
 use redundant_semi_proc_macro::should_preserve_spans;
 
index 8c5ee58dc121d5ec4b0970e25eaf9db37b1c7226..a79fba9bf3f009897feee1ad0b447f8949a9d5e5 100644 (file)
@@ -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(198..200) }, Ident { ident: "span_preservation", span: #0 bytes(201..218) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(218..220) }, Group { delimiter: Brace, stream: TokenStream [Ident { ident: "let", span: #0 bytes(228..231) }, Ident { ident: "tst", span: #0 bytes(232..235) }, Punct { ch: '=', spacing: Alone, span: #0 bytes(236..237) }, Literal { lit: Lit { kind: Integer, symbol: "123", suffix: None }, span: Span { lo: BytePos(238), hi: BytePos(241), ctxt: #0 } }, Punct { ch: ';', spacing: Joint, span: #0 bytes(241..242) }, Punct { ch: ';', spacing: Alone, span: #0 bytes(242..243) }, Ident { ident: "match", span: #0 bytes(289..294) }, Ident { ident: "tst", span: #0 bytes(295..298) }, Group { delimiter: Brace, stream: TokenStream [Literal { lit: Lit { kind: Integer, symbol: "123", suffix: None }, span: Span { lo: BytePos(483), hi: BytePos(486), ctxt: #0 } }, Punct { ch: '=', spacing: Joint, span: #0 bytes(487..489) }, Punct { ch: '>', spacing: Alone, span: #0 bytes(487..489) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(490..492) }, Punct { ch: ',', spacing: Alone, span: #0 bytes(492..493) }, Ident { ident: "_", span: #0 bytes(502..503) }, Punct { ch: '=', spacing: Joint, span: #0 bytes(504..506) }, Punct { ch: '>', spacing: Alone, span: #0 bytes(504..506) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(507..509) }], span: #0 bytes(299..515) }, Punct { ch: ';', spacing: Joint, span: #0 bytes(515..516) }, Punct { ch: ';', spacing: Joint, span: #0 bytes(516..517) }, Punct { ch: ';', spacing: Alone, span: #0 bytes(517..518) }], span: #0 bytes(222..562) }]
 error: unnecessary trailing semicolon
   --> $DIR/redundant-semi-proc-macro.rs:9:19
    |
@@ -8,8 +8,8 @@ LL |     let tst = 123;;
 note: the lint level is defined here
   --> $DIR/redundant-semi-proc-macro.rs:3:9
    |
-LL | #![deny(redundant_semicolon)]
-   |         ^^^^^^^^^^^^^^^^^^^
+LL | #![deny(redundant_semicolons)]
+   |         ^^^^^^^^^^^^^^^^^^^^
 
 error: unnecessary trailing semicolons
   --> $DIR/redundant-semi-proc-macro.rs:16:7
index 29297d08dcac4dcb059fc3948a62a0d575fd7bc5..518b5f211e5da26c9403a135de06806986d6062a 100644 (file)
@@ -1,7 +1,6 @@
 // ignore-tidy-tab
 
 #![warn(unused_mut, unused_parens)] // UI tests pass `-A unused`—see Issue #43896
-#![feature(no_debug)]
 
 #[no_mangle] const DISCOVERY: usize = 1;
 //~^ ERROR const items should never be `#[no_mangle]`
@@ -39,9 +38,6 @@ struct Equinox {
     warp_factor: f32,
 }
 
-#[no_debug] // should suggest removal of deprecated attribute
-//~^ WARN deprecated
-//~| HELP remove this attribute
 fn main() {
     while true {
     //~^ WARN denote infinite loops
index 4e218ed0f1a920cd78bb54d5d0b1fb023e319cca..0ef5d72609ae25b3bf6d814c149ebcac37fb1e93 100644 (file)
@@ -1,5 +1,5 @@
 warning: denote infinite loops with `loop { ... }`
-  --> $DIR/suggestions.rs:46:5
+  --> $DIR/suggestions.rs:42:5
    |
 LL |     while true {
    |     ^^^^^^^^^^ help: use `loop`
@@ -7,7 +7,7 @@ LL |     while true {
    = note: `#[warn(while_true)]` on by default
 
 warning: unnecessary parentheses around assigned value
-  --> $DIR/suggestions.rs:49:31
+  --> $DIR/suggestions.rs:45:31
    |
 LL |         let mut registry_no = (format!("NX-{}", 74205));
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove these parentheses
@@ -18,16 +18,8 @@ note: the lint level is defined here
 LL | #![warn(unused_mut, unused_parens)] // UI tests pass `-A unused`—see Issue #43896
    |                     ^^^^^^^^^^^^^
 
-warning: use of deprecated attribute `no_debug`: the `#[no_debug]` attribute was an experimental feature that has been deprecated due to lack of demand. See https://github.com/rust-lang/rust/issues/29721
-  --> $DIR/suggestions.rs:42:1
-   |
-LL | #[no_debug] // should suggest removal of deprecated attribute
-   | ^^^^^^^^^^^ help: remove this attribute
-   |
-   = note: `#[warn(deprecated)]` on by default
-
 warning: variable does not need to be mutable
-  --> $DIR/suggestions.rs:49:13
+  --> $DIR/suggestions.rs:45:13
    |
 LL |         let mut registry_no = (format!("NX-{}", 74205));
    |             ----^^^^^^^^^^^
@@ -41,7 +33,7 @@ LL | #![warn(unused_mut, unused_parens)] // UI tests pass `-A unused`—see Issu
    |         ^^^^^^^^^^
 
 warning: variable does not need to be mutable
-  --> $DIR/suggestions.rs:55:13
+  --> $DIR/suggestions.rs:51:13
    |
 LL |            let mut
    |   _____________^
@@ -53,7 +45,7 @@ LL | ||             b = 1;
    |               help: remove this `mut`
 
 error: const items should never be `#[no_mangle]`
-  --> $DIR/suggestions.rs:6:14
+  --> $DIR/suggestions.rs:5:14
    |
 LL | #[no_mangle] const DISCOVERY: usize = 1;
    |              -----^^^^^^^^^^^^^^^^^^^^^^
@@ -63,7 +55,7 @@ LL | #[no_mangle] const DISCOVERY: usize = 1;
    = note: `#[deny(no_mangle_const_items)]` on by default
 
 warning: functions generic over types or consts must be mangled
-  --> $DIR/suggestions.rs:12:1
+  --> $DIR/suggestions.rs:11:1
    |
 LL | #[no_mangle]
    | ------------ help: remove this attribute
@@ -74,7 +66,7 @@ LL | pub fn defiant<T>(_t: T) {}
    = note: `#[warn(no_mangle_generic_items)]` on by default
 
 warning: the `warp_factor:` in this pattern is redundant
-  --> $DIR/suggestions.rs:61:23
+  --> $DIR/suggestions.rs:57:23
    |
 LL |             Equinox { warp_factor: warp_factor } => {}
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^ help: use shorthand field pattern: `warp_factor`
@@ -82,7 +74,7 @@ LL |             Equinox { warp_factor: warp_factor } => {}
    = note: `#[warn(non_shorthand_field_patterns)]` on by default
 
 error: const items should never be `#[no_mangle]`
-  --> $DIR/suggestions.rs:22:18
+  --> $DIR/suggestions.rs:21:18
    |
 LL |     #[no_mangle] pub const DAUNTLESS: bool = true;
    |                  ---------^^^^^^^^^^^^^^^^^^^^^^^^
@@ -90,7 +82,7 @@ LL |     #[no_mangle] pub const DAUNTLESS: bool = true;
    |                  help: try a static value: `pub static`
 
 warning: functions generic over types or consts must be mangled
-  --> $DIR/suggestions.rs:25:18
+  --> $DIR/suggestions.rs:24:18
    |
 LL |     #[no_mangle] pub fn val_jean<T>() {}
    |     ------------ ^^^^^^^^^^^^^^^^^^^^^^^
@@ -98,7 +90,7 @@ LL |     #[no_mangle] pub fn val_jean<T>() {}
    |     help: remove this attribute
 
 error: const items should never be `#[no_mangle]`
-  --> $DIR/suggestions.rs:30:18
+  --> $DIR/suggestions.rs:29:18
    |
 LL |     #[no_mangle] pub(crate) const VETAR: bool = true;
    |                  ----------------^^^^^^^^^^^^^^^^^^^^
@@ -106,7 +98,7 @@ LL |     #[no_mangle] pub(crate) const VETAR: bool = true;
    |                  help: try a static value: `pub static`
 
 warning: functions generic over types or consts must be mangled
-  --> $DIR/suggestions.rs:33:18
+  --> $DIR/suggestions.rs:32:18
    |
 LL |     #[no_mangle] pub(crate) fn crossfield<T>() {}
    |     ------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
index 2432eb78b8732d8aaecb603f8bd2bb043a622fd0..a7a788b877a6d163119fb0d6c304ab30919a747b 100644 (file)
@@ -9,6 +9,7 @@ note: the lint level is defined here
    |
 LL | #![warn(overflowing_literals)]
    |         ^^^^^^^^^^^^^^^^^^^^
+   = note: the literal `255i8` does not fit into the type `i8` whose range is `-128..=127`
 
 warning: literal out of range for i8
   --> $DIR/type-overflow.rs:10:16
@@ -16,7 +17,7 @@ warning: literal out of range for i8
 LL |     let fail = 0b1000_0001i8;
    |                ^^^^^^^^^^^^^ help: consider using `u8` instead: `0b1000_0001u8`
    |
-   = note: the literal `0b1000_0001i8` (decimal `129`) does not fit into an `i8` and will become `-127i8`
+   = note: the literal `0b1000_0001i8` (decimal `129`) does not fit into the type `i8` and will become `-127i8`
 
 warning: literal out of range for i64
   --> $DIR/type-overflow.rs:12:16
@@ -24,7 +25,7 @@ warning: literal out of range for i64
 LL |     let fail = 0x8000_0000_0000_0000i64;
    |                ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `u64` instead: `0x8000_0000_0000_0000u64`
    |
-   = note: the literal `0x8000_0000_0000_0000i64` (decimal `9223372036854775808`) does not fit into an `i64` and will become `-9223372036854775808i64`
+   = note: the literal `0x8000_0000_0000_0000i64` (decimal `9223372036854775808`) does not fit into the type `i64` and will become `-9223372036854775808i64`
 
 warning: literal out of range for u32
   --> $DIR/type-overflow.rs:14:16
@@ -32,7 +33,7 @@ warning: literal out of range for u32
 LL |     let fail = 0x1_FFFF_FFFFu32;
    |                ^^^^^^^^^^^^^^^^ help: consider using `u64` instead: `0x1_FFFF_FFFFu64`
    |
-   = note: the literal `0x1_FFFF_FFFFu32` (decimal `8589934591`) does not fit into an `u32` and will become `4294967295u32`
+   = note: the literal `0x1_FFFF_FFFFu32` (decimal `8589934591`) does not fit into the type `u32` and will become `4294967295u32`
 
 warning: literal out of range for i128
   --> $DIR/type-overflow.rs:16:22
@@ -40,7 +41,7 @@ warning: literal out of range for i128
 LL |     let fail: i128 = 0x8000_0000_0000_0000_0000_0000_0000_0000;
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: the literal `0x8000_0000_0000_0000_0000_0000_0000_0000` (decimal `170141183460469231731687303715884105728`) does not fit into an `i128` and will become `-170141183460469231731687303715884105728i128`
+   = note: the literal `0x8000_0000_0000_0000_0000_0000_0000_0000` (decimal `170141183460469231731687303715884105728`) does not fit into the type `i128` and will become `-170141183460469231731687303715884105728i128`
    = help: consider using `u128` instead
 
 warning: literal out of range for i32
@@ -49,7 +50,7 @@ warning: literal out of range for i32
 LL |     let fail = 0x8FFF_FFFF_FFFF_FFFE;
    |                ^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: the literal `0x8FFF_FFFF_FFFF_FFFE` (decimal `10376293541461622782`) does not fit into an `i32` and will become `-2i32`
+   = note: the literal `0x8FFF_FFFF_FFFF_FFFE` (decimal `10376293541461622782`) does not fit into the type `i32` and will become `-2i32`
    = help: consider using `i128` instead
 
 warning: literal out of range for i8
@@ -58,5 +59,5 @@ warning: literal out of range for i8
 LL |     let fail = -0b1111_1111i8;
    |                 ^^^^^^^^^^^^^ help: consider using `i16` instead: `0b1111_1111i16`
    |
-   = note: the literal `0b1111_1111i8` (decimal `255`) does not fit into an `i8` and will become `-1i8`
+   = note: the literal `0b1111_1111i8` (decimal `255`) does not fit into the type `i8` and will become `-1i8`
 
index 6d669184deb3ef02bf349a2926cf339e6a433daf..bf0562713a497f1667792a8a37d2e2a7c512f7cf 100644 (file)
@@ -1,4 +1,4 @@
-error: the type `&'static T` does not permit zero-initialization
+error: the type `&T` does not permit zero-initialization
   --> $DIR/uninitialized-zeroed.rs:29:32
    |
 LL |         let _val: &'static T = mem::zeroed();
@@ -14,7 +14,7 @@ LL | #![deny(invalid_value)]
    |         ^^^^^^^^^^^^^
    = note: references must be non-null
 
-error: the type `&'static T` does not permit being left uninitialized
+error: the type `&T` does not permit being left uninitialized
   --> $DIR/uninitialized-zeroed.rs:30:32
    |
 LL |         let _val: &'static T = mem::uninitialized();
@@ -25,7 +25,7 @@ LL |         let _val: &'static T = mem::uninitialized();
    |
    = note: references must be non-null
 
-error: the type `Wrap<&'static T>` does not permit zero-initialization
+error: the type `Wrap<&T>` does not permit zero-initialization
   --> $DIR/uninitialized-zeroed.rs:32:38
    |
 LL |         let _val: Wrap<&'static T> = mem::zeroed();
@@ -40,7 +40,7 @@ note: references must be non-null (in this struct field)
 LL | struct Wrap<T> { wrapped: T }
    |                  ^^^^^^^^^^
 
-error: the type `Wrap<&'static T>` does not permit being left uninitialized
+error: the type `Wrap<&T>` does not permit being left uninitialized
   --> $DIR/uninitialized-zeroed.rs:33:38
    |
 LL |         let _val: Wrap<&'static T> = mem::uninitialized();
@@ -121,7 +121,7 @@ LL |         let _val: Void = mem::uninitialized();
    |
    = note: enums with no variants have no valid value
 
-error: the type `&'static i32` does not permit zero-initialization
+error: the type `&i32` does not permit zero-initialization
   --> $DIR/uninitialized-zeroed.rs:49:34
    |
 LL |         let _val: &'static i32 = mem::zeroed();
@@ -132,7 +132,7 @@ LL |         let _val: &'static i32 = mem::zeroed();
    |
    = note: references must be non-null
 
-error: the type `&'static i32` does not permit being left uninitialized
+error: the type `&i32` does not permit being left uninitialized
   --> $DIR/uninitialized-zeroed.rs:50:34
    |
 LL |         let _val: &'static i32 = mem::uninitialized();
@@ -366,7 +366,7 @@ LL |         let _val: NonBig = mem::uninitialized();
    |
    = note: `NonBig` must be initialized inside its custom valid range
 
-error: the type `&'static i32` does not permit zero-initialization
+error: the type `&i32` does not permit zero-initialization
   --> $DIR/uninitialized-zeroed.rs:84:34
    |
 LL |         let _val: &'static i32 = mem::transmute(0usize);
@@ -377,7 +377,7 @@ LL |         let _val: &'static i32 = mem::transmute(0usize);
    |
    = note: references must be non-null
 
-error: the type `&'static [i32]` does not permit zero-initialization
+error: the type `&[i32]` does not permit zero-initialization
   --> $DIR/uninitialized-zeroed.rs:85:36
    |
 LL |         let _val: &'static [i32] = mem::transmute((0usize, 0usize));
index 0dc0d247af5c13265ac9748681a0dae0b7dd689a..7176f17bc3fab20c15b967f48b55c5b650ec0b93 100644 (file)
@@ -2,7 +2,7 @@
   "message": "cannot find type `Iter` in this scope",
   "code": {
     "code": "E0412",
-    "explanation": "The type name used is not in scope.
+    "explanation": "A used type name is not in scope.
 
 Erroneous code examples:
 
index 41ed545cf1687e721ddca7eeb187a4b7ff6f66c4..2f3d48bf039074087c46d525c808800ff5120783 100644 (file)
@@ -13,66 +13,70 @@ LL |       pong!();
 error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `error`
   --> $DIR/main.rs:10:20
    |
-LL | / macro_rules! pong {
-LL | |     () => { syntax error };
-   | |                    ^^^^^ expected one of 8 possible tokens
-LL | | }
-   | |_- in this expansion of `pong!`
+LL | /  macro_rules! pong {
+LL | |      () => { syntax error };
+   | |                     ^^^^^ expected one of 8 possible tokens
+LL | |  }
+   | |__- in this expansion of `pong!`
 ...
-LL |       ping!();
-   |       -------- in this macro invocation
+LL |        ping!();
+   |        -------- in this macro invocation
    | 
-  ::: <::ping::ping macros>:1:1
+  ::: $DIR/auxiliary/ping.rs:5:1
    |
-LL |   () => { pong ! () ; }
-   |   ---------------------
-   |   |       |
-   |   |       in this macro invocation
-   |   in this expansion of `ping!`
+LL |  / macro_rules! ping {
+LL |  |     () => {
+LL |  |         pong!();
+   |  |         -------- in this macro invocation
+LL |  |     }
+LL |  | }
+   |  |_- in this expansion of `ping!`
 
 error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `error`
   --> $DIR/main.rs:10:20
    |
-LL | / macro_rules! pong {
-LL | |     () => { syntax error };
-   | |                    ^^^^^ expected one of 8 possible tokens
-LL | | }
-   | |_- in this expansion of `pong!` (#5)
+LL | /  macro_rules! pong {
+LL | |      () => { syntax error };
+   | |                     ^^^^^ expected one of 8 possible tokens
+LL | |  }
+   | |__- in this expansion of `pong!` (#5)
 ...
-LL |       deep!();
-   |       -------- in this macro invocation (#1)
+LL |        deep!();
+   |        -------- in this macro invocation (#1)
    | 
-  ::: <::ping::deep macros>:1:1
+  ::: $DIR/auxiliary/ping.rs:5:1
    |
-LL |   () => { foo ! () ; }
-   |   --------------------
-   |   |       |
-   |   |       in this macro invocation (#2)
-   |   in this expansion of `deep!` (#1)
-   | 
-  ::: <::ping::foo macros>:1:1
-   |
-LL |   () => { bar ! () ; }
-   |   --------------------
-   |   |       |
-   |   |       in this macro invocation (#3)
-   |   in this expansion of `foo!` (#2)
-   | 
-  ::: <::ping::bar macros>:1:1
-   |
-LL |   () => { ping ! () ; }
-   |   ---------------------
-   |   |       |
-   |   |       in this macro invocation (#4)
-   |   in this expansion of `bar!` (#3)
-   | 
-  ::: <::ping::ping macros>:1:1
-   |
-LL |   () => { pong ! () ; }
-   |   ---------------------
-   |   |       |
-   |   |       in this macro invocation (#5)
-   |   in this expansion of `ping!` (#4)
+LL |  / macro_rules! ping {
+LL |  |     () => {
+LL |  |         pong!();
+   |  |         -------- in this macro invocation (#5)
+LL |  |     }
+LL |  | }
+   |  |_- in this expansion of `ping!` (#4)
+...
+LL | /  macro_rules! deep {
+LL | |      () => {
+LL | |          foo!();
+   | |          ------- in this macro invocation (#2)
+LL | |      }
+LL | |  }
+   | |__- in this expansion of `deep!` (#1)
+...
+LL | /  macro_rules! foo {
+LL | |      () => {
+LL | |          bar!();
+   | |          ------- in this macro invocation (#3)
+LL | |      }
+LL | |  }
+   | |__- in this expansion of `foo!` (#2)
+...
+LL | /  macro_rules! bar {
+LL | |      () => {
+LL | |          ping!();
+   | |          -------- in this macro invocation (#4)
+LL | |      }
+LL | |  }
+   | |__- in this expansion of `bar!` (#3)
 
 error: aborting due to 3 previous errors
 
index 676ae05bf0fa67b4c1516408ca6a1636651338ec..cd7faf9bf8bfb056a8ed983dbdc1f8c54a009434 100644 (file)
@@ -13,12 +13,12 @@ fn main() {
     //~^ ERROR no rules expected
 
     assert!(true "whatever" blah);
-    //~^ WARN unexpected string literal
+    //~^ ERROR unexpected string literal
     //~^^ ERROR no rules expected
 
     assert!(true;);
-    //~^ WARN macro requires an expression
+    //~^ ERROR macro requires an expression
 
     assert!(false || true "error message");
-    //~^ WARN unexpected string literal
+    //~^ ERROR unexpected string literal
 }
index 4d18a531a800c639e56f92b1e279c9fa006c3f3b..84a6768b3f453cde932ed520909c8f88d9b189f8 100644 (file)
@@ -18,15 +18,13 @@ LL |     assert!(true, "whatever" blah);
    |                             |
    |                             help: missing comma here
 
-warning: unexpected string literal
+error: unexpected string literal
   --> $DIR/assert-trailing-junk.rs:15:18
    |
 LL |     assert!(true "whatever" blah);
    |                 -^^^^^^^^^^
    |                 |
    |                 help: try adding a comma
-   |
-   = note: this is going to be an error in the future
 
 error: no rules expected the token `blah`
   --> $DIR/assert-trailing-junk.rs:15:29
@@ -36,25 +34,21 @@ LL |     assert!(true "whatever" blah);
    |                            |
    |                            help: missing comma here
 
-warning: macro requires an expression as an argument
+error: macro requires an expression as an argument
   --> $DIR/assert-trailing-junk.rs:19:5
    |
 LL |     assert!(true;);
    |     ^^^^^^^^^^^^-^^
    |                 |
    |                 help: try removing semicolon
-   |
-   = note: this is going to be an error in the future
 
-warning: unexpected string literal
+error: unexpected string literal
   --> $DIR/assert-trailing-junk.rs:22:27
    |
 LL |     assert!(false || true "error message");
    |                          -^^^^^^^^^^^^^^^
    |                          |
    |                          help: try adding a comma
-   |
-   = note: this is going to be an error in the future
 
-error: aborting due to 4 previous errors
+error: aborting due to 7 previous errors
 
diff --git a/src/test/ui/macros/issue-58490.rs b/src/test/ui/macros/issue-58490.rs
new file mode 100644 (file)
index 0000000..97e71c9
--- /dev/null
@@ -0,0 +1,26 @@
+// Regression test for #58490
+
+macro_rules! a {
+    ( @1 $i:item ) => {
+        a! { @2 $i }
+    };
+    ( @2 $i:item ) => {
+        $i
+    };
+}
+mod b {
+    a! {
+        @1
+        #[macro_export]
+        macro_rules! b { () => () }
+    }
+    #[macro_export]
+    macro_rules! b { () => () }
+    //~^ ERROR: the name `b` is defined multiple times
+}
+mod c {
+    #[allow(unused_imports)]
+    use crate::b;
+}
+
+fn main() {}
diff --git a/src/test/ui/macros/issue-58490.stderr b/src/test/ui/macros/issue-58490.stderr
new file mode 100644 (file)
index 0000000..b1f0896
--- /dev/null
@@ -0,0 +1,14 @@
+error[E0428]: the name `b` is defined multiple times
+  --> $DIR/issue-58490.rs:18:5
+   |
+LL |         macro_rules! b { () => () }
+   |         -------------- previous definition of the macro `b` here
+...
+LL |     macro_rules! b { () => () }
+   |     ^^^^^^^^^^^^^^ `b` redefined here
+   |
+   = note: `b` must be defined only once in the macro namespace of this module
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0428`.
index dd0cac659fd312a1e4ccc8a96b3ceee10d58ab2a..83a88ab3bd97c4b0dbf6763e7f9130d38abf2d3e 100644 (file)
@@ -1,41 +1,41 @@
 error: 1 positional argument in format string, but no arguments were given
-  --> $DIR/macro-comma-behavior.rs:21:23
+  --> $DIR/macro-comma-behavior.rs:20:23
    |
 LL |     assert_eq!(1, 1, "{}",);
    |                       ^^
 
 error: 1 positional argument in format string, but no arguments were given
-  --> $DIR/macro-comma-behavior.rs:24:23
+  --> $DIR/macro-comma-behavior.rs:23:23
    |
 LL |     assert_ne!(1, 2, "{}",);
    |                       ^^
 
 error: 1 positional argument in format string, but no arguments were given
-  --> $DIR/macro-comma-behavior.rs:30:29
+  --> $DIR/macro-comma-behavior.rs:29:29
    |
 LL |     debug_assert_eq!(1, 1, "{}",);
    |                             ^^
 
 error: 1 positional argument in format string, but no arguments were given
-  --> $DIR/macro-comma-behavior.rs:33:29
+  --> $DIR/macro-comma-behavior.rs:32:29
    |
 LL |     debug_assert_ne!(1, 2, "{}",);
    |                             ^^
 
 error: 1 positional argument in format string, but no arguments were given
-  --> $DIR/macro-comma-behavior.rs:54:19
+  --> $DIR/macro-comma-behavior.rs:53:19
    |
 LL |     format_args!("{}",);
    |                   ^^
 
 error: 1 positional argument in format string, but no arguments were given
-  --> $DIR/macro-comma-behavior.rs:72:21
+  --> $DIR/macro-comma-behavior.rs:71:21
    |
 LL |     unimplemented!("{}",);
    |                     ^^
 
 error: 1 positional argument in format string, but no arguments were given
-  --> $DIR/macro-comma-behavior.rs:81:24
+  --> $DIR/macro-comma-behavior.rs:80:24
    |
 LL |             write!(f, "{}",)?;
    |                        ^^
index 006319aa9f5b2ede04fe58004e55a048962dce47..04714c65b5cb71daf78e86397487ce16a11767cd 100644 (file)
@@ -9,7 +9,6 @@
 #[cfg(std)] use std::fmt;
 #[cfg(core)] use core::fmt;
 #[cfg(core)] #[lang = "eh_personality"] fn eh_personality() {}
-#[cfg(core)] #[lang = "eh_unwind_resume"] fn eh_unwind_resume() {}
 #[cfg(core)] #[lang = "panic_impl"] fn panic_impl(panic: &core::panic::PanicInfo) -> ! { loop {} }
 
 // (see documentation of the similarly-named test in run-pass)
index 4372d89fbf5220170906f086313b8fcdf45ab7c6..26445f2c5c542c318f756ad4cf4e02c92d4cf02e 100644 (file)
@@ -1,59 +1,59 @@
 error: 1 positional argument in format string, but no arguments were given
-  --> $DIR/macro-comma-behavior.rs:21:23
+  --> $DIR/macro-comma-behavior.rs:20:23
    |
 LL |     assert_eq!(1, 1, "{}",);
    |                       ^^
 
 error: 1 positional argument in format string, but no arguments were given
-  --> $DIR/macro-comma-behavior.rs:24:23
+  --> $DIR/macro-comma-behavior.rs:23:23
    |
 LL |     assert_ne!(1, 2, "{}",);
    |                       ^^
 
 error: 1 positional argument in format string, but no arguments were given
-  --> $DIR/macro-comma-behavior.rs:30:29
+  --> $DIR/macro-comma-behavior.rs:29:29
    |
 LL |     debug_assert_eq!(1, 1, "{}",);
    |                             ^^
 
 error: 1 positional argument in format string, but no arguments were given
-  --> $DIR/macro-comma-behavior.rs:33:29
+  --> $DIR/macro-comma-behavior.rs:32:29
    |
 LL |     debug_assert_ne!(1, 2, "{}",);
    |                             ^^
 
 error: 1 positional argument in format string, but no arguments were given
-  --> $DIR/macro-comma-behavior.rs:38:18
+  --> $DIR/macro-comma-behavior.rs:37:18
    |
 LL |         eprint!("{}",);
    |                  ^^
 
 error: 1 positional argument in format string, but no arguments were given
-  --> $DIR/macro-comma-behavior.rs:50:18
+  --> $DIR/macro-comma-behavior.rs:49:18
    |
 LL |         format!("{}",);
    |                  ^^
 
 error: 1 positional argument in format string, but no arguments were given
-  --> $DIR/macro-comma-behavior.rs:54:19
+  --> $DIR/macro-comma-behavior.rs:53:19
    |
 LL |     format_args!("{}",);
    |                   ^^
 
 error: 1 positional argument in format string, but no arguments were given
-  --> $DIR/macro-comma-behavior.rs:61:17
+  --> $DIR/macro-comma-behavior.rs:60:17
    |
 LL |         print!("{}",);
    |                 ^^
 
 error: 1 positional argument in format string, but no arguments were given
-  --> $DIR/macro-comma-behavior.rs:72:21
+  --> $DIR/macro-comma-behavior.rs:71:21
    |
 LL |     unimplemented!("{}",);
    |                     ^^
 
 error: 1 positional argument in format string, but no arguments were given
-  --> $DIR/macro-comma-behavior.rs:81:24
+  --> $DIR/macro-comma-behavior.rs:80:24
    |
 LL |             write!(f, "{}",)?;
    |                        ^^
index 202a9235adbace98ed0df1f04f76f7d78adce6f8..6217decd8ef88598a80d40f65cbbf3d50304b32e 100644 (file)
@@ -5,5 +5,5 @@ LL |     println!("Hello, World!");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: expanding `println! { "Hello, World!" }`
-   = note: to `{ $crate :: io :: _print ($crate :: format_args_nl ! ("Hello, World!")) ; }`
+   = note: to `{ $crate :: io :: _print($crate :: format_args_nl ! ("Hello, World!")) ; }`
 
index a96b99ae4ff785d778a5115d785b23f12860d997..716a0005ba3e4556e4d8f7fc7e7e0cd1da4d8e4f 100644 (file)
@@ -1,3 +1,8 @@
+// FIXME: missing sysroot spans (#53081)
+// ignore-i586-unknown-linux-gnu
+// ignore-i586-unknown-linux-musl
+// ignore-i686-unknown-linux-musl
+
 // error-pattern: cannot find a built-in macro with name `line`
 
 #![feature(rustc_attrs)]
index f1e828a46d8f239676483d09f429de6bdc6e108a..ed163750a6ea48bd7506994be8c56c4c2295a83c 100644 (file)
@@ -1,14 +1,18 @@
 error: cannot find a built-in macro with name `unknown`
-  --> $DIR/unknown-builtin.rs:6:1
+  --> $DIR/unknown-builtin.rs:11:1
    |
 LL | macro_rules! unknown { () => () }
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: cannot find a built-in macro with name `line`
-  --> <::core::macros::builtin::line macros>:1:1
+  --> $SRC_DIR/libcore/macros/mod.rs:LL:COL
    |
-LL | () => { } ;
-   | ^^^^^^^^^^^
+LL | /     macro_rules! line {
+LL | |         () => {
+LL | |             /* compiler built-in */
+LL | |         };
+LL | |     }
+   | |_____^
 
 error: aborting due to 2 previous errors
 
index 2d7a0f1614197527c5c7cd5f7f65777349474cd4..297aa4cd95def012986e3929aa6b05f307a1e6a6 100644 (file)
@@ -1,4 +1,4 @@
-error[E0164]: expected tuple struct or tuple variant, found method `Path::new`
+error[E0164]: expected tuple struct or tuple variant, found associated function `Path::new`
   --> $DIR/match-fn-call.rs:6:9
    |
 LL |         Path::new("foo") => println!("foo"),
@@ -6,7 +6,7 @@ LL |         Path::new("foo") => println!("foo"),
    |
    = help: for more information, visit https://doc.rust-lang.org/book/ch18-00-patterns.html
 
-error[E0164]: expected tuple struct or tuple variant, found method `Path::new`
+error[E0164]: expected tuple struct or tuple variant, found associated function `Path::new`
   --> $DIR/match-fn-call.rs:8:9
    |
 LL |         Path::new("bar") => println!("bar"),
index 3703a59edb83616d9e6382f854f4e02eaf0d4a91..723c7fa92b10d00e68495694d61285687e70f944 100644 (file)
@@ -1,6 +1,9 @@
 error[E0308]: mismatched types
   --> $DIR/match-tag-nullary.rs:4:40
    |
+LL | enum B { B }
+   |          - unit variant defined here
+LL | 
 LL | fn main() { let x: A = A::A; match x { B::B => { } } }
    |                                    -   ^^^^ expected enum `A`, found enum `B`
    |                                    |
diff --git a/src/test/ui/methods/assign-to-method.rs b/src/test/ui/methods/assign-to-method.rs
new file mode 100644 (file)
index 0000000..85beaee
--- /dev/null
@@ -0,0 +1,24 @@
+// compile-flags: -Zsave-analysis
+// Also regression test for #69409
+
+struct Cat {
+    meows : usize,
+    how_hungry : isize,
+}
+
+impl Cat {
+    pub fn speak(&self) { self.meows += 1; }
+}
+
+fn cat(in_x : usize, in_y : isize) -> Cat {
+    Cat {
+        meows: in_x,
+        how_hungry: in_y
+    }
+}
+
+fn main() {
+    let nyan : Cat = cat(52, 99);
+    nyan.speak = || println!("meow"); //~ ERROR attempted to take value of method
+    nyan.speak += || println!("meow"); //~ ERROR attempted to take value of method
+}
diff --git a/src/test/ui/methods/assign-to-method.stderr b/src/test/ui/methods/assign-to-method.stderr
new file mode 100644 (file)
index 0000000..c0dd529
--- /dev/null
@@ -0,0 +1,19 @@
+error[E0615]: attempted to take value of method `speak` on type `Cat`
+  --> $DIR/assign-to-method.rs:22:10
+   |
+LL |     nyan.speak = || println!("meow");
+   |          ^^^^^
+   |
+   = help: methods are immutable and cannot be assigned to
+
+error[E0615]: attempted to take value of method `speak` on type `Cat`
+  --> $DIR/assign-to-method.rs:23:10
+   |
+LL |     nyan.speak += || println!("meow");
+   |          ^^^^^
+   |
+   = help: methods are immutable and cannot be assigned to
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0615`.
index 10950834ad3451f6d47ae1c70a4a2da3c596d040..c6dde67cfeba6141903901f1a29a1193aff753cd 100644 (file)
@@ -42,10 +42,13 @@ LL |     ($ident:ident) => { let $ident: i32 = 42; }
 error[E0689]: can't call method `pow` on ambiguous numeric type `{integer}`
   --> $DIR/method-on-ambiguous-numeric-type.rs:30:9
    |
-LL |     mac!(bar);
-   |     ---------- you must specify a type for this binding, like `i32`
 LL |     bar.pow(2);
    |         ^^^
+   |
+help: you must specify a type for this binding, like `i32`
+   |
+LL |     ($ident:ident) => { let $ident: i32 = 42; }
+   |                             ^^^^^^^^^^^
 
 error: aborting due to 5 previous errors
 
index f94be1734b7b148c69d7e19455041113f4a17c4e..40645309552ef16deb5b3e051e7aea217396a9ad 100644 (file)
@@ -13,20 +13,20 @@ impl MyTrait for Foo {}
 fn main() {
     match 0u32 {
         Foo::bar => {}
-        //~^ ERROR expected unit struct, unit variant or constant, found method `Foo::bar`
+        //~^ ERROR expected unit struct, unit variant or constant, found associated function
     }
     match 0u32 {
         <Foo>::bar => {}
-        //~^ ERROR expected unit struct, unit variant or constant, found method `Foo::bar`
+        //~^ ERROR expected unit struct, unit variant or constant, found associated function
     }
     match 0u32 {
         <Foo>::trait_bar => {}
-        //~^ ERROR expected unit struct, unit variant or constant, found method `Foo::trait_bar`
+        //~^ ERROR expected unit struct, unit variant or constant, found associated function
     }
     if let Foo::bar = 0u32 {}
-    //~^ ERROR expected unit struct, unit variant or constant, found method `Foo::bar`
+    //~^ ERROR expected unit struct, unit variant or constant, found associated function
     if let <Foo>::bar = 0u32 {}
-    //~^ ERROR expected unit struct, unit variant or constant, found method `Foo::bar`
+    //~^ ERROR expected unit struct, unit variant or constant, found associated function
     if let Foo::trait_bar = 0u32 {}
-    //~^ ERROR expected unit struct, unit variant or constant, found method `Foo::trait_bar`
+    //~^ ERROR expected unit struct, unit variant or constant, found associated function
 }
index 6b0c5946ff8d86c271c14878165fe73ac075b833..1d1bdb6b052a8d7e247f0f2501cd4ad2a0331d14 100644 (file)
@@ -1,34 +1,34 @@
-error[E0533]: expected unit struct, unit variant or constant, found method `Foo::bar`
+error[E0533]: expected unit struct, unit variant or constant, found associated function `Foo::bar`
   --> $DIR/method-path-in-pattern.rs:15:9
    |
 LL |         Foo::bar => {}
    |         ^^^^^^^^
 
-error[E0533]: expected unit struct, unit variant or constant, found method `Foo::bar`
+error[E0533]: expected unit struct, unit variant or constant, found associated function `Foo::bar`
   --> $DIR/method-path-in-pattern.rs:19:9
    |
 LL |         <Foo>::bar => {}
    |         ^^^^^^^^^^
 
-error[E0533]: expected unit struct, unit variant or constant, found method `Foo::trait_bar`
+error[E0533]: expected unit struct, unit variant or constant, found associated function `Foo::trait_bar`
   --> $DIR/method-path-in-pattern.rs:23:9
    |
 LL |         <Foo>::trait_bar => {}
    |         ^^^^^^^^^^^^^^^^
 
-error[E0533]: expected unit struct, unit variant or constant, found method `Foo::bar`
+error[E0533]: expected unit struct, unit variant or constant, found associated function `Foo::bar`
   --> $DIR/method-path-in-pattern.rs:26:12
    |
 LL |     if let Foo::bar = 0u32 {}
    |            ^^^^^^^^
 
-error[E0533]: expected unit struct, unit variant or constant, found method `Foo::bar`
+error[E0533]: expected unit struct, unit variant or constant, found associated function `Foo::bar`
   --> $DIR/method-path-in-pattern.rs:28:12
    |
 LL |     if let <Foo>::bar = 0u32 {}
    |            ^^^^^^^^^^
 
-error[E0533]: expected unit struct, unit variant or constant, found method `Foo::trait_bar`
+error[E0533]: expected unit struct, unit variant or constant, found associated function `Foo::trait_bar`
   --> $DIR/method-path-in-pattern.rs:30:12
    |
 LL |     if let Foo::trait_bar = 0u32 {}
index c05160792d360cb1b4b5dd19384255b5045730af..2973800a4d43bea9a7832682eed2c525bc8aa7d1 100644 (file)
@@ -9,6 +9,6 @@ impl MyTrait for Foo {}
 fn main() {
     match 0u32 {
         <Foo as MyTrait>::trait_bar => {}
-        //~^ ERROR expected unit struct, unit variant or constant, found method `MyTrait::trait_bar`
+        //~^ ERROR expected unit struct, unit variant or constant, found associated function
     }
 }
index 4b25b694e13acdbbeb0c67031dd24ee799cf79ed..7c454a9a777c539e3ce20646d524f8cce54abe37 100644 (file)
@@ -1,4 +1,4 @@
-error[E0532]: expected unit struct, unit variant or constant, found method `MyTrait::trait_bar`
+error[E0532]: expected unit struct, unit variant or constant, found associated function `MyTrait::trait_bar`
   --> $DIR/method-resolvable-path-in-pattern.rs:11:9
    |
 LL |         <Foo as MyTrait>::trait_bar => {}
diff --git a/src/test/ui/mir/issue-60390.rs b/src/test/ui/mir/issue-60390.rs
new file mode 100644 (file)
index 0000000..fd9d6b4
--- /dev/null
@@ -0,0 +1,8 @@
+// check-pass
+// compile-flags: --emit=mir,link
+// Regression test for #60390, this ICE requires `--emit=mir` flag.
+
+fn main() {
+    enum Inner { Member(u32) };
+    Inner::Member(0);
+}
index 1594421b0b13b01a12757f387a833c3f4e557ab9..799bf7f3a12a8242d848dd6ac8f380953c16967b 100644 (file)
@@ -12,7 +12,7 @@ fn evaluate_reborrow_before_assign() {
     let y = &mut &2;
     let z = &3;
     // There's an implicit reborrow of `x` on the right-hand side of the
-    // assignement. Note that writing an explicit reborrow would not show this
+    // assignment. Note that writing an explicit reborrow would not show this
     // bug, as now there would be two reborrows on the right-hand side and at
     // least one of them would happen before the left-hand side is evaluated.
     *{ x = z; &mut *y } = x;
index f5c8b02ae27223c02a5ff9cae43db644e1e7b167..ef03b67b1b0b19db03bec5b038bdc717c315cb8b 100644 (file)
@@ -1,4 +1,4 @@
-error[E0409]: variable `y` is bound in inconsistent ways within the same match arm
+error[E0409]: variable `y` is bound inconsistently across alternatives separated by `|`
   --> $DIR/E0409.rs:5:23
    |
 LL |         (0, ref y) | (y, 0) => {}
index 98b74e5f5cbca1323d74f1e5318893a3de293c0d..91b3fe15c4be7a87a4b8525988378e29831eb974 100644 (file)
@@ -1,10 +1,10 @@
 error[E0583]: file not found for module `missing`
-  --> $DIR/foo.rs:4:5
+  --> $DIR/foo.rs:4:1
    |
 LL | mod missing;
-   |     ^^^^^^^
+   | ^^^^^^^^^^^^
    |
-   = help: name the file either foo/missing.rs or foo/missing/mod.rs inside the directory "$DIR"
+   = help: to create the module `missing`, create file "$DIR/foo/missing.rs"
 
 error: aborting due to previous error
 
index 457e8fcccbfb3252c903a43c5e3393001992f6a6..f519de46c767f9627419778a00845c35a4750ab1 100644 (file)
@@ -1,10 +1,10 @@
 error[E0583]: file not found for module `missing`
-  --> $DIR/foo_inline.rs:4:9
+  --> $DIR/foo_inline.rs:4:5
    |
 LL |     mod missing;
-   |         ^^^^^^^
+   |     ^^^^^^^^^^^^
    |
-   = help: name the file either missing.rs or missing/mod.rs inside the directory "$DIR/foo_inline/inline"
+   = help: to create the module `missing`, create file "$DIR/foo_inline/inline/missing.rs"
 
 error: aborting due to previous error
 
index ef203ef082b226e0bddf7a218dde2dc983e60ac3..7b182421d34e3c0b1d7f1f2ccf95e876ad1f2f23 100644 (file)
@@ -2,4 +2,5 @@
 
 fn main() {
     assert_eq!(mod_file_aux::bar(), 10);
+    //~^ ERROR failed to resolve: use of undeclared type or module `mod_file_aux`
 }
index 2b77d866fb30b3e011e096b3e2d9317c0c18aa24..490633a3fb0ab15b620d9b362251b724e403eb58 100644 (file)
@@ -1,11 +1,18 @@
 error[E0584]: file for module `mod_file_disambig_aux` found at both mod_file_disambig_aux.rs and mod_file_disambig_aux/mod.rs
-  --> $DIR/mod_file_disambig.rs:1:5
+  --> $DIR/mod_file_disambig.rs:1:1
    |
 LL | mod mod_file_disambig_aux;
-   |     ^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: delete or rename one of them to remove the ambiguity
 
-error: aborting due to previous error
+error[E0433]: failed to resolve: use of undeclared type or module `mod_file_aux`
+  --> $DIR/mod_file_disambig.rs:4:16
+   |
+LL |     assert_eq!(mod_file_aux::bar(), 10);
+   |                ^^^^^^^^^^^^ use of undeclared type or module `mod_file_aux`
+
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0584`.
+Some errors have detailed explanations: E0433, E0584.
+For more information about an error, try `rustc --explain E0433`.
diff --git a/src/test/ui/never_type/panic-uninitialized-zeroed.rs b/src/test/ui/never_type/panic-uninitialized-zeroed.rs
deleted file mode 100644 (file)
index e0c3016..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-// run-pass
-// ignore-wasm32-bare compiled with panic=abort by default
-// This test checks that instantiating an uninhabited type via `mem::{uninitialized,zeroed}` results
-// in a runtime panic.
-
-#![feature(never_type)]
-#![allow(deprecated, invalid_value)]
-
-use std::{mem, panic};
-
-#[allow(dead_code)]
-struct Foo {
-    x: u8,
-    y: !,
-}
-
-enum Bar {}
-
-fn main() {
-    unsafe {
-        assert_eq!(
-            panic::catch_unwind(|| {
-                mem::uninitialized::<!>()
-            }).err().and_then(|a| a.downcast_ref::<String>().map(|s| {
-                s == "Attempted to instantiate uninhabited type !"
-            })),
-            Some(true)
-        );
-
-        assert_eq!(
-            panic::catch_unwind(|| {
-                mem::zeroed::<!>()
-            }).err().and_then(|a| a.downcast_ref::<String>().map(|s| {
-                s == "Attempted to instantiate uninhabited type !"
-            })),
-            Some(true)
-        );
-
-        assert_eq!(
-            panic::catch_unwind(|| {
-                mem::MaybeUninit::<!>::uninit().assume_init()
-            }).err().and_then(|a| a.downcast_ref::<String>().map(|s| {
-                s == "Attempted to instantiate uninhabited type !"
-            })),
-            Some(true)
-        );
-
-        assert_eq!(
-            panic::catch_unwind(|| {
-                mem::uninitialized::<Foo>()
-            }).err().and_then(|a| a.downcast_ref::<String>().map(|s| {
-                s == "Attempted to instantiate uninhabited type Foo"
-            })),
-            Some(true)
-        );
-
-        assert_eq!(
-            panic::catch_unwind(|| {
-                mem::zeroed::<Foo>()
-            }).err().and_then(|a| a.downcast_ref::<String>().map(|s| {
-                s == "Attempted to instantiate uninhabited type Foo"
-            })),
-            Some(true)
-        );
-
-        assert_eq!(
-            panic::catch_unwind(|| {
-                mem::MaybeUninit::<Foo>::uninit().assume_init()
-            }).err().and_then(|a| a.downcast_ref::<String>().map(|s| {
-                s == "Attempted to instantiate uninhabited type Foo"
-            })),
-            Some(true)
-        );
-
-        assert_eq!(
-            panic::catch_unwind(|| {
-                mem::uninitialized::<Bar>()
-            }).err().and_then(|a| a.downcast_ref::<String>().map(|s| {
-                s == "Attempted to instantiate uninhabited type Bar"
-            })),
-            Some(true)
-        );
-
-        assert_eq!(
-            panic::catch_unwind(|| {
-                mem::zeroed::<Bar>()
-            }).err().and_then(|a| a.downcast_ref::<String>().map(|s| {
-                s == "Attempted to instantiate uninhabited type Bar"
-            })),
-            Some(true)
-        );
-
-        assert_eq!(
-            panic::catch_unwind(|| {
-                mem::MaybeUninit::<Bar>::uninit().assume_init()
-            }).err().and_then(|a| a.downcast_ref::<String>().map(|s| {
-                s == "Attempted to instantiate uninhabited type Bar"
-            })),
-            Some(true)
-        );
-    }
-}
index 45d7cbcdfbe7fa56ca624c1f0fe77c7a20f84cbe..88773def8b7c840e44fab37dc429a407f0c0fa8f 100644 (file)
@@ -2,10 +2,7 @@ error[E0596]: cannot borrow data in a `&` reference as mutable
   --> $DIR/dont-print-desugared.rs:4:10
    |
 LL |     for &ref mut x in s {}
-   |         -^^^^^^^^^
-   |         ||
-   |         |cannot borrow as mutable through `&` reference
-   |         help: consider changing this to be a mutable reference: `&mut ref mut x`
+   |          ^^^^^^^^^ cannot borrow as mutable through `&` reference
 
 error[E0597]: `y` does not live long enough
   --> $DIR/dont-print-desugared.rs:17:16
index 0d96767a05d035f109e171785d0698eb3a682d2c..a111acca66fef1eb58ed02e496a9607c434e8e20 100644 (file)
@@ -1,4 +1,4 @@
-// Ths test case is exploring the space of how blocs with tail
+// This test case is exploring the space of how blocks with tail
 // expressions and statements can be composed, trying to keep each
 // case on one line so that we can compare them via a vertical scan
 // with the human eye.
index ee5a80ae6483f3bdf1a2e7bb1ce5619571c2baf8..41e4d83aa9213be9d9fa07e704cd86e5757eb825 100644 (file)
@@ -70,7 +70,7 @@ pub struct Foo2<'a> {
 impl<'a> Foo2<'a> {
     // should not produce outlives suggestions to name 'self
     fn get_bar(&self) -> Bar2 {
-        Bar2::new(&self) //~ERROR borrowed data escapes outside of method
+        Bar2::new(&self) //~ERROR borrowed data escapes outside of associated function
     }
 }
 
index cf55603cd71f5b54371c24e54c3496b024e384fa..6300ea66511fb9f7a0a1709c7a9f775a80772623 100644 (file)
@@ -93,16 +93,16 @@ LL |         self.x
    |
    = help: consider adding the following bound: `'b: 'a`
 
-error[E0521]: borrowed data escapes outside of method
+error[E0521]: borrowed data escapes outside of associated function
   --> $DIR/outlives-suggestion-simple.rs:73:9
    |
 LL |     fn get_bar(&self) -> Bar2 {
    |                -----
    |                |
-   |                `self` declared here, outside of the method body
-   |                `self` is a reference that is only valid in the method body
+   |                `self` declared here, outside of the associated function body
+   |                `self` is a reference that is only valid in the associated function body
 LL |         Bar2::new(&self)
-   |         ^^^^^^^^^^^^^^^^ `self` escapes the method body here
+   |         ^^^^^^^^^^^^^^^^ `self` escapes the associated function body here
 
 error: aborting due to 9 previous errors
 
diff --git a/src/test/ui/nll/user-annotations/type-annotation-with-hrtb.rs b/src/test/ui/nll/user-annotations/type-annotation-with-hrtb.rs
new file mode 100644 (file)
index 0000000..1f7c060
--- /dev/null
@@ -0,0 +1,33 @@
+// Regression test for issue #69490
+
+// check-pass
+
+pub trait Trait<T> {
+    const S: &'static str;
+}
+
+impl<T> Trait<()> for T
+where
+    T: for<'a> Trait<&'a ()>,
+{
+    // Use of `T::S` here caused an ICE
+    const S: &'static str = T::S;
+}
+
+// Some similar cases that didn't ICE:
+
+impl<'a, T> Trait<()> for (T,)
+where
+    T: Trait<&'a ()>,
+{
+    const S: &'static str = T::S;
+}
+
+impl<T> Trait<()> for [T; 1]
+where
+    T: Trait<for<'a> fn(&'a ())>,
+{
+    const S: &'static str = T::S;
+}
+
+fn main() {}
diff --git a/src/test/ui/no-landing-pads.rs b/src/test/ui/no-landing-pads.rs
deleted file mode 100644 (file)
index d9d5321..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-// run-pass
-// compile-flags: -Z no-landing-pads -C codegen-units=1
-// ignore-emscripten no threads support
-
-use std::thread;
-
-static mut HIT: bool = false;
-
-struct A;
-
-impl Drop for A {
-    fn drop(&mut self) {
-        unsafe { HIT = true; }
-    }
-}
-
-fn main() {
-    thread::spawn(move|| -> () {
-        let _a = A;
-        panic!();
-    }).join().unwrap_err();
-    assert!(unsafe { !HIT });
-}
index b76699c19ac80e7100093ae3d3132197c9419214..58e45ff73a5e645e389443a9f490df2f979f9f80 100644 (file)
@@ -12,5 +12,4 @@ fn main() {
 }
 
 #[lang = "eh_personality"] extern fn eh_personality() {}
-#[lang = "eh_unwind_resume"] extern fn eh_unwind_resume() {}
 #[lang = "panic_impl"] fn panic_impl(panic: &PanicInfo) -> ! { loop {} }
index 71baf92b2d4097aa2c837efa274e1c13aead4437..a4b33963fb0b95b6bffa497f670cf31d932a41ae 100644 (file)
@@ -4,7 +4,6 @@ error[E0658]: this is an internal attribute that will never be stable
 LL | #[rustc_on_unimplemented = "test error `{Self}` with `{Bar}`"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: see issue #29642 <https://github.com/rust-lang/rust/issues/29642> for more information
    = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/or-patterns/box-patterns.rs b/src/test/ui/or-patterns/box-patterns.rs
new file mode 100644 (file)
index 0000000..aafd479
--- /dev/null
@@ -0,0 +1,37 @@
+// Test or-patterns with box-patterns
+
+// run-pass
+
+#![feature(or_patterns)]
+#![feature(box_patterns)]
+
+#[derive(Debug, PartialEq)]
+enum MatchArm {
+    Arm(usize),
+    Wild,
+}
+
+#[derive(Debug)]
+enum Test {
+    Foo,
+    Bar,
+    Baz,
+    Qux,
+}
+
+fn test(x: Option<Box<Test>>) -> MatchArm {
+    match x {
+        Some(box Test::Foo | box Test::Bar) => MatchArm::Arm(0),
+        Some(box Test::Baz) => MatchArm::Arm(1),
+        Some(_) => MatchArm::Arm(2),
+        _ => MatchArm::Wild,
+    }
+}
+
+fn main() {
+    assert_eq!(test(Some(Box::new(Test::Foo))), MatchArm::Arm(0));
+    assert_eq!(test(Some(Box::new(Test::Bar))), MatchArm::Arm(0));
+    assert_eq!(test(Some(Box::new(Test::Baz))), MatchArm::Arm(1));
+    assert_eq!(test(Some(Box::new(Test::Qux))), MatchArm::Arm(2));
+    assert_eq!(test(None), MatchArm::Wild);
+}
index 28b5f0c02fef4beeea20a54676eb00f065462eb4..fd5cb01ab42c51f3ab50a982f38874d593a3bc1d 100644 (file)
@@ -5,22 +5,22 @@
 fn main() {
     // One level:
     let Ok(a) | Err(ref a): Result<&u8, u8> = Ok(&0);
-    //~^ ERROR variable `a` is bound in inconsistent ways
+    //~^ ERROR variable `a` is bound inconsistently
     let Ok(ref mut a) | Err(a): Result<u8, &mut u8> = Ok(0);
-    //~^ ERROR variable `a` is bound in inconsistent ways
+    //~^ ERROR variable `a` is bound inconsistently
     let Ok(ref a) | Err(ref mut a): Result<&u8, &mut u8> = Ok(&0);
-    //~^ ERROR variable `a` is bound in inconsistent ways
+    //~^ ERROR variable `a` is bound inconsistently
     //~| ERROR mismatched types
     let Ok((ref a, b)) | Err((ref mut a, ref b)) = Ok((0, &0));
-    //~^ ERROR variable `a` is bound in inconsistent ways
-    //~| ERROR variable `b` is bound in inconsistent ways
+    //~^ ERROR variable `a` is bound inconsistently
+    //~| ERROR variable `b` is bound inconsistently
     //~| ERROR mismatched types
 
     // Two levels:
     let Ok(Ok(a) | Err(a)) | Err(ref a) = Err(0);
-    //~^ ERROR variable `a` is bound in inconsistent ways
+    //~^ ERROR variable `a` is bound inconsistently
 
     // Three levels:
-    let Ok([ Ok((Ok(ref a) | Err(a),)) | Err(a) ]) | Err(a) = Err(&1);
-    //~^ ERROR variable `a` is bound in inconsistent ways
+    let Ok([Ok((Ok(ref a) | Err(a),)) | Err(a)]) | Err(a) = Err(&1);
+    //~^ ERROR variable `a` is bound inconsistently
 }
index 8c01e00bae3530598cdd5e1a1b5fc3fdb13c1ad6..c5dcef36e0580514d4971c09537e0e2f37921139 100644 (file)
@@ -1,4 +1,4 @@
-error[E0409]: variable `a` is bound in inconsistent ways within the same match arm
+error[E0409]: variable `a` is bound inconsistently across alternatives separated by `|`
   --> $DIR/inconsistent-modes.rs:7:25
    |
 LL |     let Ok(a) | Err(ref a): Result<&u8, u8> = Ok(&0);
@@ -6,7 +6,7 @@ LL |     let Ok(a) | Err(ref a): Result<&u8, u8> = Ok(&0);
    |            |
    |            first binding
 
-error[E0409]: variable `a` is bound in inconsistent ways within the same match arm
+error[E0409]: variable `a` is bound inconsistently across alternatives separated by `|`
   --> $DIR/inconsistent-modes.rs:9:29
    |
 LL |     let Ok(ref mut a) | Err(a): Result<u8, &mut u8> = Ok(0);
@@ -14,25 +14,25 @@ LL |     let Ok(ref mut a) | Err(a): Result<u8, &mut u8> = Ok(0);
    |                    |
    |                    first binding
 
-error[E0409]: variable `a` is bound in inconsistent ways within the same match arm
+error[E0409]: variable `a` is bound inconsistently across alternatives separated by `|`
   --> $DIR/inconsistent-modes.rs:11:33
    |
 LL |     let Ok(ref a) | Err(ref mut a): Result<&u8, &mut u8> = Ok(&0);
    |                - first binding  ^ bound in different ways
 
-error[E0409]: variable `a` is bound in inconsistent ways within the same match arm
+error[E0409]: variable `a` is bound inconsistently across alternatives separated by `|`
   --> $DIR/inconsistent-modes.rs:14:39
    |
 LL |     let Ok((ref a, b)) | Err((ref mut a, ref b)) = Ok((0, &0));
    |                 - first binding       ^ bound in different ways
 
-error[E0409]: variable `b` is bound in inconsistent ways within the same match arm
+error[E0409]: variable `b` is bound inconsistently across alternatives separated by `|`
   --> $DIR/inconsistent-modes.rs:14:46
    |
 LL |     let Ok((ref a, b)) | Err((ref mut a, ref b)) = Ok((0, &0));
    |                    - first binding           ^ bound in different ways
 
-error[E0409]: variable `a` is bound in inconsistent ways within the same match arm
+error[E0409]: variable `a` is bound inconsistently across alternatives separated by `|`
   --> $DIR/inconsistent-modes.rs:20:38
    |
 LL |     let Ok(Ok(a) | Err(a)) | Err(ref a) = Err(0);
@@ -40,13 +40,13 @@ LL |     let Ok(Ok(a) | Err(a)) | Err(ref a) = Err(0);
    |                        |
    |                        first binding
 
-error[E0409]: variable `a` is bound in inconsistent ways within the same match arm
-  --> $DIR/inconsistent-modes.rs:24:34
+error[E0409]: variable `a` is bound inconsistently across alternatives separated by `|`
+  --> $DIR/inconsistent-modes.rs:24:33
    |
-LL |     let Ok([ Ok((Ok(ref a) | Err(a),)) | Err(a) ]) | Err(a) = Err(&1);
-   |                         -        ^ bound in different ways
-   |                         |
-   |                         first binding
+LL |     let Ok([Ok((Ok(ref a) | Err(a),)) | Err(a)]) | Err(a) = Err(&1);
+   |                        -        ^ bound in different ways
+   |                        |
+   |                        first binding
 
 error[E0308]: mismatched types
   --> $DIR/inconsistent-modes.rs:11:25
diff --git a/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs b/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs
new file mode 100644 (file)
index 0000000..59533ce
--- /dev/null
@@ -0,0 +1,9 @@
+#![feature(or_patterns)]
+
+fn main() {
+    let 0 | (1 | 2) = 0; //~ ERROR refutable pattern in local binding
+    match 0 {
+        //~^ ERROR non-exhaustive patterns
+        0 | (1 | 2) => {}
+    }
+}
diff --git a/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr b/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr
new file mode 100644 (file)
index 0000000..58286e8
--- /dev/null
@@ -0,0 +1,25 @@
+error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` and `3i32..=std::i32::MAX` not covered
+  --> $DIR/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs:4:9
+   |
+LL |     let 0 | (1 | 2) = 0;
+   |         ^^^^^^^^^^^ patterns `std::i32::MIN..=-1i32` and `3i32..=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 0 | (1 | 2) = 0 { /* */ }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0004]: non-exhaustive patterns: `std::i32::MIN..=-1i32` and `3i32..=std::i32::MAX` not covered
+  --> $DIR/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs:5:11
+   |
+LL |     match 0 {
+   |           ^ patterns `std::i32::MIN..=-1i32` and `3i32..=std::i32::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0004, E0005.
+For more information about an error, try `rustc --explain E0004`.
diff --git a/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier.rs b/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier.rs
new file mode 100644 (file)
index 0000000..1de563d
--- /dev/null
@@ -0,0 +1,9 @@
+// check-pass
+
+#![feature(or_patterns)]
+
+fn main() {
+    let 0 | (1 | _) = 0;
+    if let 0 | (1 | 2) = 0 {}
+    if let x @ 0 | x @ (1 | 2) = 0 {}
+}
index d5e029d668d4796a6b2cb7f9b54a176bbaf25801..1dabb7c975430058b2ca0c5be09f9a2b743a82d7 100644 (file)
@@ -101,7 +101,7 @@ LL |     if let Blah::A(_, x, y) | Blah::B(x, y) = Blah::A(1, 1, 2) {
    |                          |               expected `usize`, found `isize`
    |                          first introduced with type `usize` here
    |
-   = note: in the same arm, a binding must have the same type in all alternatives
+   = note: a binding must have the same type in all alternatives
 
 error[E0308]: mismatched types
   --> $DIR/or-patterns-binding-type-mismatch.rs:38:47
@@ -112,7 +112,7 @@ LL |     if let Some(Blah::A(_, x, y) | Blah::B(x, y)) = Some(Blah::A(1, 1, 2))
    |                               |               expected `usize`, found `isize`
    |                               first introduced with type `usize` here
    |
-   = note: in the same arm, a binding must have the same type in all alternatives
+   = note: a binding must have the same type in all alternatives
 
 error[E0308]: mismatched types
   --> $DIR/or-patterns-binding-type-mismatch.rs:42:22
@@ -123,7 +123,7 @@ LL |     if let (x, y) | (y, x) = (0u8, 1u16) {
    |                |     expected `u16`, found `u8`
    |                first introduced with type `u16` here
    |
-   = note: in the same arm, a binding must have the same type in all alternatives
+   = note: a binding must have the same type in all alternatives
 
 error[E0308]: mismatched types
   --> $DIR/or-patterns-binding-type-mismatch.rs:42:25
@@ -134,7 +134,7 @@ LL |     if let (x, y) | (y, x) = (0u8, 1u16) {
    |             |           expected `u8`, found `u16`
    |             first introduced with type `u8` here
    |
-   = note: in the same arm, a binding must have the same type in all alternatives
+   = note: a binding must have the same type in all alternatives
 
 error[E0308]: mismatched types
   --> $DIR/or-patterns-binding-type-mismatch.rs:47:44
@@ -147,7 +147,7 @@ LL |     if let Some((x, Some((y, z)))) | Some((y, Some((x, z) | (z, x))))
 LL |     = Some((0u8, Some((1u16, 2u32))))
    |       ------------------------------- this expression has type `std::option::Option<(u8, std::option::Option<(u16, u32)>)>`
    |
-   = note: in the same arm, a binding must have the same type in all alternatives
+   = note: a binding must have the same type in all alternatives
 
 error[E0308]: mismatched types
   --> $DIR/or-patterns-binding-type-mismatch.rs:47:53
@@ -160,7 +160,7 @@ LL |     if let Some((x, Some((y, z)))) | Some((y, Some((x, z) | (z, x))))
 LL |     = Some((0u8, Some((1u16, 2u32))))
    |       ------------------------------- this expression has type `std::option::Option<(u8, std::option::Option<(u16, u32)>)>`
    |
-   = note: in the same arm, a binding must have the same type in all alternatives
+   = note: a binding must have the same type in all alternatives
 
 error[E0308]: mismatched types
   --> $DIR/or-patterns-binding-type-mismatch.rs:47:62
@@ -173,7 +173,7 @@ LL |     if let Some((x, Some((y, z)))) | Some((y, Some((x, z) | (z, x))))
 LL |     = Some((0u8, Some((1u16, 2u32))))
    |       ------------------------------- this expression has type `std::option::Option<(u8, std::option::Option<(u16, u32)>)>`
    |
-   = note: in the same arm, a binding must have the same type in all alternatives
+   = note: a binding must have the same type in all alternatives
 
 error[E0308]: mismatched types
   --> $DIR/or-patterns-binding-type-mismatch.rs:47:65
@@ -184,7 +184,7 @@ LL |     if let Some((x, Some((y, z)))) | Some((y, Some((x, z) | (z, x))))
 LL |     = Some((0u8, Some((1u16, 2u32))))
    |       ------------------------------- this expression has type `std::option::Option<(u8, std::option::Option<(u16, u32)>)>`
    |
-   = note: in the same arm, a binding must have the same type in all alternatives
+   = note: a binding must have the same type in all alternatives
 
 error[E0308]: mismatched types
   --> $DIR/or-patterns-binding-type-mismatch.rs:55:39
diff --git a/src/test/ui/or-patterns/slice-patterns.rs b/src/test/ui/or-patterns/slice-patterns.rs
new file mode 100644 (file)
index 0000000..05c907e
--- /dev/null
@@ -0,0 +1,53 @@
+// Test or-patterns with slice-patterns
+
+// run-pass
+
+#![feature(or_patterns)]
+
+#[derive(Debug, PartialEq)]
+enum MatchArm {
+    Arm(usize),
+    Wild,
+}
+
+#[derive(Debug)]
+enum Test {
+    Foo,
+    Bar,
+    Baz,
+    Qux,
+}
+
+fn test(foo: &[Option<Test>]) -> MatchArm {
+    match foo {
+        [.., Some(Test::Qux | Test::Foo)] => MatchArm::Arm(0),
+        [Some(Test::Foo), .., Some(Test::Baz | Test::Bar)] => MatchArm::Arm(1),
+        [.., Some(Test::Bar | Test::Baz), _] => MatchArm::Arm(2),
+        _ => MatchArm::Wild,
+    }
+}
+
+fn main() {
+    let foo = vec![
+        Some(Test::Foo),
+        Some(Test::Bar),
+        Some(Test::Baz),
+        Some(Test::Qux),
+    ];
+
+    // path 1a
+    assert_eq!(test(&foo), MatchArm::Arm(0));
+    // path 1b
+    assert_eq!(test(&[Some(Test::Bar), Some(Test::Foo)]), MatchArm::Arm(0));
+    // path 2a
+    assert_eq!(test(&foo[..3]), MatchArm::Arm(1));
+    // path 2b
+    assert_eq!(test(&[Some(Test::Foo), Some(Test::Foo), Some(Test::Bar)]), MatchArm::Arm(1));
+    // path 3a
+    assert_eq!(test(&foo[1..3]), MatchArm::Arm(2));
+    // path 3b
+    assert_eq!(test(&[Some(Test::Bar), Some(Test::Baz), Some(Test::Baz), Some(Test::Bar)]),
+        MatchArm::Arm(2));
+    // path 4
+    assert_eq!(test(&foo[4..]), MatchArm::Wild);
+}
index abe34a39caf340608cfce82685c0ffffe18f7d4d..3e5cdad7ab936b865fc98b782a5b5d6ff9b22e30 100644 (file)
@@ -11,5 +11,3 @@
 fn panic_impl(info: &PanicInfo) -> ! { loop {} }
 #[lang = "eh_personality"]
 fn eh_personality() {}
-#[lang = "eh_unwind_resume"]
-fn eh_unwind_resume() {}
diff --git a/src/test/ui/panic-while-printing.rs b/src/test/ui/panic-while-printing.rs
new file mode 100644 (file)
index 0000000..7e9fa16
--- /dev/null
@@ -0,0 +1,24 @@
+// run-pass
+// ignore-emscripten no subprocess support
+
+#![feature(set_stdio)]
+
+use std::fmt;
+use std::fmt::{Display, Formatter};
+use std::io::set_panic;
+
+pub struct A;
+
+impl Display for A {
+    fn fmt(&self, _f: &mut Formatter<'_>) -> fmt::Result {
+        panic!();
+    }
+}
+
+fn main() {
+    set_panic(Some(Box::new(Vec::new())));
+    assert!(std::panic::catch_unwind(|| {
+        eprintln!("{}", A);
+    })
+    .is_err());
+}
index 71488d2e5c3699e660f1b3276561671b4c0c466c..b1bb3ab3b17ba75ac3bf55311d507a5f37c88a31 100644 (file)
@@ -1,8 +1,8 @@
 error: expected statement after outer attribute
-  --> $DIR/attr-dangling-in-fn.rs:5:1
+  --> $DIR/attr-dangling-in-fn.rs:4:3
    |
-LL | }
-   | ^
+LL |   #[foo = "bar"]
+   |   ^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index 118bff8144c7f6d33d178375eaed8e4d01b0cccb..09f494bdc2fed2b6a8cf2d25ea4eea15652de015 100644 (file)
@@ -38,42 +38,36 @@ fn main() {}
 //~^ ERROR an inner attribute is not permitted in this context
 #[cfg(FALSE)] fn e() { let _ = #[attr] &mut #![attr] 0; }
 //~^ ERROR an inner attribute is not permitted in this context
-#[cfg(FALSE)] fn e() { let _ = #[attr] if 0 {}; }
-//~^ ERROR attributes are not yet allowed on `if` expressions
 #[cfg(FALSE)] fn e() { let _ = if 0 #[attr] {}; }
-//~^ ERROR expected `{`, found `#`
+//~^ ERROR outer attributes are not allowed on `if`
 #[cfg(FALSE)] fn e() { let _ = if 0 {#![attr]}; }
 //~^ ERROR an inner attribute is not permitted in this context
 #[cfg(FALSE)] fn e() { let _ = if 0 {} #[attr] else {}; }
 //~^ ERROR expected one of
 #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] {}; }
-//~^ ERROR expected `{`, found `#`
+//~^ ERROR outer attributes are not allowed on `if`
 #[cfg(FALSE)] fn e() { let _ = if 0 {} else {#![attr]}; }
 //~^ ERROR an inner attribute is not permitted in this context
 #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] if 0 {}; }
-//~^ ERROR attributes are not yet allowed on `if` expressions
-//~| ERROR expected `{`, found `#`
+//~^ ERROR outer attributes are not allowed on `if`
 #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 #[attr] {}; }
-//~^ ERROR expected `{`, found `#`
+//~^ ERROR outer attributes are not allowed on `if`
 #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 {#![attr]}; }
 //~^ ERROR an inner attribute is not permitted in this context
-#[cfg(FALSE)] fn e() { let _ = #[attr] if let _ = 0 {}; }
-//~^ ERROR attributes are not yet allowed on `if` expressions
 #[cfg(FALSE)] fn e() { let _ = if let _ = 0 #[attr] {}; }
-//~^ ERROR expected `{`, found `#`
+//~^ ERROR outer attributes are not allowed on `if`
 #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {#![attr]}; }
 //~^ ERROR an inner attribute is not permitted in this context
 #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} #[attr] else {}; }
 //~^ ERROR expected one of
 #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] {}; }
-//~^ ERROR expected `{`, found `#`
+//~^ ERROR outer attributes are not allowed on `if`
 #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else {#![attr]}; }
 //~^ ERROR an inner attribute is not permitted in this context
 #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] if let _ = 0 {}; }
-//~^ ERROR attributes are not yet allowed on `if` expressions
-//~| ERROR expected `{`, found `#`
+//~^ ERROR outer attributes are not allowed on `if`
 #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 #[attr] {}; }
-//~^ ERROR expected `{`, found `#`
+//~^ ERROR outer attributes are not allowed on `if`
 #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 {#![attr]}; }
 //~^ ERROR an inner attribute is not permitted in this context
 
index 4775b9b7bc003593d9c76ca2a06268b5e060ceb8..6dfe7aad6ea64b3412b04c781e26fcd907c0744c 100644 (file)
@@ -136,23 +136,17 @@ LL | #[cfg(FALSE)] fn e() { let _ = #[attr] &mut #![attr] 0; }
    |
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
-error: attributes are not yet allowed on `if` expressions
-  --> $DIR/attr-stmt-expr-attr-bad.rs:41:32
-   |
-LL | #[cfg(FALSE)] fn e() { let _ = #[attr] if 0 {}; }
-   |                                ^^^^^^^
-
-error: expected `{`, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:43:37
+error: outer attributes are not allowed on `if` and `else` branches
+  --> $DIR/attr-stmt-expr-attr-bad.rs:41:37
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if 0 #[attr] {}; }
-   |                                --   ^       --- help: try placing this code inside a block: `{ {}; }`
+   |                                --   ^^^^^^^ -- the attributes are attached to this branch
    |                                |    |
-   |                                |    expected `{`
-   |                                this `if` expression has a condition, but no block
+   |                                |    help: remove the attributes
+   |                                the branch belongs to this `if`
 
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:45:38
+  --> $DIR/attr-stmt-expr-attr-bad.rs:43:38
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if 0 {#![attr]}; }
    |                                      ^^^^^^^^
@@ -160,75 +154,65 @@ LL | #[cfg(FALSE)] fn e() { let _ = if 0 {#![attr]}; }
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: expected one of `.`, `;`, `?`, `else`, or an operator, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:47:40
+  --> $DIR/attr-stmt-expr-attr-bad.rs:45:40
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} #[attr] else {}; }
    |                                        ^ expected one of `.`, `;`, `?`, `else`, or an operator
 
-error: expected `{`, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:49:45
+error: outer attributes are not allowed on `if` and `else` branches
+  --> $DIR/attr-stmt-expr-attr-bad.rs:47:45
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] {}; }
-   |                                             ^       --- help: try placing this code inside a block: `{ {}; }`
-   |                                             |
-   |                                             expected `{`
+   |                                        ---- ^^^^^^^ -- the attributes are attached to this branch
+   |                                        |    |
+   |                                        |    help: remove the attributes
+   |                                        the branch belongs to this `else`
 
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:51:46
+  --> $DIR/attr-stmt-expr-attr-bad.rs:49:46
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else {#![attr]}; }
    |                                              ^^^^^^^^
    |
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
-error: attributes are not yet allowed on `if` expressions
-  --> $DIR/attr-stmt-expr-attr-bad.rs:53:45
+error: outer attributes are not allowed on `if` and `else` branches
+  --> $DIR/attr-stmt-expr-attr-bad.rs:51:45
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] if 0 {}; }
-   |                                             ^^^^^^^
+   |                                        ---- ^^^^^^^ ------- the attributes are attached to this branch
+   |                                        |    |
+   |                                        |    help: remove the attributes
+   |                                        the branch belongs to this `else`
 
-error: expected `{`, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:53:45
-   |
-LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] if 0 {}; }
-   |                                             ^       -------- help: try placing this code inside a block: `{ if 0 {}; }`
-   |                                             |
-   |                                             expected `{`
-
-error: expected `{`, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:56:50
+error: outer attributes are not allowed on `if` and `else` branches
+  --> $DIR/attr-stmt-expr-attr-bad.rs:53:50
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 #[attr] {}; }
-   |                                             --   ^       --- help: try placing this code inside a block: `{ {}; }`
+   |                                             --   ^^^^^^^ -- the attributes are attached to this branch
    |                                             |    |
-   |                                             |    expected `{`
-   |                                             this `if` expression has a condition, but no block
+   |                                             |    help: remove the attributes
+   |                                             the branch belongs to this `if`
 
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:58:51
+  --> $DIR/attr-stmt-expr-attr-bad.rs:55:51
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 {#![attr]}; }
    |                                                   ^^^^^^^^
    |
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
-error: attributes are not yet allowed on `if` expressions
-  --> $DIR/attr-stmt-expr-attr-bad.rs:60:32
-   |
-LL | #[cfg(FALSE)] fn e() { let _ = #[attr] if let _ = 0 {}; }
-   |                                ^^^^^^^
-
-error: expected `{`, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:62:45
+error: outer attributes are not allowed on `if` and `else` branches
+  --> $DIR/attr-stmt-expr-attr-bad.rs:57:45
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 #[attr] {}; }
-   |                                --           ^       --- help: try placing this code inside a block: `{ {}; }`
+   |                                --           ^^^^^^^ -- the attributes are attached to this branch
    |                                |            |
-   |                                |            expected `{`
-   |                                this `if` expression has a condition, but no block
+   |                                |            help: remove the attributes
+   |                                the branch belongs to this `if`
 
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:64:46
+  --> $DIR/attr-stmt-expr-attr-bad.rs:59:46
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {#![attr]}; }
    |                                              ^^^^^^^^
@@ -236,52 +220,48 @@ LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {#![attr]}; }
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: expected one of `.`, `;`, `?`, `else`, or an operator, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:66:48
+  --> $DIR/attr-stmt-expr-attr-bad.rs:61:48
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} #[attr] else {}; }
    |                                                ^ expected one of `.`, `;`, `?`, `else`, or an operator
 
-error: expected `{`, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:68:53
+error: outer attributes are not allowed on `if` and `else` branches
+  --> $DIR/attr-stmt-expr-attr-bad.rs:63:53
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] {}; }
-   |                                                     ^       --- help: try placing this code inside a block: `{ {}; }`
-   |                                                     |
-   |                                                     expected `{`
+   |                                                ---- ^^^^^^^ -- the attributes are attached to this branch
+   |                                                |    |
+   |                                                |    help: remove the attributes
+   |                                                the branch belongs to this `else`
 
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:70:54
+  --> $DIR/attr-stmt-expr-attr-bad.rs:65:54
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else {#![attr]}; }
    |                                                      ^^^^^^^^
    |
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
-error: attributes are not yet allowed on `if` expressions
-  --> $DIR/attr-stmt-expr-attr-bad.rs:72:53
+error: outer attributes are not allowed on `if` and `else` branches
+  --> $DIR/attr-stmt-expr-attr-bad.rs:67:53
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] if let _ = 0 {}; }
-   |                                                     ^^^^^^^
+   |                                                ---- ^^^^^^^ --------------- the attributes are attached to this branch
+   |                                                |    |
+   |                                                |    help: remove the attributes
+   |                                                the branch belongs to this `else`
 
-error: expected `{`, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:72:53
-   |
-LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] if let _ = 0 {}; }
-   |                                                     ^       ---------------- help: try placing this code inside a block: `{ if let _ = 0 {}; }`
-   |                                                     |
-   |                                                     expected `{`
-
-error: expected `{`, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:75:66
+error: outer attributes are not allowed on `if` and `else` branches
+  --> $DIR/attr-stmt-expr-attr-bad.rs:69:66
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 #[attr] {}; }
-   |                                                     --           ^       --- help: try placing this code inside a block: `{ {}; }`
+   |                                                     --           ^^^^^^^ -- the attributes are attached to this branch
    |                                                     |            |
-   |                                                     |            expected `{`
-   |                                                     this `if` expression has a condition, but no block
+   |                                                     |            help: remove the attributes
+   |                                                     the branch belongs to this `if`
 
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:77:67
+  --> $DIR/attr-stmt-expr-attr-bad.rs:71:67
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 {#![attr]}; }
    |                                                                   ^^^^^^^^
@@ -289,57 +269,57 @@ LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 {#![attr]}
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: an inner attribute is not permitted following an outer attribute
-  --> $DIR/attr-stmt-expr-attr-bad.rs:80:32
+  --> $DIR/attr-stmt-expr-attr-bad.rs:74:32
    |
 LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] let _ = 0; }
-   |                        ------- ^^^^^^^^ not permitted following an outer attibute
+   |                        ------- ^^^^^^^^ not permitted following an outer attribute
    |                        |
    |                        previous outer attribute
    |
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: an inner attribute is not permitted following an outer attribute
-  --> $DIR/attr-stmt-expr-attr-bad.rs:82:32
+  --> $DIR/attr-stmt-expr-attr-bad.rs:76:32
    |
 LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] 0; }
-   |                        ------- ^^^^^^^^ not permitted following an outer attibute
+   |                        ------- ^^^^^^^^ not permitted following an outer attribute
    |                        |
    |                        previous outer attribute
    |
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: an inner attribute is not permitted following an outer attribute
-  --> $DIR/attr-stmt-expr-attr-bad.rs:84:32
+  --> $DIR/attr-stmt-expr-attr-bad.rs:78:32
    |
 LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!(); }
-   |                        ------- ^^^^^^^^ not permitted following an outer attibute
+   |                        ------- ^^^^^^^^ not permitted following an outer attribute
    |                        |
    |                        previous outer attribute
    |
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: an inner attribute is not permitted following an outer attribute
-  --> $DIR/attr-stmt-expr-attr-bad.rs:86:32
+  --> $DIR/attr-stmt-expr-attr-bad.rs:80:32
    |
 LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo![]; }
-   |                        ------- ^^^^^^^^ not permitted following an outer attibute
+   |                        ------- ^^^^^^^^ not permitted following an outer attribute
    |                        |
    |                        previous outer attribute
    |
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: an inner attribute is not permitted following an outer attribute
-  --> $DIR/attr-stmt-expr-attr-bad.rs:88:32
+  --> $DIR/attr-stmt-expr-attr-bad.rs:82:32
    |
 LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!{}; }
-   |                        ------- ^^^^^^^^ not permitted following an outer attibute
+   |                        ------- ^^^^^^^^ not permitted following an outer attribute
    |                        |
    |                        previous outer attribute
    |
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error[E0586]: inclusive range with no end
-  --> $DIR/attr-stmt-expr-attr-bad.rs:94:35
+  --> $DIR/attr-stmt-expr-attr-bad.rs:88:35
    |
 LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } }
    |                                   ^^^ help: use `..` instead
@@ -347,13 +327,13 @@ LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } }
    = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
 error: expected one of `=>`, `if`, or `|`, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:94:38
+  --> $DIR/attr-stmt-expr-attr-bad.rs:88:38
    |
 LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } }
    |                                      ^ expected one of `=>`, `if`, or `|`
 
 error[E0586]: inclusive range with no end
-  --> $DIR/attr-stmt-expr-attr-bad.rs:97:35
+  --> $DIR/attr-stmt-expr-attr-bad.rs:91:35
    |
 LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] -10 => () } }
    |                                   ^^^ help: use `..` instead
@@ -361,19 +341,19 @@ LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] -10 => () } }
    = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
 error: expected one of `=>`, `if`, or `|`, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:97:38
+  --> $DIR/attr-stmt-expr-attr-bad.rs:91:38
    |
 LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] -10 => () } }
    |                                      ^ expected one of `=>`, `if`, or `|`
 
 error: unexpected token: `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:100:39
+  --> $DIR/attr-stmt-expr-attr-bad.rs:94:39
    |
 LL | #[cfg(FALSE)] fn e() { match 0 { 0..=-#[attr] 10 => () } }
    |                                       ^
 
 error[E0586]: inclusive range with no end
-  --> $DIR/attr-stmt-expr-attr-bad.rs:102:35
+  --> $DIR/attr-stmt-expr-attr-bad.rs:96:35
    |
 LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } }
    |                                   ^^^ help: use `..` instead
@@ -381,47 +361,47 @@ LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } }
    = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
 error: expected one of `=>`, `if`, or `|`, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:102:38
+  --> $DIR/attr-stmt-expr-attr-bad.rs:96:38
    |
 LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } }
    |                                      ^ expected one of `=>`, `if`, or `|`
 
 error: unexpected token: `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:106:34
+  --> $DIR/attr-stmt-expr-attr-bad.rs:100:34
    |
 LL | #[cfg(FALSE)] fn e() { let _ = x.#![attr]foo(); }
    |                                  ^
 
 error: expected one of `.`, `;`, `?`, or an operator, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:106:34
+  --> $DIR/attr-stmt-expr-attr-bad.rs:100:34
    |
 LL | #[cfg(FALSE)] fn e() { let _ = x.#![attr]foo(); }
    |                                  ^ expected one of `.`, `;`, `?`, or an operator
 
 error: unexpected token: `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:109:34
+  --> $DIR/attr-stmt-expr-attr-bad.rs:103:34
    |
 LL | #[cfg(FALSE)] fn e() { let _ = x.#[attr]foo(); }
    |                                  ^
 
 error: expected one of `.`, `;`, `?`, or an operator, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:109:34
+  --> $DIR/attr-stmt-expr-attr-bad.rs:103:34
    |
 LL | #[cfg(FALSE)] fn e() { let _ = x.#[attr]foo(); }
    |                                  ^ expected one of `.`, `;`, `?`, or an operator
 
 error: expected statement after outer attribute
-  --> $DIR/attr-stmt-expr-attr-bad.rs:114:44
+  --> $DIR/attr-stmt-expr-attr-bad.rs:108:37
    |
 LL | #[cfg(FALSE)] fn e() { { fn foo() { #[attr]; } } }
-   |                                            ^
+   |                                     ^^^^^^^
 
 error: expected statement after outer attribute
-  --> $DIR/attr-stmt-expr-attr-bad.rs:116:45
+  --> $DIR/attr-stmt-expr-attr-bad.rs:110:37
    |
 LL | #[cfg(FALSE)] fn e() { { fn foo() { #[attr] } } }
-   |                                             ^
+   |                                     ^^^^^^^
 
-error: aborting due to 57 previous errors
+error: aborting due to 53 previous errors
 
 For more information about this error, try `rustc --explain E0586`.
diff --git a/src/test/ui/parser/bad-interpolated-block.rs b/src/test/ui/parser/bad-interpolated-block.rs
new file mode 100644 (file)
index 0000000..38d53a1
--- /dev/null
@@ -0,0 +1,15 @@
+#![feature(label_break_value)]
+
+fn main() {}
+
+macro_rules! m {
+    ($b:block) => {
+        'lab: $b; //~ ERROR cannot use a `block` macro fragment here
+        unsafe $b; //~ ERROR cannot use a `block` macro fragment here
+        |x: u8| -> () $b; //~ ERROR cannot use a `block` macro fragment here
+    }
+}
+
+fn foo() {
+    m!({});
+}
diff --git a/src/test/ui/parser/bad-interpolated-block.stderr b/src/test/ui/parser/bad-interpolated-block.stderr
new file mode 100644 (file)
index 0000000..2cbb6a1
--- /dev/null
@@ -0,0 +1,39 @@
+error: cannot use a `block` macro fragment here
+  --> $DIR/bad-interpolated-block.rs:7:15
+   |
+LL |         'lab: $b;
+   |         ------^^
+   |         |
+   |         the `block` fragment is within this context
+...
+LL |     m!({});
+   |     ------- in this macro invocation
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: cannot use a `block` macro fragment here
+  --> $DIR/bad-interpolated-block.rs:8:16
+   |
+LL |         unsafe $b;
+   |         -------^^
+   |         |
+   |         the `block` fragment is within this context
+...
+LL |     m!({});
+   |     ------- in this macro invocation
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: cannot use a `block` macro fragment here
+  --> $DIR/bad-interpolated-block.rs:9:23
+   |
+LL |         |x: u8| -> () $b;
+   |                       ^^ the `block` fragment is within this context
+...
+LL |     m!({});
+   |     ------- in this macro invocation
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/parser/block-no-opening-brace.rs b/src/test/ui/parser/block-no-opening-brace.rs
new file mode 100644 (file)
index 0000000..e4bb39f
--- /dev/null
@@ -0,0 +1,31 @@
+// edition:2018
+
+#![feature(try_blocks)]
+
+fn main() {}
+
+fn f1() {
+    loop
+        let x = 0; //~ ERROR expected `{`, found keyword `let`
+        drop(0);
+    }
+
+fn f2() {
+    while true
+        let x = 0; //~ ERROR expected `{`, found keyword `let`
+    }
+
+fn f3() {
+    for x in 0..1
+        let x = 0; //~ ERROR expected `{`, found keyword `let`
+    }
+
+fn f4() {
+    try //~ ERROR expected expression, found reserved keyword `try`
+        let x = 0;
+    }
+
+fn f5() {
+    async //~ ERROR async closures are unstable
+        let x = 0; //~ ERROR expected one of `move`, `|`, or `||`, found keyword `let`
+    }
diff --git a/src/test/ui/parser/block-no-opening-brace.stderr b/src/test/ui/parser/block-no-opening-brace.stderr
new file mode 100644 (file)
index 0000000..a88e4ac
--- /dev/null
@@ -0,0 +1,53 @@
+error: expected `{`, found keyword `let`
+  --> $DIR/block-no-opening-brace.rs:9:9
+   |
+LL |         let x = 0;
+   |         ^^^-------
+   |         |
+   |         expected `{`
+   |         help: try placing this code inside a block: `{ let x = 0; }`
+
+error: expected `{`, found keyword `let`
+  --> $DIR/block-no-opening-brace.rs:15:9
+   |
+LL |         let x = 0;
+   |         ^^^-------
+   |         |
+   |         expected `{`
+   |         help: try placing this code inside a block: `{ let x = 0; }`
+
+error: expected `{`, found keyword `let`
+  --> $DIR/block-no-opening-brace.rs:20:9
+   |
+LL |         let x = 0;
+   |         ^^^-------
+   |         |
+   |         expected `{`
+   |         help: try placing this code inside a block: `{ let x = 0; }`
+
+error: expected expression, found reserved keyword `try`
+  --> $DIR/block-no-opening-brace.rs:24:5
+   |
+LL |     try
+   |     ^^^ expected expression
+
+error: expected one of `move`, `|`, or `||`, found keyword `let`
+  --> $DIR/block-no-opening-brace.rs:30:9
+   |
+LL |     async
+   |          - expected one of `move`, `|`, or `||`
+LL |         let x = 0;
+   |         ^^^ unexpected token
+
+error[E0658]: async closures are unstable
+  --> $DIR/block-no-opening-brace.rs:29:5
+   |
+LL |     async
+   |     ^^^^^
+   |
+   = note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information
+   = help: add `#![feature(async_closure)]` to the crate attributes to enable
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
index 9225cfce94eb8e832735a63eb6983894b39a4290..c9251ac5321851c786cc06862790481505887481 100644 (file)
@@ -6,6 +6,6 @@
 type A = for<'a: 'b,> fn(); // OK(rejected later by ast_validation)
 type A = for<'a: 'b +> fn(); // OK (rejected later by ast_validation)
 type A = for<'a, T> fn(); // OK (rejected later by ast_validation)
-type A = for<,> fn(); //~ ERROR expected one of `>`, `const`, identifier, or lifetime, found `,`
+type A = for<,> fn(); //~ ERROR expected one of `#`, `>`, `const`, identifier, or lifetime
 
 fn main() {}
index 12b9b61ebd17465259112728d27af3fc0fddeb83..e47a21d892b2f745a68e92e7bb3982409d9a1d6f 100644 (file)
@@ -1,8 +1,8 @@
-error: expected one of `>`, `const`, identifier, or lifetime, found `,`
+error: expected one of `#`, `>`, `const`, identifier, or lifetime, found `,`
   --> $DIR/bounds-lifetime.rs:9:14
    |
 LL | type A = for<,> fn();
-   |              ^ expected one of `>`, `const`, identifier, or lifetime
+   |              ^ expected one of `#`, `>`, `const`, identifier, or lifetime
 
 error: aborting due to previous error
 
index b85003bf0910f61a39e06c28b031822e29c59a65..1ae36a1f7605eb1a47403e393af05314b6f02a7c 100644 (file)
@@ -6,5 +6,5 @@ pub fn hi_str() -> String {
 }
 
 fn main() {
-    circular_modules_hello::say_hello();
+    circular_modules_hello::say_hello(); //~ ERROR cannot find function `say_hello` in module
 }
index 33865fb7bca95182b56126b7c8a005308e10295c..90f81c64835b74ae0eca9f50703c1cf2b79b94be 100644 (file)
@@ -1,8 +1,20 @@
 error: circular modules: $DIR/circular_modules_hello.rs -> $DIR/circular_modules_main.rs -> $DIR/circular_modules_hello.rs
-  --> $DIR/circular_modules_main.rs:2:5
+  --> $DIR/circular_modules_main.rs:2:1
    |
 LL | mod circular_modules_hello;
-   |     ^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error
+error[E0425]: cannot find function `say_hello` in module `circular_modules_hello`
+  --> $DIR/circular_modules_main.rs:9:29
+   |
+LL |     circular_modules_hello::say_hello();
+   |                             ^^^^^^^^^ not found in `circular_modules_hello`
+   |
+help: possible candidate is found in another module, you can import it into scope
+   |
+LL | use circular_modules_hello::say_hello;
+   |
+
+error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0425`.
index 54eb791d2bce41462fbebccc048d8bb6992fe33b..c6a08abeff4ba76d1094bddf8618a08c9f2e091d 100644 (file)
@@ -3,5 +3,5 @@
 
 fn main() {
     let x = || -> i32 22;
-    //~^ ERROR expected one of `!`, `(`, `+`, `::`, `<`, or `{`, found `22`
+    //~^ ERROR expected `{`, found `22`
 }
index bfb7f98c5f527568ba38790e4ceecc9211cbee0f..1ccdd977305559e318cd35b99b035fc08b9929b2 100644 (file)
@@ -1,8 +1,11 @@
-error: expected one of `!`, `(`, `+`, `::`, `<`, or `{`, found `22`
+error: expected `{`, found `22`
   --> $DIR/closure-return-syntax.rs:5:23
    |
 LL |     let x = || -> i32 22;
-   |                       ^^ expected one of `!`, `(`, `+`, `::`, `<`, or `{`
+   |                       ^^
+   |                       |
+   |                       expected `{`
+   |                       help: try placing this code inside a block: `{ 22 }`
 
 error: aborting due to previous error
 
index e158e5247db188211ee9d06bbcc63c5be560cbc8..0c24478c25c8b62af03ed797833d1a9c9902f0c5 100644 (file)
@@ -1 +1 @@
-# //~ ERROR expected `[`, found `<eof>`
+# //~ ERROR expected one of `!` or `[`, found `<eof>`
index 5cbf3d3e95965b8ec74052828fbaf03f0398c9d4..766d72a0a5a93b9cef808048fdad8c6fb3753225 100644 (file)
@@ -1,8 +1,8 @@
-error: expected `[`, found `<eof>`
+error: expected one of `!` or `[`, found `<eof>`
   --> $DIR/column-offset-1-based.rs:1:1
    |
 LL | #
-   | ^ expected `[`
+   | ^ expected one of `!` or `[`
 
 error: aborting due to previous error
 
index c3f478fe4207757f11efb0d2669a1b7b18ce48c2..405a7e1e2a33b9eca931dfe4b53b87cd884f2e25 100644 (file)
@@ -3,6 +3,4 @@ fn main() {
     //~^ ERROR found a documentation comment that doesn't document anything
     //~| HELP maybe a comment was intended
     ;
-    //~^ WARNING unnecessary trailing semicolon
-    //~| HELP remove this semicolon
 }
index b9ac30b09b2f866ae433ca82709e6146a8008da9..e6bade18d0a2da70c392493f5fe8656a6742782d 100644 (file)
@@ -6,14 +6,6 @@ LL |     /// hi
    |
    = help: doc comments must come before what they document, maybe a comment was intended with `//`?
 
-warning: unnecessary trailing semicolon
-  --> $DIR/doc-before-semi.rs:5:5
-   |
-LL |     ;
-   |     ^ help: remove this semicolon
-   |
-   = note: `#[warn(redundant_semicolon)]` on by default
-
 error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0585`.
index c85fe25a7d0d1999e30328bfff25cb21d0221593..343eac1b81ff0dc958a0e183ec9bdb11f2458ed6 100644 (file)
@@ -1,4 +1,5 @@
 fn main() {
     if true /*!*/ {}
-    //~^ ERROR expected `{`, found doc comment `/*!*/`
+    //~^ ERROR outer attributes are not allowed on
+    //~| ERROR expected outer doc comment
 }
index a720dd68bd0377baed1c590fe0e5632f6309b1c6..af21b78733f90baa9c6f92d9dcbd105b6d3e2847 100644 (file)
@@ -1,10 +1,19 @@
-error: expected `{`, found doc comment `/*!*/`
+error: expected outer doc comment
   --> $DIR/doc-comment-in-if-statement.rs:2:13
    |
 LL |     if true /*!*/ {}
-   |     --      ^^^^^ expected `{`
-   |     |
-   |     this `if` expression has a condition, but no block
+   |             ^^^^^
+   |
+   = note: inner doc comments like this (starting with `//!` or `/*!`) can only appear before items
+
+error: outer attributes are not allowed on `if` and `else` branches
+  --> $DIR/doc-comment-in-if-statement.rs:2:13
+   |
+LL |     if true /*!*/ {}
+   |     --      ^^^^^ -- the attributes are attached to this branch
+   |     |       |
+   |     |       help: remove the attributes
+   |     the branch belongs to this `if`
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/parser/fn-body-eq-expr-semi.rs b/src/test/ui/parser/fn-body-eq-expr-semi.rs
new file mode 100644 (file)
index 0000000..0944407
--- /dev/null
@@ -0,0 +1,23 @@
+fn main() {}
+
+fn syntax() {
+    fn foo() = 42; //~ ERROR function body cannot be `= expression;`
+    fn bar() -> u8 = 42; //~ ERROR function body cannot be `= expression;`
+}
+
+extern {
+    fn foo() = 42; //~ ERROR function body cannot be `= expression;`
+    //~^ ERROR incorrect function inside `extern` block
+    fn bar() -> u8 = 42; //~ ERROR function body cannot be `= expression;`
+    //~^ ERROR incorrect function inside `extern` block
+}
+
+trait Foo {
+    fn foo() = 42; //~ ERROR function body cannot be `= expression;`
+    fn bar() -> u8 = 42; //~ ERROR function body cannot be `= expression;`
+}
+
+impl Foo for () {
+    fn foo() = 42; //~ ERROR function body cannot be `= expression;`
+    fn bar() -> u8 = 42; //~ ERROR function body cannot be `= expression;`
+}
diff --git a/src/test/ui/parser/fn-body-eq-expr-semi.stderr b/src/test/ui/parser/fn-body-eq-expr-semi.stderr
new file mode 100644 (file)
index 0000000..739133e
--- /dev/null
@@ -0,0 +1,117 @@
+error: function body cannot be `= expression;`
+  --> $DIR/fn-body-eq-expr-semi.rs:4:14
+   |
+LL |     fn foo() = 42;
+   |              ^^^^^
+   |
+help: surround the expression with `{` and `}` instead of `=` and `;`
+   |
+LL |     fn foo() { 42 }
+   |              ^    ^
+
+error: function body cannot be `= expression;`
+  --> $DIR/fn-body-eq-expr-semi.rs:5:20
+   |
+LL |     fn bar() -> u8 = 42;
+   |                    ^^^^^
+   |
+help: surround the expression with `{` and `}` instead of `=` and `;`
+   |
+LL |     fn bar() -> u8 { 42 }
+   |                    ^    ^
+
+error: function body cannot be `= expression;`
+  --> $DIR/fn-body-eq-expr-semi.rs:9:14
+   |
+LL |     fn foo() = 42;
+   |              ^^^^^
+   |
+help: surround the expression with `{` and `}` instead of `=` and `;`
+   |
+LL |     fn foo() { 42 }
+   |              ^    ^
+
+error: function body cannot be `= expression;`
+  --> $DIR/fn-body-eq-expr-semi.rs:11:20
+   |
+LL |     fn bar() -> u8 = 42;
+   |                    ^^^^^
+   |
+help: surround the expression with `{` and `}` instead of `=` and `;`
+   |
+LL |     fn bar() -> u8 { 42 }
+   |                    ^    ^
+
+error: function body cannot be `= expression;`
+  --> $DIR/fn-body-eq-expr-semi.rs:16:14
+   |
+LL |     fn foo() = 42;
+   |              ^^^^^
+   |
+help: surround the expression with `{` and `}` instead of `=` and `;`
+   |
+LL |     fn foo() { 42 }
+   |              ^    ^
+
+error: function body cannot be `= expression;`
+  --> $DIR/fn-body-eq-expr-semi.rs:17:20
+   |
+LL |     fn bar() -> u8 = 42;
+   |                    ^^^^^
+   |
+help: surround the expression with `{` and `}` instead of `=` and `;`
+   |
+LL |     fn bar() -> u8 { 42 }
+   |                    ^    ^
+
+error: function body cannot be `= expression;`
+  --> $DIR/fn-body-eq-expr-semi.rs:21:14
+   |
+LL |     fn foo() = 42;
+   |              ^^^^^
+   |
+help: surround the expression with `{` and `}` instead of `=` and `;`
+   |
+LL |     fn foo() { 42 }
+   |              ^    ^
+
+error: function body cannot be `= expression;`
+  --> $DIR/fn-body-eq-expr-semi.rs:22:20
+   |
+LL |     fn bar() -> u8 = 42;
+   |                    ^^^^^
+   |
+help: surround the expression with `{` and `}` instead of `=` and `;`
+   |
+LL |     fn bar() -> u8 { 42 }
+   |                    ^    ^
+
+error: incorrect function inside `extern` block
+  --> $DIR/fn-body-eq-expr-semi.rs:9:8
+   |
+LL | extern {
+   | ------ `extern` blocks define existing foreign functions and functions inside of them cannot have a body
+LL |     fn foo() = 42;
+   |        ^^^   ----- help: remove the invalid body: `;`
+   |        |
+   |        cannot have a body
+   |
+   = help: you might have meant to write a function accessible through FFI, which can be done by writing `extern fn` outside of the `extern` block
+   = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html
+
+error: incorrect function inside `extern` block
+  --> $DIR/fn-body-eq-expr-semi.rs:11:8
+   |
+LL | extern {
+   | ------ `extern` blocks define existing foreign functions and functions inside of them cannot have a body
+...
+LL |     fn bar() -> u8 = 42;
+   |        ^^^         ----- help: remove the invalid body: `;`
+   |        |
+   |        cannot have a body
+   |
+   = help: you might have meant to write a function accessible through FFI, which can be done by writing `extern fn` outside of the `extern` block
+   = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html
+
+error: aborting due to 10 previous errors
+
index 1142cee9851b02c6c1397cd701f371441d05598f..d6b36fbb71450ed258c04fa042c687ac93b21920 100644 (file)
@@ -2,7 +2,7 @@ error: functions cannot be both `const` and `async`
   --> $DIR/fn-header-semantic-fail.rs:13:5
    |
 LL |     const async unsafe extern "C" fn ff5() {} // OK.
-   |     -----^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^-^^^^^------------------------------
    |     |     |
    |     |     `async` because of this
    |     `const` because of this
@@ -45,7 +45,7 @@ error: functions cannot be both `const` and `async`
   --> $DIR/fn-header-semantic-fail.rs:21:9
    |
 LL |         const async unsafe extern "C" fn ft5();
-   |         -----^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |         ^^^^^-^^^^^----------------------------
    |         |     |
    |         |     `async` because of this
    |         `const` because of this
@@ -88,7 +88,7 @@ error: functions cannot be both `const` and `async`
   --> $DIR/fn-header-semantic-fail.rs:34:9
    |
 LL |         const async unsafe extern "C" fn ft5() {}
-   |         -----^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |         ^^^^^-^^^^^------------------------------
    |         |     |
    |         |     `async` because of this
    |         `const` because of this
@@ -97,7 +97,7 @@ error: functions cannot be both `const` and `async`
   --> $DIR/fn-header-semantic-fail.rs:46:9
    |
 LL |         const async unsafe extern "C" fn fi5() {}
-   |         -----^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |         ^^^^^-^^^^^------------------------------
    |         |     |
    |         |     `async` because of this
    |         `const` because of this
@@ -160,7 +160,7 @@ error: functions cannot be both `const` and `async`
   --> $DIR/fn-header-semantic-fail.rs:55:9
    |
 LL |         const async unsafe extern "C" fn fe5();
-   |         -----^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |         ^^^^^-^^^^^----------------------------
    |         |     |
    |         |     `async` because of this
    |         `const` because of this
index b012abc25e7f3bd2b7755ce28798495da3be813a..c1e9e7a427f89696d50a8f6b2a46166c7a9f908c 100644 (file)
@@ -7,7 +7,7 @@ LL | |  */
    | |___- previous doc comment
 LL | 
 LL |   #![recursion_limit="100"]
-   |   ^^^^^^^^^^^^^^^^^^^^^^^^^ not permitted following an outer attibute
+   |   ^^^^^^^^^^^^^^^^^^^^^^^^^ not permitted following an outer attribute
    |
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
index 070d9f47d96f925e04bcc7abb412ebb1e06d193f..e1bf2cca1c9635b5303b19a03a0b01c98abe5d05 100644 (file)
@@ -5,7 +5,7 @@ LL | #[feature(lang_items)]
    | ---------------------- previous outer attribute
 LL | 
 LL | #![recursion_limit="100"]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^ not permitted following an outer attibute
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^ not permitted following an outer attribute
    |
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
index 3d0bf3c1c7b9f5a5d078b8e6ac4be55a5465ef20..e9fc6f15346f24ec13200f98b6a053665397cd90 100644 (file)
@@ -1,6 +1,5 @@
-// error-pattern:expected `[`, found `vec`
 mod blade_runner {
-    #vec[doc(
+    #vec[doc( //~ ERROR expected one of `!` or `[`, found `vec`
         brief = "Blade Runner is probably the best movie ever",
         desc = "I like that in the world of Blade Runner it is always
                 raining, and that it's always night time. And Aliens
index 3f656b63cdb84d69e847fab96a82237e9acf2b65..0c390a0ec563c95c78e25b7fcf996520a33f0bd0 100644 (file)
@@ -1,8 +1,8 @@
-error: expected `[`, found `vec`
-  --> $DIR/issue-1655.rs:3:6
+error: expected one of `!` or `[`, found `vec`
+  --> $DIR/issue-1655.rs:2:6
    |
 LL |     #vec[doc(
-   |      ^^^ expected `[`
+   |      ^^^ expected one of `!` or `[`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/issue-35813-postfix-after-cast.rs b/src/test/ui/parser/issue-35813-postfix-after-cast.rs
new file mode 100644 (file)
index 0000000..e725aa5
--- /dev/null
@@ -0,0 +1,171 @@
+// edition:2018
+#![crate_type = "lib"]
+#![feature(type_ascription)]
+use std::future::Future;
+use std::pin::Pin;
+
+// This tests the parser for "x as Y[z]". It errors, but we want to give useful
+// errors and parse such that further code gives useful errors.
+pub fn index_after_as_cast() {
+    vec![1, 2, 3] as Vec<i32>[0];
+    //~^ ERROR: casts cannot be followed by indexing
+    vec![1, 2, 3]: Vec<i32>[0];
+    //~^ ERROR: casts cannot be followed by indexing
+}
+
+pub fn index_after_cast_to_index() {
+    (&[0]) as &[i32][0];
+    //~^ ERROR: casts cannot be followed by indexing
+    (&[0i32]): &[i32; 1][0];
+    //~^ ERROR: casts cannot be followed by indexing
+}
+
+pub fn cast_after_cast() {
+    if 5u64 as i32 as u16 == 0u16 {
+
+    }
+    if 5u64: u64: u64 == 0u64 {
+
+    }
+    let _ = 5u64: u64: u64 as u8 as i8 == 9i8;
+    let _ = 0i32: i32: i32;
+    let _ = 0 as i32: i32;
+    let _ = 0i32: i32 as i32;
+    let _ = 0 as i32 as i32;
+    let _ = 0i32: i32: i32 as u32 as i32;
+}
+
+pub fn cast_cast_method_call() {
+    let _ = 0i32: i32: i32.count_ones();
+    //~^ ERROR: casts cannot be followed by a method call
+    let _ = 0 as i32: i32.count_ones();
+    //~^ ERROR: casts cannot be followed by a method call
+    let _ = 0i32: i32 as i32.count_ones();
+    //~^ ERROR: casts cannot be followed by a method call
+    let _ = 0 as i32 as i32.count_ones();
+    //~^ ERROR: casts cannot be followed by a method call
+    let _ = 0i32: i32: i32 as u32 as i32.count_ones();
+    //~^ ERROR: casts cannot be followed by a method call
+    let _ = 0i32: i32.count_ones(): u32;
+    //~^ ERROR: casts cannot be followed by a method call
+    let _ = 0 as i32.count_ones(): u32;
+    //~^ ERROR: casts cannot be followed by a method call
+    let _ = 0i32: i32.count_ones() as u32;
+    //~^ ERROR: casts cannot be followed by a method call
+    let _ = 0 as i32.count_ones() as u32;
+    //~^ ERROR: casts cannot be followed by a method call
+    let _ = 0i32: i32: i32.count_ones() as u32 as i32;
+    //~^ ERROR: casts cannot be followed by a method call
+}
+
+pub fn multiline_error() {
+    let _ = 0
+        as i32
+        .count_ones();
+    //~^^^ ERROR: casts cannot be followed by a method call
+}
+
+// this tests that the precedence for `!x as Y.Z` is still what we expect
+pub fn precedence() {
+    let x: i32 = &vec![1, 2, 3] as &Vec<i32>[0];
+    //~^ ERROR: casts cannot be followed by indexing
+}
+
+pub fn method_calls() {
+    0 as i32.max(0);
+    //~^ ERROR: casts cannot be followed by a method call
+    0: i32.max(0);
+    //~^ ERROR: casts cannot be followed by a method call
+}
+
+pub fn complex() {
+    let _ = format!(
+        "{} and {}",
+        if true { 33 } else { 44 } as i32.max(0),
+        //~^ ERROR: casts cannot be followed by a method call
+        if true { 33 } else { 44 }: i32.max(0)
+        //~^ ERROR: casts cannot be followed by a method call
+    );
+}
+
+pub fn in_condition() {
+    if 5u64 as i32.max(0) == 0 {
+        //~^ ERROR: casts cannot be followed by a method call
+    }
+    if 5u64: u64.max(0) == 0 {
+        //~^ ERROR: casts cannot be followed by a method call
+    }
+}
+
+pub fn inside_block() {
+    let _ = if true {
+        5u64 as u32.max(0) == 0
+        //~^ ERROR: casts cannot be followed by a method call
+    } else { false };
+    let _ = if true {
+        5u64: u64.max(0) == 0
+        //~^ ERROR: casts cannot be followed by a method call
+    } else { false };
+}
+
+static bar: &[i32] = &(&[1,2,3] as &[i32][0..1]);
+//~^ ERROR: casts cannot be followed by indexing
+
+static bar2: &[i32] = &(&[1i32,2,3]: &[i32; 3][0..1]);
+//~^ ERROR: casts cannot be followed by indexing
+
+
+pub fn cast_then_try() -> Result<u64,u64> {
+    Err(0u64) as Result<u64,u64>?;
+    //~^ ERROR: casts cannot be followed by ?
+    Err(0u64): Result<u64,u64>?;
+    //~^ ERROR: casts cannot be followed by ?
+    Ok(1)
+}
+
+
+pub fn cast_then_call() {
+    type F = fn(u8);
+    // type ascription won't actually do [unique drop fn type] -> fn(u8) casts.
+    let drop_ptr = drop as fn(u8);
+    drop as F();
+    //~^ ERROR: parenthesized type parameters may only be used with a `Fn` trait [E0214]
+    drop_ptr: F();
+    //~^ ERROR: parenthesized type parameters may only be used with a `Fn` trait [E0214]
+}
+
+pub fn cast_to_fn_should_work() {
+    let drop_ptr = drop as fn(u8);
+    drop as fn(u8);
+    drop_ptr: fn(u8);
+}
+
+pub fn parens_after_cast_error() {
+    let drop_ptr = drop as fn(u8);
+    drop as fn(u8)(0);
+    //~^ ERROR: casts cannot be followed by a function call
+    drop_ptr: fn(u8)(0);
+    //~^ ERROR: casts cannot be followed by a function call
+}
+
+pub async fn cast_then_await() {
+    Box::pin(noop()) as Pin<Box<dyn Future<Output = ()>>>.await;
+    //~^ ERROR: casts cannot be followed by `.await`
+
+    Box::pin(noop()): Pin<Box<_>>.await;
+    //~^ ERROR: casts cannot be followed by `.await`
+}
+
+pub async fn noop() {}
+
+#[derive(Default)]
+pub struct Foo {
+    pub bar: u32,
+}
+
+pub fn struct_field() {
+    Foo::default() as Foo.bar;
+    //~^ ERROR: cannot be followed by a field access
+    Foo::default(): Foo.bar;
+    //~^ ERROR: cannot be followed by a field access
+}
diff --git a/src/test/ui/parser/issue-35813-postfix-after-cast.stderr b/src/test/ui/parser/issue-35813-postfix-after-cast.stderr
new file mode 100644 (file)
index 0000000..255e9f4
--- /dev/null
@@ -0,0 +1,392 @@
+error: casts cannot be followed by indexing
+  --> $DIR/issue-35813-postfix-after-cast.rs:10:5
+   |
+LL |     vec![1, 2, 3] as Vec<i32>[0];
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: try surrounding the expression in parentheses
+   |
+LL |     (vec![1, 2, 3] as Vec<i32>)[0];
+   |     ^                         ^
+
+error: casts cannot be followed by indexing
+  --> $DIR/issue-35813-postfix-after-cast.rs:12:5
+   |
+LL |     vec![1, 2, 3]: Vec<i32>[0];
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: try surrounding the expression in parentheses
+   |
+LL |     (vec![1, 2, 3]: Vec<i32>)[0];
+   |     ^                       ^
+
+error: casts cannot be followed by indexing
+  --> $DIR/issue-35813-postfix-after-cast.rs:17:5
+   |
+LL |     (&[0]) as &[i32][0];
+   |     ^^^^^^^^^^^^^^^^
+   |
+help: try surrounding the expression in parentheses
+   |
+LL |     ((&[0]) as &[i32])[0];
+   |     ^                ^
+
+error: casts cannot be followed by indexing
+  --> $DIR/issue-35813-postfix-after-cast.rs:19:5
+   |
+LL |     (&[0i32]): &[i32; 1][0];
+   |     ^^^^^^^^^^^^^^^^^^^^
+   |
+help: try surrounding the expression in parentheses
+   |
+LL |     ((&[0i32]): &[i32; 1])[0];
+   |     ^                    ^
+
+error: casts cannot be followed by a method call
+  --> $DIR/issue-35813-postfix-after-cast.rs:39:13
+   |
+LL |     let _ = 0i32: i32: i32.count_ones();
+   |             ^^^^^^^^^^^^^^
+   |
+help: try surrounding the expression in parentheses
+   |
+LL |     let _ = (0i32: i32: i32).count_ones();
+   |             ^              ^
+
+error: casts cannot be followed by a method call
+  --> $DIR/issue-35813-postfix-after-cast.rs:41:13
+   |
+LL |     let _ = 0 as i32: i32.count_ones();
+   |             ^^^^^^^^^^^^^
+   |
+help: try surrounding the expression in parentheses
+   |
+LL |     let _ = (0 as i32: i32).count_ones();
+   |             ^             ^
+
+error: casts cannot be followed by a method call
+  --> $DIR/issue-35813-postfix-after-cast.rs:43:13
+   |
+LL |     let _ = 0i32: i32 as i32.count_ones();
+   |             ^^^^^^^^^^^^^^^^
+   |
+help: try surrounding the expression in parentheses
+   |
+LL |     let _ = (0i32: i32 as i32).count_ones();
+   |             ^                ^
+
+error: casts cannot be followed by a method call
+  --> $DIR/issue-35813-postfix-after-cast.rs:45:13
+   |
+LL |     let _ = 0 as i32 as i32.count_ones();
+   |             ^^^^^^^^^^^^^^^
+   |
+help: try surrounding the expression in parentheses
+   |
+LL |     let _ = (0 as i32 as i32).count_ones();
+   |             ^               ^
+
+error: casts cannot be followed by a method call
+  --> $DIR/issue-35813-postfix-after-cast.rs:47:13
+   |
+LL |     let _ = 0i32: i32: i32 as u32 as i32.count_ones();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: try surrounding the expression in parentheses
+   |
+LL |     let _ = (0i32: i32: i32 as u32 as i32).count_ones();
+   |             ^                            ^
+
+error: casts cannot be followed by a method call
+  --> $DIR/issue-35813-postfix-after-cast.rs:49:13
+   |
+LL |     let _ = 0i32: i32.count_ones(): u32;
+   |             ^^^^^^^^^
+   |
+help: try surrounding the expression in parentheses
+   |
+LL |     let _ = (0i32: i32).count_ones(): u32;
+   |             ^         ^
+
+error: casts cannot be followed by a method call
+  --> $DIR/issue-35813-postfix-after-cast.rs:51:13
+   |
+LL |     let _ = 0 as i32.count_ones(): u32;
+   |             ^^^^^^^^
+   |
+help: try surrounding the expression in parentheses
+   |
+LL |     let _ = (0 as i32).count_ones(): u32;
+   |             ^        ^
+
+error: casts cannot be followed by a method call
+  --> $DIR/issue-35813-postfix-after-cast.rs:53:13
+   |
+LL |     let _ = 0i32: i32.count_ones() as u32;
+   |             ^^^^^^^^^
+   |
+help: try surrounding the expression in parentheses
+   |
+LL |     let _ = (0i32: i32).count_ones() as u32;
+   |             ^         ^
+
+error: casts cannot be followed by a method call
+  --> $DIR/issue-35813-postfix-after-cast.rs:55:13
+   |
+LL |     let _ = 0 as i32.count_ones() as u32;
+   |             ^^^^^^^^
+   |
+help: try surrounding the expression in parentheses
+   |
+LL |     let _ = (0 as i32).count_ones() as u32;
+   |             ^        ^
+
+error: casts cannot be followed by a method call
+  --> $DIR/issue-35813-postfix-after-cast.rs:57:13
+   |
+LL |     let _ = 0i32: i32: i32.count_ones() as u32 as i32;
+   |             ^^^^^^^^^^^^^^
+   |
+help: try surrounding the expression in parentheses
+   |
+LL |     let _ = (0i32: i32: i32).count_ones() as u32 as i32;
+   |             ^              ^
+
+error: casts cannot be followed by a method call
+  --> $DIR/issue-35813-postfix-after-cast.rs:62:13
+   |
+LL |       let _ = 0
+   |  _____________^
+LL | |         as i32
+   | |______________^
+   |
+help: try surrounding the expression in parentheses
+   |
+LL |     let _ = (0
+LL |         as i32)
+   |
+
+error: casts cannot be followed by indexing
+  --> $DIR/issue-35813-postfix-after-cast.rs:70:18
+   |
+LL |     let x: i32 = &vec![1, 2, 3] as &Vec<i32>[0];
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: try surrounding the expression in parentheses
+   |
+LL |     let x: i32 = (&vec![1, 2, 3] as &Vec<i32>)[0];
+   |                  ^                           ^
+
+error: casts cannot be followed by a method call
+  --> $DIR/issue-35813-postfix-after-cast.rs:75:5
+   |
+LL |     0 as i32.max(0);
+   |     ^^^^^^^^
+   |
+help: try surrounding the expression in parentheses
+   |
+LL |     (0 as i32).max(0);
+   |     ^        ^
+
+error: casts cannot be followed by a method call
+  --> $DIR/issue-35813-postfix-after-cast.rs:77:5
+   |
+LL |     0: i32.max(0);
+   |     ^^^^^^
+   |
+help: try surrounding the expression in parentheses
+   |
+LL |     (0: i32).max(0);
+   |     ^      ^
+
+error: casts cannot be followed by a method call
+  --> $DIR/issue-35813-postfix-after-cast.rs:92:8
+   |
+LL |     if 5u64 as i32.max(0) == 0 {
+   |        ^^^^^^^^^^^
+   |
+help: try surrounding the expression in parentheses
+   |
+LL |     if (5u64 as i32).max(0) == 0 {
+   |        ^           ^
+
+error: casts cannot be followed by a method call
+  --> $DIR/issue-35813-postfix-after-cast.rs:95:8
+   |
+LL |     if 5u64: u64.max(0) == 0 {
+   |        ^^^^^^^^^
+   |
+help: try surrounding the expression in parentheses
+   |
+LL |     if (5u64: u64).max(0) == 0 {
+   |        ^         ^
+
+error: casts cannot be followed by a method call
+  --> $DIR/issue-35813-postfix-after-cast.rs:102:9
+   |
+LL |         5u64 as u32.max(0) == 0
+   |         ^^^^^^^^^^^
+   |
+help: try surrounding the expression in parentheses
+   |
+LL |         (5u64 as u32).max(0) == 0
+   |         ^           ^
+
+error: casts cannot be followed by a method call
+  --> $DIR/issue-35813-postfix-after-cast.rs:106:9
+   |
+LL |         5u64: u64.max(0) == 0
+   |         ^^^^^^^^^
+   |
+help: try surrounding the expression in parentheses
+   |
+LL |         (5u64: u64).max(0) == 0
+   |         ^         ^
+
+error: casts cannot be followed by indexing
+  --> $DIR/issue-35813-postfix-after-cast.rs:111:24
+   |
+LL | static bar: &[i32] = &(&[1,2,3] as &[i32][0..1]);
+   |                        ^^^^^^^^^^^^^^^^^^
+   |
+help: try surrounding the expression in parentheses
+   |
+LL | static bar: &[i32] = &((&[1,2,3] as &[i32])[0..1]);
+   |                        ^                  ^
+
+error: casts cannot be followed by indexing
+  --> $DIR/issue-35813-postfix-after-cast.rs:114:25
+   |
+LL | static bar2: &[i32] = &(&[1i32,2,3]: &[i32; 3][0..1]);
+   |                         ^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: try surrounding the expression in parentheses
+   |
+LL | static bar2: &[i32] = &((&[1i32,2,3]: &[i32; 3])[0..1]);
+   |                         ^                      ^
+
+error: casts cannot be followed by ?
+  --> $DIR/issue-35813-postfix-after-cast.rs:119:5
+   |
+LL |     Err(0u64) as Result<u64,u64>?;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: try surrounding the expression in parentheses
+   |
+LL |     (Err(0u64) as Result<u64,u64>)?;
+   |     ^                            ^
+
+error: casts cannot be followed by ?
+  --> $DIR/issue-35813-postfix-after-cast.rs:121:5
+   |
+LL |     Err(0u64): Result<u64,u64>?;
+   |     ^^^^^^^^^-^^^^^^^^^^^^^^^^
+   |              |
+   |              help: maybe write a path separator here: `::`
+   |
+   = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `<expr>: <type>`
+   = note: see issue #23416 <https://github.com/rust-lang/rust/issues/23416> for more information
+
+error: casts cannot be followed by a function call
+  --> $DIR/issue-35813-postfix-after-cast.rs:145:5
+   |
+LL |     drop as fn(u8)(0);
+   |     ^^^^^^^^^^^^^^
+   |
+help: try surrounding the expression in parentheses
+   |
+LL |     (drop as fn(u8))(0);
+   |     ^              ^
+
+error: casts cannot be followed by a function call
+  --> $DIR/issue-35813-postfix-after-cast.rs:147:5
+   |
+LL |     drop_ptr: fn(u8)(0);
+   |     ^^^^^^^^^^^^^^^^
+   |
+help: try surrounding the expression in parentheses
+   |
+LL |     (drop_ptr: fn(u8))(0);
+   |     ^                ^
+
+error: casts cannot be followed by `.await`
+  --> $DIR/issue-35813-postfix-after-cast.rs:152:5
+   |
+LL |     Box::pin(noop()) as Pin<Box<dyn Future<Output = ()>>>.await;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: try surrounding the expression in parentheses
+   |
+LL |     (Box::pin(noop()) as Pin<Box<dyn Future<Output = ()>>>).await;
+   |     ^                                                     ^
+
+error: casts cannot be followed by `.await`
+  --> $DIR/issue-35813-postfix-after-cast.rs:155:5
+   |
+LL |     Box::pin(noop()): Pin<Box<_>>.await;
+   |     ^^^^^^^^^^^^^^^^-^^^^^^^^^^^^
+   |                     |
+   |                     help: maybe write a path separator here: `::`
+   |
+   = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `<expr>: <type>`
+   = note: see issue #23416 <https://github.com/rust-lang/rust/issues/23416> for more information
+
+error: casts cannot be followed by a field access
+  --> $DIR/issue-35813-postfix-after-cast.rs:167:5
+   |
+LL |     Foo::default() as Foo.bar;
+   |     ^^^^^^^^^^^^^^^^^^^^^
+   |
+help: try surrounding the expression in parentheses
+   |
+LL |     (Foo::default() as Foo).bar;
+   |     ^                     ^
+
+error: casts cannot be followed by a field access
+  --> $DIR/issue-35813-postfix-after-cast.rs:169:5
+   |
+LL |     Foo::default(): Foo.bar;
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+help: try surrounding the expression in parentheses
+   |
+LL |     (Foo::default(): Foo).bar;
+   |     ^                   ^
+
+error: casts cannot be followed by a method call
+  --> $DIR/issue-35813-postfix-after-cast.rs:84:9
+   |
+LL |         if true { 33 } else { 44 } as i32.max(0),
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: try surrounding the expression in parentheses
+   |
+LL |         (if true { 33 } else { 44 } as i32).max(0),
+   |         ^                                 ^
+
+error: casts cannot be followed by a method call
+  --> $DIR/issue-35813-postfix-after-cast.rs:86:9
+   |
+LL |         if true { 33 } else { 44 }: i32.max(0)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: try surrounding the expression in parentheses
+   |
+LL |         (if true { 33 } else { 44 }: i32).max(0)
+   |         ^                               ^
+
+error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
+  --> $DIR/issue-35813-postfix-after-cast.rs:131:13
+   |
+LL |     drop as F();
+   |             ^^^ only `Fn` traits may use parentheses
+
+error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
+  --> $DIR/issue-35813-postfix-after-cast.rs:133:15
+   |
+LL |     drop_ptr: F();
+   |               ^^^ only `Fn` traits may use parentheses
+
+error: aborting due to 36 previous errors
+
+For more information about this error, try `rustc --explain E0214`.
index 6cf902ca86e799d950f99739b8b73eb9318d0f72..bdb5c91ff91eb084cee75f781937ef5eb2309be4 100644 (file)
@@ -1,8 +1,8 @@
 error: couldn't read $DIR/../parser: $ACCESS_DENIED_MSG (os error $ACCESS_DENIED_CODE)
-  --> $DIR/issue-5806.rs:5:5
+  --> $DIR/issue-5806.rs:5:1
    |
 LL | mod foo;
-   |     ^^^
+   | ^^^^^^^^
 
 error: aborting due to previous error
 
index 2beb73d83d261c877639c3ebdf00eb4f801d27ac..15cd3df860b0da7a44d1cd045877b545f5d99e0b 100644 (file)
@@ -12,7 +12,7 @@ error: expected one of `!`, `(`, `)`, `+`, `,`, `::`, or `<`, found `;`
 LL | impl W <s(f;Y(;]
    |            ^ expected one of 7 possible tokens
 
-error: expected one of `!`, `&&`, `&`, `(`, `)`, `*`, `+`, `,`, `->`, `...`, `::`, `<`, `>`, `?`, `[`, `_`, `dyn`, `extern`, `fn`, `for`, `impl`, `unsafe`, or lifetime, found `;`
+error: expected one of `!`, `&&`, `&`, `(`, `)`, `*`, `+`, `,`, `->`, `...`, `::`, `<`, `>`, `?`, `[`, `_`, `dyn`, `extern`, `fn`, `for`, `impl`, `unsafe`, lifetime, or path, found `;`
   --> $DIR/issue-63116.rs:3:15
    |
 LL | impl W <s(f;Y(;]
index 7d46b8904f03341956202a6f2392e9076d3e744c..a5a8de85466bbccf5c549f3d538f82bf69ccc854 100644 (file)
@@ -1,3 +1,3 @@
-// error-pattern: aborting due to 7 previous errors
+// error-pattern: aborting due to 5 previous errors
 
 fn i(n{...,f #
index 04afae93be0e59f83fe81ce394306c29213c7111..396aec8335dbf162fa2c574bd3b78a328aa7cc6c 100644 (file)
@@ -31,23 +31,11 @@ LL | fn i(n{...,f #
    |        |  expected `}`
    |        `..` must be at the end and cannot have a trailing comma
 
-error: expected `[`, found `}`
+error: expected one of `!` or `[`, found `}`
   --> $DIR/issue-63135.rs:3:16
    |
 LL | fn i(n{...,f #
-   |                ^ expected `[`
+   |                ^ expected one of `!` or `[`
 
-error: expected one of `:` or `|`, found `)`
-  --> $DIR/issue-63135.rs:3:16
-   |
-LL | fn i(n{...,f #
-   |                ^ expected one of `:` or `|`
-
-error: expected `;` or `{`, found `<eof>`
-  --> $DIR/issue-63135.rs:3:16
-   |
-LL | fn i(n{...,f #
-   |                ^ expected `;` or `{`
-
-error: aborting due to 7 previous errors
+error: aborting due to 5 previous errors
 
index b570e9417751b01f67db9a2e4edfa7631400b8d9..20e18b4bcbb323d50ecfe254f9800cd5aa0a4a40 100644 (file)
Binary files a/src/test/ui/parser/issue-68730.rs and b/src/test/ui/parser/issue-68730.rs differ
index 090b41d839f82b68c11fe38111b9fda254aa39b0..9f8833e17fe25afc9f10b08683294ecd7e9efe32 100644 (file)
Binary files a/src/test/ui/parser/issue-68730.stderr and b/src/test/ui/parser/issue-68730.stderr differ
diff --git a/src/test/ui/parser/issue-68890-2.rs b/src/test/ui/parser/issue-68890-2.rs
new file mode 100644 (file)
index 0000000..ae02246
--- /dev/null
@@ -0,0 +1,6 @@
+fn main() {}
+
+type X<'a> = (?'a) +;
+//~^ ERROR `?` may only modify trait bounds, not lifetime bounds
+//~| ERROR at least one trait is required for an object type
+//~| WARN trait objects without an explicit `dyn` are deprecated
diff --git a/src/test/ui/parser/issue-68890-2.stderr b/src/test/ui/parser/issue-68890-2.stderr
new file mode 100644 (file)
index 0000000..d475c79
--- /dev/null
@@ -0,0 +1,22 @@
+error: `?` may only modify trait bounds, not lifetime bounds
+  --> $DIR/issue-68890-2.rs:3:15
+   |
+LL | type X<'a> = (?'a) +;
+   |               ^
+
+warning: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/issue-68890-2.rs:3:14
+   |
+LL | type X<'a> = (?'a) +;
+   |              ^^^^^^^ help: use `dyn`: `dyn (?'a) +`
+   |
+   = note: `#[warn(bare_trait_objects)]` on by default
+
+error[E0224]: at least one trait is required for an object type
+  --> $DIR/issue-68890-2.rs:3:14
+   |
+LL | type X<'a> = (?'a) +;
+   |              ^^^^^^^
+
+error: aborting due to 2 previous errors
+
index a7c5a5e13008aab8f32a4ef0fce4aef0b0af3b60..bab4ed7f800c5d7dcf32f2c344542703016cb4c7 100644 (file)
@@ -1,4 +1,4 @@
 enum e{A((?'a a+?+l))}
 //~^ ERROR `?` may only modify trait bounds, not lifetime bounds
 //~| ERROR expected one of `)`, `+`, or `,`
-//~| ERROR expected trait bound, not lifetime bound
+//~| ERROR expected item, found `)`
index 9bb8761b67b5fad3807d0afba91197a1d67da339..2a3bf6b41f02ea7c363eebc582786a62d4f7559a 100644 (file)
@@ -10,11 +10,11 @@ error: expected one of `)`, `+`, or `,`, found `a`
 LL | enum e{A((?'a a+?+l))}
    |               ^ expected one of `)`, `+`, or `,`
 
-error: expected trait bound, not lifetime bound
-  --> $DIR/issue-68890.rs:1:11
+error: expected item, found `)`
+  --> $DIR/issue-68890.rs:1:21
    |
 LL | enum e{A((?'a a+?+l))}
-   |           ^^^
+   |                     ^ expected item
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/parser/labeled-no-colon-expr.rs b/src/test/ui/parser/labeled-no-colon-expr.rs
new file mode 100644 (file)
index 0000000..db9ef52
--- /dev/null
@@ -0,0 +1,17 @@
+#![feature(label_break_value)]
+
+fn main() {
+    'l0 while false {} //~ ERROR labeled expression must be followed by `:`
+    'l1 for _ in 0..1 {} //~ ERROR labeled expression must be followed by `:`
+    'l2 loop {} //~ ERROR labeled expression must be followed by `:`
+    'l3 {} //~ ERROR labeled expression must be followed by `:`
+    'l4 0; //~ ERROR labeled expression must be followed by `:`
+    //~^ ERROR expected `while`, `for`, `loop` or `{`
+
+    macro_rules! m {
+        ($b:block) => {
+            'l5 $b; //~ ERROR cannot use a `block` macro fragment here
+        }
+    }
+    m!({}); //~ ERROR labeled expression must be followed by `:`
+}
diff --git a/src/test/ui/parser/labeled-no-colon-expr.stderr b/src/test/ui/parser/labeled-no-colon-expr.stderr
new file mode 100644 (file)
index 0000000..4f5e8f7
--- /dev/null
@@ -0,0 +1,89 @@
+error: labeled expression must be followed by `:`
+  --> $DIR/labeled-no-colon-expr.rs:4:5
+   |
+LL |     'l0 while false {}
+   |     ----^^^^^^^^^^^^^^
+   |     |  |
+   |     |  help: add `:` after the label
+   |     the label
+   |
+   = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them
+
+error: labeled expression must be followed by `:`
+  --> $DIR/labeled-no-colon-expr.rs:5:5
+   |
+LL |     'l1 for _ in 0..1 {}
+   |     ----^^^^^^^^^^^^^^^^
+   |     |  |
+   |     |  help: add `:` after the label
+   |     the label
+   |
+   = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them
+
+error: labeled expression must be followed by `:`
+  --> $DIR/labeled-no-colon-expr.rs:6:5
+   |
+LL |     'l2 loop {}
+   |     ----^^^^^^^
+   |     |  |
+   |     |  help: add `:` after the label
+   |     the label
+   |
+   = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them
+
+error: labeled expression must be followed by `:`
+  --> $DIR/labeled-no-colon-expr.rs:7:5
+   |
+LL |     'l3 {}
+   |     ----^^
+   |     |  |
+   |     |  help: add `:` after the label
+   |     the label
+   |
+   = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them
+
+error: expected `while`, `for`, `loop` or `{` after a label
+  --> $DIR/labeled-no-colon-expr.rs:8:9
+   |
+LL |     'l4 0;
+   |         ^ expected `while`, `for`, `loop` or `{` after a label
+
+error: labeled expression must be followed by `:`
+  --> $DIR/labeled-no-colon-expr.rs:8:9
+   |
+LL |     'l4 0;
+   |     ----^
+   |     |  |
+   |     |  help: add `:` after the label
+   |     the label
+   |
+   = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them
+
+error: cannot use a `block` macro fragment here
+  --> $DIR/labeled-no-colon-expr.rs:13:17
+   |
+LL |             'l5 $b;
+   |             ----^^
+   |             |
+   |             the `block` fragment is within this context
+...
+LL |     m!({});
+   |     ------- in this macro invocation
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: labeled expression must be followed by `:`
+  --> $DIR/labeled-no-colon-expr.rs:16:8
+   |
+LL |             'l5 $b;
+   |             ---- help: add `:` after the label
+   |             |
+   |             the label
+...
+LL |     m!({});
+   |        ^^
+   |
+   = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them
+
+error: aborting due to 8 previous errors
+
index 80d867d3b568e87ca05fc3e6868754ffb309dc77..170ac22780b6319d4a1bb9876231af29e8b5ee36 100644 (file)
@@ -2,9 +2,14 @@
 // `ty` matcher in particular doesn't accept a single lifetime
 
 macro_rules! m {
-    ($t: ty) => ( let _: $t; )
+    ($t: ty) => {
+        let _: $t;
+    };
 }
 
 fn main() {
-    m!('static); //~ ERROR expected type, found `'static`
+    m!('static);
+    //~^ ERROR lifetime in trait object type must be followed by `+`
+    //~| ERROR at least one trait is required for an object type
+    //~| WARN trait objects without an explicit `dyn` are deprecated
 }
index f02f60e4bfb1df142f74a4886049a65d524b500e..230733371ddd8a362efd512eb042126d82568a96 100644 (file)
@@ -1,8 +1,22 @@
-error: expected type, found `'static`
-  --> $DIR/trait-object-macro-matcher.rs:9:8
+error: lifetime in trait object type must be followed by `+`
+  --> $DIR/trait-object-macro-matcher.rs:11:8
    |
 LL |     m!('static);
-   |        ^^^^^^^ expected type
+   |        ^^^^^^^
 
-error: aborting due to previous error
+warning: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/trait-object-macro-matcher.rs:11:8
+   |
+LL |     m!('static);
+   |        ^^^^^^^ help: use `dyn`: `dyn 'static`
+   |
+   = note: `#[warn(bare_trait_objects)]` on by default
+
+error[E0224]: at least one trait is required for an object type
+  --> $DIR/trait-object-macro-matcher.rs:11:8
+   |
+LL |     m!('static);
+   |        ^^^^^^^
+
+error: aborting due to 2 previous errors
 
index 311f1768d829c7ff6273c7185280a12033d870ed..f1be5dc5ba7fad55b4e5c2a814e65c02ad984cb8 100644 (file)
@@ -1,14 +1,8 @@
 error: unexpected closing 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 closing delimiter
+LL | }
+   | ^ unexpected closing delimiter
 
 error: aborting due to previous error
 
index e662c707a38b9037dd5dedba3066eaf57761b0d1..f4a27b52ec5b48f113221558dbe3aef4f62ac09a 100644 (file)
@@ -1,8 +1,9 @@
 // ignore-windows
 
 mod not_a_real_file; //~ ERROR file not found for module `not_a_real_file`
-//~^ HELP name the file either not_a_real_file.rs or not_a_real_file/mod.rs inside the directory
+//~^ HELP to create the module `not_a_real_file`, create file
 
 fn main() {
     assert_eq!(mod_file_aux::bar(), 10);
+    //~^ ERROR failed to resolve: use of undeclared type or module `mod_file_aux`
 }
index dadf4b29dcf397660d19ff87d1245391aebcce51..087ae9fe3e016c92e9cc1ebfc0e3510b86f4dd0b 100644 (file)
@@ -1,11 +1,18 @@
 error[E0583]: file not found for module `not_a_real_file`
-  --> $DIR/mod_file_not_exist.rs:3:5
+  --> $DIR/mod_file_not_exist.rs:3:1
    |
 LL | mod not_a_real_file;
-   |     ^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^
    |
-   = help: name the file either not_a_real_file.rs or not_a_real_file/mod.rs inside the directory "$DIR"
+   = help: to create the module `not_a_real_file`, create file "$DIR/not_a_real_file.rs"
 
-error: aborting due to previous error
+error[E0433]: failed to resolve: use of undeclared type or module `mod_file_aux`
+  --> $DIR/mod_file_not_exist.rs:7:16
+   |
+LL |     assert_eq!(mod_file_aux::bar(), 10);
+   |                ^^^^^^^^^^^^ use of undeclared type or module `mod_file_aux`
+
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0583`.
+Some errors have detailed explanations: E0433, E0583.
+For more information about an error, try `rustc --explain E0433`.
index 0cd9e9c799f1d95c1bfbdbcd06ad58226b7da8fe..4b7d7a02bbe78cc468d605715b09cdda7c16f2bf 100644 (file)
@@ -1,8 +1,9 @@
 // only-windows
 
 mod not_a_real_file; //~ ERROR file not found for module `not_a_real_file`
-//~^ HELP name the file either not_a_real_file.rs or not_a_real_file\mod.rs inside the directory
+//~^ HELP to create the module `not_a_real_file`, create file
 
 fn main() {
     assert_eq!(mod_file_aux::bar(), 10);
+    //~^ ERROR failed to resolve: use of undeclared type or module `mod_file_aux`
 }
index 60ae00abab1edb9c1a5d3420548733c3bc37e052..d67205cfdf1007cf9959fb3ed835fea809f119d5 100644 (file)
@@ -1,11 +1,18 @@
 error[E0583]: file not found for module `not_a_real_file`
-  --> $DIR/mod_file_not_exist_windows.rs:3:5
+  --> $DIR/mod_file_not_exist_windows.rs:3:1
    |
 LL | mod not_a_real_file;
-   |     ^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^
    |
-   = help: name the file either not_a_real_file.rs or not_a_real_file/mod.rs inside the directory "$DIR"
+   = help: to create the module `not_a_real_file`, create file "$DIR/not_a_real_file.rs"
 
-error: aborting due to previous error
+error[E0433]: failed to resolve: use of undeclared type or module `mod_file_aux`
+  --> $DIR/mod_file_not_exist_windows.rs:7:16
+   |
+LL |     assert_eq!(mod_file_aux::bar(), 10);
+   |                ^^^^^^^^^^^^ use of undeclared type or module `mod_file_aux`
+
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0583`.
+Some errors have detailed explanations: E0433, E0583.
+For more information about an error, try `rustc --explain E0433`.
index 004b5d7963a1d5985e8484afa66267bc10ae0a17..cd1add73d58400b7ea41d757995f34b334a1e831 100644 (file)
@@ -1,8 +1,8 @@
 error: couldn't read $DIR/not_a_real_file.rs: $FILE_NOT_FOUND_MSG (os error 2)
-  --> $DIR/mod_file_with_path_attr.rs:4:5
+  --> $DIR/mod_file_with_path_attr.rs:4:1
    |
 LL | mod m;
-   |     ^
+   | ^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/recovery-attr-on-if.rs b/src/test/ui/parser/recovery-attr-on-if.rs
deleted file mode 100644 (file)
index 0d1f5be..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-fn main() {
-    #[attr] if true {};
-    //~^ ERROR cannot find attribute
-    //~| ERROR attributes are not yet allowed on `if` expressions
-    #[attr] if true {};
-    //~^ ERROR cannot find attribute
-    //~| ERROR attributes are not yet allowed on `if` expressions
-    let _recovery_witness: () = 0; //~ ERROR mismatched types
-}
diff --git a/src/test/ui/parser/recovery-attr-on-if.stderr b/src/test/ui/parser/recovery-attr-on-if.stderr
deleted file mode 100644 (file)
index a028468..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-error: attributes are not yet allowed on `if` expressions
-  --> $DIR/recovery-attr-on-if.rs:2:5
-   |
-LL |     #[attr] if true {};
-   |     ^^^^^^^
-
-error: attributes are not yet allowed on `if` expressions
-  --> $DIR/recovery-attr-on-if.rs:5:5
-   |
-LL |     #[attr] if true {};
-   |     ^^^^^^^
-
-error: cannot find attribute `attr` in this scope
-  --> $DIR/recovery-attr-on-if.rs:5:7
-   |
-LL |     #[attr] if true {};
-   |       ^^^^
-
-error: cannot find attribute `attr` in this scope
-  --> $DIR/recovery-attr-on-if.rs:2:7
-   |
-LL |     #[attr] if true {};
-   |       ^^^^
-
-error[E0308]: mismatched types
-  --> $DIR/recovery-attr-on-if.rs:8:33
-   |
-LL |     let _recovery_witness: () = 0;
-   |                            --   ^ expected `()`, found integer
-   |                            |
-   |                            expected due to this
-
-error: aborting due to 5 previous errors
-
-For more information about this error, try `rustc --explain E0308`.
index 21369d0be61b1f20badd9dbb1877ce9b40a84160..d223619e1de9ed3bdb23d80dc9ad9f9260b04874 100644 (file)
@@ -4,7 +4,7 @@ fn foo(cond: bool) {
     let mut x;
 
     if cond {
-        x = &'blk [1,2,3]; //~ ERROR expected `:`, found `[`
+        x = &'blk [1,2,3]; //~ ERROR borrow expressions cannot be annotated with lifetimes
     }
 }
 
index 8d9bf0b7a0445308d239e9f239b7b4f0f945c054..bbc657ffd614c40cac5689a7cca84156a72536c8 100644 (file)
@@ -1,8 +1,11 @@
-error: expected `:`, found `[`
-  --> $DIR/regions-out-of-scope-slice.rs:7:19
+error: borrow expressions cannot be annotated with lifetimes
+  --> $DIR/regions-out-of-scope-slice.rs:7:13
    |
 LL |         x = &'blk [1,2,3];
-   |                   ^ expected `:`
+   |             ^----^^^^^^^^
+   |              |
+   |              annotated with lifetime here
+   |              help: remove the lifetime annotation
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/stripped-nested-outline-mod-pass.rs b/src/test/ui/parser/stripped-nested-outline-mod-pass.rs
new file mode 100644 (file)
index 0000000..1b4669a
--- /dev/null
@@ -0,0 +1,13 @@
+// Expansion drives parsing, so conditional compilation will strip
+// out outline modules and we will never attempt parsing them.
+
+// check-pass
+
+fn main() {}
+
+#[cfg(FALSE)]
+mod foo {
+    mod bar {
+        mod baz; // This was an error before.
+    }
+}
index c8b0eb684f33dff1c14b7017bf1990b4d66076c0..5a5c19f32e8060553581805d79d4e819e94d51d4 100644 (file)
@@ -6,9 +6,7 @@ fn f<'a, T: Trait + ('a)>() {} //~ ERROR parenthesized lifetime bounds are not s
 
 fn check<'a>() {
     let _: Box<Trait + ('a)>; //~ ERROR parenthesized lifetime bounds are not supported
-    let _: Box<('a) + Trait>;
-    //~^ ERROR expected type, found `'a`
-    //~| ERROR expected `:`, found `)`
+    let _: Box<('a) + Trait>; //~ ERROR lifetime in trait object type must be followed by `+`
 }
 
 fn main() {}
index 319a308c0137c307bddf0b693ccc617fc02d0a1f..1289c248275dc8b39b6b16ea8bee252fc17727eb 100644 (file)
@@ -10,19 +10,11 @@ error: parenthesized lifetime bounds are not supported
 LL |     let _: Box<Trait + ('a)>;
    |                        ^^^^ help: remove the parentheses
 
-error: expected `:`, found `)`
-  --> $DIR/trait-object-lifetime-parens.rs:9:19
-   |
-LL |     let _: Box<('a) + Trait>;
-   |                   ^ expected `:`
-
-error: expected type, found `'a`
+error: lifetime in trait object type must be followed by `+`
   --> $DIR/trait-object-lifetime-parens.rs:9:17
    |
 LL |     let _: Box<('a) + Trait>;
-   |         -       ^^ expected type
-   |         |
-   |         while parsing the type for `_`
+   |                 ^^
 
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
index a113de14b6fbc5db9a01e8c6c2c61a8ca67de123..9fbc938c4dce81e290668ffab3ebddfc3e993db3 100644 (file)
@@ -1,15 +1,20 @@
 trait Trait<'a> {}
 
+trait Obj {}
+
 fn f<T: (Copy) + (?Sized) + (for<'a> Trait<'a>)>() {}
 
 fn main() {
-    let _: Box<(Copy) + (?Sized) + (for<'a> Trait<'a>)>;
+    let _: Box<(Obj) + (?Sized) + (for<'a> Trait<'a>)>;
+    //~^ ERROR `?Trait` is not permitted in trait object types
+    //~| ERROR only auto traits can be used as additional traits
+    //~| WARN trait objects without an explicit `dyn` are deprecated
+    let _: Box<(?Sized) + (for<'a> Trait<'a>) + (Obj)>;
     //~^ ERROR `?Trait` is not permitted in trait object types
+    //~| ERROR only auto traits can be used as additional traits
     //~| WARN trait objects without an explicit `dyn` are deprecated
-    let _: Box<(?Sized) + (for<'a> Trait<'a>) + (Copy)>;
-    //~^ WARN trait objects without an explicit `dyn` are deprecated
-    let _: Box<(for<'a> Trait<'a>) + (Copy) + (?Sized)>;
-    //~^ ERROR use of undeclared lifetime name `'a`
-    //~| ERROR `?Trait` is not permitted in trait object types
+    let _: Box<(for<'a> Trait<'a>) + (Obj) + (?Sized)>;
+    //~^ ERROR `?Trait` is not permitted in trait object types
+    //~| ERROR only auto traits can be used as additional traits
     //~| WARN trait objects without an explicit `dyn` are deprecated
 }
index 4b9f49423cbf447158b692ab93e4b1c54ce6854c..7022a66ca1a17be179961799c2bba804dbaa4cc8 100644 (file)
@@ -1,44 +1,74 @@
 error: `?Trait` is not permitted in trait object types
-  --> $DIR/trait-object-trait-parens.rs:6:25
+  --> $DIR/trait-object-trait-parens.rs:8:24
    |
-LL |     let _: Box<(Copy) + (?Sized) + (for<'a> Trait<'a>)>;
-   |                         ^^^^^^^^
+LL |     let _: Box<(Obj) + (?Sized) + (for<'a> Trait<'a>)>;
+   |                        ^^^^^^^^
 
 error: `?Trait` is not permitted in trait object types
-  --> $DIR/trait-object-trait-parens.rs:11:47
+  --> $DIR/trait-object-trait-parens.rs:12:17
    |
-LL |     let _: Box<(for<'a> Trait<'a>) + (Copy) + (?Sized)>;
-   |                                               ^^^^^^^^
+LL |     let _: Box<(?Sized) + (for<'a> Trait<'a>) + (Obj)>;
+   |                 ^^^^^^
+
+error: `?Trait` is not permitted in trait object types
+  --> $DIR/trait-object-trait-parens.rs:16:46
+   |
+LL |     let _: Box<(for<'a> Trait<'a>) + (Obj) + (?Sized)>;
+   |                                              ^^^^^^^^
 
 warning: trait objects without an explicit `dyn` are deprecated
-  --> $DIR/trait-object-trait-parens.rs:6:16
+  --> $DIR/trait-object-trait-parens.rs:8:16
    |
-LL |     let _: Box<(Copy) + (?Sized) + (for<'a> Trait<'a>)>;
-   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `dyn`: `dyn (Copy) + (?Sized) + (for<'a> Trait<'a>)`
+LL |     let _: Box<(Obj) + (?Sized) + (for<'a> Trait<'a>)>;
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `dyn`: `dyn (Obj) + (?Sized) + (for<'a> Trait<'a>)`
    |
    = note: `#[warn(bare_trait_objects)]` on by default
 
 warning: trait objects without an explicit `dyn` are deprecated
-  --> $DIR/trait-object-trait-parens.rs:9:16
+  --> $DIR/trait-object-trait-parens.rs:12:16
    |
-LL |     let _: Box<(?Sized) + (for<'a> Trait<'a>) + (Copy)>;
-   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `dyn`: `dyn (?Sized) + (for<'a> Trait<'a>) + (Copy)`
+LL |     let _: Box<(?Sized) + (for<'a> Trait<'a>) + (Obj)>;
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `dyn`: `dyn (?Sized) + (for<'a> Trait<'a>) + (Obj)`
 
 warning: trait objects without an explicit `dyn` are deprecated
-  --> $DIR/trait-object-trait-parens.rs:11:16
+  --> $DIR/trait-object-trait-parens.rs:16:16
+   |
+LL |     let _: Box<(for<'a> Trait<'a>) + (Obj) + (?Sized)>;
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `dyn`: `dyn (for<'a> Trait<'a>) + (Obj) + (?Sized)`
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+  --> $DIR/trait-object-trait-parens.rs:8:35
+   |
+LL |     let _: Box<(Obj) + (?Sized) + (for<'a> Trait<'a>)>;
+   |                -----              ^^^^^^^^^^^^^^^^^^^
+   |                |                  |
+   |                |                  additional non-auto trait
+   |                |                  trait alias used in trait object type (additional use)
+   |                first non-auto trait
+   |                trait alias used in trait object type (first use)
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+  --> $DIR/trait-object-trait-parens.rs:12:49
    |
-LL |     let _: Box<(for<'a> Trait<'a>) + (Copy) + (?Sized)>;
-   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `dyn`: `dyn (for<'a> Trait<'a>) + (Copy) + (?Sized)`
+LL |     let _: Box<(?Sized) + (for<'a> Trait<'a>) + (Obj)>;
+   |                           -------------------   ^^^^^
+   |                           |                     |
+   |                           |                     additional non-auto trait
+   |                           |                     trait alias used in trait object type (additional use)
+   |                           first non-auto trait
+   |                           trait alias used in trait object type (first use)
 
-error[E0261]: use of undeclared lifetime name `'a`
-  --> $DIR/trait-object-trait-parens.rs:11:31
+error[E0225]: only auto traits can be used as additional traits in a trait object
+  --> $DIR/trait-object-trait-parens.rs:16:38
    |
-LL | fn main() {
-   |        - help: consider introducing lifetime `'a` here: `<'a>`
-...
-LL |     let _: Box<(for<'a> Trait<'a>) + (Copy) + (?Sized)>;
-   |                               ^^ undeclared lifetime
+LL |     let _: Box<(for<'a> Trait<'a>) + (Obj) + (?Sized)>;
+   |                 -----------------    ^^^^^
+   |                 |                    |
+   |                 |                    additional non-auto trait
+   |                 |                    trait alias used in trait object type (additional use)
+   |                 first non-auto trait
+   |                 trait alias used in trait object type (first use)
 
-error: aborting due to 3 previous errors
+error: aborting due to 6 previous errors
 
-For more information about this error, try `rustc --explain E0261`.
+For more information about this error, try `rustc --explain E0225`.
diff --git a/src/test/ui/pattern/bindings-after-at/box-patterns.rs b/src/test/ui/pattern/bindings-after-at/box-patterns.rs
new file mode 100644 (file)
index 0000000..ef9669a
--- /dev/null
@@ -0,0 +1,36 @@
+// Test bindings-after-at with box-patterns
+
+// run-pass
+
+#![feature(bindings_after_at)]
+#![feature(box_patterns)]
+
+#[derive(Debug, PartialEq)]
+enum MatchArm {
+    Arm(usize),
+    Wild,
+}
+
+fn test(x: Option<Box<i32>>) -> MatchArm {
+    match x {
+        ref bar @ Some(box n) if n > 0 => {
+            // bar is a &Option<Box<i32>>
+            assert_eq!(bar, &x);
+
+            MatchArm::Arm(0)
+        },
+        Some(ref bar @ box n) if n < 0 => {
+            // bar is a &Box<i32> here
+            assert_eq!(**bar, n);
+
+            MatchArm::Arm(1)
+        },
+        _ => MatchArm::Wild,
+    }
+}
+
+fn main() {
+    assert_eq!(test(Some(Box::new(2))), MatchArm::Arm(0));
+    assert_eq!(test(Some(Box::new(-1))), MatchArm::Arm(1));
+    assert_eq!(test(Some(Box::new(0))), MatchArm::Wild);
+}
diff --git a/src/test/ui/pattern/bindings-after-at/or-patterns-box-patterns.rs b/src/test/ui/pattern/bindings-after-at/or-patterns-box-patterns.rs
new file mode 100644 (file)
index 0000000..ca8826f
--- /dev/null
@@ -0,0 +1,45 @@
+// Test bindings-after-at with or-patterns and box-patterns
+
+// run-pass
+
+#![feature(bindings_after_at)]
+#![feature(or_patterns)]
+#![feature(box_patterns)]
+
+#[derive(Debug, PartialEq)]
+enum MatchArm {
+    Arm(usize),
+    Wild,
+}
+
+#[derive(Debug, PartialEq)]
+enum Test {
+    Foo,
+    Bar,
+    Baz,
+    Qux,
+}
+
+fn test(foo: Option<Box<Test>>) -> MatchArm {
+    match foo {
+        ref bar @ Some(box Test::Foo | box Test::Bar) => {
+            assert_eq!(bar, &foo);
+
+            MatchArm::Arm(0)
+        },
+        Some(ref bar @ box Test::Baz | ref bar @ box Test::Qux) => {
+            assert!(**bar == Test::Baz || **bar == Test::Qux);
+
+            MatchArm::Arm(1)
+        },
+        _ => MatchArm::Wild,
+    }
+}
+
+fn main() {
+    assert_eq!(test(Some(Box::new(Test::Foo))), MatchArm::Arm(0));
+    assert_eq!(test(Some(Box::new(Test::Bar))), MatchArm::Arm(0));
+    assert_eq!(test(Some(Box::new(Test::Baz))), MatchArm::Arm(1));
+    assert_eq!(test(Some(Box::new(Test::Qux))), MatchArm::Arm(1));
+    assert_eq!(test(None), MatchArm::Wild);
+}
diff --git a/src/test/ui/pattern/bindings-after-at/or-patterns-slice-patterns.rs b/src/test/ui/pattern/bindings-after-at/or-patterns-slice-patterns.rs
new file mode 100644 (file)
index 0000000..65c2b37
--- /dev/null
@@ -0,0 +1,56 @@
+// Test bindings-after-at with or-patterns and slice-patterns
+
+// run-pass
+
+#![feature(bindings_after_at)]
+#![feature(or_patterns)]
+
+#[derive(Debug, PartialEq)]
+enum MatchArm {
+    Arm(usize),
+    Wild,
+}
+
+#[derive(Debug, PartialEq)]
+enum Test {
+    Foo,
+    Bar,
+    Baz,
+    Qux,
+}
+
+fn test(foo: &[Option<Test>]) -> MatchArm {
+    match foo {
+        bar @ [Some(Test::Foo), .., Some(Test::Qux | Test::Foo)] => {
+            assert_eq!(bar, foo);
+
+            MatchArm::Arm(0)
+        },
+        [.., bar @ Some(Test::Bar | Test::Qux), _] => {
+            assert!(bar == &Some(Test::Bar) || bar == &Some(Test::Qux));
+
+            MatchArm::Arm(1)
+        },
+        _ => MatchArm::Wild,
+    }
+}
+
+fn main() {
+    let foo = vec![
+        Some(Test::Foo),
+        Some(Test::Bar),
+        Some(Test::Baz),
+        Some(Test::Qux),
+    ];
+
+    // path 1a
+    assert_eq!(test(&foo), MatchArm::Arm(0));
+    // path 1b
+    assert_eq!(test(&[Some(Test::Foo), Some(Test::Bar), Some(Test::Foo)]), MatchArm::Arm(0));
+    // path 2a
+    assert_eq!(test(&foo[..3]), MatchArm::Arm(1));
+    // path 2b
+    assert_eq!(test(&[Some(Test::Bar), Some(Test::Qux), Some(Test::Baz)]), MatchArm::Arm(1));
+    // path 3
+    assert_eq!(test(&foo[1..2]), MatchArm::Wild);
+}
diff --git a/src/test/ui/pattern/bindings-after-at/or-patterns.rs b/src/test/ui/pattern/bindings-after-at/or-patterns.rs
new file mode 100644 (file)
index 0000000..a0e1400
--- /dev/null
@@ -0,0 +1,40 @@
+// Test bindings-after-at with or-patterns
+
+// run-pass
+
+#![feature(bindings_after_at)]
+#![feature(or_patterns)]
+
+#[derive(Debug, PartialEq)]
+enum MatchArm {
+    Arm(usize),
+    Wild,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq)]
+enum Test {
+    Foo,
+    Bar,
+    Baz,
+    Qux,
+}
+
+fn test(foo: Option<Test>) -> MatchArm {
+    match foo {
+        bar @ Some(Test::Foo | Test::Bar) => {
+            assert!(bar == Some(Test::Foo) || bar == Some(Test::Bar));
+
+            MatchArm::Arm(0)
+        },
+        Some(_) => MatchArm::Arm(1),
+        _ => MatchArm::Wild,
+    }
+}
+
+fn main() {
+    assert_eq!(test(Some(Test::Foo)), MatchArm::Arm(0));
+    assert_eq!(test(Some(Test::Bar)), MatchArm::Arm(0));
+    assert_eq!(test(Some(Test::Baz)), MatchArm::Arm(1));
+    assert_eq!(test(Some(Test::Qux)), MatchArm::Arm(1));
+    assert_eq!(test(None), MatchArm::Wild);
+}
diff --git a/src/test/ui/pattern/bindings-after-at/slice-patterns.rs b/src/test/ui/pattern/bindings-after-at/slice-patterns.rs
new file mode 100644 (file)
index 0000000..7e50527
--- /dev/null
@@ -0,0 +1,40 @@
+// Test bindings-after-at with slice-patterns
+
+// run-pass
+
+#![feature(bindings_after_at)]
+
+#[derive(Debug, PartialEq)]
+enum MatchArm {
+    Arm(usize),
+    Wild,
+}
+
+fn test(foo: &[i32]) -> MatchArm {
+    match foo {
+        [bar @ .., n] if n == &5 => {
+            for i in bar {
+                assert!(i < &5);
+            }
+
+            MatchArm::Arm(0)
+        },
+        bar @ [x0, .., xn] => {
+            assert_eq!(x0, &1);
+            assert_eq!(x0, &1);
+            assert_eq!(xn, &4);
+            assert_eq!(bar, &[1, 2, 3, 4]);
+
+            MatchArm::Arm(1)
+        },
+        _ => MatchArm::Wild,
+    }
+}
+
+fn main() {
+    let foo = vec![1, 2, 3, 4, 5];
+
+    assert_eq!(test(&foo), MatchArm::Arm(0));
+    assert_eq!(test(&foo[..4]), MatchArm::Arm(1));
+    assert_eq!(test(&foo[0..1]), MatchArm::Wild);
+}
index 11eae2af9c95f74711ca9c4e0e5e9c0a316129ff..7d1cac8a442f5eae819c049f52de8966fb3d0fe7 100644 (file)
@@ -21,7 +21,7 @@ fn uninhab_union() -> Foo {
 
 fn match_on_uninhab() {
     match uninhab_ref() {
-        //~^ ERROR non-exhaustive patterns: type `&'static !` is non-empty
+        //~^ ERROR non-exhaustive patterns: type `&!` is non-empty
     }
 
     match uninhab_union() {
index 1b1096c977ad4e915641319ca048c79a9bb57a27..e1079f912d076821d3d95434b4df0c6754f55b7d 100644 (file)
@@ -1,4 +1,4 @@
-error[E0004]: non-exhaustive patterns: type `&'static !` is non-empty
+error[E0004]: non-exhaustive patterns: type `&!` is non-empty
   --> $DIR/always-inhabited-union-ref.rs:23:11
    |
 LL |     match uninhab_ref() {
index fcf7b19572f1ff509b7897979a2dae2b10d1c70c..e28fd13b97f2378d5d5a496136a4ca1392b6300b 100644 (file)
@@ -74,7 +74,7 @@ fn test() {
         }
         self::baz::A;
         self::baz::A::foo();
-        self::baz::A::bar(); //~ ERROR: method `bar` is private
+        self::baz::A::bar(); //~ ERROR: associated function `bar` is private
         self::baz::A.foo2();
 
         // this used to cause an ICE in privacy traversal.
@@ -92,21 +92,21 @@ pub fn gpub() {}
 fn lol() {
     bar::A;
     bar::A::foo();
-    bar::A::bar(); //~ ERROR: method `bar` is private
+    bar::A::bar(); //~ ERROR: associated function `bar` is private
     bar::A.foo2();
 }
 
 mod foo {
     fn test() {
         ::bar::A::foo();
-        ::bar::A::bar();        //~ ERROR: method `bar` is private
+        ::bar::A::bar();        //~ ERROR: associated function `bar` is private
         ::bar::A.foo2();
         ::bar::baz::A::foo();   //~ ERROR: module `baz` is private
         ::bar::baz::A::bar();   //~ ERROR: module `baz` is private
-                                //~^ ERROR: method `bar` is private
+                                //~^ ERROR: associated function `bar` is private
         ::bar::baz::A.foo2();   //~ ERROR: module `baz` is private
         ::bar::baz::A.bar2();   //~ ERROR: module `baz` is private
-                                //~^ ERROR: method `bar2` is private
+                                //~^ ERROR: associated function `bar2` is private
 
         let _: isize =
         ::bar::B::foo();        //~ ERROR: trait `B` is private
index 215df0dc754410997470dbc1b78447d5b1b2efd2..ec2bc0d84ac0e32c82130d90b17131df24f028b3 100644 (file)
@@ -154,31 +154,31 @@ note: the trait `B` is defined here
 LL |     trait B {
    |     ^^^^^^^
 
-error[E0624]: method `bar` is private
+error[E0624]: associated function `bar` is private
   --> $DIR/privacy1.rs:77:9
    |
 LL |         self::baz::A::bar();
    |         ^^^^^^^^^^^^^^^^^
 
-error[E0624]: method `bar` is private
+error[E0624]: associated function `bar` is private
   --> $DIR/privacy1.rs:95:5
    |
 LL |     bar::A::bar();
    |     ^^^^^^^^^^^
 
-error[E0624]: method `bar` is private
+error[E0624]: associated function `bar` is private
   --> $DIR/privacy1.rs:102:9
    |
 LL |         ::bar::A::bar();
    |         ^^^^^^^^^^^^^
 
-error[E0624]: method `bar` is private
+error[E0624]: associated function `bar` is private
   --> $DIR/privacy1.rs:105:9
    |
 LL |         ::bar::baz::A::bar();
    |         ^^^^^^^^^^^^^^^^^^
 
-error[E0624]: method `bar2` is private
+error[E0624]: associated function `bar2` is private
   --> $DIR/privacy1.rs:108:23
    |
 LL |         ::bar::baz::A.bar2();
index 719dc27ccf4d6bddbded7ff6e8917d8890d7762c..b10c3a5265971c6ce14fedcf765f92c267486dbf 100644 (file)
@@ -10,11 +10,16 @@ error[E0603]: function import `foo` is private
 LL |     use bar::glob::foo;
    |                    ^^^ this function import is private
    |
-note: the function import `foo` is defined here
+note: the function import `foo` is defined here...
   --> $DIR/privacy2.rs:10:13
    |
 LL |         use foo;
    |             ^^^
+note: ...and refers to the function `foo` which is defined here
+  --> $DIR/privacy2.rs:14:1
+   |
+LL | pub fn foo() {}
+   | ^^^^^^^^^^^^ consider importing it directly
 
 error: requires `sized` lang_item
 
index b5587920f1cc9d0b86c735cbffe22544438f36bb..f7be6726c5eaa73d99d7fafcda4334c4afc06f9c 100644 (file)
@@ -17,5 +17,5 @@ fn bar(&self) {} // This should be visible outside `f`
 fn main() {
     let s = a::Foo { x: 1 };
     s.bar();
-    s.foo();    //~ ERROR method `foo` is private
+    s.foo();    //~ ERROR associated function `foo` is private
 }
index e1da3f47a4ef76f6b8857d04500e3344977e30e9..6833cdb4df9db49f5cca022f5dae33b65e00d06a 100644 (file)
@@ -1,4 +1,4 @@
-error[E0624]: method `foo` is private
+error[E0624]: associated function `foo` is private
   --> $DIR/private-impl-method.rs:20:7
    |
 LL |     s.foo();
index 4da44e0682be909d9eb9c2e6f48a2b6f3919defa..ab3bbdfe496696ca0f6deca0ec69e87f1111966c 100644 (file)
@@ -4,5 +4,5 @@
 
 fn main() {
   let nyan : cat = cat(52, 99);
-  nyan.nap();   //~ ERROR method `nap` is private
+  nyan.nap();   //~ ERROR associated function `nap` is private
 }
index 10e0bfe5b13676433f8edb578382c41501baf1de..6b49063815a6691b23e2c93c2bc114ecc2a30727 100644 (file)
@@ -1,4 +1,4 @@
-error[E0624]: method `nap` is private
+error[E0624]: associated function `nap` is private
   --> $DIR/private-method-cross-crate.rs:7:8
    |
 LL |   nyan.nap();
index bc27027e886ba5e8393f4b0c476c01e8754c5104..2f6454288ae6884a9e731e62f60d0874ccf0c27c 100644 (file)
@@ -10,5 +10,5 @@ fn f(self) {}
 
 fn main() {
     let x = a::Foo;
-    x.f();  //~ ERROR method `f` is private
+    x.f();  //~ ERROR associated function `f` is private
 }
index d2ba591ef0cc151cefd427d10695876b96edc43c..5551e1bd759078d0944bd2a67f861adb09dfa596 100644 (file)
@@ -1,4 +1,4 @@
-error[E0624]: method `f` is private
+error[E0624]: associated function `f` is private
   --> $DIR/private-method-inherited.rs:13:7
    |
 LL |     x.f();
index a9bea520e75735191009d99473f342ee33709c57..76a642cde1a8aff461601be2d06b8f138c9d71dc 100644 (file)
@@ -19,5 +19,5 @@ pub fn cat(in_x : usize, in_y : isize) -> Cat {
 
 fn main() {
   let nyan : kitties::Cat = kitties::cat(52, 99);
-  nyan.nap(); //~ ERROR method `nap` is private
+  nyan.nap(); //~ ERROR associated function `nap` is private
 }
index 61fc122e318ee5eb1cbc5aa9c04c202e880392dd..583dc123e246bb2de36d216e900ccce7bbb81ef3 100644 (file)
@@ -1,4 +1,4 @@
-error[E0624]: method `nap` is private
+error[E0624]: associated function `nap` is private
   --> $DIR/private-method.rs:22:8
    |
 LL |   nyan.nap();
index aac444b8e3c98054f67a1a7dad6f368682ef72d1..e73f723ed0ab63bf7e65c31eb4d87fc1307d304f 100644 (file)
@@ -52,13 +52,13 @@ error[E0616]: field `x` of struct `foo::bar::S` is private
 LL |     S::default().x;
    |     ^^^^^^^^^^^^^^
 
-error[E0624]: method `f` is private
+error[E0624]: associated function `f` is private
   --> $DIR/test.rs:32:18
    |
 LL |     S::default().f();
    |                  ^
 
-error[E0624]: method `g` is private
+error[E0624]: associated function `g` is private
   --> $DIR/test.rs:33:5
    |
 LL |     S::g();
@@ -76,13 +76,13 @@ error[E0616]: field `z` of struct `pub_restricted::Universe` is private
 LL |     let _ = u.z;
    |             ^^^
 
-error[E0624]: method `g` is private
+error[E0624]: associated function `g` is private
   --> $DIR/test.rs:45:7
    |
 LL |     u.g();
    |       ^
 
-error[E0624]: method `h` is private
+error[E0624]: associated function `h` is private
   --> $DIR/test.rs:46:7
    |
 LL |     u.h();
index faf31712156654edaf1f5431c435c1d5af7388a7..cf9a97491f03941ce9902ed181d1a848cfb8b364 100644 (file)
@@ -1 +1 @@
-fn main () { let y : u32 = "z" ; { let x : u32 = "y" ; } }
+fn main() { let y : u32 = "z" ; { let x : u32 = "y" ; } }
index f702df66db1b87aca4c34ac6b9def3606aef25f1..2ccd3f88200e340259b982ca652dc7749c35522f 100644 (file)
@@ -10,5 +10,5 @@
 #[proc_macro_derive(Unstable)]
 pub fn derive(_input: TokenStream) -> TokenStream {
 
-    "unsafe fn foo() -> u32 { ::std::intrinsics::init() }".parse().unwrap()
+    "unsafe fn foo() -> u32 { ::std::intrinsics::abort() }".parse().unwrap()
 }
diff --git a/src/test/ui/proc-macro/crt-static.rs b/src/test/ui/proc-macro/crt-static.rs
new file mode 100644 (file)
index 0000000..90e3d42
--- /dev/null
@@ -0,0 +1,16 @@
+// Test proc-macro crate can be built without addtional RUSTFLAGS
+// on musl target
+// override -Ctarget-feature=-crt-static from compiletest
+// compile-flags: -Ctarget-feature=
+// ignore-wasm32
+// build-pass
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(Foo)]
+pub fn derive_foo(input: TokenStream) -> TokenStream {
+    input
+}
index ea06f6c1acaf993b948b6c64543e0c6c6cfe597b..15433bebde967df2bfe250a52ab4f89ba4e2b5e0 100644 (file)
@@ -1,4 +1,4 @@
-PRINT-BANG INPUT (DISPLAY): struct M ($crate :: S) ;
+PRINT-BANG INPUT (DISPLAY): struct M($crate :: S) ;
 PRINT-BANG INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
@@ -39,7 +39,7 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
     },
 ]
 PRINT-ATTR INPUT (DISPLAY): struct A(crate::S);
-PRINT-ATTR RE-COLLECTED (DISPLAY): struct A ($crate :: S) ;
+PRINT-ATTR RE-COLLECTED (DISPLAY): struct A($crate :: S) ;
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
index 619b2fd5321fff0f4026f3cdd0c750383256cd54..73e407918ec8cf68b7585d7018eb5105c9ccdaff 100644 (file)
@@ -1,5 +1,5 @@
 PRINT-ATTR INPUT (DISPLAY): struct A(identity!(crate :: S));
-PRINT-ATTR RE-COLLECTED (DISPLAY): struct A (identity ! ($crate :: S)) ;
+PRINT-ATTR RE-COLLECTED (DISPLAY): struct A(identity ! ($crate :: S)) ;
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
@@ -55,7 +55,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
     },
 ]
 PRINT-ATTR INPUT (DISPLAY): struct B(identity!(::dollar_crate_external :: S));
-PRINT-ATTR RE-COLLECTED (DISPLAY): struct B (identity ! ($crate :: S)) ;
+PRINT-ATTR RE-COLLECTED (DISPLAY): struct B(identity ! ($crate :: S)) ;
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
index 5fdc6f8ee96ca44d3071b9294b049eaa59b295d2..e125a3e7f17370619ce2917e190fa6b5596d09a1 100644 (file)
@@ -1,4 +1,4 @@
-PRINT-BANG INPUT (DISPLAY): struct M ($crate :: S) ;
+PRINT-BANG INPUT (DISPLAY): struct M($crate :: S) ;
 PRINT-BANG INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
@@ -39,7 +39,7 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
     },
 ]
 PRINT-ATTR INPUT (DISPLAY): struct A(crate::S);
-PRINT-ATTR RE-COLLECTED (DISPLAY): struct A ($crate :: S) ;
+PRINT-ATTR RE-COLLECTED (DISPLAY): struct A($crate :: S) ;
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
@@ -80,7 +80,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
     },
 ]
 PRINT-DERIVE INPUT (DISPLAY): struct D(crate::S);
-PRINT-DERIVE RE-COLLECTED (DISPLAY): struct D ($crate :: S) ;
+PRINT-DERIVE RE-COLLECTED (DISPLAY): struct D($crate :: S) ;
 PRINT-DERIVE INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
@@ -120,7 +120,7 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [
         span: #3 bytes(LO..HI),
     },
 ]
-PRINT-BANG INPUT (DISPLAY): struct M ($crate :: S) ;
+PRINT-BANG INPUT (DISPLAY): struct M($crate :: S) ;
 PRINT-BANG INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
@@ -161,7 +161,7 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
     },
 ]
 PRINT-ATTR INPUT (DISPLAY): struct A(::dollar_crate_external::S);
-PRINT-ATTR RE-COLLECTED (DISPLAY): struct A ($crate :: S) ;
+PRINT-ATTR RE-COLLECTED (DISPLAY): struct A($crate :: S) ;
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
@@ -202,7 +202,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
     },
 ]
 PRINT-DERIVE INPUT (DISPLAY): struct D(::dollar_crate_external::S);
-PRINT-DERIVE RE-COLLECTED (DISPLAY): struct D ($crate :: S) ;
+PRINT-DERIVE RE-COLLECTED (DISPLAY): struct D($crate :: S) ;
 PRINT-DERIVE INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
index ff2e3af3777a15c854e2f519afa0c3b607216620..19144b210a12740bbf6f7e55e40d9e737f7e55a7 100644 (file)
@@ -4,7 +4,6 @@ error[E0658]: attributes starting with `rustc` are reserved for use by the `rust
 LL | #[derive(Unstable)]
    |          ^^^^^^^^
    |
-   = note: see issue #29642 <https://github.com/rust-lang/rust/issues/29642> for more information
    = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable
    = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
index c344147ed93ca1f9db4520444422e65670a31f96..30a4cd7c116a627917ac5868ac03aad2c39f20bd 100644 (file)
@@ -21,21 +21,10 @@ 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
+  --> $DIR/mixed-site-span.rs:26:1
+   |
+LL | pass_dollar_crate!();
+   | ^^^^^^^^^^^^^^^^^^^^^ not found in `$crate`
    |
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 help: possible candidate is found in another module, you can import it into scope
index c9390a04b9e2468c36a9665c5431339cded00b6b..4405278528eebe973c37c2b83f21241a06301fd8 100644 (file)
@@ -1,19 +1,8 @@
 error: hello to you, too!
-  --> $DIR/auxiliary/multispan.rs:31:1
-   |
-LL | / pub fn hello(input: TokenStream) -> TokenStream {
-LL | |     if let Err(diag) = parse(input) {
-LL | |         diag.emit();
-LL | |     }
-LL | |
-LL | |     TokenStream::new()
-LL | | }
-   | |_^
-   | 
-  ::: $DIR/multispan.rs:14:5
-   |
-LL |       hello!(hi);
-   |       ----------- in this macro invocation
+  --> $DIR/multispan.rs:14:5
+   |
+LL |     hello!(hi);
+   |     ^^^^^^^^^^^
    |
 note: found these 'hi's
   --> $DIR/multispan.rs:14:12
@@ -23,21 +12,10 @@ LL |     hello!(hi);
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: hello to you, too!
-  --> $DIR/auxiliary/multispan.rs:31:1
-   |
-LL | / pub fn hello(input: TokenStream) -> TokenStream {
-LL | |     if let Err(diag) = parse(input) {
-LL | |         diag.emit();
-LL | |     }
-LL | |
-LL | |     TokenStream::new()
-LL | | }
-   | |_^
-   | 
-  ::: $DIR/multispan.rs:17:5
-   |
-LL |       hello!(hi hi);
-   |       -------------- in this macro invocation
+  --> $DIR/multispan.rs:17:5
+   |
+LL |     hello!(hi hi);
+   |     ^^^^^^^^^^^^^^
    |
 note: found these 'hi's
   --> $DIR/multispan.rs:17:12
@@ -47,21 +25,10 @@ LL |     hello!(hi hi);
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: hello to you, too!
-  --> $DIR/auxiliary/multispan.rs:31:1
-   |
-LL | / pub fn hello(input: TokenStream) -> TokenStream {
-LL | |     if let Err(diag) = parse(input) {
-LL | |         diag.emit();
-LL | |     }
-LL | |
-LL | |     TokenStream::new()
-LL | | }
-   | |_^
-   | 
-  ::: $DIR/multispan.rs:20:5
-   |
-LL |       hello!(hi hi hi);
-   |       ----------------- in this macro invocation
+  --> $DIR/multispan.rs:20:5
+   |
+LL |     hello!(hi hi hi);
+   |     ^^^^^^^^^^^^^^^^^
    |
 note: found these 'hi's
   --> $DIR/multispan.rs:20:12
@@ -71,21 +38,10 @@ LL |     hello!(hi hi hi);
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: hello to you, too!
-  --> $DIR/auxiliary/multispan.rs:31:1
-   |
-LL | / pub fn hello(input: TokenStream) -> TokenStream {
-LL | |     if let Err(diag) = parse(input) {
-LL | |         diag.emit();
-LL | |     }
-LL | |
-LL | |     TokenStream::new()
-LL | | }
-   | |_^
-   | 
-  ::: $DIR/multispan.rs:23:5
-   |
-LL |       hello!(hi hey hi yo hi beep beep hi hi);
-   |       ---------------------------------------- in this macro invocation
+  --> $DIR/multispan.rs:23:5
+   |
+LL |     hello!(hi hey hi yo hi beep beep hi hi);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: found these 'hi's
   --> $DIR/multispan.rs:23:12
@@ -95,21 +51,10 @@ LL |     hello!(hi hey hi yo hi beep beep hi hi);
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: hello to you, too!
-  --> $DIR/auxiliary/multispan.rs:31:1
-   |
-LL | / pub fn hello(input: TokenStream) -> TokenStream {
-LL | |     if let Err(diag) = parse(input) {
-LL | |         diag.emit();
-LL | |     }
-LL | |
-LL | |     TokenStream::new()
-LL | | }
-   | |_^
-   | 
-  ::: $DIR/multispan.rs:24:5
-   |
-LL |       hello!(hi there, hi how are you? hi... hi.);
-   |       -------------------------------------------- in this macro invocation
+  --> $DIR/multispan.rs:24:5
+   |
+LL |     hello!(hi there, hi how are you? hi... hi.);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: found these 'hi's
   --> $DIR/multispan.rs:24:12
@@ -119,21 +64,10 @@ LL |     hello!(hi there, hi how are you? hi... hi.);
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: hello to you, too!
-  --> $DIR/auxiliary/multispan.rs:31:1
-   |
-LL | / pub fn hello(input: TokenStream) -> TokenStream {
-LL | |     if let Err(diag) = parse(input) {
-LL | |         diag.emit();
-LL | |     }
-LL | |
-LL | |     TokenStream::new()
-LL | | }
-   | |_^
-   | 
-  ::: $DIR/multispan.rs:25:5
-   |
-LL |       hello!(whoah. hi di hi di ho);
-   |       ------------------------------ in this macro invocation
+  --> $DIR/multispan.rs:25:5
+   |
+LL |     hello!(whoah. hi di hi di ho);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: found these 'hi's
   --> $DIR/multispan.rs:25:19
@@ -143,21 +77,10 @@ LL |     hello!(whoah. hi di hi di ho);
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: hello to you, too!
-  --> $DIR/auxiliary/multispan.rs:31:1
-   |
-LL | / pub fn hello(input: TokenStream) -> TokenStream {
-LL | |     if let Err(diag) = parse(input) {
-LL | |         diag.emit();
-LL | |     }
-LL | |
-LL | |     TokenStream::new()
-LL | | }
-   | |_^
-   | 
-  ::: $DIR/multispan.rs:26:5
-   |
-LL |       hello!(hi good hi and good bye);
-   |       -------------------------------- in this macro invocation
+  --> $DIR/multispan.rs:26:5
+   |
+LL |     hello!(hi good hi and good bye);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: found these 'hi's
   --> $DIR/multispan.rs:26:12
index 3667e14c9e058cc9df6dfd9a5c3dc50dad1c4287..5c0cbd77a8da7f810bc72ea40346ef02cb8b6f6a 100644 (file)
@@ -11,7 +11,9 @@
 
 extern crate span_api_tests;
 
-use span_api_tests::{reemit, assert_fake_source_file, assert_source_file, macro_stringify};
+// FIXME(69775): Investigate `assert_fake_source_file`.
+
+use span_api_tests::{reemit, assert_source_file, macro_stringify};
 
 macro_rules! say_hello {
     ($macname:ident) => ( $macname! { "Hello, world!" })
@@ -25,7 +27,7 @@ macro_rules! say_hello {
     assert_source_file! { "Hello, world!" }
 }
 
-say_hello_extern! { assert_fake_source_file }
+say_hello_extern! { assert_source_file }
 
 reemit! {
     assert_source_file! { "Hello, world!" }
index 82c4167262fdd691ab41f2ff6597f316dab27b20..ca82a3453452559cf5f4f40de65a7f45973622e7 100644 (file)
@@ -1,19 +1,8 @@
 error: found 2 equal signs, need exactly 3
-  --> $DIR/auxiliary/three-equals.rs:42:1
-   |
-LL | / pub fn three_equals(input: TokenStream) -> TokenStream {
-LL | |     if let Err(diag) = parse(input) {
-LL | |         diag.emit();
-LL | |         return TokenStream::new();
-...  |
-LL | |     "3".parse().unwrap()
-LL | | }
-   | |_^
-   | 
-  ::: $DIR/three-equals.rs:15:5
-   |
-LL |       three_equals!(==);
-   |       ------------------ in this macro invocation
+  --> $DIR/three-equals.rs:15:5
+   |
+LL |     three_equals!(==);
+   |     ^^^^^^^^^^^^^^^^^^
    |
    = help: input must be: `===`
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
index b1b60b4b73fb9dbd6e0e8420b29fafb8b4ffbd42..65549d909d0470325eae3b48bcd1e6a16d0b320b 100644 (file)
@@ -18,7 +18,7 @@ fn f<T>() {}
 fn main() {
     match 10 {
         <S as Tr>::A::f::<u8> => {}
-    //~^ ERROR expected unit struct, unit variant or constant, found method `<<S as Tr>::A>::f<u8>`
+    //~^ ERROR expected unit struct, unit variant or constant, found associated function
         0 ..= <S as Tr>::A::f::<u8> => {} //~ ERROR only char and numeric types are allowed in range
     }
 }
index 7a74a37021bdbe064fac8959030863db732bfc22..7ff43f4404c54e6e9f920538eeac2c6cdd4e3f60 100644 (file)
@@ -1,4 +1,4 @@
-error[E0533]: expected unit struct, unit variant or constant, found method `<<S as Tr>::A>::f<u8>`
+error[E0533]: expected unit struct, unit variant or constant, found associated function `<<S as Tr>::A>::f<u8>`
   --> $DIR/qualified-path-params.rs:20:9
    |
 LL |         <S as Tr>::A::f::<u8> => {}
index 22cf15fb2e4a1458b8bab26e645ac6b833540627..c6a3cc346fc808cd4d2c75e89c27a6586d0f733e 100644 (file)
 #[lang = "eh_personality"]
 extern fn eh_personality() {}
 
-#[cfg(target_os = "windows")]
-#[lang = "eh_unwind_resume"]
-extern fn eh_unwind_resume() {}
-
 
 // take a reference to any built-in range
 fn take_range(_r: &impl RangeBounds<i8>) {}
index aead80fa500a9de3fecf79b3c435aadca2b4f73a..909340611328a47e1364c8560790998dc5d1d762 100644 (file)
@@ -1,7 +1,7 @@
 error: `#[panic_handler]` function required, but not found
 
 error[E0308]: mismatched types
-  --> $DIR/issue-54505-no-std.rs:28:16
+  --> $DIR/issue-54505-no-std.rs:24:16
    |
 LL |     take_range(0..1);
    |                ^^^^
@@ -13,7 +13,7 @@ LL |     take_range(0..1);
                  found struct `core::ops::Range<{integer}>`
 
 error[E0308]: mismatched types
-  --> $DIR/issue-54505-no-std.rs:33:16
+  --> $DIR/issue-54505-no-std.rs:29:16
    |
 LL |     take_range(1..);
    |                ^^^
@@ -25,7 +25,7 @@ LL |     take_range(1..);
                  found struct `core::ops::RangeFrom<{integer}>`
 
 error[E0308]: mismatched types
-  --> $DIR/issue-54505-no-std.rs:38:16
+  --> $DIR/issue-54505-no-std.rs:34:16
    |
 LL |     take_range(..);
    |                ^^
@@ -37,7 +37,7 @@ LL |     take_range(..);
                  found struct `core::ops::RangeFull`
 
 error[E0308]: mismatched types
-  --> $DIR/issue-54505-no-std.rs:43:16
+  --> $DIR/issue-54505-no-std.rs:39:16
    |
 LL |     take_range(0..=1);
    |                ^^^^^
@@ -49,7 +49,7 @@ LL |     take_range(0..=1);
                  found struct `core::ops::RangeInclusive<{integer}>`
 
 error[E0308]: mismatched types
-  --> $DIR/issue-54505-no-std.rs:48:16
+  --> $DIR/issue-54505-no-std.rs:44:16
    |
 LL |     take_range(..5);
    |                ^^^
@@ -61,7 +61,7 @@ LL |     take_range(..5);
                  found struct `core::ops::RangeTo<{integer}>`
 
 error[E0308]: mismatched types
-  --> $DIR/issue-54505-no-std.rs:53:16
+  --> $DIR/issue-54505-no-std.rs:49:16
    |
 LL |     take_range(..=42);
    |                ^^^^^
index 425aa83e70a8542f664bbf27e4ba48ff92950324..eb6224ad1bbb6d1766f1a5abc6c926570b0b3094 100644 (file)
@@ -41,13 +41,13 @@ unsafe fn allocate(layout: Layout) -> *mut u8 {
             println!("allocate({:?})", layout);
         }
 
-        let ret = Global.alloc(layout).unwrap_or_else(|_| handle_alloc_error(layout));
+        let (ptr, _) = Global.alloc(layout).unwrap_or_else(|_| handle_alloc_error(layout));
 
         if PRINT {
-            println!("allocate({:?}) = {:?}", layout, ret);
+            println!("allocate({:?}) = {:?}", layout, ptr);
         }
 
-        ret.cast().as_ptr()
+        ptr.cast().as_ptr()
     }
 
     unsafe fn deallocate(ptr: *mut u8, layout: Layout) {
@@ -63,16 +63,16 @@ unsafe fn reallocate(ptr: *mut u8, old: Layout, new: Layout) -> *mut u8 {
             println!("reallocate({:?}, old={:?}, new={:?})", ptr, old, new);
         }
 
-        let ret = Global.realloc(NonNull::new_unchecked(ptr), old, new.size())
+        let (ptr, _) = Global.realloc(NonNull::new_unchecked(ptr), old, new.size())
             .unwrap_or_else(|_| handle_alloc_error(
                 Layout::from_size_align_unchecked(new.size(), old.align())
             ));
 
         if PRINT {
             println!("reallocate({:?}, old={:?}, new={:?}) = {:?}",
-                     ptr, old, new, ret);
+                     ptr, old, new, ptr);
         }
-        ret.cast().as_ptr()
+        ptr.cast().as_ptr()
     }
 
     fn idx_to_size(i: usize) -> usize { (i+1) * 10 }
index 2a064f3e1159946cb1c15683422f392b518d5a69..31ff9c1e3a72e0290f17e6162597d6b15b6bf1e2 100644 (file)
@@ -1,6 +1,6 @@
 // Test the parse error for an empty recursion_limit
 
-#![recursion_limit = ""] //~ ERROR `recursion_limit` must be a non-negative integer
-                         //~| `recursion_limit` must be a non-negative integer
+#![recursion_limit = ""] //~ ERROR `limit` must be a non-negative integer
+                         //~| `limit` must be a non-negative integer
 
 fn main() {}
index 690c33a746307aaf2640b121191d9bb2ff857ce6..bcd1d27e59b56be8926ceaa16a36d7dbb0b28422 100644 (file)
@@ -1,10 +1,10 @@
-error: `recursion_limit` must be a non-negative integer
+error: `limit` must be a non-negative integer
   --> $DIR/empty.rs:3:1
    |
 LL | #![recursion_limit = ""]
    | ^^^^^^^^^^^^^^^^^^^^^--^
    |                      |
-   |                      `recursion_limit` must be a non-negative integer
+   |                      `limit` must be a non-negative integer
 
 error: aborting due to previous error
 
index 903d8040476961837d4791f9772910ffd71ebe80..759d69d0af20d08e33fa25f736b45d46c97da6ef 100644 (file)
@@ -1,6 +1,6 @@
 // Test the parse error for an invalid digit in recursion_limit
 
-#![recursion_limit = "-100"] //~ ERROR `recursion_limit` must be a non-negative integer
+#![recursion_limit = "-100"] //~ ERROR `limit` must be a non-negative integer
                              //~| not a valid integer
 
 fn main() {}
index 1dcfea547c0bd5a3381ce50bec84934cac36af01..e6fd6b72a0900e04013f6db6d2c5600ce1ca7e18 100644 (file)
@@ -1,4 +1,4 @@
-error: `recursion_limit` must be a non-negative integer
+error: `limit` must be a non-negative integer
   --> $DIR/invalid_digit.rs:3:1
    |
 LL | #![recursion_limit = "-100"]
index 6487b1350aa98cd93f393fad50eb295e12f4ea39..8eee2792b23832cf6d5a6528a0bf67df474a6c8d 100644 (file)
@@ -1,7 +1,7 @@
 // Test the parse error for an overflowing recursion_limit
 
 #![recursion_limit = "999999999999999999999999"]
-//~^ ERROR `recursion_limit` must be a non-negative integer
-//~| `recursion_limit` is too large
+//~^ ERROR `limit` must be a non-negative integer
+//~| `limit` is too large
 
 fn main() {}
index c3fc11989dcec7845cbd5c669fb689ddb144059a..f6ed76c1ebc0e096facf4431f9edfefd65331fcf 100644 (file)
@@ -1,10 +1,10 @@
-error: `recursion_limit` must be a non-negative integer
+error: `limit` must be a non-negative integer
   --> $DIR/overflow.rs:3:1
    |
 LL | #![recursion_limit = "999999999999999999999999"]
    | ^^^^^^^^^^^^^^^^^^^^^--------------------------^
    |                      |
-   |                      `recursion_limit` is too large
+   |                      `limit` is too large
 
 error: aborting due to previous error
 
index f7199944e0063de178d0eaae838dc702670050c6..eb95d7babc6b213a00cd7aa4641568bb38ca5bb0 100644 (file)
@@ -1,4 +1,4 @@
-// Test that a `recursion_limit` of 0 is valid
+// Test that a `limit` of 0 is valid
 
 #![recursion_limit = "0"]
 
index a33d3583552dce2fc634ab77a8e567c37ed68227..06e1b0f1ac262288cc384c6b59c8041037bce83e 100644 (file)
@@ -1,32 +1,54 @@
-error[E0623]: lifetime mismatch
+error[E0491]: in type `&'b &'a usize`, reference has a longer lifetime than the data it references
   --> $DIR/regions-free-region-ordering-caller.rs:11:12
    |
-LL | fn call2<'a, 'b>(a: &'a usize, b: &'b usize) {
-   |                     ---------     ---------
-   |                     |
-   |                     these two types are declared with different lifetimes...
 LL |     let z: Option<&'b &'a usize> = None;
-   |            ^^^^^^^^^^^^^^^^^^^^^ ...but data from `a` flows into `b` here
+   |            ^^^^^^^^^^^^^^^^^^^^^
+   |
+note: the pointer is valid for the lifetime `'b` as defined on the function body at 10:14
+  --> $DIR/regions-free-region-ordering-caller.rs:10:14
+   |
+LL | fn call2<'a, 'b>(a: &'a usize, b: &'b usize) {
+   |              ^^
+note: but the referenced data is only valid for the lifetime `'a` as defined on the function body at 10:10
+  --> $DIR/regions-free-region-ordering-caller.rs:10:10
+   |
+LL | fn call2<'a, 'b>(a: &'a usize, b: &'b usize) {
+   |          ^^
 
-error[E0623]: lifetime mismatch
+error[E0491]: in type `&'b Paramd<'a>`, reference has a longer lifetime than the data it references
   --> $DIR/regions-free-region-ordering-caller.rs:17:12
    |
-LL | fn call3<'a, 'b>(a: &'a usize, b: &'b usize) {
-   |                     ---------     ---------
-   |                     |
-   |                     these two types are declared with different lifetimes...
-LL |     let y: Paramd<'a> = Paramd { x: a };
 LL |     let z: Option<&'b Paramd<'a>> = None;
-   |            ^^^^^^^^^^^^^^^^^^^^^^ ...but data from `a` flows into `b` here
+   |            ^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: the pointer is valid for the lifetime `'b` as defined on the function body at 15:14
+  --> $DIR/regions-free-region-ordering-caller.rs:15:14
+   |
+LL | fn call3<'a, 'b>(a: &'a usize, b: &'b usize) {
+   |              ^^
+note: but the referenced data is only valid for the lifetime `'a` as defined on the function body at 15:10
+  --> $DIR/regions-free-region-ordering-caller.rs:15:10
+   |
+LL | fn call3<'a, 'b>(a: &'a usize, b: &'b usize) {
+   |          ^^
 
-error[E0623]: lifetime mismatch
+error[E0491]: in type `&'a &'b usize`, reference has a longer lifetime than the data it references
   --> $DIR/regions-free-region-ordering-caller.rs:22:12
    |
-LL | fn call4<'a, 'b>(a: &'a usize, b: &'b usize) {
-   |                     ---------     --------- these two types are declared with different lifetimes...
 LL |     let z: Option<&'a &'b usize> = None;
-   |            ^^^^^^^^^^^^^^^^^^^^^ ...but data from `b` flows into `a` here
+   |            ^^^^^^^^^^^^^^^^^^^^^
+   |
+note: the pointer is valid for the lifetime `'a` as defined on the function body at 21:10
+  --> $DIR/regions-free-region-ordering-caller.rs:21:10
+   |
+LL | fn call4<'a, 'b>(a: &'a usize, b: &'b usize) {
+   |          ^^
+note: but the referenced data is only valid for the lifetime `'b` as defined on the function body at 21:14
+  --> $DIR/regions-free-region-ordering-caller.rs:21:14
+   |
+LL | fn call4<'a, 'b>(a: &'a usize, b: &'b usize) {
+   |              ^^
 
 error: aborting due to 3 previous errors
 
-For more information about this error, try `rustc --explain E0623`.
+For more information about this error, try `rustc --explain E0491`.
index c0b12f23cdba7ae28daeb747291e46194ce929a4..2bf4734cf73802137006e1cd64f2865447231f85 100644 (file)
@@ -8,18 +8,18 @@
 struct Paramd<'a> { x: &'a usize }
 
 fn call2<'a, 'b>(a: &'a usize, b: &'b usize) {
-    let z: Option<&'b &'a usize> = None;//[migrate]~ ERROR E0623
+    let z: Option<&'b &'a usize> = None;//[migrate]~ ERROR E0491
     //[nll]~^ ERROR lifetime may not live long enough
 }
 
 fn call3<'a, 'b>(a: &'a usize, b: &'b usize) {
     let y: Paramd<'a> = Paramd { x: a };
-    let z: Option<&'b Paramd<'a>> = None;//[migrate]~ ERROR E0623
+    let z: Option<&'b Paramd<'a>> = None;//[migrate]~ ERROR E0491
     //[nll]~^ ERROR lifetime may not live long enough
 }
 
 fn call4<'a, 'b>(a: &'a usize, b: &'b usize) {
-    let z: Option<&'a &'b usize> = None;//[migrate]~ ERROR E0623
+    let z: Option<&'a &'b usize> = None;//[migrate]~ ERROR E0491
     //[nll]~^ ERROR lifetime may not live long enough
 }
 
index f50b1c8b17f2886dfdfb76ed1618e49b4523b6ad..fe3a864fe4ba58be0286e4a9c98fe8b5d25ecace 100644 (file)
@@ -24,29 +24,29 @@ struct Ccx {
     x: isize
 }
 
-fn alloc<'a>(_bcx : &'a arena) -> &'a Bcx<'a> {
+fn alloc(_bcx: &arena) -> &Bcx<'_> {
     unsafe {
         let layout = Layout::new::<Bcx>();
-        let ptr = Global.alloc(layout).unwrap_or_else(|_| handle_alloc_error(layout));
+        let (ptr, _) = Global.alloc(layout).unwrap_or_else(|_| handle_alloc_error(layout));
         &*(ptr.as_ptr() as *const _)
     }
 }
 
-fn h<'a>(bcx : &'a Bcx<'a>) -> &'a Bcx<'a> {
+fn h<'a>(bcx: &'a Bcx<'a>) -> &'a Bcx<'a> {
     return alloc(bcx.fcx.arena);
 }
 
-fn g(fcx : &Fcx) {
-    let bcx = Bcx { fcx: fcx };
+fn g(fcx: &Fcx) {
+    let bcx = Bcx { fcx };
     let bcx2 = h(&bcx);
     unsafe {
         Global.dealloc(NonNull::new_unchecked(bcx2 as *const _ as *mut _), Layout::new::<Bcx>());
     }
 }
 
-fn f(ccx : &Ccx) {
+fn f(ccx: &Ccx) {
     let a = arena(());
-    let fcx = Fcx { arena: &a, ccx: ccx };
+    let fcx = Fcx { arena: &a, ccx };
     return g(&fcx);
 }
 
index 192312d165bc856477668e2f1c286c9d25793fdb..b878ae0d17337a4c07eb65748f757ef936b48b3a 100644 (file)
@@ -24,3 +24,4 @@ LL | #[repr(align="8")]
 
 error: aborting due to 4 previous errors
 
+For more information about this error, try `rustc --explain E0693`.
index 2870cb57e9cafeed65af5ec0a0107a87ebe53935..c387bba0a13102c9fbb424a6021f4c34a00786dc 100644 (file)
@@ -4,7 +4,6 @@ error[E0658]: attributes starting with `rustc` are reserved for use by the `rust
 LL | #[rustc_attribute_should_be_reserved]
    |   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: see issue #29642 <https://github.com/rust-lang/rust/issues/29642> for more information
    = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable
 
 error: cannot determine resolution for the macro `foo`
diff --git a/src/test/ui/resolve/raw-ident-in-path.rs b/src/test/ui/resolve/raw-ident-in-path.rs
new file mode 100644 (file)
index 0000000..1bcbef5
--- /dev/null
@@ -0,0 +1,5 @@
+// Regression test for issue #63882.
+
+type A = crate::r#break; //~ ERROR cannot find type `r#break` in module `crate`
+
+fn main() {}
diff --git a/src/test/ui/resolve/raw-ident-in-path.stderr b/src/test/ui/resolve/raw-ident-in-path.stderr
new file mode 100644 (file)
index 0000000..f2efcbc
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0412]: cannot find type `r#break` in module `crate`
+  --> $DIR/raw-ident-in-path.rs:3:17
+   |
+LL | type A = crate::r#break;
+   |                 ^^^^^^^ not found in `crate`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0412`.
index e9c4e47f88775f7016f5cf138449436545ae8589..43e9378b7d0ecd656f71eb763e8f162b0d080227 100644 (file)
@@ -1,39 +1,40 @@
 enum Opts {
-    A(isize), B(isize), C(isize)
+    A(isize),
+    B(isize),
+    C(isize),
 }
 
 fn matcher1(x: Opts) {
     match x {
-      Opts::A(ref i) | Opts::B(i) => {}
-      //~^ ERROR variable `i` is bound in inconsistent ways within the same match arm
-      //~^^ ERROR mismatched types
-      Opts::C(_) => {}
+        Opts::A(ref i) | Opts::B(i) => {}
+        //~^ ERROR variable `i` is bound inconsistently
+        //~^^ ERROR mismatched types
+        Opts::C(_) => {}
     }
 }
 
 fn matcher2(x: Opts) {
     match x {
-      Opts::A(ref i) | Opts::B(i) => {}
-      //~^ ERROR variable `i` is bound in inconsistent ways within the same match arm
-      //~^^ ERROR mismatched types
-      Opts::C(_) => {}
+        Opts::A(ref i) | Opts::B(i) => {}
+        //~^ ERROR variable `i` is bound inconsistently
+        //~^^ ERROR mismatched types
+        Opts::C(_) => {}
     }
 }
 
 fn matcher4(x: Opts) {
     match x {
-      Opts::A(ref mut i) | Opts::B(ref i) => {}
-      //~^ ERROR variable `i` is bound in inconsistent ways within the same match arm
-      //~^^ ERROR mismatched types
-      Opts::C(_) => {}
+        Opts::A(ref mut i) | Opts::B(ref i) => {}
+        //~^ ERROR variable `i` is bound inconsistently
+        //~^^ ERROR mismatched types
+        Opts::C(_) => {}
     }
 }
 
-
 fn matcher5(x: Opts) {
     match x {
-      Opts::A(ref i) | Opts::B(ref i) => {}
-      Opts::C(_) => {}
+        Opts::A(ref i) | Opts::B(ref i) => {}
+        Opts::C(_) => {}
     }
 }
 
index 749ed131b204eacf85fee158e7fcd1e91041c45e..c14dfa3601a8c0bf9d8919e74611bb4dd2c3ae61 100644 (file)
@@ -1,58 +1,58 @@
-error[E0409]: variable `i` is bound in inconsistent ways within the same match arm
-  --> $DIR/resolve-inconsistent-binding-mode.rs:7:32
+error[E0409]: variable `i` is bound inconsistently across alternatives separated by `|`
+  --> $DIR/resolve-inconsistent-binding-mode.rs:9:34
    |
-LL |       Opts::A(ref i) | Opts::B(i) => {}
-   |                   -            ^ bound in different ways
-   |                   |
-   |                   first binding
+LL |         Opts::A(ref i) | Opts::B(i) => {}
+   |                     -            ^ bound in different ways
+   |                     |
+   |                     first binding
 
-error[E0409]: variable `i` is bound in inconsistent ways within the same match arm
-  --> $DIR/resolve-inconsistent-binding-mode.rs:16:32
+error[E0409]: variable `i` is bound inconsistently across alternatives separated by `|`
+  --> $DIR/resolve-inconsistent-binding-mode.rs:18:34
    |
-LL |       Opts::A(ref i) | Opts::B(i) => {}
-   |                   -            ^ bound in different ways
-   |                   |
-   |                   first binding
+LL |         Opts::A(ref i) | Opts::B(i) => {}
+   |                     -            ^ bound in different ways
+   |                     |
+   |                     first binding
 
-error[E0409]: variable `i` is bound in inconsistent ways within the same match arm
-  --> $DIR/resolve-inconsistent-binding-mode.rs:25:40
+error[E0409]: variable `i` is bound inconsistently across alternatives separated by `|`
+  --> $DIR/resolve-inconsistent-binding-mode.rs:27:42
    |
-LL |       Opts::A(ref mut i) | Opts::B(ref i) => {}
-   |                       - first binding  ^ bound in different ways
+LL |         Opts::A(ref mut i) | Opts::B(ref i) => {}
+   |                         - first binding  ^ bound in different ways
 
 error[E0308]: mismatched types
-  --> $DIR/resolve-inconsistent-binding-mode.rs:7:32
+  --> $DIR/resolve-inconsistent-binding-mode.rs:9:34
    |
 LL |     match x {
    |           - this expression has type `Opts`
-LL |       Opts::A(ref i) | Opts::B(i) => {}
-   |               -----            ^ expected `&isize`, found `isize`
-   |               |
-   |               first introduced with type `&isize` here
+LL |         Opts::A(ref i) | Opts::B(i) => {}
+   |                 -----            ^ expected `&isize`, found `isize`
+   |                 |
+   |                 first introduced with type `&isize` here
    |
    = note: in the same arm, a binding must have the same type in all alternatives
 
 error[E0308]: mismatched types
-  --> $DIR/resolve-inconsistent-binding-mode.rs:16:32
+  --> $DIR/resolve-inconsistent-binding-mode.rs:18:34
    |
 LL |     match x {
    |           - this expression has type `Opts`
-LL |       Opts::A(ref i) | Opts::B(i) => {}
-   |               -----            ^ expected `&isize`, found `isize`
-   |               |
-   |               first introduced with type `&isize` here
+LL |         Opts::A(ref i) | Opts::B(i) => {}
+   |                 -----            ^ expected `&isize`, found `isize`
+   |                 |
+   |                 first introduced with type `&isize` here
    |
    = note: in the same arm, a binding must have the same type in all alternatives
 
 error[E0308]: mismatched types
-  --> $DIR/resolve-inconsistent-binding-mode.rs:25:36
+  --> $DIR/resolve-inconsistent-binding-mode.rs:27:38
    |
 LL |     match x {
    |           - this expression has type `Opts`
-LL |       Opts::A(ref mut i) | Opts::B(ref i) => {}
-   |               ---------            ^^^^^ types differ in mutability
-   |               |
-   |               first introduced with type `&mut isize` here
+LL |         Opts::A(ref mut i) | Opts::B(ref i) => {}
+   |                 ---------            ^^^^^ types differ in mutability
+   |                 |
+   |                 first introduced with type `&mut isize` here
    |
    = note: expected type `&mut isize`
               found type `&isize`
index 2fb803c4b2ad429dbefb667dbd6f55688c67146b..b9202f556d12b63f64af42975e994977eb50034b 100644 (file)
@@ -19,7 +19,7 @@ fn main() {
         (A, B) | (ref B, c) | (c, A) => ()
         //~^ ERROR variable `A` is not bound in all patterns
         //~| ERROR variable `B` is not bound in all patterns
-        //~| ERROR variable `B` is bound in inconsistent ways
+        //~| ERROR variable `B` is bound inconsistently
         //~| ERROR mismatched types
         //~| ERROR variable `c` is not bound in all patterns
         //~| HELP consider making the path in the pattern qualified: `?::A`
index 1d3079c90baf657693c3d4b68f4fc32f69378dc5..70e9c2e5bf598e5621378721dfa3a29e90e31d1d 100644 (file)
@@ -47,7 +47,7 @@ LL |         (A, B) | (ref B, c) | (c, A) => ()
    |         |                variable not in all patterns
    |         pattern doesn't bind `c`
 
-error[E0409]: variable `B` is bound in inconsistent ways within the same match arm
+error[E0409]: variable `B` is bound inconsistently across alternatives separated by `|`
   --> $DIR/resolve-inconsistent-names.rs:19:23
    |
 LL |         (A, B) | (ref B, c) | (c, A) => ()
index 27efd450b9471157126a4d22f72003c0dd92ea19..10d30ec1a1b189941d8143a2b559d264b3718895 100644 (file)
@@ -1,10 +1,17 @@
 error[E0308]: mismatched types
   --> $DIR/const.rs:14:9
    |
+LL | const FOO: Foo = Foo{bar: 5};
+   | ----------------------------- constant defined here
+...
 LL |     match &f {
    |           -- this expression has type `&Foo`
 LL |         FOO => {},
-   |         ^^^ expected `&Foo`, found struct `Foo`
+   |         ^^^
+   |         |
+   |         expected `&Foo`, found struct `Foo`
+   |         `FOO` is interpreted as a constant, not a new binding
+   |         help: introduce a new binding instead: `other_foo`
 
 error: aborting due to previous error
 
index aa013d4bf3528fbdc0262a9867a01af91953a14d..b4a0d8145c1d690b95b365e7880e64dc990794ab 100644 (file)
@@ -4,7 +4,7 @@ pub fn main() {
     let x = &Some((3, 3));
     let _: &i32 = match x {
         Some((x, 3)) | &Some((ref x, 5)) => x,
-        //~^ ERROR is bound in inconsistent ways
+        //~^ ERROR is bound inconsistently
         _ => &5i32,
     };
 }
index ff8dce32b2ab32ef421fc260d247d497da0bf0a6..e1e1bf7f6d9711e264476ff2d65354e2dbd1c304 100644 (file)
@@ -1,4 +1,4 @@
-error[E0409]: variable `x` is bound in inconsistent ways within the same match arm
+error[E0409]: variable `x` is bound inconsistently across alternatives separated by `|`
   --> $DIR/issue-44912-or.rs:6:35
    |
 LL |         Some((x, 3)) | &Some((ref x, 5)) => x,
index 7becb9c5b60af3a111f131e3528fd5cc1a0a88cc..c2fb8fa1eb6caceff1b55b985ecb5ab2b2e6e03b 100644 (file)
@@ -8,3 +8,4 @@ LL | struct S;
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0739`.
index 3ea58a3728a5dc3d2cabd73e76b4852baf6aa3da..834f6a409f5b69bcbf8c1410a51f6c365880c05f 100644 (file)
@@ -1,18 +1,18 @@
 error: inherent impls cannot be `const`
-  --> $DIR/inherent-impl.rs:9:1
+  --> $DIR/inherent-impl.rs:9:12
    |
 LL | impl const S {}
-   | ^^^^^-----^^^^^
+   |      ----- ^ inherent impl for this type
    |      |
    |      `const` because of this
    |
    = note: only trait implementations may be annotated with `const`
 
 error: inherent impls cannot be `const`
-  --> $DIR/inherent-impl.rs:12:1
+  --> $DIR/inherent-impl.rs:12:12
    |
 LL | impl const T {}
-   | ^^^^^-----^^^^^
+   |      ----- ^ inherent impl for this type
    |      |
    |      `const` because of this
    |
index 6cd54aa68aedd0a8f88f08f5b67148ff5fb714ee..65400163ddd86ab09fe09102de41923eabda44d5 100644 (file)
@@ -4,7 +4,7 @@
 
 #![warn(macro_use_extern_crate, unused)]
 
-#[macro_use] //~ WARN should be replaced at use sites with a `use` statement
+#[macro_use] //~ WARN should be replaced at use sites with a `use` item
 extern crate macro_use_warned_against;
 #[macro_use] //~ WARN unused `#[macro_use]`
 extern crate macro_use_warned_against2;
index 611b9d5dac9fd11e3922b3496df77719e094d451..ef00b865815c06032c5b268751921c2904350b16 100644 (file)
@@ -1,4 +1,4 @@
-warning: deprecated `#[macro_use]` directive used to import macros should be replaced at use sites with a `use` statement to import the macro instead
+warning: deprecated `#[macro_use]` attribute used to import macros should be replaced at use sites with a `use` item to import the macro instead
   --> $DIR/macro-use-warned-against.rs:7:1
    |
 LL | #[macro_use]
index d27a30a2dc55f9e65db391fb888dd49fa0f2f1ef..f8650cd86d51e8bf80942d0e32d21e0ba5cba970 100644 (file)
@@ -1,16 +1,15 @@
 // needs-sanitizer-support
 // only-x86_64
 //
-// compile-flags: -Z sanitizer=address -O
+// compile-flags: -Z sanitizer=address -O -g
 //
 // run-fail
 // error-pattern: AddressSanitizer: stack-buffer-overflow
-// error-pattern: 'xs' <== Memory access at offset
+// error-pattern: 'xs' (line 15) <== Memory access at offset
 
 #![feature(test)]
 
 use std::hint::black_box;
-use std::mem;
 
 fn main() {
     let xs = [0, 1, 2, 3];
diff --git a/src/test/ui/sanitize/badfree.rs b/src/test/ui/sanitize/badfree.rs
new file mode 100644 (file)
index 0000000..1ca082c
--- /dev/null
@@ -0,0 +1,19 @@
+// needs-sanitizer-support
+// only-x86_64
+//
+// compile-flags: -Z sanitizer=address -O
+//
+// run-fail
+// error-pattern: AddressSanitizer: SEGV
+
+use std::ffi::c_void;
+
+extern "C" {
+    fn free(ptr: *mut c_void);
+}
+
+fn main() {
+    unsafe {
+        free(1 as *mut c_void);
+    }
+}
diff --git a/src/test/ui/sanitize/new-llvm-pass-manager-thin-lto.rs b/src/test/ui/sanitize/new-llvm-pass-manager-thin-lto.rs
new file mode 100644 (file)
index 0000000..d0984bb
--- /dev/null
@@ -0,0 +1,27 @@
+// Regression test for sanitizer function instrumentation passes not
+// being run when compiling with new LLVM pass manager and ThinLTO.
+// Note: The issue occurred only on non-zero opt-level.
+//
+// min-llvm-version 9.0
+// needs-sanitizer-support
+// only-x86_64
+//
+// no-prefer-dynamic
+// revisions: opt0 opt1
+// compile-flags: -Znew-llvm-pass-manager=yes -Zsanitizer=address -Clto=thin
+//[opt0]compile-flags: -Copt-level=0
+//[opt1]compile-flags: -Copt-level=1
+// run-fail
+// error-pattern: ERROR: AddressSanitizer: stack-use-after-scope
+
+static mut P: *mut usize = std::ptr::null_mut();
+
+fn main() {
+    unsafe {
+        {
+            let mut x = 0;
+            P = &mut x;
+        }
+        std::ptr::write_volatile(P, 123);
+    }
+}
index 6afcf24cd3e1ea37eb0ff6d9c9a5f4ad3e2b95e0..57374b7e3bb277d9e9c1bfe9010935e8bf57f43a 100644 (file)
@@ -2,7 +2,7 @@ error: lifetime may not live long enough
   --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:8:52
    |
 LL |     async fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f }
-   |                          -         -               ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |                          -         -               ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
    |                          |         |
    |                          |         let's call the lifetime of this reference `'1`
    |                          let's call the lifetime of this reference `'2`
@@ -11,7 +11,7 @@ error: lifetime may not live long enough
   --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:11:75
    |
 LL |     async fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) }
-   |                          -          -                                     ^^^^^^^^^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |                          -          -                                     ^^^^^^^^^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
    |                          |          |
    |                          |          let's call the lifetime of this reference `'1`
    |                          let's call the lifetime of this reference `'2`
@@ -20,7 +20,7 @@ error: lifetime may not live long enough
   --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:17:64
    |
 LL |     async fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg }
-   |                  --              -                             ^^^ method was supposed to return data with lifetime `'1` but it is returning data with lifetime `'a`
+   |                  --              -                             ^^^ associated function was supposed to return data with lifetime `'1` but it is returning data with lifetime `'a`
    |                  |               |
    |                  |               let's call the lifetime of this reference `'1`
    |                  lifetime `'a` defined here
index a659e4487856cf98b2be3c3e019e3e8e97a0e59e..17099201d11107028f2dc985af767d7e9175c8d3 100644 (file)
@@ -2,7 +2,7 @@ error: lifetime may not live long enough
   --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:6:46
    |
 LL |     fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f }
-   |                    -         -               ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |                    -         -               ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
    |                    |         |
    |                    |         let's call the lifetime of this reference `'1`
    |                    let's call the lifetime of this reference `'2`
@@ -11,7 +11,7 @@ error: lifetime may not live long enough
   --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:8:69
    |
 LL |     fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) }
-   |                    -          -                                     ^^^^^^^^^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |                    -          -                                     ^^^^^^^^^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
    |                    |          |
    |                    |          let's call the lifetime of this reference `'1`
    |                    let's call the lifetime of this reference `'2`
@@ -20,7 +20,7 @@ error: lifetime may not live long enough
   --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:13:58
    |
 LL |     fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg }
-   |            --  ---- has type `std::pin::Pin<&'1 Foo>`    ^^^ method was supposed to return data with lifetime `'1` but it is returning data with lifetime `'a`
+   |            --  ---- has type `std::pin::Pin<&'1 Foo>`    ^^^ associated function was supposed to return data with lifetime `'1` but it is returning data with lifetime `'a`
    |            |
    |            lifetime `'a` defined here
 
index 57d0929c50a792140442fd3cd45ca2387ac6f064..c10b8824e6d63d6d36114d92016d1dab9f5025f2 100644 (file)
@@ -6,7 +6,7 @@ LL |     async fn ref_self(&self, f: &u32) -> &u32 {
    |                       |
    |                       let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/lt-ref-self-async.rs:19:9
@@ -16,7 +16,7 @@ LL |     async fn ref_Self(self: &Self, f: &u32) -> &u32 {
    |                             |
    |                             let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/lt-ref-self-async.rs:23:9
@@ -26,7 +26,7 @@ LL |     async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
    |                                     |
    |                                     let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/lt-ref-self-async.rs:27:9
@@ -36,7 +36,7 @@ LL |     async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
    |                                     |
    |                                     let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/lt-ref-self-async.rs:31:9
@@ -46,7 +46,7 @@ LL |     async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
    |                                             |
    |                                             let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/lt-ref-self-async.rs:35:9
@@ -56,7 +56,7 @@ LL |     async fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
    |                                         |
    |                                         let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: aborting due to 6 previous errors
 
index b51b5a0ba38f2b1232fe151f27c86175c95744ae..e2de743b8f63eb1aaf7f08432d56b33e9dd4b9f4 100644 (file)
@@ -6,7 +6,7 @@ LL |     fn ref_self(&self, f: &u32) -> &u32 {
    |                 |
    |                 let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/lt-ref-self.rs:17:9
@@ -16,7 +16,7 @@ LL |     fn ref_Self(self: &Self, f: &u32) -> &u32 {
    |                       |
    |                       let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/lt-ref-self.rs:21:9
@@ -26,7 +26,7 @@ LL |     fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
    |                               |
    |                               let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/lt-ref-self.rs:25:9
@@ -36,7 +36,7 @@ LL |     fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
    |                               |
    |                               let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/lt-ref-self.rs:29:9
@@ -46,7 +46,7 @@ LL |     fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
    |                                       |
    |                                       let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/lt-ref-self.rs:33:9
@@ -56,7 +56,7 @@ LL |     fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
    |                                   |
    |                                   let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: aborting due to 6 previous errors
 
index 46e828390b0fc8507fb541e4cd032b578a417268..19496a5ef6d326eaf10b8e28f00e12615cdf88be 100644 (file)
@@ -6,7 +6,7 @@ LL |     async fn ref_self(&mut self, f: &u32) -> &u32 {
    |                       |
    |                       let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-mut-self-async.rs:19:9
@@ -16,7 +16,7 @@ LL |     async fn ref_Self(self: &mut Self, f: &u32) -> &u32 {
    |                             |
    |                             let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-mut-self-async.rs:23:9
@@ -26,7 +26,7 @@ LL |     async fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 {
    |                                     |
    |                                     let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-mut-self-async.rs:27:9
@@ -36,7 +36,7 @@ LL |     async fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 {
    |                                     |
    |                                     let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-mut-self-async.rs:31:9
@@ -46,7 +46,7 @@ LL |     async fn box_box_ref_Self(self: Box<Box<&mut Self>>, f: &u32) -> &u32 {
    |                                             |
    |                                             let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-mut-self-async.rs:35:9
@@ -56,7 +56,7 @@ LL |     async fn box_pin_ref_Self(self: Box<Pin<&mut Self>>, f: &u32) -> &u32 {
    |                                             |
    |                                             let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: aborting due to 6 previous errors
 
index 6c8c030e5fffaf2361e93e913688556d07ca3e58..94bfc5f4a818693776b35b4fc60e72b399d87f85 100644 (file)
@@ -6,7 +6,7 @@ LL |     fn ref_self(&mut self, f: &u32) -> &u32 {
    |                 |
    |                 let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-mut-self.rs:17:9
@@ -16,7 +16,7 @@ LL |     fn ref_Self(self: &mut Self, f: &u32) -> &u32 {
    |                       |
    |                       let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-mut-self.rs:21:9
@@ -26,7 +26,7 @@ LL |     fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 {
    |                               |
    |                               let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-mut-self.rs:25:9
@@ -36,7 +36,7 @@ LL |     fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 {
    |                               |
    |                               let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-mut-self.rs:29:9
@@ -46,7 +46,7 @@ LL |     fn box_box_ref_Self(self: Box<Box<&mut Self>>, f: &u32) -> &u32 {
    |                                       |
    |                                       let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-mut-self.rs:33:9
@@ -56,7 +56,7 @@ LL |     fn box_pin_ref_Self(self: Box<Pin<&mut Self>>, f: &u32) -> &u32 {
    |                                       |
    |                                       let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: aborting due to 6 previous errors
 
index 99340800790ecba516781cc31a6b2171271aa437..94671c7c87a5e516113ea7a986bf366ba70f3130 100644 (file)
@@ -6,7 +6,7 @@ LL |     async fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 {
    |                               |
    |                               let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-mut-struct-async.rs:17:9
@@ -16,7 +16,7 @@ LL |     async fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 {
    |                                       |
    |                                       let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-mut-struct-async.rs:21:9
@@ -26,7 +26,7 @@ LL |     async fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 {
    |                                       |
    |                                       let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-mut-struct-async.rs:25:9
@@ -36,7 +36,7 @@ LL |     async fn box_box_ref_Struct(self: Box<Box<&mut Struct>>, f: &u32) -> &u
    |                                               |
    |                                               let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-mut-struct-async.rs:29:9
@@ -46,7 +46,7 @@ LL |     async fn box_pin_ref_Struct(self: Box<Pin<&mut Struct>>, f: &u32) -> &u
    |                                               |
    |                                               let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: aborting due to 5 previous errors
 
index e3886444db2ad0500f443e22b01aa9c38dcd9eee..c9e7479ea5dff46a2154088e44e1c877a74837c5 100644 (file)
@@ -6,7 +6,7 @@ LL |     fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 {
    |                         |
    |                         let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-mut-struct.rs:15:9
@@ -16,7 +16,7 @@ LL |     fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 {
    |                                 |
    |                                 let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-mut-struct.rs:19:9
@@ -26,7 +26,7 @@ LL |     fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 {
    |                                 |
    |                                 let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-mut-struct.rs:23:9
@@ -36,7 +36,7 @@ LL |     fn box_box_ref_Struct(self: Box<Box<&mut Struct>>, f: &u32) -> &u32 {
    |                                         |
    |                                         let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-mut-struct.rs:27:9
@@ -46,7 +46,7 @@ LL |     fn box_pin_ref_Struct(self: Box<Pin<&mut Struct>>, f: &u32) -> &u32 {
    |                                         |
    |                                         let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: aborting due to 5 previous errors
 
index ecac1ce3378d6a72547ccba0f091f76eb421d92e..d1fd209102e6952454549b03a34501e1b54ca321 100644 (file)
@@ -6,7 +6,7 @@ LL |     fn ref_self(&self, f: &u32) -> &u32 {
    |                 |
    |                 let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-self.rs:27:9
@@ -16,7 +16,7 @@ LL |     fn ref_Self(self: &Self, f: &u32) -> &u32 {
    |                       |
    |                       let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-self.rs:31:9
@@ -26,7 +26,7 @@ LL |     fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
    |                               |
    |                               let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-self.rs:35:9
@@ -36,7 +36,7 @@ LL |     fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
    |                               |
    |                               let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-self.rs:39:9
@@ -46,7 +46,7 @@ LL |     fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
    |                                       |
    |                                       let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-self.rs:43:9
@@ -56,7 +56,7 @@ LL |     fn box_pin_ref_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
    |                                       |
    |                                       let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-self.rs:47:9
@@ -66,7 +66,7 @@ LL |     fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 {
    |                                      |
    |                                      let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: aborting due to 7 previous errors
 
index bcbf79bc039fde1c103393f16943cc3a674ce221..9361b6f3f81f429eb20393248016a3fcee3e6c9b 100644 (file)
@@ -6,7 +6,7 @@ LL |     async fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
    |                               |
    |                               let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-struct-async.rs:17:9
@@ -16,7 +16,7 @@ LL |     async fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 {
    |                                       |
    |                                       let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-struct-async.rs:21:9
@@ -26,7 +26,7 @@ LL |     async fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 {
    |                                       |
    |                                       let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-struct-async.rs:25:9
@@ -36,7 +36,7 @@ LL |     async fn box_box_ref_Struct(self: Box<Box<&Struct>>, f: &u32) -> &u32 {
    |                                               |
    |                                               let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-struct-async.rs:29:9
@@ -46,7 +46,7 @@ LL |     async fn box_pin_Struct(self: Box<Pin<&Struct>>, f: &u32) -> &u32 {
    |                                           |
    |                                           let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: aborting due to 5 previous errors
 
index 39e7631f31e7bd6c7efed1a817e8f560400ca57e..e1cc38b7c952f949b95ed227592ac40214e43e0d 100644 (file)
@@ -6,7 +6,7 @@ LL |     fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
    |                         |
    |                         let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-struct.rs:15:9
@@ -16,7 +16,7 @@ LL |     fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 {
    |                                 |
    |                                 let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-struct.rs:19:9
@@ -26,7 +26,7 @@ LL |     fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 {
    |                                 |
    |                                 let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-struct.rs:23:9
@@ -36,7 +36,7 @@ LL |     fn box_box_ref_Struct(self: Box<Box<&Struct>>, f: &u32) -> &u32 {
    |                                         |
    |                                         let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-struct.rs:27:9
@@ -46,7 +46,7 @@ LL |     fn box_pin_Struct(self: Box<Pin<&Struct>>, f: &u32) -> &u32 {
    |                                     |
    |                                     let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: aborting due to 5 previous errors
 
index cd8ec13794c6f13d6abe6df2c78bb1ea10c76d0a..2244f3a46b266b3e05851f5f4da883795993863b 100644 (file)
@@ -4,11 +4,16 @@ error[E0603]: module import `bar` is private
 LL |     use foo::bar::f as g;
    |              ^^^ this module import is private
    |
-note: the module import `bar` is defined here
+note: the module import `bar` is defined here...
   --> $DIR/shadowed-use-visibility.rs:4:9
    |
 LL |     use foo as bar;
    |         ^^^^^^^^^^
+note: ...and refers to the module `foo` which is defined here
+  --> $DIR/shadowed-use-visibility.rs:1:1
+   |
+LL | mod foo {
+   | ^^^^^^^
 
 error[E0603]: module import `f` is private
   --> $DIR/shadowed-use-visibility.rs:15:10
@@ -16,11 +21,16 @@ error[E0603]: module import `f` is private
 LL | use bar::f::f;
    |          ^ this module import is private
    |
-note: the module import `f` is defined here
+note: the module import `f` is defined here...
   --> $DIR/shadowed-use-visibility.rs:11:9
    |
 LL |     use foo as f;
    |         ^^^^^^^^
+note: ...and refers to the module `foo` which is defined here
+  --> $DIR/shadowed-use-visibility.rs:1:1
+   |
+LL | mod foo {
+   | ^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/span/auxiliary/transitive_dep_three.rs b/src/test/ui/span/auxiliary/transitive_dep_three.rs
new file mode 100644 (file)
index 0000000..99b5162
--- /dev/null
@@ -0,0 +1,9 @@
+#[macro_export]
+macro_rules! define_parse_error {
+    () => {
+        #[macro_export]
+        macro_rules! parse_error {
+            () => { parse error }
+        }
+    }
+}
diff --git a/src/test/ui/span/auxiliary/transitive_dep_two.rs b/src/test/ui/span/auxiliary/transitive_dep_two.rs
new file mode 100644 (file)
index 0000000..5110c42
--- /dev/null
@@ -0,0 +1,3 @@
+extern crate transitive_dep_three;
+
+transitive_dep_three::define_parse_error!();
diff --git a/src/test/ui/span/transitive-dep-span.rs b/src/test/ui/span/transitive-dep-span.rs
new file mode 100644 (file)
index 0000000..b445d38
--- /dev/null
@@ -0,0 +1,13 @@
+// Tests that we properly serialize/deserialize spans from transitive dependencies
+// (e.g. imported SourceFiles)
+//
+// The order of these next lines is important, since we need
+// transitive_dep_two.rs to be able to reference transitive_dep_three.rs
+//
+// aux-build: transitive_dep_three.rs
+// aux-build: transitive_dep_two.rs
+// compile-flags: -Z macro-backtrace
+
+extern crate transitive_dep_two;
+
+transitive_dep_two::parse_error!(); //~ ERROR expected one of
diff --git a/src/test/ui/span/transitive-dep-span.stderr b/src/test/ui/span/transitive-dep-span.stderr
new file mode 100644 (file)
index 0000000..68d8911
--- /dev/null
@@ -0,0 +1,19 @@
+error: expected one of `!` or `::`, found `error`
+  --> $DIR/auxiliary/transitive_dep_three.rs:6:27
+   |
+LL | /         macro_rules! parse_error {
+LL | |             () => { parse error }
+   | |                           ^^^^^ expected one of `!` or `::`
+LL | |         }
+   | |_________- in this expansion of `transitive_dep_two::parse_error!`
+   | 
+  ::: $DIR/transitive-dep-span.rs:13:1
+   |
+LL |   transitive_dep_two::parse_error!();
+   |   -----------------------------------
+   |   |
+   |   in this macro invocation
+   |   in this macro invocation
+
+error: aborting due to previous error
+
index 2b92f9b93bff202d649abff9553db97955d293ad..35d994e194f3f9ec4c3f119767ca98f866cbb318 100644 (file)
@@ -4,7 +4,7 @@ error[E0282]: type annotations needed
 LL |     let _ = (vec![1,2,3]).into_iter().sum() as f64;
    |                                       ^^^
    |                                       |
-   |                                       cannot infer type for type parameter `S` declared on the method `sum`
+   |                                       cannot infer type for type parameter `S` declared on the associated function `sum`
    |                                       help: consider specifying the type argument in the method call: `sum::<S>`
    |
    = note: type must be known at this point
index 03b1ef69ca0725c0016d4f5f13861a44d5586598..6e19d79e48f6b136e02150e6a6154c2cceb8fbb6 100644 (file)
@@ -1,8 +1,8 @@
 error: inherent impls cannot be `default`
-  --> $DIR/validation.rs:7:1
+  --> $DIR/validation.rs:7:14
    |
 LL | default impl S {}
-   | -------^^^^^^^
+   | -------      ^ inherent impl for this type
    | |
    | `default` because of this
    |
diff --git a/src/test/ui/specialization/min_specialization/auxiliary/specialization-trait.rs b/src/test/ui/specialization/min_specialization/auxiliary/specialization-trait.rs
new file mode 100644 (file)
index 0000000..6ec0d26
--- /dev/null
@@ -0,0 +1,6 @@
+#![feature(rustc_attrs)]
+
+#[rustc_specialization_trait]
+pub trait SpecTrait {
+    fn method(&self);
+}
diff --git a/src/test/ui/specialization/min_specialization/dyn-trait-assoc-types.rs b/src/test/ui/specialization/min_specialization/dyn-trait-assoc-types.rs
new file mode 100644 (file)
index 0000000..03cab00
--- /dev/null
@@ -0,0 +1,32 @@
+// Test that associated types in trait objects are not considered to be
+// constrained.
+
+#![feature(min_specialization)]
+
+trait Specializable {
+    fn f();
+}
+
+trait B<T> {
+    type Y;
+}
+
+trait C {
+    type Y;
+}
+
+impl<A: ?Sized> Specializable for A {
+    default fn f() {}
+}
+
+impl<'a, T> Specializable for dyn B<T, Y = T> + 'a {
+    //~^ ERROR specializing impl repeats parameter `T`
+    fn f() {}
+}
+
+impl<'a, T> Specializable for dyn C<Y = (T, T)> + 'a {
+    //~^ ERROR specializing impl repeats parameter `T`
+    fn f() {}
+}
+
+fn main() {}
diff --git a/src/test/ui/specialization/min_specialization/dyn-trait-assoc-types.stderr b/src/test/ui/specialization/min_specialization/dyn-trait-assoc-types.stderr
new file mode 100644 (file)
index 0000000..6345cee
--- /dev/null
@@ -0,0 +1,20 @@
+error: specializing impl repeats parameter `T`
+  --> $DIR/dyn-trait-assoc-types.rs:22:1
+   |
+LL | / impl<'a, T> Specializable for dyn B<T, Y = T> + 'a {
+LL | |
+LL | |     fn f() {}
+LL | | }
+   | |_^
+
+error: specializing impl repeats parameter `T`
+  --> $DIR/dyn-trait-assoc-types.rs:27:1
+   |
+LL | / impl<'a, T> Specializable for dyn C<Y = (T, T)> + 'a {
+LL | |
+LL | |     fn f() {}
+LL | | }
+   | |_^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/specialization/min_specialization/impl_specialization_trait.rs b/src/test/ui/specialization/min_specialization/impl_specialization_trait.rs
new file mode 100644 (file)
index 0000000..723ed71
--- /dev/null
@@ -0,0 +1,16 @@
+// Check that specialization traits can't be implemented without a feature.
+
+// gate-test-min_specialization
+
+// aux-build:specialization-trait.rs
+
+extern crate specialization_trait;
+
+struct A {}
+
+impl specialization_trait::SpecTrait for A {
+    //~^ ERROR implementing `rustc_specialization_trait` traits is unstable
+    fn method(&self) {}
+}
+
+fn main() {}
diff --git a/src/test/ui/specialization/min_specialization/impl_specialization_trait.stderr b/src/test/ui/specialization/min_specialization/impl_specialization_trait.stderr
new file mode 100644 (file)
index 0000000..934103d
--- /dev/null
@@ -0,0 +1,10 @@
+error: implementing `rustc_specialization_trait` traits is unstable
+  --> $DIR/impl_specialization_trait.rs:11:1
+   |
+LL | impl specialization_trait::SpecTrait for A {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add `#![feature(min_specialization)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/specialization/min_specialization/implcit-well-formed-bounds.rs b/src/test/ui/specialization/min_specialization/implcit-well-formed-bounds.rs
new file mode 100644 (file)
index 0000000..98d7f91
--- /dev/null
@@ -0,0 +1,30 @@
+// Test that specializing on the well-formed predicates of the trait and
+// self-type of an impl is allowed.
+
+// check-pass
+
+#![feature(min_specialization)]
+
+struct OrdOnly<T: Ord>(T);
+
+trait SpecTrait<U> {
+    fn f();
+}
+
+impl<T, U> SpecTrait<U> for T {
+    default fn f() {}
+}
+
+impl<T: Ord> SpecTrait<()> for OrdOnly<T> {
+    fn f() {}
+}
+
+impl<T: Ord> SpecTrait<OrdOnly<T>> for () {
+    fn f() {}
+}
+
+impl<T: Ord, U: Ord, V: Ord> SpecTrait<(OrdOnly<T>, OrdOnly<U>)> for &[OrdOnly<V>] {
+    fn f() {}
+}
+
+fn main() {}
diff --git a/src/test/ui/specialization/min_specialization/repeated_projection_type.rs b/src/test/ui/specialization/min_specialization/repeated_projection_type.rs
new file mode 100644 (file)
index 0000000..f21f39f
--- /dev/null
@@ -0,0 +1,24 @@
+// Test that projection bounds can't be specialized on.
+
+#![feature(min_specialization)]
+
+trait X {
+    fn f();
+}
+trait Id {
+    type This;
+}
+impl<T> Id for T {
+    type This = T;
+}
+
+impl<T: Id> X for T {
+    default fn f() {}
+}
+
+impl<I, V: Id<This = (I,)>> X for V {
+    //~^ ERROR cannot specialize on
+    fn f() {}
+}
+
+fn main() {}
diff --git a/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr b/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr
new file mode 100644 (file)
index 0000000..7cc4357
--- /dev/null
@@ -0,0 +1,11 @@
+error: cannot specialize on `Binder(ProjectionPredicate(ProjectionTy { substs: [V], item_def_id: DefId(0:6 ~ repeated_projection_type[317d]::Id[0]::This[0]) }, (I,)))`
+  --> $DIR/repeated_projection_type.rs:19:1
+   |
+LL | / impl<I, V: Id<This = (I,)>> X for V {
+LL | |
+LL | |     fn f() {}
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/specialization/min_specialization/repeating_lifetimes.rs b/src/test/ui/specialization/min_specialization/repeating_lifetimes.rs
new file mode 100644 (file)
index 0000000..49bface
--- /dev/null
@@ -0,0 +1,19 @@
+// Test that directly specializing on repeated lifetime parameters is not
+// allowed.
+
+#![feature(min_specialization)]
+
+trait X {
+    fn f();
+}
+
+impl<T> X for T {
+    default fn f() {}
+}
+
+impl<'a> X for (&'a u8, &'a u8) {
+    //~^ ERROR specializing impl repeats parameter `'a`
+    fn f() {}
+}
+
+fn main() {}
diff --git a/src/test/ui/specialization/min_specialization/repeating_lifetimes.stderr b/src/test/ui/specialization/min_specialization/repeating_lifetimes.stderr
new file mode 100644 (file)
index 0000000..ce9309f
--- /dev/null
@@ -0,0 +1,11 @@
+error: specializing impl repeats parameter `'a`
+  --> $DIR/repeating_lifetimes.rs:14:1
+   |
+LL | / impl<'a> X for (&'a u8, &'a u8) {
+LL | |
+LL | |     fn f() {}
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/specialization/min_specialization/repeating_param.rs b/src/test/ui/specialization/min_specialization/repeating_param.rs
new file mode 100644 (file)
index 0000000..5a1c97f
--- /dev/null
@@ -0,0 +1,17 @@
+// Test that specializing on two type parameters being equal is not allowed.
+
+#![feature(min_specialization)]
+
+trait X {
+    fn f();
+}
+
+impl<T> X for T {
+    default fn f() {}
+}
+impl<T> X for (T, T) {
+    //~^ ERROR specializing impl repeats parameter `T`
+    fn f() {}
+}
+
+fn main() {}
diff --git a/src/test/ui/specialization/min_specialization/repeating_param.stderr b/src/test/ui/specialization/min_specialization/repeating_param.stderr
new file mode 100644 (file)
index 0000000..8b4be1c
--- /dev/null
@@ -0,0 +1,11 @@
+error: specializing impl repeats parameter `T`
+  --> $DIR/repeating_param.rs:12:1
+   |
+LL | / impl<T> X for (T, T) {
+LL | |
+LL | |     fn f() {}
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/specialization/min_specialization/spec-iter.rs b/src/test/ui/specialization/min_specialization/spec-iter.rs
new file mode 100644 (file)
index 0000000..e17e9dd
--- /dev/null
@@ -0,0 +1,20 @@
+// Check that we can specialize on a concrete iterator type. This requires us
+// to consider which parameters in the parent impl are constrained.
+
+// check-pass
+
+#![feature(min_specialization)]
+
+trait SpecFromIter<T> {
+    fn f(&self);
+}
+
+impl<'a, T: 'a, I: Iterator<Item = &'a T>> SpecFromIter<T> for I {
+    default fn f(&self) {}
+}
+
+impl<'a, T> SpecFromIter<T> for std::slice::Iter<'a, T> {
+    fn f(&self) {}
+}
+
+fn main() {}
diff --git a/src/test/ui/specialization/min_specialization/spec-reference.rs b/src/test/ui/specialization/min_specialization/spec-reference.rs
new file mode 100644 (file)
index 0000000..377889e
--- /dev/null
@@ -0,0 +1,19 @@
+// Check that lifetime parameters are allowed in specializing impls.
+
+// check-pass
+
+#![feature(min_specialization)]
+
+trait MySpecTrait {
+    fn f();
+}
+
+impl<T> MySpecTrait for T {
+    default fn f() {}
+}
+
+impl<'a, T: ?Sized> MySpecTrait for &'a T {
+    fn f() {}
+}
+
+fn main() {}
diff --git a/src/test/ui/specialization/min_specialization/specialization_marker.rs b/src/test/ui/specialization/min_specialization/specialization_marker.rs
new file mode 100644 (file)
index 0000000..93462d0
--- /dev/null
@@ -0,0 +1,17 @@
+// Test that `rustc_unsafe_specialization_marker` is only allowed on marker traits.
+
+#![feature(rustc_attrs)]
+
+#[rustc_unsafe_specialization_marker]
+trait SpecMarker {
+    fn f();
+    //~^ ERROR marker traits
+}
+
+#[rustc_unsafe_specialization_marker]
+trait SpecMarker2 {
+    type X;
+    //~^ ERROR marker traits
+}
+
+fn main() {}
diff --git a/src/test/ui/specialization/min_specialization/specialization_marker.stderr b/src/test/ui/specialization/min_specialization/specialization_marker.stderr
new file mode 100644 (file)
index 0000000..ffeced1
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0714]: marker traits cannot have associated items
+  --> $DIR/specialization_marker.rs:7:5
+   |
+LL |     fn f();
+   |     ^^^^^^^
+
+error[E0714]: marker traits cannot have associated items
+  --> $DIR/specialization_marker.rs:13:5
+   |
+LL |     type X;
+   |     ^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0714`.
diff --git a/src/test/ui/specialization/min_specialization/specialization_super_trait.rs b/src/test/ui/specialization/min_specialization/specialization_super_trait.rs
new file mode 100644 (file)
index 0000000..145f376
--- /dev/null
@@ -0,0 +1,18 @@
+// Test that supertraits can't be assumed in impls of
+// `rustc_specialization_trait`, as such impls would
+// allow specializing on the supertrait.
+
+#![feature(min_specialization)]
+#![feature(rustc_attrs)]
+
+#[rustc_specialization_trait]
+trait SpecMarker: Default {
+    fn f();
+}
+
+impl<T: Default> SpecMarker for T {
+    //~^ ERROR cannot specialize
+    fn f() {}
+}
+
+fn main() {}
diff --git a/src/test/ui/specialization/min_specialization/specialization_super_trait.stderr b/src/test/ui/specialization/min_specialization/specialization_super_trait.stderr
new file mode 100644 (file)
index 0000000..154c839
--- /dev/null
@@ -0,0 +1,11 @@
+error: cannot specialize on trait `std::default::Default`
+  --> $DIR/specialization_super_trait.rs:13:1
+   |
+LL | / impl<T: Default> SpecMarker for T {
+LL | |
+LL | |     fn f() {}
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/specialization/min_specialization/specialization_trait.rs b/src/test/ui/specialization/min_specialization/specialization_trait.rs
new file mode 100644 (file)
index 0000000..d597278
--- /dev/null
@@ -0,0 +1,26 @@
+// Test that `rustc_specialization_trait` requires always applicable impls.
+
+#![feature(min_specialization)]
+#![feature(rustc_attrs)]
+
+#[rustc_specialization_trait]
+trait SpecMarker {
+    fn f();
+}
+
+impl SpecMarker for &'static u8 {
+    //~^ ERROR cannot specialize
+    fn f() {}
+}
+
+impl<T> SpecMarker for (T, T) {
+    //~^ ERROR specializing impl
+    fn f() {}
+}
+
+impl<T: Clone> SpecMarker for [T] {
+    //~^ ERROR cannot specialize
+    fn f() {}
+}
+
+fn main() {}
diff --git a/src/test/ui/specialization/min_specialization/specialization_trait.stderr b/src/test/ui/specialization/min_specialization/specialization_trait.stderr
new file mode 100644 (file)
index 0000000..4357d23
--- /dev/null
@@ -0,0 +1,29 @@
+error: cannot specialize on `'static` lifetime
+  --> $DIR/specialization_trait.rs:11:1
+   |
+LL | / impl SpecMarker for &'static u8 {
+LL | |
+LL | |     fn f() {}
+LL | | }
+   | |_^
+
+error: specializing impl repeats parameter `T`
+  --> $DIR/specialization_trait.rs:16:1
+   |
+LL | / impl<T> SpecMarker for (T, T) {
+LL | |
+LL | |     fn f() {}
+LL | | }
+   | |_^
+
+error: cannot specialize on trait `std::clone::Clone`
+  --> $DIR/specialization_trait.rs:21:1
+   |
+LL | / impl<T: Clone> SpecMarker for [T] {
+LL | |
+LL | |     fn f() {}
+LL | | }
+   | |_^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/specialization/min_specialization/specialize_on_marker.rs b/src/test/ui/specialization/min_specialization/specialize_on_marker.rs
new file mode 100644 (file)
index 0000000..4219bd1
--- /dev/null
@@ -0,0 +1,24 @@
+// Test that specializing on a `rustc_unsafe_specialization_marker` trait is
+// allowed.
+
+// check-pass
+
+#![feature(min_specialization)]
+#![feature(rustc_attrs)]
+
+#[rustc_unsafe_specialization_marker]
+trait SpecMarker {}
+
+trait X {
+    fn f();
+}
+
+impl<T> X for T {
+    default fn f() {}
+}
+
+impl<T: SpecMarker> X for T {
+    fn f() {}
+}
+
+fn main() {}
diff --git a/src/test/ui/specialization/min_specialization/specialize_on_spec_trait.rs b/src/test/ui/specialization/min_specialization/specialize_on_spec_trait.rs
new file mode 100644 (file)
index 0000000..abbab5c
--- /dev/null
@@ -0,0 +1,27 @@
+// Test that specializing on a `rustc_specialization_trait` trait is allowed.
+
+// check-pass
+
+#![feature(min_specialization)]
+#![feature(rustc_attrs)]
+
+#[rustc_specialization_trait]
+trait SpecTrait {
+    fn g(&self);
+}
+
+trait X {
+    fn f(&self);
+}
+
+impl<T> X for T {
+    default fn f(&self) {}
+}
+
+impl<T: SpecTrait> X for T {
+    fn f(&self) {
+        self.g();
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/specialization/min_specialization/specialize_on_static.rs b/src/test/ui/specialization/min_specialization/specialize_on_static.rs
new file mode 100644 (file)
index 0000000..dd1b054
--- /dev/null
@@ -0,0 +1,18 @@
+// Test that directly specializing on `'static` is not allowed.
+
+#![feature(min_specialization)]
+
+trait X {
+    fn f();
+}
+
+impl<T> X for &'_ T {
+    default fn f() {}
+}
+
+impl X for &'static u8 {
+    //~^ ERROR cannot specialize on `'static` lifetime
+    fn f() {}
+}
+
+fn main() {}
diff --git a/src/test/ui/specialization/min_specialization/specialize_on_static.stderr b/src/test/ui/specialization/min_specialization/specialize_on_static.stderr
new file mode 100644 (file)
index 0000000..d1809d6
--- /dev/null
@@ -0,0 +1,11 @@
+error: cannot specialize on `'static` lifetime
+  --> $DIR/specialize_on_static.rs:13:1
+   |
+LL | / impl X for &'static u8 {
+LL | |
+LL | |     fn f() {}
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/specialization/min_specialization/specialize_on_trait.rs b/src/test/ui/specialization/min_specialization/specialize_on_trait.rs
new file mode 100644 (file)
index 0000000..0588442
--- /dev/null
@@ -0,0 +1,20 @@
+// Test that specializing on a trait is not allowed in general.
+
+#![feature(min_specialization)]
+
+trait SpecMarker {}
+
+trait X {
+    fn f();
+}
+
+impl<T> X for T {
+    default fn f() {}
+}
+
+impl<T: SpecMarker> X for T {
+    //~^ ERROR cannot specialize on trait `SpecMarker`
+    fn f() {}
+}
+
+fn main() {}
diff --git a/src/test/ui/specialization/min_specialization/specialize_on_trait.stderr b/src/test/ui/specialization/min_specialization/specialize_on_trait.stderr
new file mode 100644 (file)
index 0000000..35445fd
--- /dev/null
@@ -0,0 +1,11 @@
+error: cannot specialize on trait `SpecMarker`
+  --> $DIR/specialize_on_trait.rs:15:1
+   |
+LL | / impl<T: SpecMarker> X for T {
+LL | |
+LL | |     fn f() {}
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
index b637037f60e8f6167e9a3a8c415d36cf4bd6cfc0..9ee59b320edcdd5727d87b3b7031246086e0145d 100644 (file)
@@ -6,5 +6,5 @@ fn new() -> S { S }
 }
 
 fn main() {
-    let _ = a::S::new();    //~ ERROR method `new` is private
+    let _ = a::S::new();    //~ ERROR associated function `new` is private
 }
index 14ca9f58301e2c9ec053d30bfc6f4684ecbf4326..78d211438cc920b84bb387c95924bda34e29c829 100644 (file)
@@ -1,4 +1,4 @@
-error[E0624]: method `new` is private
+error[E0624]: associated function `new` is private
   --> $DIR/static-method-privacy.rs:9:13
    |
 LL |     let _ = a::S::new();
index 10a119a628c704e19a8c51a6b7de96b449945051..c7c257ba5fe5386ace366ae430588704de0b3fb1 100644 (file)
@@ -4,7 +4,6 @@ error[E0658]: attributes starting with `rustc` are reserved for use by the `rust
 LL | #[rustc_err]
    |   ^^^^^^^^^
    |
-   = note: see issue #29642 <https://github.com/rust-lang/rust/issues/29642> for more information
    = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable
 
 error: cannot find attribute `rustc_err` in this scope
diff --git a/src/test/ui/suggestions/const-in-struct-pat.rs b/src/test/ui/suggestions/const-in-struct-pat.rs
new file mode 100644 (file)
index 0000000..1cbba93
--- /dev/null
@@ -0,0 +1,11 @@
+#[allow(non_camel_case_types)]
+struct foo;
+struct Thing {
+    foo: String,
+}
+
+fn example(t: Thing) {
+    let Thing { foo } = t; //~ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/const-in-struct-pat.stderr b/src/test/ui/suggestions/const-in-struct-pat.stderr
new file mode 100644 (file)
index 0000000..0a010dc
--- /dev/null
@@ -0,0 +1,16 @@
+error[E0308]: mismatched types
+  --> $DIR/const-in-struct-pat.rs:8:17
+   |
+LL | struct foo;
+   | ----------- unit struct defined here
+...
+LL |     let Thing { foo } = t;
+   |                 ^^^     - this expression has type `Thing`
+   |                 |
+   |                 expected struct `std::string::String`, found struct `foo`
+   |                 `foo` is interpreted as a unit struct, not a new binding
+   |                 help: bind the struct field to a different name instead: `foo: other_foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
index 99200a965dd2160b58e2f3d43e8d0324ba0340f4..6b79697e9839e1947c11e1a04e4f16285d4ff51e 100644 (file)
@@ -43,4 +43,4 @@ fn main() {}
 static mut SM = "abc";
 //~^ ERROR missing type for `static mut` item
 //~| HELP provide a type for the item
-//~| SUGGESTION &'static str
+//~| SUGGESTION &str
index c4f17109dc5c75e48c558bbaa7c3e54268c45e87..a7b5aa5e5b124397475ba3e421d4942d8427c6b0 100644 (file)
@@ -14,7 +14,7 @@ error: missing type for `static mut` item
   --> $DIR/const-no-type.rs:43:12
    |
 LL | static mut SM = "abc";
-   |            ^^ help: provide a type for the item: `SM: &'static str`
+   |            ^^ help: provide a type for the item: `SM: &str`
 
 error: missing type for `const` item
   --> $DIR/const-no-type.rs:14:7
index a715c565946e041ca5ff7926b0180415f498f51e..c343071ac3e0c27ee9e56e0c9ed5a02e6ba16264 100644 (file)
@@ -5,19 +5,19 @@ LL | struct Foo;
    | ----------- method `bat` not found for this
 ...
 LL |     f.bat(1.0);
-   |       ^^^ help: there is a method with a similar name: `bar`
+   |       ^^^ help: there is an associated function with a similar name: `bar`
 
 error[E0599]: no method named `is_emtpy` found for struct `std::string::String` in the current scope
   --> $DIR/suggest-methods.rs:21:15
    |
 LL |     let _ = s.is_emtpy();
-   |               ^^^^^^^^ help: there is a method with a similar name: `is_empty`
+   |               ^^^^^^^^ help: there is an associated function with a similar name: `is_empty`
 
 error[E0599]: no method named `count_eos` found for type `u32` in the current scope
   --> $DIR/suggest-methods.rs:25:19
    |
 LL |     let _ = 63u32.count_eos();
-   |                   ^^^^^^^^^ help: there is a method with a similar name: `count_zeros`
+   |                   ^^^^^^^^^ help: there is an associated function with a similar name: `count_zeros`
 
 error[E0599]: no method named `count_o` found for type `u32` in the current scope
   --> $DIR/suggest-methods.rs:28:19
index ed76377278b8270220c6986ae82be3d16c367670..5d4c1b354f700614cb27649b367962a9f5dc471c 100644 (file)
@@ -1,8 +1,8 @@
 error[E0658]: negative trait bounds are not yet fully implemented; use marker types for now
-  --> $DIR/syntax-trait-polarity-feature-gate.rs:7:1
+  --> $DIR/syntax-trait-polarity-feature-gate.rs:7:6
    |
 LL | impl !Send for TestType {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |      ^^^^^
    |
    = note: see issue #13231 <https://github.com/rust-lang/rust/issues/13231> for more information
    = help: add `#![feature(optin_builtin_traits)]` to the crate attributes to enable
index fef3a65088855df8fc32db0b11704f7fbc931549..5777e0ade908eb315ecf16ab0b6311ab9b747f57 100644 (file)
@@ -1,29 +1,35 @@
 error: inherent impls cannot be negative
-  --> $DIR/syntax-trait-polarity.rs:7:1
+  --> $DIR/syntax-trait-polarity.rs:7:7
    |
 LL | impl !TestType {}
-   | ^^^^^^^^^^^^^^^^^
+   |      -^^^^^^^^ inherent impl for this type
+   |      |
+   |      negative because of this
 
 error[E0198]: negative impls cannot be unsafe
-  --> $DIR/syntax-trait-polarity.rs:12:1
+  --> $DIR/syntax-trait-polarity.rs:12:13
    |
 LL | unsafe impl !Send for TestType {}
-   | ------^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   | |
+   | ------      -^^^^
+   | |           |
+   | |           negative because of this
    | unsafe because of this
 
 error: inherent impls cannot be negative
-  --> $DIR/syntax-trait-polarity.rs:19:1
+  --> $DIR/syntax-trait-polarity.rs:19:10
    |
 LL | impl<T> !TestType2<T> {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^
+   |         -^^^^^^^^^^^^ inherent impl for this type
+   |         |
+   |         negative because of this
 
 error[E0198]: negative impls cannot be unsafe
-  --> $DIR/syntax-trait-polarity.rs:22:1
+  --> $DIR/syntax-trait-polarity.rs:22:16
    |
 LL | unsafe impl<T> !Send for TestType2<T> {}
-   | ------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   | |
+   | ------         -^^^^
+   | |              |
+   | |              negative because of this
    | unsafe because of this
 
 error[E0192]: negative impls are only allowed for auto traits (e.g., `Send` and `Sync`)
diff --git a/src/test/ui/test-panic-while-printing.rs b/src/test/ui/test-panic-while-printing.rs
new file mode 100644 (file)
index 0000000..23f4540
--- /dev/null
@@ -0,0 +1,24 @@
+// compile-flags:--test
+// run-pass
+// ignore-emscripten no subprocess support
+
+use std::fmt;
+use std::fmt::{Display, Formatter};
+
+pub struct A(Vec<u32>);
+
+impl Display for A {
+    fn fmt(&self, _f: &mut Formatter<'_>) -> fmt::Result {
+        self.0[0];
+        Ok(())
+    }
+}
+
+#[test]
+fn main() {
+    let result = std::panic::catch_unwind(|| {
+        let a = A(vec![]);
+        eprintln!("{}", a);
+    });
+    assert!(result.is_err());
+}
index d12834084e7140fea0204913b644870c2731988b..743e4b658c6b7a5daca671ec39d1b4ec2838e06e 100644 (file)
@@ -4,7 +4,6 @@ error[E0658]: diagnostic items compiler internal support for linting
 LL | #[rustc_diagnostic_item = "foomp"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: see issue #29642 <https://github.com/rust-lang/rust/issues/29642> for more information
    = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable
 
 error: aborting due to previous error
index 8507d8ef17e3649c9204b442b9d7a253b0440c07..1ea1d65df627ce676c86db77ec75578b27d7bb4f 100644 (file)
@@ -69,7 +69,7 @@ fn check_method() {
     S.c(); // OK
     // a, b, c are resolved as inherent items, their traits don't need to be in scope
     let c = &S as &dyn C;
-    c.a(); //~ ERROR method `a` is private
+    c.a(); //~ ERROR associated function `a` is private
     c.b(); // OK
     c.c(); // OK
 
@@ -81,7 +81,7 @@ fn check_method() {
     //~^ ERROR no function or associated item named `b` found
     S::c(&S); // OK
     // a, b, c are resolved as inherent items, their traits don't need to be in scope
-    C::a(&S); //~ ERROR method `a` is private
+    C::a(&S); //~ ERROR associated function `a` is private
     C::b(&S); // OK
     C::c(&S); // OK
 }
index 2c0591c95f69086b4ccdae985aeeefb2af479df4..4b40c6405c47b25d7c3f8add939a468789aeee09 100644 (file)
@@ -36,7 +36,7 @@ help: the following trait is implemented but not in scope; perhaps add a `use` f
 LL | use method::B;
    |
 
-error[E0624]: method `a` is private
+error[E0624]: associated function `a` is private
   --> $DIR/trait-item-privacy.rs:72:7
    |
 LL |     c.a();
@@ -73,7 +73,7 @@ help: the following trait is implemented but not in scope; perhaps add a `use` f
 LL | use method::B;
    |
 
-error[E0624]: method `a` is private
+error[E0624]: associated function `a` is private
   --> $DIR/trait-item-privacy.rs:84:5
    |
 LL |     C::a(&S);
index 10552acb348bee424b40958ffcafc35d14ad4b4a..035c1ea092b291efa79255136f41ad2a7c4864a5 100644 (file)
@@ -1,4 +1,4 @@
-error[E0624]: method `method` is private
+error[E0624]: associated function `method` is private
   --> $DIR/trait-method-private.rs:19:9
    |
 LL |     foo.method();
index c398785d3949ec13b314db720fbc8ea55ec385e9..0738d2973e2d7585ff28efa876e207ac43eaf0a4 100644 (file)
@@ -1,14 +1,10 @@
 error[E0197]: inherent impls cannot be unsafe
-  --> $DIR/trait-safety-inherent-impl.rs:5:1
+  --> $DIR/trait-safety-inherent-impl.rs:5:13
    |
-LL |   unsafe impl SomeStruct {
-   |   ^-----
-   |   |
-   |  _unsafe because of this
+LL | unsafe impl SomeStruct {
+   | ------      ^^^^^^^^^^ inherent impl for this type
    | |
-LL | |     fn foo(self) { }
-LL | | }
-   | |_^
+   | unsafe because of this
 
 error: aborting due to previous error
 
index 63182a6bd95813290d685296e044ec295acd8eb4..a83ff3701511d8e608e57e39d993d71a7b41a552 100644 (file)
@@ -1,8 +1,10 @@
 error[E0568]: auto traits cannot have super traits
-  --> $DIR/traits-inductive-overflow-supertrait-oibit.rs:7:1
+  --> $DIR/traits-inductive-overflow-supertrait-oibit.rs:7:19
    |
 LL | auto trait Magic: Copy {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |            -----  ^^^^ help: remove the super traits
+   |            |
+   |            auto trait cannot have super traits
 
 error[E0277]: the trait bound `NoClone: std::marker::Copy` is not satisfied
   --> $DIR/traits-inductive-overflow-supertrait-oibit.rs:15:23
index c72876e050f057d0b45be2e00719433cbe7c8d78..4e781318329bf0dd0c4cf925b290d132269564df 100644 (file)
@@ -4,8 +4,7 @@ error[E0512]: cannot transmute between types of different sizes, or dependently-
 LL |     transmute(x)
    |     ^^^^^^^^^
    |
-   = note: source type: `<C as TypeConstructor<'a>>::T` (size can vary because of <C as TypeConstructor>::T)
-   = note: target type: `<C as TypeConstructor<'b>>::T` (size can vary because of <C as TypeConstructor>::T)
+   = note: `<C as TypeConstructor>::T` does not have a fixed size
 
 error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
   --> $DIR/main.rs:20:17
diff --git a/src/test/ui/type-alias-impl-trait/issue-55099-lifetime-inference.rs b/src/test/ui/type-alias-impl-trait/issue-55099-lifetime-inference.rs
new file mode 100644 (file)
index 0000000..8e8508c
--- /dev/null
@@ -0,0 +1,28 @@
+// check-pass
+// Regression test for issue #55099
+// Tests that we don't incorrectly consider a lifetime to part
+// of the concrete type
+
+#![feature(type_alias_impl_trait)]
+
+trait Future {
+}
+
+struct AndThen<F>(F);
+
+impl<F> Future for AndThen<F> {
+}
+
+struct Foo<'a> {
+    x: &'a mut (),
+}
+
+type F = impl Future;
+
+impl<'a> Foo<'a> {
+    fn reply(&mut self) -> F {
+        AndThen(|| ())
+    }
+}
+
+fn main() {}
index 4ba778d53ac08a2fb4bca339155cd1d38c58a950..af6d5010920173c815a265894666c9f27eec5d47 100644 (file)
@@ -6,7 +6,7 @@
 
 use std::marker::PhantomData;
 
-/* copied Index and TryFrom for convinience (and simplicity) */
+/* copied Index and TryFrom for convenience (and simplicity) */
 trait MyIndex<T> {
     type O;
     fn my_index(self) -> Self::O;
index 2f844b4a05f5f6bc884a35b0ee2ad11b8b3a6c85..7da0b049264c298b610c3a29ed1809dff125bf0f 100644 (file)
@@ -1,6 +1,6 @@
 // check-pass
 // Regression test for issue #67844
-// Ensures that we properly handle nested TAIT occurences
+// Ensures that we properly handle nested TAIT occurrences
 // with generic parameters
 
 #![feature(type_alias_impl_trait)]
index b9258b20f5addebb58e9bea0231ecd6a688d2afa..24122e658679a39df43f7d7b81b45b7e37d4d9ac 100644 (file)
@@ -4,7 +4,7 @@ error[E0282]: type annotations needed
 LL |         .or_else(|err| {
    |          ^^^^^^^
    |          |
-   |          cannot infer type for type parameter `F` declared on the method `or_else`
+   |          cannot infer type for type parameter `F` declared on the associated function `or_else`
    |          help: consider specifying the type arguments in the method call: `or_else::<F, O>`
 
 error: aborting due to previous error
index e74c0dfa5e20c8e1e316e0ef29982c68e8be0339..bb108adcd64af53d4568c5d31888ab4e024a3914 100644 (file)
@@ -4,7 +4,7 @@ error[E0282]: type annotations needed
 LL |     lst.sort_by_key(|&(v, _)| v.iter().sum());
    |         ^^^^^^^^^^^                    --- help: consider specifying the type argument in the method call: `sum::<S>`
    |         |
-   |         cannot infer type for type parameter `K` declared on the method `sort_by_key`
+   |         cannot infer type for type parameter `K` declared on the associated function `sort_by_key`
 
 error: aborting due to previous error
 
index b53bfe5df03f3c16f5902667260f9499a134b799..8d6fd2abb6d5f133fb2f85f79d5ace8c28ca75e0 100644 (file)
@@ -2,5 +2,7 @@
 
 fn main() {
     println!("{}", std::mem:size_of::<BTreeMap<u32, u32>>());
-    //~^ ERROR expected one of
+    //~^ ERROR casts cannot be followed by a function call
+    //~| ERROR expected value, found module `std::mem` [E0423]
+    //~| ERROR cannot find type `size_of` in this scope [E0412]
 }
index 7127f67cd7dde71c3f7d7adcb34ee67b1566892f..fdf35700ef94cf278af823c94ad56a0ff24495fa 100644 (file)
@@ -1,13 +1,31 @@
-error: expected one of `!`, `,`, or `::`, found `(`
-  --> $DIR/issue-54516.rs:4:58
+error: casts cannot be followed by a function call
+  --> $DIR/issue-54516.rs:4:20
    |
 LL |     println!("{}", std::mem:size_of::<BTreeMap<u32, u32>>());
-   |                            -                             ^ expected one of `!`, `,`, or `::`
+   |                    ^^^^^^^^-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |                            |
    |                            help: maybe write a path separator here: `::`
    |
    = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `<expr>: <type>`
    = note: see issue #23416 <https://github.com/rust-lang/rust/issues/23416> for more information
 
-error: aborting due to previous error
+error[E0423]: expected value, found module `std::mem`
+  --> $DIR/issue-54516.rs:4:20
+   |
+LL |     println!("{}", std::mem:size_of::<BTreeMap<u32, u32>>());
+   |                    ^^^^^^^^- help: maybe you meant to write a path separator here: `::`
+   |                    |
+   |                    not a value
+
+error[E0412]: cannot find type `size_of` in this scope
+  --> $DIR/issue-54516.rs:4:29
+   |
+LL |     println!("{}", std::mem:size_of::<BTreeMap<u32, u32>>());
+   |                            -^^^^^^^ not found in this scope
+   |                            |
+   |                            help: maybe you meant to write a path separator here: `::`
+
+error: aborting due to 3 previous errors
 
+Some errors have detailed explanations: E0412, E0423.
+For more information about an error, try `rustc --explain E0412`.
index 8fb06c887bd3e7a16a332717fb881702f95e94e2..bcf9f88cb414b0ac93d260d555d8bd2cf0e54864 100644 (file)
@@ -1,4 +1,6 @@
 fn main() {
     let u: usize = std::mem:size_of::<u32>();
-    //~^ ERROR expected one of
+    //~^ ERROR casts cannot be followed by a function call
+    //~| ERROR expected value, found module `std::mem` [E0423]
+    //~| ERROR cannot find type `size_of` in this scope [E0412]
 }
index 7130767b6c6f3ee9ff7a81524660e8981d4adc1a..cd9ae8f49f4f1e8c7406bc91ff44b99a2d50d158 100644 (file)
@@ -1,13 +1,31 @@
-error: expected one of `!`, `::`, or `;`, found `(`
-  --> $DIR/issue-60933.rs:2:43
+error: casts cannot be followed by a function call
+  --> $DIR/issue-60933.rs:2:20
    |
 LL |     let u: usize = std::mem:size_of::<u32>();
-   |                            -              ^ expected one of `!`, `::`, or `;`
+   |                    ^^^^^^^^-^^^^^^^^^^^^^^
    |                            |
    |                            help: maybe write a path separator here: `::`
    |
    = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `<expr>: <type>`
    = note: see issue #23416 <https://github.com/rust-lang/rust/issues/23416> for more information
 
-error: aborting due to previous error
+error[E0423]: expected value, found module `std::mem`
+  --> $DIR/issue-60933.rs:2:20
+   |
+LL |     let u: usize = std::mem:size_of::<u32>();
+   |                    ^^^^^^^^- help: maybe you meant to write a path separator here: `::`
+   |                    |
+   |                    not a value
+
+error[E0412]: cannot find type `size_of` in this scope
+  --> $DIR/issue-60933.rs:2:29
+   |
+LL |     let u: usize = std::mem:size_of::<u32>();
+   |                            -^^^^^^^ not found in this scope
+   |                            |
+   |                            help: maybe you meant to write a path separator here: `::`
+
+error: aborting due to 3 previous errors
 
+Some errors have detailed explanations: E0412, E0423.
+For more information about an error, try `rustc --explain E0412`.
index c57e8149574c94d3b2b90b050c1e9ce7de83f5cd..7bf151514c3dd35a997622abd879ad0b00e49a2e 100644 (file)
@@ -1,4 +1,4 @@
-// Fix issue 52082: Confusing error if accidentially defining a type paramter with the same name as
+// Fix issue 52082: Confusing error if accidentally defining a type parameter with the same name as
 // an existing type
 //
 // To this end, make sure that when trying to retrieve a field of a (reference to) type parameter,
index 8755bcded9d2fc07161d6f459845348f4d00a02c..e3976293277549ae8972901670efa6ef51ca37e2 100644 (file)
@@ -1,8 +1,10 @@
 error[E0568]: auto traits cannot have super traits
-  --> $DIR/typeck-auto-trait-no-supertraits-2.rs:3:1
+  --> $DIR/typeck-auto-trait-no-supertraits-2.rs:3:20
    |
 LL | auto trait Magic : Sized where Option<Self> : Magic {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |            -----   ^^^^^ help: remove the super traits
+   |            |
+   |            auto trait cannot have super traits
 
 error: aborting due to previous error
 
index 5a38883490959d3cd8941cca5ccfe575c6ca4859..b1602e3642ecb4d190f0736c2be7c6f7bdc19aa3 100644 (file)
@@ -1,8 +1,10 @@
 error[E0568]: auto traits cannot have super traits
-  --> $DIR/typeck-auto-trait-no-supertraits.rs:27:1
+  --> $DIR/typeck-auto-trait-no-supertraits.rs:27:19
    |
 LL | auto trait Magic: Copy {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |            -----  ^^^^ help: remove the super traits
+   |            |
+   |            auto trait cannot have super traits
 
 error: aborting due to previous error
 
index f2d02f70f4a667247b07b11c5350f273e8844db4..dc86ab30dfe415a3a067627339659ae25c0a8a8f 100644 (file)
@@ -70,7 +70,7 @@ LL | static TEST3: _ = "test";
    |               ^
    |               |
    |               not allowed in type signatures
-   |               help: replace `_` with the correct type: `&'static str`
+   |               help: replace `_` with the correct type: `&str`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item.rs:15:15
@@ -232,7 +232,7 @@ LL |     static FN_TEST3: _ = "test";
    |                      ^
    |                      |
    |                      not allowed in type signatures
-   |                      help: replace `_` with the correct type: `&'static str`
+   |                      help: replace `_` with the correct type: `&str`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item.rs:88:22
index e8c767b13e9cf8a39918b53195c9584e5fa32836..e6470aa6d64f07d82110e9b503cbe8ca7d011327 100644 (file)
@@ -49,8 +49,8 @@ fn main() {
     <u8 as Tr::Y>::NN; //~ ERROR cannot find method or associated constant `NN` in `Tr::Y`
     <u8 as E::Y>::NN; //~ ERROR failed to resolve: `Y` is a variant, not a module
 
-    let _: <u8 as Dr>::Z; //~ ERROR expected associated type, found method `Dr::Z`
+    let _: <u8 as Dr>::Z; //~ ERROR expected associated type, found associated function `Dr::Z`
     <u8 as Dr>::X; //~ ERROR expected method or associated constant, found associated type `Dr::X`
-    let _: <u8 as Dr>::Z::N; //~ ERROR expected associated type, found method `Dr::Z`
+    let _: <u8 as Dr>::Z::N; //~ ERROR expected associated type, found associated function `Dr::Z`
     <u8 as Dr>::X::N; //~ ERROR no associated item named `N` found for type `u16`
 }
index e5e6ed9fac91142b6b804a293acd86d181d32cea..7177ca4908545c64f554f4c94bd1c33023c54866 100644 (file)
@@ -35,10 +35,10 @@ error[E0576]: cannot find method or associated constant `N` in trait `Tr`
   --> $DIR/ufcs-partially-resolved.rs:22:17
    |
 LL |     fn Y() {}
-   |     --------- similarly named method `Y` defined here
+   |     --------- similarly named associated function `Y` defined here
 ...
 LL |     <u8 as Tr>::N;
-   |                 ^ help: a method with a similar name exists: `Y`
+   |                 ^ help: an associated function with a similar name exists: `Y`
 
 error[E0576]: cannot find method or associated constant `N` in enum `E`
   --> $DIR/ufcs-partially-resolved.rs:23:16
@@ -166,7 +166,7 @@ error[E0576]: cannot find method or associated constant `NN` in `Tr::Y`
 LL |     <u8 as Tr::Y>::NN;
    |                    ^^ not found in `Tr::Y`
 
-error[E0575]: expected associated type, found method `Dr::Z`
+error[E0575]: expected associated type, found associated function `Dr::Z`
   --> $DIR/ufcs-partially-resolved.rs:52:12
    |
 LL |     type X = u16;
@@ -181,16 +181,16 @@ error[E0575]: expected method or associated constant, found associated type `Dr:
   --> $DIR/ufcs-partially-resolved.rs:53:5
    |
 LL |     fn Z() {}
-   |     --------- similarly named method `Z` defined here
+   |     --------- similarly named associated function `Z` defined here
 ...
 LL |     <u8 as Dr>::X;
    |     ^^^^^^^^^^^^-
    |                 |
-   |                 help: a method with a similar name exists: `Z`
+   |                 help: an associated function with a similar name exists: `Z`
    |
    = note: can't use a type alias as a constructor
 
-error[E0575]: expected associated type, found method `Dr::Z`
+error[E0575]: expected associated type, found associated function `Dr::Z`
   --> $DIR/ufcs-partially-resolved.rs:54:12
    |
 LL |     type X = u16;
index 13e0c3681fa0070b3990cb9fb8c7dc0bd7b274ad..895f33638f95aa0154beb2036b78494bf56ed9ea 100644 (file)
@@ -1,10 +1,11 @@
 error: expected `{`, found `std`
   --> $DIR/unsafe-block-without-braces.rs:3:9
    |
-LL |     unsafe //{
-   |           - expected `{`
 LL |         std::mem::transmute::<f32, u32>(1.0);
-   |         ^^^ unexpected token
+   |         ^^^----------------------------------
+   |         |
+   |         expected `{`
+   |         help: try placing this code inside a block: `{ std::mem::transmute::<f32, u32>(1.0); }`
 
 error: aborting due to previous error
 
index 41c2d3c43e9755876479b64a91dc5116781eebdb..34bf22034265cc12a69031040d35444f6da0e4b3 100644 (file)
@@ -1,4 +1,4 @@
-// Check that array elemen types must be Sized. Issue #25692.
+// Check that array element types must be Sized. Issue #25692.
 
 
 #![allow(dead_code)]
index e95cab93d750e4781e9481250c45def6825bae7b..f05994646b3c489bb1882db2dd605457225856f8 100644 (file)
@@ -4,8 +4,8 @@
 
 fn main() {
     let _ = xc_private_method_lib::Struct::static_meth_struct();
-    //~^ ERROR: method `static_meth_struct` is private
+    //~^ ERROR: associated function `static_meth_struct` is private
 
     let _ = xc_private_method_lib::Enum::static_meth_enum();
-    //~^ ERROR: method `static_meth_enum` is private
+    //~^ ERROR: associated function `static_meth_enum` is private
 }
index 91bec2551c1e0655b1215365e3728305b2435752..6a68bef90efd7a80349c6e530d54b44920d98e32 100644 (file)
@@ -1,10 +1,10 @@
-error[E0624]: method `static_meth_struct` is private
+error[E0624]: associated function `static_meth_struct` is private
   --> $DIR/xc-private-method.rs:6:13
    |
 LL |     let _ = xc_private_method_lib::Struct::static_meth_struct();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0624]: method `static_meth_enum` is private
+error[E0624]: associated function `static_meth_enum` is private
   --> $DIR/xc-private-method.rs:9:13
    |
 LL |     let _ = xc_private_method_lib::Enum::static_meth_enum();
index f11b251082bf2ed8abea4cb1c5260ea8fd474edb..92946923f6e70ae0d04cc6c4ea18a09287811742 100644 (file)
@@ -4,8 +4,8 @@
 
 fn main() {
     let _ = xc_private_method_lib::Struct{ x: 10 }.meth_struct();
-    //~^ ERROR method `meth_struct` is private
+    //~^ ERROR associated function `meth_struct` is private
 
     let _ = xc_private_method_lib::Enum::Variant1(20).meth_enum();
-    //~^ ERROR method `meth_enum` is private
+    //~^ ERROR associated function `meth_enum` is private
 }
index 36ad850fb19198f3ba047096d9f3247272624a3c..84a8b9817c0d076f79d8e9b711259918bd1dbe71 100644 (file)
@@ -1,10 +1,10 @@
-error[E0624]: method `meth_struct` is private
+error[E0624]: associated function `meth_struct` is private
   --> $DIR/xc-private-method2.rs:6:52
    |
 LL |     let _ = xc_private_method_lib::Struct{ x: 10 }.meth_struct();
    |                                                    ^^^^^^^^^^^
 
-error[E0624]: method `meth_enum` is private
+error[E0624]: associated function `meth_enum` is private
   --> $DIR/xc-private-method2.rs:9:55
    |
 LL |     let _ = xc_private_method_lib::Enum::Variant1(20).meth_enum();
index e57bd02999c9f40d52116e0beca7d1dccb0643de..7019b3ed3d539db7429d10a343b69be8c426b576 160000 (submodule)
@@ -1 +1 @@
-Subproject commit e57bd02999c9f40d52116e0beca7d1dccb0643de
+Subproject commit 7019b3ed3d539db7429d10a343b69be8c426b576
index fc5d0cc583cb1cd35d58fdb7f3e0cfa12dccd6c0..23549a8c362a403026432f65a6cb398cb10d44b7 160000 (submodule)
@@ -1 +1 @@
-Subproject commit fc5d0cc583cb1cd35d58fdb7f3e0cfa12dccd6c0
+Subproject commit 23549a8c362a403026432f65a6cb398cb10d44b7
index c3d699b3e23071efcf0481b5306ba2650f48259c..8f685fb8559f5a7d834b5fbddc85f120e2431ed3 100644 (file)
@@ -125,7 +125,7 @@ fn parse_expected(
     let captures = RE.captures(line)?;
 
     match (cfg, captures.name("cfgs")) {
-        // Only error messages that contain our `cfg` betweeen the square brackets apply to us.
+        // Only error messages that contain our `cfg` between the square brackets apply to us.
         (Some(cfg), Some(filter)) if !filter.as_str().split(',').any(|s| s == cfg) => return None,
         (Some(_), Some(_)) => {}
 
index 38fa778219de23e14d469bcda9ca37e4d74a4b20..6c478f7e29da479e2078f3c995ca2c0c45710372 100644 (file)
@@ -109,6 +109,24 @@ fn no_system_llvm() {
     assert!(parse_rs(&config, "// no-system-llvm").ignore);
 }
 
+#[test]
+fn llvm_version() {
+    let mut config = config();
+
+    config.llvm_version = Some("8.1.2-rust".to_owned());
+    assert!(parse_rs(&config, "// min-llvm-version 9.0").ignore);
+
+    config.llvm_version = Some("9.0.1-rust-1.43.0-dev".to_owned());
+    assert!(parse_rs(&config, "// min-llvm-version 9.2").ignore);
+
+    config.llvm_version = Some("9.3.1-rust-1.43.0-dev".to_owned());
+    assert!(!parse_rs(&config, "// min-llvm-version 9.2").ignore);
+
+    // FIXME.
+    // config.llvm_version = Some("10.0.0-rust".to_owned());
+    // assert!(!parse_rs(&config, "// min-llvm-version 9.0").ignore);
+}
+
 #[test]
 fn ignore_target() {
     let mut config = config();
index ac808b1f14e13eb3431c06bf4459e5d2ac5e154c..b04012af515ddad35e66572dc98995bbc62c069a 100644 (file)
@@ -1487,7 +1487,7 @@ fn compile_test_general(
                 // can turn it back on if needed.
                 if !self.is_rustdoc()
                     // Note that we use the local pass mode here as we don't want
-                    // to set unused to allow if we've overriden the pass mode
+                    // to set unused to allow if we've overridden the pass mode
                     // via command line flags.
                     && local_pm != Some(PassMode::Run)
                 {
@@ -2779,7 +2779,7 @@ fn run_js_doc_test(&self) {
                 Command::new(&nodejs)
                     .arg(root.join("src/tools/rustdoc-js/tester.js"))
                     .arg(out_dir.parent().expect("no parent"))
-                    .arg(&self.testpaths.file.file_stem().expect("couldn't get file stem")),
+                    .arg(self.testpaths.file.with_extension("js")),
             );
             if !res.status.success() {
                 self.fatal_proc_rec("rustdoc-js test failed!", &res);
@@ -3204,7 +3204,9 @@ fn normalize_output(&self, output: &str, custom_rules: &[(String, String)]) -> S
         let json = cflags.contains("--error-format json")
             || cflags.contains("--error-format pretty-json")
             || cflags.contains("--error-format=json")
-            || cflags.contains("--error-format=pretty-json");
+            || cflags.contains("--error-format=pretty-json")
+            || cflags.contains("--output-format json")
+            || cflags.contains("--output-format=json");
 
         let mut normalized = output.to_string();
 
index 3c444bf6a6cff3b9014005f21cc44995b34862ce..0ff05c4cfe534321b194bf3bedf028df92ef519c 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 3c444bf6a6cff3b9014005f21cc44995b34862ce
+Subproject commit 0ff05c4cfe534321b194bf3bedf028df92ef519c
index 5fbb986286ade77da32c45f7d50dce3f51143396..b389cd0373cc4da052b52f36660472b1f98089a9 100755 (executable)
@@ -1,11 +1,10 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
-# This script publishes the new "current" toolstate in the toolstate repo (not to be
-# confused with publishing the test results, which happens in
-# `src/ci/docker/x86_64-gnu-tools/checktools.sh`).
-# It is set as callback for `src/ci/docker/x86_64-gnu-tools/repo.sh` by the CI scripts
-# when a new commit lands on `master` (i.e., after it passed all checks on `auto`).
+# This script computes the new "current" toolstate for the toolstate repo (not to be
+# confused with publishing the test results, which happens in `src/bootstrap/toolstate.rs`).
+# It gets called from `src/ci/publish_toolstate.sh` when a new commit lands on `master`
+# (i.e., after it passed all checks on `auto`).
 
 from __future__ import print_function
 
index d5f0ab9f4292d56ab4508c1b27b1a697e1d3323c..08930ff1227970b3ba1ef965cf0b4a8924b5399b 100644 (file)
@@ -1,6 +1,5 @@
 const fs = require('fs');
-
-const TEST_FOLDER = 'src/test/rustdoc-js-std/';
+const path = require('path');
 
 function getNextStep(content, pos, stop) {
     while (pos < content.length && content[pos] !== stop &&
@@ -246,17 +245,16 @@ function readFileMatching(dir, name, extension) {
 }
 
 function main(argv) {
-    if (argv.length !== 3) {
-        console.error("Expected toolchain to check as argument (for example \
-                       'x86_64-apple-darwin')");
+    if (argv.length !== 4) {
+        console.error("USAGE: node tester.js STD_DOCS TEST_FOLDER");
         return 1;
     }
-    var toolchain = argv[2];
+    var std_docs = argv[2];
+    var test_folder = argv[3];
 
-    var mainJs = readFileMatching("build/" + toolchain + "/doc/", "main", ".js");
-    var ALIASES = readFileMatching("build/" + toolchain + "/doc/", "aliases", ".js");
-    var searchIndex = readFileMatching("build/" + toolchain + "/doc/",
-                                       "search-index", ".js").split("\n");
+    var mainJs = readFileMatching(std_docs, "main", ".js");
+    var ALIASES = readFileMatching(std_docs, "aliases", ".js");
+    var searchIndex = readFileMatching(std_docs, "search-index", ".js").split("\n");
     if (searchIndex[searchIndex.length - 1].length === 0) {
         searchIndex.pop();
     }
@@ -265,7 +263,7 @@ function main(argv) {
     finalJS = "";
 
     var arraysToLoad = ["itemTypes"];
-    var variablesToLoad = ["MAX_LEV_DISTANCE", "MAX_RESULTS",
+    var variablesToLoad = ["MAX_LEV_DISTANCE", "MAX_RESULTS", "NO_TYPE_FILTER",
                            "GENERICS_DATA", "NAME", "INPUTS_DATA", "OUTPUT_DATA",
                            "TY_PRIMITIVE", "TY_KEYWORD",
                            "levenshtein_row2"];
@@ -287,8 +285,8 @@ function main(argv) {
 
     var errors = 0;
 
-    fs.readdirSync(TEST_FOLDER).forEach(function(file) {
-        var loadedFile = loadContent(readFile(TEST_FOLDER + file) +
+    fs.readdirSync(test_folder).forEach(function(file) {
+        var loadedFile = loadContent(readFile(path.join(test_folder, file)) +
                                'exports.QUERY = QUERY;exports.EXPECTED = EXPECTED;');
         const expected = loadedFile.EXPECTED;
         const query = loadedFile.QUERY;
@@ -338,7 +336,7 @@ function main(argv) {
             console.log("OK");
         }
     });
-    return errors;
+    return errors > 0 ? 1 : 0;
 }
 
 process.exit(main(process.argv));
index 833ce5d1370471f8544f8d23353477abc5f80c37..143e1a7480d3da3aa5836940c3f79fc86cf2c076 100644 (file)
@@ -1,8 +1,7 @@
 const fs = require('fs');
+const path = require('path');
 const { spawnSync } = require('child_process');
 
-const TEST_FOLDER = 'src/test/rustdoc-js/';
-
 function getNextStep(content, pos, stop) {
     while (pos < content.length && content[pos] !== stop &&
            (content[pos] === ' ' || content[pos] === '\t' || content[pos] === '\n')) {
@@ -232,7 +231,7 @@ function load_files(out_folder, crate) {
     finalJS = "";
 
     var arraysToLoad = ["itemTypes"];
-    var variablesToLoad = ["MAX_LEV_DISTANCE", "MAX_RESULTS",
+    var variablesToLoad = ["MAX_LEV_DISTANCE", "MAX_RESULTS", "NO_TYPE_FILTER",
                            "GENERICS_DATA", "NAME", "INPUTS_DATA", "OUTPUT_DATA",
                            "TY_PRIMITIVE", "TY_KEYWORD",
                            "levenshtein_row2"];
@@ -266,10 +265,11 @@ function main(argv) {
     var errors = 0;
 
     for (var j = 3; j < argv.length; ++j) {
-        const test_name = argv[j];
+        const test_file = argv[j];
+        const test_name = path.basename(test_file, ".js");
 
         process.stdout.write('Checking "' + test_name + '" ... ');
-        if (!fs.existsSync(TEST_FOLDER + test_name + ".js")) {
+        if (!fs.existsSync(test_file)) {
             errors += 1;
             console.error("FAILED");
             console.error("==> Missing '" + test_name + ".js' file...");
@@ -279,7 +279,7 @@ function main(argv) {
         const test_out_folder = out_folder + test_name;
 
         var [loaded, index] = load_files(test_out_folder, test_name);
-        var loadedFile = loadContent(readFile(TEST_FOLDER + test_name + ".js") +
+        var loadedFile = loadContent(readFile(test_file) +
                                'exports.QUERY = QUERY;exports.EXPECTED = EXPECTED;');
         const expected = loadedFile.EXPECTED;
         const query = loadedFile.QUERY;
@@ -328,7 +328,7 @@ function main(argv) {
             console.log("OK");
         }
     }
-    return errors;
+    return errors > 0 ? 1 : 0;
 }
 
 process.exit(main(process.argv));
index 43cae31f33f1faf76f29f762861446f67f4ea422..f984e5b61a5fd5462c812f52abd275763af7c830 100644 (file)
@@ -5,8 +5,7 @@ authors = ["Alex Crichton <alex@alexcrichton.com>"]
 edition = "2018"
 
 [dependencies]
+cargo_metadata = "0.9.1"
 regex = "1"
-serde = { version = "1.0.8", features = ["derive"] }
-serde_json = "1.0.2"
 lazy_static = "1"
 walkdir = "2"
index 7a20a96130ccb5429bf86ffed167264fc9b5f4f6..1ffc415fb2497cc146c9114011a6fde66849c167 100644 (file)
@@ -1,13 +1,11 @@
-//! Checks the licenses of third-party dependencies by inspecting vendors.
+//! Checks the licenses of third-party dependencies.
 
-use std::collections::{BTreeSet, HashMap, HashSet};
-use std::fs;
+use cargo_metadata::{Metadata, Package, PackageId, Resolve};
+use std::collections::{BTreeSet, HashSet};
 use std::path::Path;
-use std::process::Command;
-
-use serde::Deserialize;
-use serde_json;
 
+/// These are licenses that are allowed for all crates, including the runtime,
+/// rustc, tools, etc.
 const LICENSES: &[&str] = &[
     "MIT/Apache-2.0",
     "MIT / Apache-2.0",
 /// should be considered bugs. Exceptions are only allowed in Rust
 /// tooling. It is _crucial_ that no exception crates be dependencies
 /// of the Rust runtime (std/test).
-const EXCEPTIONS: &[&str] = &[
-    "mdbook",             // MPL2, mdbook
-    "openssl",            // BSD+advertising clause, cargo, mdbook
-    "pest",               // MPL2, mdbook via handlebars
-    "arrayref",           // BSD-2-Clause, mdbook via handlebars via pest
-    "thread-id",          // Apache-2.0, mdbook
-    "toml-query",         // MPL-2.0, mdbook
-    "is-match",           // MPL-2.0, mdbook
-    "cssparser",          // MPL-2.0, rustdoc
-    "smallvec",           // MPL-2.0, rustdoc
-    "rdrand",             // ISC, mdbook, rustfmt
-    "fuchsia-cprng",      // BSD-3-Clause, mdbook, rustfmt
-    "fuchsia-zircon-sys", // BSD-3-Clause, rustdoc, rustc, cargo
-    "fuchsia-zircon",     // BSD-3-Clause, rustdoc, rustc, cargo (jobserver & tempdir)
-    "cssparser-macros",   // MPL-2.0, rustdoc
-    "selectors",          // MPL-2.0, rustdoc
-    "clippy_lints",       // MPL-2.0, rls
-    "colored",            // MPL-2.0, rustfmt
-    "ordslice",           // Apache-2.0, rls
-    "cloudabi",           // BSD-2-Clause, (rls -> crossbeam-channel 0.2 -> rand 0.5)
-    "ryu",                // Apache-2.0, rls/cargo/... (because of serde)
-    "bytesize",           // Apache-2.0, cargo
-    "im-rc",              // MPL-2.0+, cargo
-    "adler32",            // BSD-3-Clause AND Zlib, cargo dep that isn't used
-    "constant_time_eq",   // CC0-1.0, rustfmt
-    "utf8parse",          // Apache-2.0 OR MIT, cargo via strip-ansi-escapes
-    "vte",                // Apache-2.0 OR MIT, cargo via strip-ansi-escapes
-    "sized-chunks",       // MPL-2.0+, cargo via im-rc
-    "bitmaps",            // MPL-2.0+, cargo via im-rc
+const EXCEPTIONS: &[(&str, &str)] = &[
+    ("mdbook", "MPL-2.0"),                  // mdbook
+    ("openssl", "Apache-2.0"),              // cargo, mdbook
+    ("arrayref", "BSD-2-Clause"),           // mdbook via handlebars via pest
+    ("toml-query", "MPL-2.0"),              // mdbook
+    ("toml-query_derive", "MPL-2.0"),       // mdbook
+    ("is-match", "MPL-2.0"),                // mdbook
+    ("rdrand", "ISC"),                      // mdbook, rustfmt
+    ("fuchsia-cprng", "BSD-3-Clause"),      // mdbook, rustfmt
+    ("fuchsia-zircon-sys", "BSD-3-Clause"), // rustdoc, rustc, cargo
+    ("fuchsia-zircon", "BSD-3-Clause"),     // rustdoc, rustc, cargo (jobserver & tempdir)
+    ("colored", "MPL-2.0"),                 // rustfmt
+    ("ordslice", "Apache-2.0"),             // rls
+    ("cloudabi", "BSD-2-Clause"),           // (rls -> crossbeam-channel 0.2 -> rand 0.5)
+    ("ryu", "Apache-2.0 OR BSL-1.0"),       // rls/cargo/... (because of serde)
+    ("bytesize", "Apache-2.0"),             // cargo
+    ("im-rc", "MPL-2.0+"),                  // cargo
+    ("adler32", "BSD-3-Clause AND Zlib"),   // cargo dep that isn't used
+    ("constant_time_eq", "CC0-1.0"),        // rustfmt
+    ("sized-chunks", "MPL-2.0+"),           // cargo via im-rc
+    ("bitmaps", "MPL-2.0+"),                // cargo via im-rc
     // FIXME: this dependency violates the documentation comment above:
-    "fortanix-sgx-abi",   // MPL-2.0+, libstd but only for `sgx` target
-    "dunce",              // CC0-1.0 mdbook-linkcheck
-    "codespan-reporting", // Apache-2.0 mdbook-linkcheck
-    "codespan",           // Apache-2.0 mdbook-linkcheck
-    "crossbeam-channel",  // MIT/Apache-2.0 AND BSD-2-Clause, cargo
+    ("fortanix-sgx-abi", "MPL-2.0"), // libstd but only for `sgx` target
+    ("dunce", "CC0-1.0"),            // mdbook-linkcheck
+    ("codespan-reporting", "Apache-2.0"), // mdbook-linkcheck
+    ("codespan", "Apache-2.0"),      // mdbook-linkcheck
+    ("crossbeam-channel", "MIT/Apache-2.0 AND BSD-2-Clause"), // cargo
 ];
 
+/// These are the root crates that are part of the runtime. The licenses for
+/// these and all their dependencies *must not* be in the exception list.
+const RUNTIME_CRATES: &[&str] = &["std", "core", "alloc", "test", "panic_abort", "panic_unwind"];
+
 /// Which crates to check against the whitelist?
-const WHITELIST_CRATES: &[CrateVersion<'_>] =
-    &[CrateVersion("rustc", "0.0.0"), CrateVersion("rustc_codegen_llvm", "0.0.0")];
+const WHITELIST_CRATES: &[&str] = &["rustc", "rustc_codegen_llvm"];
 
 /// Whitelist of crates rustc is allowed to depend on. Avoid adding to the list if possible.
-const WHITELIST: &[Crate<'_>] = &[
-    Crate("adler32"),
-    Crate("aho-corasick"),
-    Crate("annotate-snippets"),
-    Crate("ansi_term"),
-    Crate("arrayvec"),
-    Crate("atty"),
-    Crate("autocfg"),
-    Crate("backtrace"),
-    Crate("backtrace-sys"),
-    Crate("bitflags"),
-    Crate("build_const"),
-    Crate("byteorder"),
-    Crate("c2-chacha"),
-    Crate("cc"),
-    Crate("cfg-if"),
-    Crate("chalk-engine"),
-    Crate("chalk-macros"),
-    Crate("cloudabi"),
-    Crate("cmake"),
-    Crate("compiler_builtins"),
-    Crate("crc"),
-    Crate("crc32fast"),
-    Crate("crossbeam-deque"),
-    Crate("crossbeam-epoch"),
-    Crate("crossbeam-queue"),
-    Crate("crossbeam-utils"),
-    Crate("datafrog"),
-    Crate("dlmalloc"),
-    Crate("either"),
-    Crate("ena"),
-    Crate("env_logger"),
-    Crate("filetime"),
-    Crate("flate2"),
-    Crate("fortanix-sgx-abi"),
-    Crate("fuchsia-zircon"),
-    Crate("fuchsia-zircon-sys"),
-    Crate("getopts"),
-    Crate("getrandom"),
-    Crate("hashbrown"),
-    Crate("humantime"),
-    Crate("indexmap"),
-    Crate("itertools"),
-    Crate("jobserver"),
-    Crate("kernel32-sys"),
-    Crate("lazy_static"),
-    Crate("libc"),
-    Crate("libz-sys"),
-    Crate("lock_api"),
-    Crate("log"),
-    Crate("log_settings"),
-    Crate("measureme"),
-    Crate("memchr"),
-    Crate("memmap"),
-    Crate("memoffset"),
-    Crate("miniz-sys"),
-    Crate("miniz_oxide"),
-    Crate("miniz_oxide_c_api"),
-    Crate("nodrop"),
-    Crate("num_cpus"),
-    Crate("owning_ref"),
-    Crate("parking_lot"),
-    Crate("parking_lot_core"),
-    Crate("pkg-config"),
-    Crate("polonius-engine"),
-    Crate("ppv-lite86"),
-    Crate("proc-macro2"),
-    Crate("punycode"),
-    Crate("quick-error"),
-    Crate("quote"),
-    Crate("rand"),
-    Crate("rand_chacha"),
-    Crate("rand_core"),
-    Crate("rand_hc"),
-    Crate("rand_isaac"),
-    Crate("rand_pcg"),
-    Crate("rand_xorshift"),
-    Crate("redox_syscall"),
-    Crate("redox_termios"),
-    Crate("regex"),
-    Crate("regex-syntax"),
-    Crate("remove_dir_all"),
-    Crate("rustc-demangle"),
-    Crate("rustc-hash"),
-    Crate("rustc-rayon"),
-    Crate("rustc-rayon-core"),
-    Crate("rustc_version"),
-    Crate("scoped-tls"),
-    Crate("scopeguard"),
-    Crate("semver"),
-    Crate("semver-parser"),
-    Crate("serde"),
-    Crate("serde_derive"),
-    Crate("smallvec"),
-    Crate("stable_deref_trait"),
-    Crate("syn"),
-    Crate("synstructure"),
-    Crate("tempfile"),
-    Crate("termcolor"),
-    Crate("terminon"),
-    Crate("termion"),
-    Crate("termize"),
-    Crate("thread_local"),
-    Crate("ucd-util"),
-    Crate("unicode-normalization"),
-    Crate("unicode-script"),
-    Crate("unicode-security"),
-    Crate("unicode-width"),
-    Crate("unicode-xid"),
-    Crate("unreachable"),
-    Crate("utf8-ranges"),
-    Crate("vcpkg"),
-    Crate("version_check"),
-    Crate("void"),
-    Crate("wasi"),
-    Crate("winapi"),
-    Crate("winapi-build"),
-    Crate("winapi-i686-pc-windows-gnu"),
-    Crate("winapi-util"),
-    Crate("winapi-x86_64-pc-windows-gnu"),
-    Crate("wincolor"),
-    Crate("hermit-abi"),
+///
+/// This list is here to provide a speed-bump to adding a new dependency to
+/// rustc. Please check with the compiler team before adding an entry.
+const WHITELIST: &[&str] = &[
+    "adler32",
+    "aho-corasick",
+    "annotate-snippets",
+    "ansi_term",
+    "arrayvec",
+    "atty",
+    "autocfg",
+    "backtrace",
+    "backtrace-sys",
+    "bitflags",
+    "byteorder",
+    "c2-chacha",
+    "cc",
+    "cfg-if",
+    "cloudabi",
+    "cmake",
+    "compiler_builtins",
+    "crc32fast",
+    "crossbeam-deque",
+    "crossbeam-epoch",
+    "crossbeam-queue",
+    "crossbeam-utils",
+    "datafrog",
+    "dlmalloc",
+    "either",
+    "ena",
+    "env_logger",
+    "filetime",
+    "flate2",
+    "fortanix-sgx-abi",
+    "fuchsia-zircon",
+    "fuchsia-zircon-sys",
+    "getopts",
+    "getrandom",
+    "hashbrown",
+    "hermit-abi",
+    "humantime",
+    "indexmap",
+    "itertools",
+    "jobserver",
+    "kernel32-sys",
+    "lazy_static",
+    "libc",
+    "libz-sys",
+    "lock_api",
+    "log",
+    "log_settings",
+    "measureme",
+    "memchr",
+    "memmap",
+    "memoffset",
+    "miniz_oxide",
+    "nodrop",
+    "num_cpus",
+    "parking_lot",
+    "parking_lot_core",
+    "pkg-config",
+    "polonius-engine",
+    "ppv-lite86",
+    "proc-macro2",
+    "punycode",
+    "quick-error",
+    "quote",
+    "rand",
+    "rand_chacha",
+    "rand_core",
+    "rand_hc",
+    "rand_isaac",
+    "rand_pcg",
+    "rand_xorshift",
+    "redox_syscall",
+    "redox_termios",
+    "regex",
+    "regex-syntax",
+    "remove_dir_all",
+    "rustc-demangle",
+    "rustc-hash",
+    "rustc-rayon",
+    "rustc-rayon-core",
+    "rustc_version",
+    "scoped-tls",
+    "scopeguard",
+    "semver",
+    "semver-parser",
+    "serde",
+    "serde_derive",
+    "smallvec",
+    "stable_deref_trait",
+    "syn",
+    "synstructure",
+    "tempfile",
+    "termcolor",
+    "termion",
+    "termize",
+    "thread_local",
+    "ucd-util",
+    "unicode-normalization",
+    "unicode-script",
+    "unicode-security",
+    "unicode-width",
+    "unicode-xid",
+    "utf8-ranges",
+    "vcpkg",
+    "version_check",
+    "wasi",
+    "winapi",
+    "winapi-build",
+    "winapi-i686-pc-windows-gnu",
+    "winapi-util",
+    "winapi-x86_64-pc-windows-gnu",
+    "wincolor",
 ];
 
-// Some types for Serde to deserialize the output of `cargo metadata` to.
-
-#[derive(Deserialize)]
-struct Output {
-    resolve: Resolve,
-}
-
-#[derive(Deserialize)]
-struct Resolve {
-    nodes: Vec<ResolveNode>,
-}
-
-#[derive(Deserialize)]
-struct ResolveNode {
-    id: String,
-    dependencies: Vec<String>,
-}
-
-/// A unique identifier for a crate.
-#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Debug, Hash)]
-struct Crate<'a>(&'a str); // (name)
-
-#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Debug, Hash)]
-struct CrateVersion<'a>(&'a str, &'a str); // (name, version)
-
-impl Crate<'_> {
-    pub fn id_str(&self) -> String {
-        format!("{} ", self.0)
-    }
-}
-
-impl<'a> CrateVersion<'a> {
-    /// Returns the struct and whether or not the dependency is in-tree.
-    pub fn from_str(s: &'a str) -> (Self, bool) {
-        let mut parts = s.split(' ');
-        let name = parts.next().unwrap();
-        let version = parts.next().unwrap();
-        let path = parts.next().unwrap();
-
-        let is_path_dep = path.starts_with("(path+");
-
-        (CrateVersion(name, version), is_path_dep)
-    }
-
-    pub fn id_str(&self) -> String {
-        format!("{} {}", self.0, self.1)
-    }
+/// Dependency checks.
+///
+/// `path` is path to the `src` directory, `cargo` is path to the cargo executable.
+pub fn check(path: &Path, cargo: &Path, bad: &mut bool) {
+    let mut cmd = cargo_metadata::MetadataCommand::new();
+    cmd.cargo_path(cargo)
+        .manifest_path(path.parent().unwrap().join("Cargo.toml"))
+        .features(cargo_metadata::CargoOpt::AllFeatures);
+    let metadata = t!(cmd.exec());
+    check_exceptions(&metadata, bad);
+    check_whitelist(&metadata, bad);
+    check_crate_duplicate(&metadata, bad);
 }
 
-impl<'a> From<CrateVersion<'a>> for Crate<'a> {
-    fn from(cv: CrateVersion<'a>) -> Crate<'a> {
-        Crate(cv.0)
+/// Check that all licenses are in the valid list in `LICENSES`.
+///
+/// Packages listed in `EXCEPTIONS` are allowed for tools.
+fn check_exceptions(metadata: &Metadata, bad: &mut bool) {
+    // Validate the EXCEPTIONS list hasn't changed.
+    for (name, license) in EXCEPTIONS {
+        // Check that the package actually exists.
+        if !metadata.packages.iter().any(|p| p.name == *name) {
+            println!(
+                "could not find exception package `{}`\n\
+                Remove from EXCEPTIONS list if it is no longer used.",
+                name
+            );
+            *bad = true;
+        }
+        // Check that the license hasn't changed.
+        for pkg in metadata.packages.iter().filter(|p| p.name == *name) {
+            if pkg.name == "fuchsia-cprng" {
+                // This package doesn't declare a license expression. Manual
+                // inspection of the license file is necessary, which appears
+                // to be BSD-3-Clause.
+                assert!(pkg.license.is_none());
+                continue;
+            }
+            match &pkg.license {
+                None => {
+                    println!(
+                        "dependency exception `{}` does not declare a license expression",
+                        pkg.id
+                    );
+                    *bad = true;
+                }
+                Some(pkg_license) => {
+                    if pkg_license.as_str() != *license {
+                        println!("dependency exception `{}` license has changed", name);
+                        println!("    previously `{}` now `{}`", license, pkg_license);
+                        println!("    update EXCEPTIONS for the new license");
+                        *bad = true;
+                    }
+                }
+            }
+        }
     }
-}
 
-/// Checks the dependency at the given path. Changes `bad` to `true` if a check failed.
-///
-/// Specifically, this checks that the license is correct.
-pub fn check(path: &Path, bad: &mut bool) {
-    // Check licences.
-    let path = path.join("../vendor");
-    assert!(path.exists(), "vendor directory missing");
-    let mut saw_dir = false;
-    for dir in t!(path.read_dir()) {
-        saw_dir = true;
-        let dir = t!(dir);
+    let exception_names: Vec<_> = EXCEPTIONS.iter().map(|(name, _license)| *name).collect();
+    let runtime_ids = compute_runtime_crates(metadata);
 
-        // Skip our exceptions.
-        let is_exception = EXCEPTIONS.iter().any(|exception| {
-            dir.path().to_str().unwrap().contains(&format!("vendor/{}", exception))
-        });
-        if is_exception {
+    // Check if any package does not have a valid license.
+    for pkg in &metadata.packages {
+        if pkg.source.is_none() {
+            // No need to check local packages.
             continue;
         }
-
-        let toml = dir.path().join("Cargo.toml");
-        *bad = !check_license(&toml) || *bad;
+        if !runtime_ids.contains(&pkg.id) && exception_names.contains(&pkg.name.as_str()) {
+            continue;
+        }
+        let license = match &pkg.license {
+            Some(license) => license,
+            None => {
+                println!("dependency `{}` does not define a license expression", pkg.id,);
+                *bad = true;
+                continue;
+            }
+        };
+        if !LICENSES.contains(&license.as_str()) {
+            if pkg.name == "fortanix-sgx-abi" {
+                // This is a specific exception because SGX is considered
+                // "third party". See
+                // https://github.com/rust-lang/rust/issues/62620 for more. In
+                // general, these should never be added.
+                continue;
+            }
+            println!("invalid license `{}` in `{}`", license, pkg.id);
+            *bad = true;
+        }
     }
-    assert!(saw_dir, "no vendored source");
 }
 
 /// Checks the dependency of `WHITELIST_CRATES` at the given path. Changes `bad` to `true` if a
 /// check failed.
 ///
 /// Specifically, this checks that the dependencies are on the `WHITELIST`.
-pub fn check_whitelist(path: &Path, cargo: &Path, bad: &mut bool) {
-    // Get dependencies from Cargo metadata.
-    let resolve = get_deps(path, cargo);
-
+fn check_whitelist(metadata: &Metadata, bad: &mut bool) {
+    // Check that the WHITELIST does not have unused entries.
+    for name in WHITELIST {
+        if !metadata.packages.iter().any(|p| p.name == *name) {
+            println!(
+                "could not find whitelisted package `{}`\n\
+                Remove from WHITELIST list if it is no longer used.",
+                name
+            );
+            *bad = true;
+        }
+    }
     // Get the whitelist in a convenient form.
     let whitelist: HashSet<_> = WHITELIST.iter().cloned().collect();
 
@@ -287,122 +292,59 @@ pub fn check_whitelist(path: &Path, cargo: &Path, bad: &mut bool) {
     let mut visited = BTreeSet::new();
     let mut unapproved = BTreeSet::new();
     for &krate in WHITELIST_CRATES.iter() {
-        let mut bad = check_crate_whitelist(&whitelist, &resolve, &mut visited, krate, false);
+        let pkg = pkg_from_name(metadata, krate);
+        let mut bad = check_crate_whitelist(&whitelist, metadata, &mut visited, pkg);
         unapproved.append(&mut bad);
     }
 
     if !unapproved.is_empty() {
         println!("Dependencies not on the whitelist:");
         for dep in unapproved {
-            println!("* {}", dep.id_str());
+            println!("* {}", dep);
         }
         *bad = true;
     }
-
-    check_crate_duplicate(&resolve, bad);
-}
-
-fn check_license(path: &Path) -> bool {
-    if !path.exists() {
-        panic!("{} does not exist", path.display());
-    }
-    let contents = t!(fs::read_to_string(&path));
-
-    let mut found_license = false;
-    for line in contents.lines() {
-        if !line.starts_with("license") {
-            continue;
-        }
-        let license = extract_license(line);
-        if !LICENSES.contains(&&*license) {
-            println!("invalid license {} in {}", license, path.display());
-            return false;
-        }
-        found_license = true;
-        break;
-    }
-    if !found_license {
-        println!("no license in {}", path.display());
-        return false;
-    }
-
-    true
-}
-
-fn extract_license(line: &str) -> String {
-    let first_quote = line.find('"');
-    let last_quote = line.rfind('"');
-    if let (Some(f), Some(l)) = (first_quote, last_quote) {
-        let license = &line[f + 1..l];
-        license.into()
-    } else {
-        "bad-license-parse".into()
-    }
-}
-
-/// Gets the dependencies of the crate at the given path using `cargo metadata`.
-fn get_deps(path: &Path, cargo: &Path) -> Resolve {
-    // Run `cargo metadata` to get the set of dependencies.
-    let output = Command::new(cargo)
-        .arg("metadata")
-        .arg("--format-version")
-        .arg("1")
-        .arg("--manifest-path")
-        .arg(path.join("../Cargo.toml"))
-        .output()
-        .expect("Unable to run `cargo metadata`")
-        .stdout;
-    let output = String::from_utf8_lossy(&output);
-    let output: Output = serde_json::from_str(&output).unwrap();
-
-    output.resolve
 }
 
 /// Checks the dependencies of the given crate from the given cargo metadata to see if they are on
 /// the whitelist. Returns a list of illegal dependencies.
 fn check_crate_whitelist<'a>(
-    whitelist: &'a HashSet<Crate<'_>>,
-    resolve: &'a Resolve,
-    visited: &mut BTreeSet<CrateVersion<'a>>,
-    krate: CrateVersion<'a>,
-    must_be_on_whitelist: bool,
-) -> BTreeSet<Crate<'a>> {
+    whitelist: &'a HashSet<&'static str>,
+    metadata: &'a Metadata,
+    visited: &mut BTreeSet<&'a PackageId>,
+    krate: &'a Package,
+) -> BTreeSet<&'a PackageId> {
     // This will contain bad deps.
     let mut unapproved = BTreeSet::new();
 
     // Check if we have already visited this crate.
-    if visited.contains(&krate) {
+    if visited.contains(&krate.id) {
         return unapproved;
     }
 
-    visited.insert(krate);
+    visited.insert(&krate.id);
 
     // If this path is in-tree, we don't require it to be on the whitelist.
-    if must_be_on_whitelist {
+    if krate.source.is_some() {
         // If this dependency is not on `WHITELIST`, add to bad set.
-        if !whitelist.contains(&krate.into()) {
-            unapproved.insert(krate.into());
+        if !whitelist.contains(krate.name.as_str()) {
+            unapproved.insert(&krate.id);
         }
     }
 
-    // Do a DFS in the crate graph (it's a DAG, so we know we have no cycles!).
-    let to_check = resolve
-        .nodes
-        .iter()
-        .find(|n| n.id.starts_with(&krate.id_str()))
-        .expect("crate does not exist");
+    // Do a DFS in the crate graph.
+    let to_check = deps_of(metadata, &krate.id);
 
-    for dep in to_check.dependencies.iter() {
-        let (krate, is_path_dep) = CrateVersion::from_str(dep);
-
-        let mut bad = check_crate_whitelist(whitelist, resolve, visited, krate, !is_path_dep);
+    for dep in to_check {
+        let mut bad = check_crate_whitelist(whitelist, metadata, visited, dep);
         unapproved.append(&mut bad);
     }
 
     unapproved
 }
 
-fn check_crate_duplicate(resolve: &Resolve, bad: &mut bool) {
+/// Prevents multiple versions of some expensive crates.
+fn check_crate_duplicate(metadata: &Metadata, bad: &mut bool) {
     const FORBIDDEN_TO_HAVE_DUPLICATES: &[&str] = &[
         // These two crates take quite a long time to build, so don't allow two versions of them
         // to accidentally sneak into our dependency graph, in order to ensure we keep our CI times
@@ -410,19 +352,97 @@ fn check_crate_duplicate(resolve: &Resolve, bad: &mut bool) {
         "cargo",
         "rustc-ap-syntax",
     ];
-    let mut name_to_id: HashMap<_, Vec<_>> = HashMap::new();
-    for node in resolve.nodes.iter() {
-        name_to_id.entry(node.id.split_whitespace().next().unwrap()).or_default().push(&node.id);
-    }
 
-    for name in FORBIDDEN_TO_HAVE_DUPLICATES {
-        if name_to_id[name].len() <= 1 {
-            continue;
-        }
-        println!("crate `{}` is duplicated in `Cargo.lock`", name);
-        for id in name_to_id[name].iter() {
-            println!("  * {}", id);
+    for &name in FORBIDDEN_TO_HAVE_DUPLICATES {
+        let matches: Vec<_> = metadata.packages.iter().filter(|pkg| pkg.name == name).collect();
+        match matches.len() {
+            0 => {
+                println!(
+                    "crate `{}` is missing, update `check_crate_duplicate` \
+                    if it is no longer used",
+                    name
+                );
+                *bad = true;
+            }
+            1 => {}
+            _ => {
+                println!(
+                    "crate `{}` is duplicated in `Cargo.lock`, \
+                    it is too expensive to build multiple times, \
+                    so make sure only one version appears across all dependencies",
+                    name
+                );
+                for pkg in matches {
+                    println!("  * {}", pkg.id);
+                }
+                *bad = true;
+            }
         }
-        *bad = true;
+    }
+}
+
+/// Returns a list of dependencies for the given package.
+fn deps_of<'a>(metadata: &'a Metadata, pkg_id: &'a PackageId) -> Vec<&'a Package> {
+    let resolve = metadata.resolve.as_ref().unwrap();
+    let node = resolve
+        .nodes
+        .iter()
+        .find(|n| &n.id == pkg_id)
+        .unwrap_or_else(|| panic!("could not find `{}` in resolve", pkg_id));
+    node.deps
+        .iter()
+        .map(|dep| {
+            metadata.packages.iter().find(|pkg| pkg.id == dep.pkg).unwrap_or_else(|| {
+                panic!("could not find dep `{}` for pkg `{}` in resolve", dep.pkg, pkg_id)
+            })
+        })
+        .collect()
+}
+
+/// Finds a package with the given name.
+fn pkg_from_name<'a>(metadata: &'a Metadata, name: &'static str) -> &'a Package {
+    let mut i = metadata.packages.iter().filter(|p| p.name == name);
+    let result =
+        i.next().unwrap_or_else(|| panic!("could not find package `{}` in package list", name));
+    assert!(i.next().is_none(), "more than one package found for `{}`", name);
+    result
+}
+
+/// Finds all the packages that are in the rust runtime.
+fn compute_runtime_crates<'a>(metadata: &'a Metadata) -> HashSet<&'a PackageId> {
+    let resolve = metadata.resolve.as_ref().unwrap();
+    let mut result = HashSet::new();
+    for name in RUNTIME_CRATES {
+        let id = &pkg_from_name(metadata, name).id;
+        normal_deps_of_r(resolve, id, &mut result);
+    }
+    result
+}
+
+/// Recursively find all normal dependencies.
+fn normal_deps_of_r<'a>(
+    resolve: &'a Resolve,
+    pkg_id: &'a PackageId,
+    result: &mut HashSet<&'a PackageId>,
+) {
+    if !result.insert(pkg_id) {
+        return;
+    }
+    let node = resolve
+        .nodes
+        .iter()
+        .find(|n| &n.id == pkg_id)
+        .unwrap_or_else(|| panic!("could not find `{}` in resolve", pkg_id));
+    // Don't care about dev-dependencies.
+    // Build dependencies *shouldn't* matter unless they do some kind of
+    // codegen. For now we'll assume they don't.
+    let deps = node.deps.iter().filter(|node_dep| {
+        node_dep
+            .dep_kinds
+            .iter()
+            .any(|kind_info| kind_info.kind == cargo_metadata::DependencyKind::Normal)
+    });
+    for dep in deps {
+        normal_deps_of_r(resolve, &dep.pkg, result);
     }
 }
index 12f93a87cb1729818bccf8636ef6f907441ed553..d9320e9147cffd31da018f866c6765d21b6f4621 100644 (file)
@@ -63,20 +63,6 @@ pub struct CollectedFeatures {
 pub fn collect_lib_features(base_src_path: &Path) -> Features {
     let mut lib_features = Features::new();
 
-    // This library feature is defined in the `compiler_builtins` crate, which
-    // has been moved out-of-tree. Now it can no longer be auto-discovered by
-    // `tidy`, because we need to filter out its (submodule) directory. Manually
-    // add it to the set of known library features so we can still generate docs.
-    lib_features.insert(
-        "compiler_builtins_lib".to_owned(),
-        Feature {
-            level: Status::Unstable,
-            since: None,
-            has_gate_test: false,
-            tracking_issue: None,
-        },
-    );
-
     map_lib_features(base_src_path, &mut |res, _, _| {
         if let Ok((name, feature)) = res {
             lib_features.insert(name.to_owned(), feature);
index ec8b14c288a2f10a4af400b61eca0ec6bc398fa7..e2856c690550abfd9d0c828649406a20590cf924 100644 (file)
@@ -1,8 +1,8 @@
 //! Tidy checks source code in this repository.
 //!
 //! This program runs all of the various tidy checks for style, cleanliness,
-//! etc. This is run by default on `make check` and as part of the auto
-//! builders.
+//! etc. This is run by default on `./x.py test` and as part of the auto
+//! builders. The tidy checks can be executed with `./x.py test tidy`.
 
 #![deny(warnings)]
 
@@ -30,10 +30,7 @@ fn main() {
     pal::check(&path, &mut bad);
     unstable_book::check(&path, collected, &mut bad);
     unit_tests::check(&path, &mut bad);
-    if !args.iter().any(|s| *s == "--no-vendor") {
-        deps::check(&path, &mut bad);
-    }
-    deps::check_whitelist(&path, &cargo, &mut bad);
+    deps::check(&path, &cargo, &mut bad);
     extdeps::check(&path, &mut bad);
     ui_tests::check(&path, &mut bad);
     error_codes_check::check(&path, &mut bad);
index f11394bd95f1f8cd5280887473751fae11fe6195..247e85603cfc2e2305db675ca0f45670231e6d73 100644 (file)
@@ -41,7 +41,7 @@
     "src/libpanic_unwind",
     "src/libunwind",
     // black_box implementation is LLVM-version specific and it uses
-    // target_os to tell targets with different LLVM-versions appart
+    // target_os to tell targets with different LLVM-versions apart
     // (e.g. `wasm32-unknown-emscripten` vs `wasm32-unknown-unknown`):
     "src/libcore/hint.rs",
     "src/libstd/sys/", // Platform-specific code for std lives here.
@@ -59,6 +59,8 @@
     "src/libstd/sys_common/mod.rs",
     "src/libstd/sys_common/net.rs",
     "src/libstd/sys_common/backtrace.rs",
+    // panic_unwind shims
+    "src/libstd/panicking.rs",
     "src/libterm", // Not sure how to make this crate portable, but test crate needs it.
     "src/libtest", // Probably should defer to unstable `std::sys` APIs.
     "src/libstd/sync/mpsc", // some tests are only run on non-emscripten
index 472d66459d724d9465300180630b1ef363b973c2..7dfb6224d240a69e54ba88400f36a8c39f628ad1 100644 (file)
@@ -1,4 +1,4 @@
-use crate::features::{CollectedFeatures, Feature, Features, Status};
+use crate::features::{CollectedFeatures, Features, Status};
 use std::collections::BTreeSet;
 use std::fs;
 use std::path::{Path, PathBuf};
@@ -73,26 +73,12 @@ fn collect_unstable_book_lib_features_section_file_names(base_src_path: &Path) -
 
 pub fn check(path: &Path, features: CollectedFeatures, bad: &mut bool) {
     let lang_features = features.lang;
-    let mut lib_features = features
+    let lib_features = features
         .lib
         .into_iter()
         .filter(|&(ref name, _)| !lang_features.contains_key(name))
         .collect::<Features>();
 
-    // This library feature is defined in the `compiler_builtins` crate, which
-    // has been moved out-of-tree. Now it can no longer be auto-discovered by
-    // `tidy`, because we need to filter out its (submodule) directory. Manually
-    // add it to the set of known library features so we can still generate docs.
-    lib_features.insert(
-        "compiler_builtins_lib".to_owned(),
-        Feature {
-            level: Status::Unstable,
-            since: None,
-            has_gate_test: false,
-            tracking_issue: None,
-        },
-    );
-
     // Library features
     let unstable_lib_feature_names = collect_unstable_feature_names(&lib_features);
     let unstable_book_lib_features_section_file_names =
index be8508e3973a2486bc6f1b43d58371a7f5bfa23d..839d914baa9548ee856e7913ad76bcc9894daa05 100644 (file)
@@ -147,7 +147,7 @@ fn main() {
         eprintln!("Must provide path to write unicode tables to");
         eprintln!(
             "e.g. {} src/libcore/unicode/unicode_data.rs",
-            std::env::args().nth(0).unwrap_or_default()
+            std::env::args().next().unwrap_or_default()
         );
         std::process::exit(1);
     });
index a174dd1e7f3fe4815de097037d36d160b8e2e23e..2476f414e0e0328407a65175a9f8a546d27d8855 100644 (file)
@@ -11,23 +11,25 @@ allow-unauthenticated = [
 [assign]
 
 [ping.icebreakers-llvm]
+alias = ["llvm", "llvms"]
 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
+[instructions]: https://rustc-dev-guide.rust-lang.org/ice-breaker/llvm.html
 """
 label = "ICEBreaker-LLVM"
 
 [ping.icebreakers-cleanup-crew]
+alias = ["cleanup", "cleanups", "cleanup-crew", "shrink", "reduce", "bisect"]
 message = """\
 Hey Cleanup Crew ICE-breakers! This bug has been identified as a good
 "Cleanup 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/cleanup-crew.html
+[instructions]: https://rustc-dev-guide.rust-lang.org/ice-breaker/cleanup-crew.html
 """
 label = "ICEBreaker-Cleanup-Crew"