]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #75780 - matklad:unconfuseunpindocs, r=KodrAus
authorDylan DPC <dylan.dpc@gmail.com>
Wed, 26 Aug 2020 23:14:06 +0000 (01:14 +0200)
committerGitHub <noreply@github.com>
Wed, 26 Aug 2020 23:14:06 +0000 (01:14 +0200)
Unconfuse Unpin docs a bit

* Don't say that Unpin is used to prevent moves, because it is used
  to *allow* moves
* Be more precise about kindedness of things, it is
  `Pin<Pointer<Data>>`, rather than just `Pin<Pointer>`.

499 files changed:
.github/workflows/ci.yml
.gitmodules
.mailmap
Cargo.lock
library/alloc/src/alloc.rs
library/alloc/src/boxed.rs
library/alloc/src/collections/binary_heap.rs
library/alloc/src/collections/linked_list.rs
library/alloc/src/fmt.rs
library/alloc/src/lib.rs
library/alloc/src/macros.rs
library/alloc/src/raw_vec.rs
library/alloc/src/rc.rs
library/alloc/src/slice.rs
library/alloc/src/string.rs
library/alloc/src/sync.rs
library/alloc/src/sync/tests.rs
library/core/src/alloc/layout.rs
library/core/src/alloc/mod.rs
library/core/src/array/mod.rs
library/core/src/char/mod.rs
library/core/src/cmp.rs
library/core/src/ffi.rs
library/core/src/fmt/mod.rs
library/core/src/intrinsics.rs
library/core/src/lib.rs
library/core/src/macros/mod.rs
library/core/src/mem/manually_drop.rs
library/core/src/mem/mod.rs
library/core/src/num/f32.rs
library/core/src/num/f64.rs
library/core/src/num/mod.rs
library/core/src/ops/deref.rs
library/core/src/ops/drop.rs
library/core/src/ops/function.rs
library/core/src/ops/index.rs
library/core/src/ops/mod.rs
library/core/src/ops/range.rs
library/core/src/ops/unsize.rs
library/core/src/pin.rs
library/core/src/ptr/const_ptr.rs
library/core/src/ptr/mut_ptr.rs
library/core/src/raw.rs
library/core/src/result.rs
library/core/src/str/mod.rs
library/core/src/str/pattern.rs
library/core/tests/ascii.rs
library/core/tests/lib.rs
library/core/tests/ptr.rs
library/core/tests/slice.rs
library/panic_abort/src/lib.rs
library/proc_macro/src/lib.rs
library/profiler_builtins/build.rs
library/std/src/alloc.rs
library/std/src/collections/mod.rs
library/std/src/error.rs
library/std/src/ffi/c_str.rs
library/std/src/fs.rs
library/std/src/io/mod.rs
library/std/src/io/stdio.rs
library/std/src/lazy.rs
library/std/src/lib.rs
library/std/src/macros.rs
library/std/src/net/addr.rs
library/std/src/net/ip.rs
library/std/src/os/linux/raw.rs
library/std/src/primitive_docs.rs
library/std/src/process.rs
library/std/src/sync/barrier.rs
library/std/src/sync/condvar.rs
library/std/src/sync/mpsc/mod.rs
library/std/src/sync/mutex.rs
library/std/src/sync/rwlock.rs
library/std/src/sys/cloudabi/stdio.rs
library/std/src/sys/hermit/stdio.rs
library/std/src/sys/sgx/stdio.rs
library/std/src/sys/unix/stdio.rs
library/std/src/sys/unsupported/stdio.rs
library/std/src/sys/vxworks/fd.rs
library/std/src/sys/vxworks/process/process_common.rs
library/std/src/sys/vxworks/stdio.rs
library/std/src/sys/vxworks/thread_local_dtor.rs
library/std/src/sys/wasi/stdio.rs
library/std/src/sys/windows/mod.rs
library/std/src/sys/windows/stdio.rs
library/std/src/sys/windows/stdio_uwp.rs
library/std/src/sys_common/net.rs
library/std/src/thread/local.rs
library/std/src/thread/mod.rs
library/test/src/stats.rs
src/bootstrap/cc_detect.rs
src/bootstrap/config.rs
src/bootstrap/dist.rs
src/bootstrap/doc.rs
src/bootstrap/flags.rs
src/bootstrap/format.rs
src/bootstrap/lib.rs
src/bootstrap/native.rs
src/bootstrap/test.rs
src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh
src/ci/docker/host-x86_64/x86_64-gnu-full-bootstrap/Dockerfile [deleted file]
src/ci/github-actions/ci.yml
src/ci/scripts/install-clang.sh
src/doc/rustdoc/src/unstable-features.md
src/doc/unstable-book/src/compiler-flags/control-flow-guard.md
src/librustc_ast/ast.rs
src/librustc_ast/mut_visit.rs
src/librustc_ast/token.rs
src/librustc_ast_lowering/item.rs
src/librustc_ast_lowering/lib.rs
src/librustc_ast_passes/feature_gate.rs
src/librustc_builtin_macros/deriving/generic/mod.rs
src/librustc_builtin_macros/global_allocator.rs
src/librustc_builtin_macros/test_harness.rs
src/librustc_codegen_llvm/asm.rs
src/librustc_codegen_ssa/base.rs
src/librustc_codegen_ssa/mir/block.rs
src/librustc_codegen_ssa/mir/rvalue.rs
src/librustc_expand/mbe.rs
src/librustc_expand/proc_macro_server.rs
src/librustc_feature/active.rs
src/librustc_hir/definitions.rs
src/librustc_hir/hir.rs
src/librustc_hir/lang_items.rs
src/librustc_hir/weak_lang_items.rs
src/librustc_infer/infer/error_reporting/mod.rs
src/librustc_infer/lib.rs
src/librustc_lexer/Cargo.toml
src/librustc_lexer/src/lib.rs
src/librustc_lexer/src/tests.rs
src/librustc_lint/builtin.rs
src/librustc_llvm/build.rs
src/librustc_metadata/dynamic_lib.rs
src/librustc_metadata/lib.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_metadata/rmeta/table.rs
src/librustc_middle/hir/map/mod.rs
src/librustc_middle/lib.rs
src/librustc_middle/middle/cstore.rs
src/librustc_middle/middle/lang_items.rs
src/librustc_middle/mir/mod.rs
src/librustc_middle/mir/terminator/mod.rs
src/librustc_middle/traits/mod.rs
src/librustc_middle/ty/adjustment.rs
src/librustc_middle/ty/context.rs
src/librustc_middle/ty/instance.rs
src/librustc_middle/ty/layout.rs
src/librustc_middle/ty/mod.rs
src/librustc_middle/ty/sty.rs
src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs
src/librustc_mir/borrow_check/diagnostics/mod.rs
src/librustc_mir/borrow_check/diagnostics/move_errors.rs
src/librustc_mir/borrow_check/diagnostics/outlives_suggestion.rs
src/librustc_mir/borrow_check/mod.rs
src/librustc_mir/borrow_check/type_check/mod.rs
src/librustc_mir/borrow_check/universal_regions.rs
src/librustc_mir/dataflow/move_paths/builder.rs
src/librustc_mir/interpret/intrinsics/caller_location.rs
src/librustc_mir/interpret/place.rs
src/librustc_mir/lib.rs
src/librustc_mir/monomorphize/collector.rs
src/librustc_mir/monomorphize/mod.rs
src/librustc_mir/monomorphize/partitioning.rs [deleted file]
src/librustc_mir/monomorphize/partitioning/default.rs [new file with mode: 0644]
src/librustc_mir/monomorphize/partitioning/merging.rs [new file with mode: 0644]
src/librustc_mir/monomorphize/partitioning/mod.rs [new file with mode: 0644]
src/librustc_mir/shim.rs
src/librustc_mir/transform/check_consts/validation.rs
src/librustc_mir/transform/elaborate_drops.rs
src/librustc_mir/transform/generator.rs
src/librustc_mir/util/aggregate.rs
src/librustc_mir/util/elaborate_drops.rs
src/librustc_mir_build/build/matches/mod.rs
src/librustc_mir_build/build/matches/test.rs
src/librustc_mir_build/build/matches/util.rs
src/librustc_mir_build/build/mod.rs
src/librustc_mir_build/lints.rs
src/librustc_mir_build/thir/pattern/const_to_pat.rs
src/librustc_parse/lib.rs
src/librustc_parse/parser/expr.rs
src/librustc_parse/parser/item.rs
src/librustc_passes/weak_lang_items.rs
src/librustc_resolve/late.rs
src/librustc_resolve/lib.rs
src/librustc_save_analysis/sig.rs
src/librustc_session/options.rs
src/librustc_session/session.rs
src/librustc_span/symbol.rs
src/librustc_symbol_mangling/legacy.rs
src/librustc_target/spec/aarch64_unknown_hermit.rs
src/librustc_target/spec/hermit_base.rs
src/librustc_target/spec/hermit_kernel_base.rs
src/librustc_trait_selection/infer.rs
src/librustc_trait_selection/traits/error_reporting/mod.rs
src/librustc_trait_selection/traits/error_reporting/suggestions.rs
src/librustc_trait_selection/traits/project.rs
src/librustc_trait_selection/traits/select/confirmation.rs
src/librustc_trait_selection/traits/structural_match.rs
src/librustc_trait_selection/traits/wf.rs
src/librustc_ty/common_traits.rs
src/librustc_typeck/astconv.rs [deleted file]
src/librustc_typeck/astconv/errors.rs [new file with mode: 0644]
src/librustc_typeck/astconv/generics.rs [new file with mode: 0644]
src/librustc_typeck/astconv/mod.rs [new file with mode: 0644]
src/librustc_typeck/bounds.rs [new file with mode: 0644]
src/librustc_typeck/check/_match.rs
src/librustc_typeck/check/cast.rs
src/librustc_typeck/check/closure.rs
src/librustc_typeck/check/demand.rs
src/librustc_typeck/check/expr.rs
src/librustc_typeck/check/method/suggest.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/wfcheck.rs
src/librustc_typeck/coherence/builtin.rs
src/librustc_typeck/collect.rs
src/librustc_typeck/lib.rs
src/librustdoc/clean/auto_trait.rs
src/librustdoc/clean/types.rs
src/librustdoc/config.rs
src/librustdoc/core.rs
src/librustdoc/html/render/mod.rs
src/librustdoc/lib.rs
src/librustdoc/passes/calculate_doc_coverage.rs
src/librustdoc/passes/collect_intra_doc_links.rs
src/librustdoc/passes/collect_trait_impls.rs
src/librustdoc/passes/doc_test_lints.rs
src/librustdoc/test.rs
src/llvm-project
src/rustllvm/CoverageMappingWrapper.cpp
src/test/assembly/asm/aarch64-types.rs
src/test/assembly/asm/riscv-types.rs
src/test/codegen/scalar-pair-bool.rs
src/test/mir-opt/array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.mir.32bit
src/test/mir-opt/array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.mir.64bit
src/test/mir-opt/box_expr.main.ElaborateDrops.before.mir
src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff
src/test/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff
src/test/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff
src/test/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.diff
src/test/mir-opt/const_prop/issue_66971.main.ConstProp.diff
src/test/mir-opt/const_prop/issue_67019.main.ConstProp.diff
src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.ConstProp.diff
src/test/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff
src/test/mir-opt/const_prop/reify_fn_ptr.main.ConstProp.diff
src/test/mir-opt/const_prop/scalar_literal_propagation.main.ConstProp.diff
src/test/mir-opt/const_prop/switch_int.main.ConstProp.diff
src/test/mir-opt/const_prop/switch_int.main.SimplifyBranches-after-const-prop.diff
src/test/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.diff
src/test/mir-opt/copy_propagation_arg.bar.CopyPropagation.diff
src/test/mir-opt/copy_propagation_arg.foo.CopyPropagation.diff
src/test/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff
src/test/mir-opt/generator_storage_dead_unwind.main-{{closure}}.StateTransform.before.mir
src/test/mir-opt/generator_tiny.main-{{closure}}.generator_resume.0.mir
src/test/mir-opt/inline/inline_any_operand.bar.Inline.after.mir
src/test/mir-opt/inline/inline_into_box_place.main.Inline.diff.32bit
src/test/mir-opt/inline/inline_into_box_place.main.Inline.diff.64bit
src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir
src/test/mir-opt/inline/inline_specialization.main.Inline.diff
src/test/mir-opt/inline/inline_trait_method.test.Inline.after.mir
src/test/mir-opt/inline/inline_trait_method_2.test2.Inline.after.mir
src/test/mir-opt/instrument_coverage.main.InstrumentCoverage.diff
src/test/mir-opt/issue_41110.main.ElaborateDrops.after.mir
src/test/mir-opt/issue_41110.test.ElaborateDrops.after.mir
src/test/mir-opt/issue_41888.main.ElaborateDrops.after.mir
src/test/mir-opt/issue_49232.main.mir_map.0.mir
src/test/mir-opt/issue_62289.test.ElaborateDrops.before.mir
src/test/mir-opt/issue_72181.main.mir_map.0.mir.32bit
src/test/mir-opt/issue_72181.main.mir_map.0.mir.64bit
src/test/mir-opt/issue_72181_1.main.mir_map.0.mir
src/test/mir-opt/issue_73223.main.PreCodegen.diff.32bit
src/test/mir-opt/issue_73223.main.PreCodegen.diff.64bit
src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff.32bit
src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff.64bit
src/test/mir-opt/match_false_edges.full_tested_match.PromoteTemps.after.mir
src/test/mir-opt/match_false_edges.full_tested_match2.PromoteTemps.before.mir
src/test/mir-opt/match_false_edges.main.PromoteTemps.before.mir
src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.mir.32bit
src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.mir.64bit
src/test/mir-opt/no_drop_for_inactive_variant.unwrap.SimplifyCfg-elaborate-drops.after.mir
src/test/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.mir
src/test/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir
src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir
src/test/mir-opt/simplify_cfg.main.SimplifyCfg-early-opt.diff
src/test/mir-opt/simplify_cfg.main.SimplifyCfg-initial.diff
src/test/mir-opt/simplify_if.main.SimplifyBranches-after-const-prop.diff
src/test/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals.diff
src/test/mir-opt/simplify_match.main.ConstProp.diff
src/test/mir-opt/simplify_try_if_let.{{impl}}-append.SimplifyArmIdentity.diff
src/test/mir-opt/unreachable.main.UnreachablePropagation.diff
src/test/mir-opt/unreachable_asm.main.UnreachablePropagation.diff
src/test/mir-opt/unreachable_asm_2.main.UnreachablePropagation.diff
src/test/mir-opt/unreachable_diverging.main.UnreachablePropagation.diff
src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.std__vec__Vec_i32_.AddMovesForPackedDrops.before.mir.32bit
src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.std__vec__Vec_i32_.AddMovesForPackedDrops.before.mir.64bit
src/test/mir-opt/while_storage.while_loop.PreCodegen.after.mir
src/test/run-make-fulldeps/instrument-coverage/expected_export_coverage.json
src/test/rustdoc-ui/assoc-item-not-in-scope.rs [new file with mode: 0644]
src/test/rustdoc-ui/assoc-item-not-in-scope.stderr [new file with mode: 0644]
src/test/rustdoc-ui/coverage/basic.stdout
src/test/rustdoc-ui/coverage/doc-examples-json.rs [new file with mode: 0644]
src/test/rustdoc-ui/coverage/doc-examples-json.stdout [new file with mode: 0644]
src/test/rustdoc-ui/coverage/doc-examples.stdout
src/test/rustdoc-ui/coverage/empty.stdout
src/test/rustdoc-ui/coverage/enums.stdout
src/test/rustdoc-ui/coverage/exotic.stdout
src/test/rustdoc-ui/coverage/json.rs
src/test/rustdoc-ui/coverage/json.stdout
src/test/rustdoc-ui/coverage/private.stdout
src/test/rustdoc-ui/coverage/statics-consts.stdout
src/test/rustdoc-ui/coverage/traits.stdout
src/test/rustdoc-ui/intra-link-prim-conflict.rs [new file with mode: 0644]
src/test/rustdoc-ui/intra-link-prim-conflict.stderr [new file with mode: 0644]
src/test/rustdoc-ui/lint-missing-doc-code-example.rs
src/test/rustdoc-ui/lint-missing-doc-code-example.stderr
src/test/rustdoc-ui/unknown-renamed-lints.rs [new file with mode: 0644]
src/test/rustdoc-ui/unknown-renamed-lints.stderr [new file with mode: 0644]
src/test/rustdoc/intra-link-associated-defaults.rs [new file with mode: 0644]
src/test/rustdoc/intra-link-associated-items.rs [new file with mode: 0644]
src/test/rustdoc/intra-link-prim-precedence.rs
src/test/ui/associated-types/bound-lifetime-in-binding-only.ok.stderr
src/test/ui/associated-types/bound-lifetime-in-return-only.ok.stderr
src/test/ui/associated-types/cache/project-fn-ret-contravariant.ok.stderr
src/test/ui/associated-types/cache/project-fn-ret-contravariant.oneuse.stderr
src/test/ui/associated-types/cache/project-fn-ret-invariant.ok.stderr
src/test/ui/associated-types/higher-ranked-projection.good.stderr
src/test/ui/async-await/issues/issue-66958-non-copy-infered-type-arg.rs
src/test/ui/async-await/issues/issue-66958-non-copy-infered-type-arg.stderr
src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.stderr
src/test/ui/binding/issue-53114-borrow-checks.stderr
src/test/ui/block-result/issue-20862.stderr
src/test/ui/borrowck/borrowck-move-out-from-array-match.rs
src/test/ui/borrowck/borrowck-move-out-from-array-match.stderr
src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap-match.rs
src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap-match.stderr
src/test/ui/borrowck/borrowck-move-out-from-array-use-match.stderr
src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap-match.rs
src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap-match.stderr
src/test/ui/borrowck/borrowck-move-out-from-array-use.stderr
src/test/ui/borrowck/borrowck-move-out-from-array.stderr
src/test/ui/borrowck/borrowck-uninit-field-access.stderr
src/test/ui/borrowck/move-in-pattern-mut.rs
src/test/ui/borrowck/move-in-pattern-mut.stderr
src/test/ui/borrowck/move-in-pattern.fixed
src/test/ui/borrowck/move-in-pattern.rs
src/test/ui/borrowck/move-in-pattern.stderr
src/test/ui/codemap_tests/coherence-overlapping-inherent-impl-trait.stderr
src/test/ui/codemap_tests/overlapping_inherent_impls.stderr
src/test/ui/coherence/coherence-inherited-subtyping.old.stderr
src/test/ui/coherence/coherence-inherited-subtyping.re.stderr
src/test/ui/coherence/coherence-overlap-downstream-inherent.stderr
src/test/ui/coherence/coherence-overlap-issue-23516-inherent.stderr
src/test/ui/coherence/coherence-overlap-upstream-inherent.stderr
src/test/ui/consts/const-eval/const-eval-query-stack.rs
src/test/ui/consts/const-eval/const-eval-query-stack.stderr
src/test/ui/consts/const-extern-fn/const-extern-fn-call-extern-fn.stderr
src/test/ui/consts/const-float-bits-conv.rs [new file with mode: 0644]
src/test/ui/consts/const-float-classify.rs [new file with mode: 0644]
src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr
src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr
src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.stderr
src/test/ui/consts/offset.rs
src/test/ui/consts/offset_from.rs
src/test/ui/consts/offset_from_ub.rs
src/test/ui/consts/offset_from_ub.stderr
src/test/ui/duplicate/dupe-symbols-1.stderr
src/test/ui/duplicate/dupe-symbols-2.stderr
src/test/ui/duplicate/dupe-symbols-3.stderr
src/test/ui/duplicate/dupe-symbols-4.stderr
src/test/ui/duplicate/dupe-symbols-5.stderr
src/test/ui/duplicate/dupe-symbols-7.stderr
src/test/ui/duplicate/dupe-symbols-8.stderr
src/test/ui/duplicate_entry_error.stderr
src/test/ui/error-codes/E0445.stderr
src/test/ui/error-codes/E0446.stderr
src/test/ui/hr-subtype/hr-subtype.bound_a_b_vs_bound_a.stderr
src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr
src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr
src/test/ui/hr-subtype/hr-subtype.bound_co_a_b_vs_bound_co_a.stderr
src/test/ui/hr-subtype/hr-subtype.bound_co_a_co_b_ret_contra_a.stderr
src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr
src/test/ui/hr-subtype/hr-subtype.bound_contra_a_contra_b_ret_co_a.stderr
src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr
src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr
src/test/ui/hrtb/issue-58451.stderr
src/test/ui/infinite/infinite-instantiation.stderr
src/test/ui/issues/issue-16683.stderr
src/test/ui/issues/issue-17740.stderr
src/test/ui/issues/issue-17758.stderr
src/test/ui/issues/issue-17905-2.stderr
src/test/ui/issues/issue-20831-debruijn.stderr
src/test/ui/issues/issue-22638.stderr
src/test/ui/issues/issue-30079.stderr
src/test/ui/issues/issue-33140.stderr
src/test/ui/issues/issue-37311-type-length-limit/issue-37311.stderr
src/test/ui/issues/issue-37884.stderr
src/test/ui/issues/issue-67552.stderr
src/test/ui/issues/issue-8727.stderr
src/test/ui/lint/clashing-extern-fn.rs
src/test/ui/marker_trait_attr/marker-trait-with-associated-items.stderr
src/test/ui/match/match-incompat-type-semi.rs [new file with mode: 0644]
src/test/ui/match/match-incompat-type-semi.stderr [new file with mode: 0644]
src/test/ui/moves/moves-based-on-type-cyclic-types-issue-4821.rs
src/test/ui/moves/moves-based-on-type-cyclic-types-issue-4821.stderr
src/test/ui/moves/moves-based-on-type-match-bindings.rs
src/test/ui/moves/moves-based-on-type-match-bindings.stderr
src/test/ui/nll/issue-52742.stderr
src/test/ui/nll/issue-55394.stderr
src/test/ui/nll/move-subpaths-moves-root.rs
src/test/ui/nll/move-subpaths-moves-root.stderr
src/test/ui/nll/type-alias-free-regions.stderr
src/test/ui/offset_from.rs
src/test/ui/panic-handler/panic-handler-bad-signature-4.stderr
src/test/ui/panic-handler/panic-handler-duplicate.stderr
src/test/ui/panic-handler/panic-handler-std.stderr
src/test/ui/parser/struct-literal-in-match-guard.rs [new file with mode: 0644]
src/test/ui/privacy/private-in-public-lint.stderr
src/test/ui/privacy/private-in-public-non-principal.stderr
src/test/ui/privacy/private-in-public-warn.stderr
src/test/ui/privacy/private-in-public.stderr
src/test/ui/privacy/pub-priv-dep/pub-priv1.stderr
src/test/ui/privacy/restricted/private-in-public.stderr
src/test/ui/proc-macro/group-compat-hack/auxiliary/group-compat-hack.rs [new file with mode: 0644]
src/test/ui/proc-macro/group-compat-hack/group-compat-hack.rs [new file with mode: 0644]
src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stdout [new file with mode: 0644]
src/test/ui/proc-macro/group-compat-hack/js-sys/src/lib.rs [new file with mode: 0644]
src/test/ui/proc-macro/group-compat-hack/time-macros-impl/src/lib.rs [new file with mode: 0644]
src/test/ui/proc-macro/input-interpolated.stdout
src/test/ui/proc-macro/macro-rules-derive.rs
src/test/ui/proc-macro/macro-rules-derive.stderr
src/test/ui/proc-macro/no-macro-use-attr.stderr
src/test/ui/proc-macro/nodelim-groups.stdout
src/test/ui/proc-macro/weird-hygiene.rs
src/test/ui/proc-macro/weird-hygiene.stderr [new file with mode: 0644]
src/test/ui/range_inclusive.rs
src/test/ui/realloc-16687.rs
src/test/ui/recursion/recursion.stderr
src/test/ui/ref-suggestion.rs
src/test/ui/ref-suggestion.stderr
src/test/ui/regions/regions-infer-paramd-indirect.stderr
src/test/ui/regions/regions-normalize-in-where-clause-list.stderr
src/test/ui/regions/regions-trait-1.stderr
src/test/ui/rfc-2091-track-caller/error-with-main.stderr
src/test/ui/rfc-2091-track-caller/error-with-start.stderr
src/test/ui/rfc-2294-if-let-guard/feature-gate.rs [new file with mode: 0644]
src/test/ui/rfc-2294-if-let-guard/feature-gate.stderr [new file with mode: 0644]
src/test/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.stderr
src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/feature-gate.gated.stderr
src/test/ui/rfc-2632-const-trait-impl/feature-gate.gated.stderr
src/test/ui/rfc-2632-const-trait-impl/stability.stderr
src/test/ui/rfc1445/feature-gate.with_gate.stderr
src/test/ui/rfcs/rfc-1014-2.rs
src/test/ui/rfcs/rfc-1014.rs
src/test/ui/rfcs/rfc-2396-target_feature-11/feature-gate-target_feature_11.stderr
src/test/ui/rfcs/rfc-2396-target_feature-11/trait-impl.stderr
src/test/ui/rustc-error.stderr
src/test/ui/specialization/specialization-overlap-hygiene.stderr
src/test/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.stderr
src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.nll.stderr
src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr
src/test/ui/target-feature/invalid-attribute.stderr
src/test/ui/traits/trait-object-auto-dedup-in-impl.stderr
src/test/ui/type-alias-impl-trait/different_defining_uses.stderr
src/test/ui/type-alias-impl-trait/different_defining_uses_never_type.stderr
src/test/ui/type-alias-impl-trait/generic_different_defining_uses.stderr
src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr
src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr
src/test/ui/type-alias-impl-trait/generic_duplicate_param_use5.stderr
src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr
src/test/ui/type-alias-impl-trait/generic_duplicate_param_use8.stderr
src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr
src/test/ui/type-alias-impl-trait/issue-52843-closure-constrain.stderr
src/test/ui/type-alias-impl-trait/not_a_defining_use.stderr
src/test/ui/ufcs/ufcs-explicit-self-bad.stderr
src/test/ui/unboxed-closures/unboxed-closures-infer-recursive-fn.rs
src/test/ui/unsized-locals/borrow-after-move.stderr
src/test/ui/unsized-locals/double-move.stderr
src/tools/cargotest/main.rs
src/tools/clippy/tests/ui/len_zero_ranges.fixed
src/tools/clippy/tests/ui/len_zero_ranges.rs
src/tools/clippy/tests/ui/len_zero_ranges.stderr
src/tools/compiletest/src/errors.rs
src/tools/compiletest/src/header.rs
src/tools/compiletest/src/json.rs
src/tools/compiletest/src/main.rs
src/tools/compiletest/src/runtest.rs
src/tools/compiletest/src/util.rs
src/tools/expand-yaml-anchors/src/main.rs
src/tools/linkchecker/main.rs
src/tools/publish_toolstate.py
src/tools/rust-analyzer
src/tools/tidy/Cargo.toml
src/tools/tidy/src/deps.rs
src/tools/tidy/src/error_codes_check.rs
src/tools/unicode-table-generator/src/main.rs
src/tools/unicode-table-generator/src/raw_emitter.rs
src/tools/unstable-book-gen/src/main.rs

index a19cca9071f011c582289a2807bcb96293f63839..f6f181612c92627d71b71f678e5b4db0384fb637 100644 (file)
@@ -364,9 +364,6 @@ jobs:
           - name: x86_64-gnu-distcheck
             os: ubuntu-latest-xl
             env: {}
-          - name: x86_64-gnu-full-bootstrap
-            os: ubuntu-latest-xl
-            env: {}
           - name: x86_64-gnu-llvm-8
             env:
               RUST_BACKTRACE: 1
index a327aaa8d5a34501ae7c78625f95340cfbd77b06..8f4d3768c21e8601b31becfa0a2fda7ba75ced69 100644 (file)
@@ -37,7 +37,7 @@
 [submodule "src/llvm-project"]
        path = src/llvm-project
        url = https://github.com/rust-lang/llvm-project.git
-       branch = rustc/10.0-2020-05-05
+       branch = rustc/11.0-2020-08-20
 [submodule "src/doc/embedded-book"]
        path = src/doc/embedded-book
        url = https://github.com/rust-embedded/book.git
index 15ca403456a4ede8efd866b41fc16f2a1b104ad3..cc7b2a677baf6e056006558527a750e823e9c4c3 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -176,8 +176,8 @@ Mark Sinclair <mark.edward.x@gmail.com> =Mark Sinclair <=125axel125@gmail.com>
 Markus Westerlind <marwes91@gmail.com> Markus <marwes91@gmail.com>
 Martin Hafskjold Thoresen <martinhath@gmail.com>
 Matej Lach <matej.lach@gmail.com> Matej Ä½ach <matej.lach@gmail.com>
-Mateusz MikuÅ‚a <matti@marinelayer.io> <mati865@gmail.com>
-Mateusz MikuÅ‚a <matti@marinelayer.io> <mati865@users.noreply.github.com>
+Mateusz MikuÅ‚a <mati865@gmail.com> <mati865@users.noreply.github.com>
+Mateusz MikuÅ‚a <mati865@gmail.com> <matti@marinelayer.io>
 Matt Brubeck <mbrubeck@limpet.net> <mbrubeck@cs.hmc.edu>
 Matthew Auld <matthew.auld@intel.com>
 Matthew Kraai <kraai@ftbfs.org>
index f8fa2971b49d8fced1cebb6e8c0042c6fdba29fa..1bbae2cbd80c97a8869d51302cc501d3855392f1 100644 (file)
@@ -403,6 +403,17 @@ dependencies = [
  "serde_json",
 ]
 
+[[package]]
+name = "cargo_metadata"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "89fec17b16f1ac67908af82e47d0a90a7afd0e1827b181cd77504323d3263d35"
+dependencies = [
+ "semver 0.10.0",
+ "serde",
+ "serde_json",
+]
+
 [[package]]
 name = "cargotest2"
 version = "0.1.0"
@@ -997,6 +1008,16 @@ dependencies = [
  "yaml-rust 0.4.4",
 ]
 
+[[package]]
+name = "expect-test"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a3e383741ea1982866572109d1a8c807bd36aad91fca701489fdca56ef92b3b8"
+dependencies = [
+ "difference",
+ "once_cell",
+]
+
 [[package]]
 name = "failure"
 version = "0.1.8"
@@ -3642,6 +3663,7 @@ dependencies = [
 name = "rustc_lexer"
 version = "0.1.0"
 dependencies = [
+ "expect-test",
  "unicode-xid",
 ]
 
@@ -4680,7 +4702,7 @@ dependencies = [
 name = "tidy"
 version = "0.1.0"
 dependencies = [
- "cargo_metadata 0.9.1",
+ "cargo_metadata 0.11.1",
  "lazy_static",
  "regex",
  "walkdir",
index fa5eb1823f1a0755c721abbed9a13b5e5e5a0b84..5f09f8def4d0a1eb6a7a76ae832617d14bd73a17 100644 (file)
@@ -3,7 +3,7 @@
 #![stable(feature = "alloc_module", since = "1.28.0")]
 
 use core::intrinsics::{self, min_align_of_val, size_of_val};
-use core::ptr::{NonNull, Unique};
+use core::ptr::{self, NonNull, Unique};
 
 #[stable(feature = "alloc_module", since = "1.28.0")]
 #[doc(inline)]
@@ -36,8 +36,6 @@
 ///
 /// Note: while this type is unstable, the functionality it provides can be
 /// accessed through the [free functions in `alloc`](index.html#functions).
-///
-/// [`AllocRef`]: trait.AllocRef.html
 #[unstable(feature = "allocator_api", issue = "32838")]
 #[derive(Copy, Clone, Default, Debug)]
 pub struct Global;
 ///
 /// See [`GlobalAlloc::alloc`].
 ///
-/// [`Global`]: struct.Global.html
-/// [`AllocRef`]: trait.AllocRef.html
-/// [`GlobalAlloc::alloc`]: trait.GlobalAlloc.html#tymethod.alloc
-///
 /// # Examples
 ///
 /// ```
@@ -92,10 +86,6 @@ pub unsafe fn alloc(layout: Layout) -> *mut u8 {
 /// # Safety
 ///
 /// See [`GlobalAlloc::dealloc`].
-///
-/// [`Global`]: struct.Global.html
-/// [`AllocRef`]: trait.AllocRef.html
-/// [`GlobalAlloc::dealloc`]: trait.GlobalAlloc.html#tymethod.dealloc
 #[stable(feature = "global_alloc", since = "1.28.0")]
 #[inline]
 pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) {
@@ -114,10 +104,6 @@ pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) {
 /// # Safety
 ///
 /// See [`GlobalAlloc::realloc`].
-///
-/// [`Global`]: struct.Global.html
-/// [`AllocRef`]: trait.AllocRef.html
-/// [`GlobalAlloc::realloc`]: trait.GlobalAlloc.html#method.realloc
 #[stable(feature = "global_alloc", since = "1.28.0")]
 #[inline]
 pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
@@ -137,10 +123,6 @@ pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8
 ///
 /// See [`GlobalAlloc::alloc_zeroed`].
 ///
-/// [`Global`]: struct.Global.html
-/// [`AllocRef`]: trait.AllocRef.html
-/// [`GlobalAlloc::alloc_zeroed`]: trait.GlobalAlloc.html#method.alloc_zeroed
-///
 /// # Examples
 ///
 /// ```
@@ -180,36 +162,45 @@ fn alloc_impl(&mut self, layout: Layout, zeroed: bool) -> Result<NonNull<[u8]>,
     unsafe fn grow_impl(
         &mut self,
         ptr: NonNull<u8>,
-        layout: Layout,
-        new_size: usize,
+        old_layout: Layout,
+        new_layout: Layout,
         zeroed: bool,
     ) -> Result<NonNull<[u8]>, AllocErr> {
         debug_assert!(
-            new_size >= layout.size(),
-            "`new_size` must be greater than or equal to `layout.size()`"
+            new_layout.size() >= old_layout.size(),
+            "`new_layout.size()` must be greater than or equal to `old_layout.size()`"
         );
 
-        match layout.size() {
-            // SAFETY: the caller must ensure that the `new_size` does not overflow.
-            // `layout.align()` comes from a `Layout` and is thus guaranteed to be valid for a Layout.
-            0 => unsafe {
-                let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
-                self.alloc_impl(new_layout, zeroed)
-            },
+        match old_layout.size() {
+            0 => self.alloc_impl(new_layout, zeroed),
 
             // SAFETY: `new_size` is non-zero as `old_size` is greater than or equal to `new_size`
             // as required by safety conditions. Other conditions must be upheld by the caller
-            old_size => unsafe {
-                // `realloc` probably checks for `new_size >= size` or something similar.
-                intrinsics::assume(new_size >= layout.size());
+            old_size if old_layout.align() == new_layout.align() => unsafe {
+                let new_size = new_layout.size();
 
-                let raw_ptr = realloc(ptr.as_ptr(), layout, new_size);
+                // `realloc` probably checks for `new_size >= old_layout.size()` or something similar.
+                intrinsics::assume(new_size >= old_layout.size());
+
+                let raw_ptr = realloc(ptr.as_ptr(), old_layout, new_size);
                 let ptr = NonNull::new(raw_ptr).ok_or(AllocErr)?;
                 if zeroed {
                     raw_ptr.add(old_size).write_bytes(0, new_size - old_size);
                 }
                 Ok(NonNull::slice_from_raw_parts(ptr, new_size))
             },
+
+            // SAFETY: because `new_layout.size()` must be greater than or equal to `old_size`,
+            // both the old and new memory allocation are valid for reads and writes for `old_size`
+            // bytes. Also, because the old allocation wasn't yet deallocated, it cannot overlap
+            // `new_ptr`. Thus, the call to `copy_nonoverlapping` is safe. The safety contract
+            // for `dealloc` must be upheld by the caller.
+            old_size => unsafe {
+                let new_ptr = self.alloc_impl(new_layout, zeroed)?;
+                ptr::copy_nonoverlapping(ptr.as_ptr(), new_ptr.as_mut_ptr(), old_size);
+                self.dealloc(ptr, old_layout);
+                Ok(new_ptr)
+            },
         }
     }
 }
@@ -239,52 +230,64 @@ unsafe fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout) {
     unsafe fn grow(
         &mut self,
         ptr: NonNull<u8>,
-        layout: Layout,
-        new_size: usize,
+        old_layout: Layout,
+        new_layout: Layout,
     ) -> Result<NonNull<[u8]>, AllocErr> {
         // SAFETY: all conditions must be upheld by the caller
-        unsafe { self.grow_impl(ptr, layout, new_size, false) }
+        unsafe { self.grow_impl(ptr, old_layout, new_layout, false) }
     }
 
     #[inline]
     unsafe fn grow_zeroed(
         &mut self,
         ptr: NonNull<u8>,
-        layout: Layout,
-        new_size: usize,
+        old_layout: Layout,
+        new_layout: Layout,
     ) -> Result<NonNull<[u8]>, AllocErr> {
         // SAFETY: all conditions must be upheld by the caller
-        unsafe { self.grow_impl(ptr, layout, new_size, true) }
+        unsafe { self.grow_impl(ptr, old_layout, new_layout, true) }
     }
 
     #[inline]
     unsafe fn shrink(
         &mut self,
         ptr: NonNull<u8>,
-        layout: Layout,
-        new_size: usize,
+        old_layout: Layout,
+        new_layout: Layout,
     ) -> Result<NonNull<[u8]>, AllocErr> {
         debug_assert!(
-            new_size <= layout.size(),
-            "`new_size` must be smaller than or equal to `layout.size()`"
+            new_layout.size() <= old_layout.size(),
+            "`new_layout.size()` must be smaller than or equal to `old_layout.size()`"
         );
 
-        match new_size {
+        match new_layout.size() {
             // SAFETY: conditions must be upheld by the caller
             0 => unsafe {
-                self.dealloc(ptr, layout);
-                Ok(NonNull::slice_from_raw_parts(layout.dangling(), 0))
+                self.dealloc(ptr, old_layout);
+                Ok(NonNull::slice_from_raw_parts(new_layout.dangling(), 0))
             },
 
             // SAFETY: `new_size` is non-zero. Other conditions must be upheld by the caller
-            new_size => unsafe {
-                // `realloc` probably checks for `new_size <= size` or something similar.
-                intrinsics::assume(new_size <= layout.size());
+            new_size if old_layout.align() == new_layout.align() => unsafe {
+                // `realloc` probably checks for `new_size <= old_layout.size()` or something similar.
+                intrinsics::assume(new_size <= old_layout.size());
 
-                let raw_ptr = realloc(ptr.as_ptr(), layout, new_size);
+                let raw_ptr = realloc(ptr.as_ptr(), old_layout, new_size);
                 let ptr = NonNull::new(raw_ptr).ok_or(AllocErr)?;
                 Ok(NonNull::slice_from_raw_parts(ptr, new_size))
             },
+
+            // SAFETY: because `new_size` must be smaller than or equal to `old_layout.size()`,
+            // both the old and new memory allocation are valid for reads and writes for `new_size`
+            // bytes. Also, because the old allocation wasn't yet deallocated, it cannot overlap
+            // `new_ptr`. Thus, the call to `copy_nonoverlapping` is safe. The safety contract
+            // for `dealloc` must be upheld by the caller.
+            new_size => unsafe {
+                let new_ptr = self.alloc(new_layout)?;
+                ptr::copy_nonoverlapping(ptr.as_ptr(), new_ptr.as_mut_ptr(), new_size);
+                self.dealloc(ptr, old_layout);
+                Ok(new_ptr)
+            },
         }
     }
 }
@@ -297,7 +300,7 @@ unsafe fn shrink(
 unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 {
     let layout = unsafe { Layout::from_size_align_unchecked(size, align) };
     match Global.alloc(layout) {
-        Ok(ptr) => ptr.as_non_null_ptr().as_ptr(),
+        Ok(ptr) => ptr.as_mut_ptr(),
         Err(_) => handle_alloc_error(layout),
     }
 }
index 5e304beff78ab1cb469ce5bdab2e24a2004e4407..05211e2037bb78a1f41f373995ebb8ff4f3415ff 100644 (file)
 //! described in [rust-lang/unsafe-code-guidelines#198][ucg#198].
 //!
 //! [ucg#198]: https://github.com/rust-lang/unsafe-code-guidelines/issues/198
-//! [dereferencing]: ../../std/ops/trait.Deref.html
-//! [`Box`]: struct.Box.html
-//! [`Box<T>`]: struct.Box.html
-//! [`Box::<T>::from_raw(value)`]: struct.Box.html#method.from_raw
-//! [`Box::<T>::into_raw`]: struct.Box.html#method.into_raw
-//! [`Global`]: ../alloc/struct.Global.html
-//! [`Layout`]: ../alloc/struct.Layout.html
-//! [`Layout::for_value(&*value)`]: ../alloc/struct.Layout.html#method.for_value
+//! [dereferencing]: core::ops::Deref
+//! [`Box<T>`]: Box
+//! [`Box::<T>::from_raw(value)`]: Box::from_raw
+//! [`Box::<T>::into_raw`]: Box::into_raw
+//! [`Global`]: crate::alloc::Global
+//! [`Layout`]: crate::alloc::Layout
+//! [`Layout::for_value(&*value)`]: crate::alloc::Layout::for_value
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
@@ -240,7 +239,6 @@ pub fn pin(x: T) -> Pin<Box<T>> {
     /// Converts a `Box<T>` into a `Box<[T]>`
     ///
     /// This conversion does not allocate on the heap and happens in place.
-    ///
     #[unstable(feature = "box_into_boxed_slice", issue = "71582")]
     pub fn into_boxed_slice(boxed: Box<T>) -> Box<[T]> {
         // *mut T and *mut [T; 1] have the same size and alignment
@@ -273,6 +271,29 @@ impl<T> Box<[T]> {
     pub fn new_uninit_slice(len: usize) -> Box<[mem::MaybeUninit<T>]> {
         unsafe { RawVec::with_capacity(len).into_box(len) }
     }
+
+    /// Constructs a new boxed slice with uninitialized contents, with the memory
+    /// being filled with `0` bytes.
+    ///
+    /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage
+    /// of this method.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(new_uninit)]
+    ///
+    /// let values = Box::<[u32]>::new_zeroed_slice(3);
+    /// let values = unsafe { values.assume_init() };
+    ///
+    /// assert_eq!(*values, [0, 0, 0])
+    /// ```
+    ///
+    /// [zeroed]: ../../std/mem/union.MaybeUninit.html#method.zeroed
+    #[unstable(feature = "new_uninit", issue = "63291")]
+    pub fn new_zeroed_slice(len: usize) -> Box<[mem::MaybeUninit<T>]> {
+        unsafe { RawVec::with_capacity_zeroed(len).into_box(len) }
+    }
 }
 
 impl<T> Box<mem::MaybeUninit<T>> {
@@ -386,9 +407,8 @@ impl<T: ?Sized> Box<T> {
     /// }
     /// ```
     ///
-    /// [memory layout]: index.html#memory-layout
-    /// [`Layout`]: ../alloc/struct.Layout.html
-    /// [`Box::into_raw`]: struct.Box.html#method.into_raw
+    /// [memory layout]: self#memory-layout
+    /// [`Layout`]: crate::Layout
     #[stable(feature = "box_raw", since = "1.4.0")]
     #[inline]
     pub unsafe fn from_raw(raw: *mut T) -> Self {
@@ -433,8 +453,7 @@ pub unsafe fn from_raw(raw: *mut T) -> Self {
     /// }
     /// ```
     ///
-    /// [memory layout]: index.html#memory-layout
-    /// [`Box::from_raw`]: struct.Box.html#method.from_raw
+    /// [memory layout]: self#memory-layout
     #[stable(feature = "box_raw", since = "1.4.0")]
     #[inline]
     pub fn into_raw(b: Box<T>) -> *mut T {
@@ -478,8 +497,6 @@ pub fn into_unique(b: Box<T>) -> Unique<T> {
     /// to call it as `Box::leak(b)` instead of `b.leak()`. This
     /// is so that there is no conflict with a method on the inner type.
     ///
-    /// [`Box::from_raw`]: struct.Box.html#method.from_raw
-    ///
     /// # Examples
     ///
     /// Simple usage:
index 8398cfa3bd34e2ea07fbca98e3ce7ec9a7d1f1ed..477a598ff5b0027512da38aae24b426601d3302f 100644 (file)
@@ -12,9 +12,9 @@
 //! to solve the [shortest path problem][sssp] on a [directed graph][dir_graph].
 //! It shows how to use [`BinaryHeap`] with custom types.
 //!
-//! [dijkstra]: http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm
-//! [sssp]: http://en.wikipedia.org/wiki/Shortest_path_problem
-//! [dir_graph]: http://en.wikipedia.org/wiki/Directed_graph
+//! [dijkstra]: https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm
+//! [sssp]: https://en.wikipedia.org/wiki/Shortest_path_problem
+//! [dir_graph]: https://en.wikipedia.org/wiki/Directed_graph
 //! [`BinaryHeap`]: struct.BinaryHeap.html
 //!
 //! ```
index 02a746f0e24880893ff89f1983bada892057ae41..5390b57a1d98dddcd84ef1e2dfc0e7896c1ddd20 100644 (file)
@@ -7,8 +7,8 @@
 //! array-based containers are generally faster,
 //! more memory efficient, and make better use of CPU cache.
 //!
-//! [`Vec`]: ../../vec/struct.Vec.html
-//! [`VecDeque`]: ../vec_deque/struct.VecDeque.html
+//! [`Vec`]: crate::vec::Vec
+//! [`VecDeque`]: super::vec_deque::VecDeque
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
@@ -50,11 +50,8 @@ struct Node<T> {
 
 /// An iterator over the elements of a `LinkedList`.
 ///
-/// This `struct` is created by the [`iter`] method on [`LinkedList`]. See its
+/// This `struct` is created by [`LinkedList::iter()`]. See its
 /// documentation for more.
-///
-/// [`iter`]: struct.LinkedList.html#method.iter
-/// [`LinkedList`]: struct.LinkedList.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Iter<'a, T: 'a> {
     head: Option<NonNull<Node<T>>>,
@@ -80,11 +77,8 @@ fn clone(&self) -> Self {
 
 /// A mutable iterator over the elements of a `LinkedList`.
 ///
-/// This `struct` is created by the [`iter_mut`] method on [`LinkedList`]. See its
+/// This `struct` is created by [`LinkedList::iter_mut()`]. See its
 /// documentation for more.
-///
-/// [`iter_mut`]: struct.LinkedList.html#method.iter_mut
-/// [`LinkedList`]: struct.LinkedList.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct IterMut<'a, T: 'a> {
     // We do *not* exclusively own the entire list here, references to node's `element`
@@ -109,7 +103,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 /// (provided by the `IntoIterator` trait). See its documentation for more.
 ///
 /// [`into_iter`]: struct.LinkedList.html#method.into_iter
-/// [`LinkedList`]: struct.LinkedList.html
 #[derive(Clone)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct IntoIter<T> {
index a0b151a4496f114c86d3530990b16c73012c82eb..a886e17f5a9c3022a07467ccdded6bdec6e9c7b0 100644 (file)
 //! it would internally pass around this structure until it has been determined
 //! where output should go to.
 //!
-//! [`usize`]: ../../std/primitive.usize.html
-//! [`isize`]: ../../std/primitive.isize.html
-//! [`i8`]: ../../std/primitive.i8.html
-//! [`Display`]: trait.Display.html
-//! [`Binary`]: trait.Binary.html
-//! [`fmt::Result`]: type.Result.html
-//! [`Result`]: ../../std/result/enum.Result.html
-//! [`std::fmt::Error`]: struct.Error.html
-//! [`Formatter`]: struct.Formatter.html
-//! [`write!`]: ../../std/macro.write.html
-//! [`Debug`]: trait.Debug.html
-//! [`format!`]: ../../std/macro.format.html
-//! [`to_string`]: ../../std/string/trait.ToString.html
-//! [`writeln!`]: ../../std/macro.writeln.html
+//! [`fmt::Result`]: Result
+//! [`Result`]: core::result::Result
+//! [`std::fmt::Error`]: Error
+//! [`write!`]: core::write
+//! [`write`]: core::write
+//! [`format!`]: crate::format
+//! [`to_string`]: crate::string::ToString
+//! [`writeln!`]: core::writeln
 //! [`write_fmt`]: ../../std/io/trait.Write.html#method.write_fmt
 //! [`std::io::Write`]: ../../std/io/trait.Write.html
 //! [`print!`]: ../../std/macro.print.html
 //! [`println!`]: ../../std/macro.println.html
 //! [`eprint!`]: ../../std/macro.eprint.html
 //! [`eprintln!`]: ../../std/macro.eprintln.html
-//! [`write!`]: ../../std/macro.write.html
-//! [`format_args!`]: ../../std/macro.format_args.html
-//! [`fmt::Arguments`]: struct.Arguments.html
-//! [`write`]: fn.write.html
-//! [`format`]: fn.format.html
+//! [`format_args!`]: core::format_args
+//! [`fmt::Arguments`]: Arguments
+//! [`format`]: crate::format
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
 /// assert_eq!(s, "Hello, world!");
 /// ```
 ///
-/// [`Arguments`]: struct.Arguments.html
-/// [`format_args!`]: ../../std/macro.format_args.html
-/// [`format!`]: ../../std/macro.format.html
+/// [`format_args!`]: core::format_args
+/// [`format!`]: crate::format
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn format(args: Arguments<'_>) -> string::String {
     let capacity = args.estimated_capacity();
index 2d25941a52412187c8a43f1bb03c25fb865eb3ab..755a21934f0c5120432e34e1a618da9175ea79c1 100644 (file)
 //! The [`alloc`](alloc/index.html) module defines the low-level interface to the
 //! default global allocator. It is not compatible with the libc allocator API.
 //!
-//! [`Arc`]: sync/index.html
-//! [`Box`]: boxed/index.html
-//! [`Cell`]: ../core/cell/index.html
-//! [`Rc`]: rc/index.html
-//! [`RefCell`]: ../core/cell/index.html
+//! [`Arc`]: sync
+//! [`Box`]: boxed
+//! [`Cell`]: core::cell
+//! [`Rc`]: rc
+//! [`RefCell`]: core::cell
 
 #![allow(unused_attributes)]
 #![stable(feature = "alloc", since = "1.36.0")]
 #![feature(or_patterns)]
 #![feature(pattern)]
 #![feature(ptr_internals)]
-#![feature(ptr_offset_from)]
 #![feature(raw_ref_op)]
 #![feature(rustc_attrs)]
 #![feature(receiver_trait)]
 #![feature(alloc_layout_extra)]
 #![feature(try_trait)]
 #![feature(associated_type_bounds)]
-
 // Allow testing this library
 
 #[cfg(test)]
index e163a166b498fceab4aa669f23d3069f76195629..2f744618d6936937224ee92fe41c1ac9f9b545ac 100644 (file)
@@ -29,8 +29,7 @@
 /// to the same boxed integer value, not five references pointing to independently
 /// boxed integers.
 ///
-/// [`Vec`]: ../std/vec/struct.Vec.html
-/// [`Clone`]: ../std/clone/trait.Clone.html
+/// [`Vec`]: crate::vec::Vec
 #[cfg(not(test))]
 #[macro_export]
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -81,11 +80,11 @@ macro_rules! vec {
 /// To convert a single value to a string, use the [`to_string`] method. This
 /// will use the [`Display`] formatting trait.
 ///
-/// [fmt]: ../std/fmt/index.html
+/// [fmt]: core::fmt
 /// [`print!`]: ../std/macro.print.html
-/// [`write!`]: ../std/macro.write.html
-/// [`to_string`]: ../std/string/trait.ToString.html
-/// [`Display`]: ../std/fmt/trait.Display.html
+/// [`write!`]: core::write
+/// [`to_string`]: crate::string::ToString
+/// [`Display`]: core::fmt::Display
 ///
 /// # Panics
 ///
index 247b636c808acf5e15a2b16acf212860872c73b3..05382d0b5594edfece3d193fb5d1698b8fdcdab0 100644 (file)
@@ -3,6 +3,7 @@
 
 use core::alloc::LayoutErr;
 use core::cmp;
+use core::intrinsics;
 use core::mem::{self, ManuallyDrop, MaybeUninit};
 use core::ops::Drop;
 use core::ptr::{NonNull, Unique};
@@ -465,8 +466,9 @@ fn shrink(&mut self, amount: usize) -> Result<(), TryReserveError> {
         let new_size = amount * mem::size_of::<T>();
 
         let ptr = unsafe {
-            self.alloc.shrink(ptr, layout, new_size).map_err(|_| TryReserveError::AllocError {
-                layout: Layout::from_size_align_unchecked(new_size, layout.align()),
+            let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
+            self.alloc.shrink(ptr, layout, new_layout).map_err(|_| TryReserveError::AllocError {
+                layout: new_layout,
                 non_exhaustive: (),
             })?
         };
@@ -494,13 +496,16 @@ fn finish_grow<A>(
 
     let memory = if let Some((ptr, old_layout)) = current_memory {
         debug_assert_eq!(old_layout.align(), new_layout.align());
-        unsafe { alloc.grow(ptr, old_layout, new_layout.size()) }
+        unsafe {
+            // The allocator checks for alignment equality
+            intrinsics::assume(old_layout.align() == new_layout.align());
+            alloc.grow(ptr, old_layout, new_layout)
+        }
     } else {
         alloc.alloc(new_layout)
-    }
-    .map_err(|_| AllocError { layout: new_layout, non_exhaustive: () })?;
+    };
 
-    Ok(memory)
+    memory.map_err(|_| AllocError { layout: new_layout, non_exhaustive: () })
 }
 
 unsafe impl<#[may_dangle] T, A: AllocRef> Drop for RawVec<T, A> {
index d0a47ccea0a76f96fabc05773bb226bd74d69a37..1046397f4be601beda58eb79e2c49605aec492cd 100644 (file)
 //! }
 //! ```
 //!
-//! [`Rc`]: struct.Rc.html
-//! [`Weak`]: struct.Weak.html
-//! [clone]: ../../std/clone/trait.Clone.html#tymethod.clone
-//! [`Cell`]: ../../std/cell/struct.Cell.html
-//! [`RefCell`]: ../../std/cell/struct.RefCell.html
-//! [send]: ../../std/marker/trait.Send.html
+//! [clone]: Clone::clone
+//! [`Cell`]: core::cell::Cell
+//! [`RefCell`]: core::cell::RefCell
+//! [send]: core::marker::Send
 //! [arc]: ../../std/sync/struct.Arc.html
-//! [`Deref`]: ../../std/ops/trait.Deref.html
-//! [downgrade]: struct.Rc.html#method.downgrade
-//! [upgrade]: struct.Weak.html#method.upgrade
-//! [`None`]: ../../std/option/enum.Option.html#variant.None
-//! [mutability]: ../../std/cell/index.html#introducing-mutability-inside-of-something-immutable
+//! [`Deref`]: core::ops::Deref
+//! [downgrade]: Rc::downgrade
+//! [upgrade]: Weak::upgrade
+//! [mutability]: core::cell#introducing-mutability-inside-of-something-immutable
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
 use core::ptr::{self, NonNull};
 use core::slice::from_raw_parts_mut;
 
-use crate::alloc::{box_free, handle_alloc_error, AllocRef, Global, Layout};
+use crate::alloc::{box_free, handle_alloc_error, AllocErr, AllocRef, Global, Layout};
 use crate::borrow::{Cow, ToOwned};
 use crate::string::String;
 use crate::vec::Vec;
@@ -352,9 +349,11 @@ pub fn new(value: T) -> Rc<T> {
     #[unstable(feature = "new_uninit", issue = "63291")]
     pub fn new_uninit() -> Rc<mem::MaybeUninit<T>> {
         unsafe {
-            Rc::from_ptr(Rc::allocate_for_layout(Layout::new::<T>(), |mem| {
-                mem as *mut RcBox<mem::MaybeUninit<T>>
-            }))
+            Rc::from_ptr(Rc::allocate_for_layout(
+                Layout::new::<T>(),
+                |layout| Global.alloc(layout),
+                |mem| mem as *mut RcBox<mem::MaybeUninit<T>>,
+            ))
         }
     }
 
@@ -381,9 +380,11 @@ pub fn new_uninit() -> Rc<mem::MaybeUninit<T>> {
     #[unstable(feature = "new_uninit", issue = "63291")]
     pub fn new_zeroed() -> Rc<mem::MaybeUninit<T>> {
         unsafe {
-            let mut uninit = Self::new_uninit();
-            ptr::write_bytes::<T>(Rc::get_mut_unchecked(&mut uninit).as_mut_ptr(), 0, 1);
-            uninit
+            Rc::from_ptr(Rc::allocate_for_layout(
+                Layout::new::<T>(),
+                |layout| Global.alloc_zeroed(layout),
+                |mem| mem as *mut RcBox<mem::MaybeUninit<T>>,
+            ))
         }
     }
 
@@ -396,13 +397,11 @@ pub fn pin(value: T) -> Pin<Rc<T>> {
 
     /// Returns the inner value, if the `Rc` has exactly one strong reference.
     ///
-    /// Otherwise, an [`Err`][result] is returned with the same `Rc` that was
+    /// Otherwise, an [`Err`] is returned with the same `Rc` that was
     /// passed in.
     ///
     /// This will succeed even if there are outstanding weak references.
     ///
-    /// [result]: ../../std/result/enum.Result.html
-    ///
     /// # Examples
     ///
     /// ```
@@ -465,6 +464,40 @@ impl<T> Rc<[T]> {
     pub fn new_uninit_slice(len: usize) -> Rc<[mem::MaybeUninit<T>]> {
         unsafe { Rc::from_ptr(Rc::allocate_for_slice(len)) }
     }
+
+    /// Constructs a new reference-counted slice with uninitialized contents, with the memory being
+    /// filled with `0` bytes.
+    ///
+    /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and
+    /// incorrect usage of this method.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(new_uninit)]
+    ///
+    /// use std::rc::Rc;
+    ///
+    /// let values = Rc::<[u32]>::new_zeroed_slice(3);
+    /// let values = unsafe { values.assume_init() };
+    ///
+    /// assert_eq!(*values, [0, 0, 0])
+    /// ```
+    ///
+    /// [zeroed]: ../../std/mem/union.MaybeUninit.html#method.zeroed
+    #[unstable(feature = "new_uninit", issue = "63291")]
+    pub fn new_zeroed_slice(len: usize) -> Rc<[mem::MaybeUninit<T>]> {
+        unsafe {
+            Rc::from_ptr(Rc::allocate_for_layout(
+                Layout::array::<T>(len).unwrap(),
+                |layout| Global.alloc_zeroed(layout),
+                |mem| {
+                    ptr::slice_from_raw_parts_mut(mem as *mut T, len)
+                        as *mut RcBox<[mem::MaybeUninit<T>]>
+                },
+            ))
+        }
+    }
 }
 
 impl<T> Rc<mem::MaybeUninit<T>> {
@@ -553,7 +586,7 @@ impl<T: ?Sized> Rc<T> {
     /// To avoid a memory leak the pointer must be converted back to an `Rc` using
     /// [`Rc::from_raw`][from_raw].
     ///
-    /// [from_raw]: struct.Rc.html#method.from_raw
+    /// [from_raw]: Rc::from_raw
     ///
     /// # Examples
     ///
@@ -613,8 +646,8 @@ pub fn as_ptr(this: &Self) -> *const T {
     /// This function is unsafe because improper use may lead to memory unsafety,
     /// even if the returned `Rc<T>` is never accessed.
     ///
-    /// [into_raw]: struct.Rc.html#method.into_raw
-    /// [transmute]: ../../std/mem/fn.transmute.html
+    /// [into_raw]: Rc::into_raw
+    /// [transmute]: core::mem::transmute
     ///
     /// # Examples
     ///
@@ -645,9 +678,7 @@ pub unsafe fn from_raw(ptr: *const T) -> Self {
         unsafe { Self::from_ptr(rc_ptr) }
     }
 
-    /// Creates a new [`Weak`][weak] pointer to this allocation.
-    ///
-    /// [weak]: struct.Weak.html
+    /// Creates a new [`Weak`] pointer to this allocation.
     ///
     /// # Examples
     ///
@@ -666,9 +697,7 @@ pub fn downgrade(this: &Self) -> Weak<T> {
         Weak { ptr: this.ptr }
     }
 
-    /// Gets the number of [`Weak`][weak] pointers to this allocation.
-    ///
-    /// [weak]: struct.Weak.html
+    /// Gets the number of [`Weak`] pointers to this allocation.
     ///
     /// # Examples
     ///
@@ -704,17 +733,15 @@ pub fn strong_count(this: &Self) -> usize {
         this.strong()
     }
 
-    /// Returns `true` if there are no other `Rc` or [`Weak`][weak] pointers to
+    /// Returns `true` if there are no other `Rc` or [`Weak`] pointers to
     /// this allocation.
-    ///
-    /// [weak]: struct.Weak.html
     #[inline]
     fn is_unique(this: &Self) -> bool {
         Rc::weak_count(this) == 0 && Rc::strong_count(this) == 1
     }
 
     /// Returns a mutable reference into the given `Rc`, if there are
-    /// no other `Rc` or [`Weak`][weak] pointers to the same allocation.
+    /// no other `Rc` or [`Weak`] pointers to the same allocation.
     ///
     /// Returns [`None`] otherwise, because it is not safe to
     /// mutate a shared value.
@@ -722,10 +749,8 @@ fn is_unique(this: &Self) -> bool {
     /// See also [`make_mut`][make_mut], which will [`clone`][clone]
     /// the inner value when there are other pointers.
     ///
-    /// [weak]: struct.Weak.html
-    /// [`None`]: ../../std/option/enum.Option.html#variant.None
-    /// [make_mut]: struct.Rc.html#method.make_mut
-    /// [clone]: ../../std/clone/trait.Clone.html#tymethod.clone
+    /// [make_mut]: Rc::make_mut
+    /// [clone]: Clone::clone
     ///
     /// # Examples
     ///
@@ -750,7 +775,7 @@ pub fn get_mut(this: &mut Self) -> Option<&mut T> {
     ///
     /// See also [`get_mut`], which is safe and does appropriate checks.
     ///
-    /// [`get_mut`]: struct.Rc.html#method.get_mut
+    /// [`get_mut`]: Rc::get_mut
     ///
     /// # Safety
     ///
@@ -796,7 +821,7 @@ pub unsafe fn get_mut_unchecked(this: &mut Self) -> &mut T {
     /// assert!(!Rc::ptr_eq(&five, &other_five));
     /// ```
     ///
-    /// [`ptr::eq`]: ../../std/ptr/fn.eq.html
+    /// [`ptr::eq`]: core::ptr::eq
     pub fn ptr_eq(this: &Self, other: &Self) -> bool {
         this.ptr.as_ptr() == other.ptr.as_ptr()
     }
@@ -814,9 +839,8 @@ impl<T: Clone> Rc<T> {
     ///
     /// See also [`get_mut`], which will fail rather than cloning.
     ///
-    /// [`Weak`]: struct.Weak.html
-    /// [`clone`]: ../../std/clone/trait.Clone.html#tymethod.clone
-    /// [`get_mut`]: struct.Rc.html#method.get_mut
+    /// [`clone`]: Clone::clone
+    /// [`get_mut`]: Rc::get_mut
     ///
     /// # Examples
     ///
@@ -919,6 +943,7 @@ impl<T: ?Sized> Rc<T> {
     /// and must return back a (potentially fat)-pointer for the `RcBox<T>`.
     unsafe fn allocate_for_layout(
         value_layout: Layout,
+        allocate: impl FnOnce(Layout) -> Result<NonNull<[u8]>, AllocErr>,
         mem_to_rcbox: impl FnOnce(*mut u8) -> *mut RcBox<T>,
     ) -> *mut RcBox<T> {
         // Calculate layout using the given value layout.
@@ -928,7 +953,7 @@ unsafe fn allocate_for_layout(
         let layout = Layout::new::<RcBox<()>>().extend(value_layout).unwrap().0.pad_to_align();
 
         // Allocate for the layout.
-        let ptr = Global.alloc(layout).unwrap_or_else(|_| handle_alloc_error(layout));
+        let ptr = allocate(layout).unwrap_or_else(|_| handle_alloc_error(layout));
 
         // Initialize the RcBox
         let inner = mem_to_rcbox(ptr.as_non_null_ptr().as_ptr());
@@ -946,9 +971,11 @@ unsafe fn allocate_for_layout(
     unsafe fn allocate_for_ptr(ptr: *const T) -> *mut RcBox<T> {
         // Allocate for the `RcBox<T>` using the given value.
         unsafe {
-            Self::allocate_for_layout(Layout::for_value(&*ptr), |mem| {
-                set_data_ptr(ptr as *mut T, mem) as *mut RcBox<T>
-            })
+            Self::allocate_for_layout(
+                Layout::for_value(&*ptr),
+                |layout| Global.alloc(layout),
+                |mem| set_data_ptr(ptr as *mut T, mem) as *mut RcBox<T>,
+            )
         }
     }
 
@@ -979,9 +1006,11 @@ impl<T> Rc<[T]> {
     /// Allocates an `RcBox<[T]>` with the given length.
     unsafe fn allocate_for_slice(len: usize) -> *mut RcBox<[T]> {
         unsafe {
-            Self::allocate_for_layout(Layout::array::<T>(len).unwrap(), |mem| {
-                ptr::slice_from_raw_parts_mut(mem as *mut T, len) as *mut RcBox<[T]>
-            })
+            Self::allocate_for_layout(
+                Layout::array::<T>(len).unwrap(),
+                |layout| Global.alloc(layout),
+                |mem| ptr::slice_from_raw_parts_mut(mem as *mut T, len) as *mut RcBox<[T]>,
+            )
         }
     }
 }
@@ -1117,8 +1146,6 @@ unsafe impl<#[may_dangle] T: ?Sized> Drop for Rc<T> {
     /// drop(foo);    // Doesn't print anything
     /// drop(foo2);   // Prints "dropped!"
     /// ```
-    ///
-    /// [`Weak`]: ../../std/rc/struct.Weak.html
     fn drop(&mut self) {
         unsafe {
             self.dec_strong();
@@ -1600,11 +1627,7 @@ fn to_rc_slice(self) -> Rc<[T]> {
 ///
 /// The typical way to obtain a `Weak` pointer is to call [`Rc::downgrade`].
 ///
-/// [`Rc`]: struct.Rc.html
-/// [`Rc::downgrade`]: struct.Rc.html#method.downgrade
-/// [`upgrade`]: struct.Weak.html#method.upgrade
-/// [`Option`]: ../../std/option/enum.Option.html
-/// [`None`]: ../../std/option/enum.Option.html#variant.None
+/// [`upgrade`]: Weak::upgrade
 #[stable(feature = "rc_weak", since = "1.4.0")]
 pub struct Weak<T: ?Sized> {
     // This is a `NonNull` to allow optimizing the size of this type in enums,
@@ -1631,8 +1654,7 @@ impl<T> Weak<T> {
     /// Constructs a new `Weak<T>`, without allocating any memory.
     /// Calling [`upgrade`] on the return value always gives [`None`].
     ///
-    /// [`upgrade`]: #method.upgrade
-    /// [`None`]: ../../std/option/enum.Option.html
+    /// [`upgrade`]: Weak::upgrade
     ///
     /// # Examples
     ///
@@ -1671,7 +1693,7 @@ pub fn new() -> Weak<T> {
     /// // assert_eq!("hello", unsafe { &*weak.as_ptr() });
     /// ```
     ///
-    /// [`null`]: ../../std/ptr/fn.null.html
+    /// [`null`]: core::ptr::null
     #[stable(feature = "rc_as_ptr", since = "1.45.0")]
     pub fn as_ptr(&self) -> *const T {
         let ptr: *mut RcBox<T> = NonNull::as_ptr(self.ptr);
@@ -1713,8 +1735,8 @@ pub fn as_ptr(&self) -> *const T {
     /// assert_eq!(0, Rc::weak_count(&strong));
     /// ```
     ///
-    /// [`from_raw`]: struct.Weak.html#method.from_raw
-    /// [`as_ptr`]: struct.Weak.html#method.as_ptr
+    /// [`from_raw`]: Weak::from_raw
+    /// [`as_ptr`]: Weak::as_ptr
     #[stable(feature = "weak_into_raw", since = "1.45.0")]
     pub fn into_raw(self) -> *const T {
         let result = self.as_ptr();
@@ -1761,12 +1783,9 @@ pub fn into_raw(self) -> *const T {
     /// assert!(unsafe { Weak::from_raw(raw_2) }.upgrade().is_none());
     /// ```
     ///
-    /// [`into_raw`]: struct.Weak.html#method.into_raw
-    /// [`upgrade`]: struct.Weak.html#method.upgrade
-    /// [`Rc`]: struct.Rc.html
-    /// [`Weak`]: struct.Weak.html
-    /// [`new`]: struct.Weak.html#method.new
-    /// [`forget`]: ../../std/mem/fn.forget.html
+    /// [`into_raw`]: Weak::into_raw
+    /// [`upgrade`]: Weak::upgrade
+    /// [`new`]: Weak::new
     #[stable(feature = "weak_into_raw", since = "1.45.0")]
     pub unsafe fn from_raw(ptr: *const T) -> Self {
         if ptr.is_null() {
@@ -1794,9 +1813,6 @@ impl<T: ?Sized> Weak<T> {
     ///
     /// Returns [`None`] if the inner value has since been dropped.
     ///
-    /// [`Rc`]: struct.Rc.html
-    /// [`None`]: ../../std/option/enum.Option.html
-    ///
     /// # Examples
     ///
     /// ```
@@ -1829,8 +1845,6 @@ pub fn upgrade(&self) -> Option<Rc<T>> {
     /// Gets the number of strong (`Rc`) pointers pointing to this allocation.
     ///
     /// If `self` was created using [`Weak::new`], this will return 0.
-    ///
-    /// [`Weak::new`]: #method.new
     #[stable(feature = "weak_counts", since = "1.41.0")]
     pub fn strong_count(&self) -> usize {
         if let Some(inner) = self.inner() { inner.strong() } else { 0 }
@@ -1899,7 +1913,7 @@ fn inner(&self) -> Option<&RcBox<T>> {
     /// assert!(!first.ptr_eq(&third));
     /// ```
     ///
-    /// [`ptr::eq`]: ../../std/ptr/fn.eq.html
+    /// [`ptr::eq`]: core::ptr::eq
     #[inline]
     #[stable(feature = "weak_ptr_eq", since = "1.39.0")]
     pub fn ptr_eq(&self, other: &Self) -> bool {
@@ -1981,8 +1995,8 @@ impl<T> Default for Weak<T> {
     /// Constructs a new `Weak<T>`, allocating memory for `T` without initializing
     /// it. Calling [`upgrade`] on the return value always gives [`None`].
     ///
-    /// [`None`]: ../../std/option/enum.Option.html
-    /// [`upgrade`]: ../../std/rc/struct.Weak.html#method.upgrade
+    /// [`None`]: Option
+    /// [`upgrade`]: Weak::upgrade
     ///
     /// # Examples
     ///
@@ -2090,7 +2104,7 @@ fn as_ref(&self) -> &T {
 #[stable(feature = "pin", since = "1.33.0")]
 impl<T: ?Sized> Unpin for Rc<T> {}
 
-/// Get the offset within an `ArcInner` for
+/// Get the offset within an `RcBox` for
 /// a payload of type described by a pointer.
 ///
 /// # Safety
index b791c775548cda7f8f81f013ad0f38e566e493da..8ea2c6dc859b274c4afa9764e777a7f488f68a77 100644 (file)
 //! * Further methods that return iterators are [`.split`], [`.splitn`],
 //!   [`.chunks`], [`.windows`] and more.
 //!
-//! [`Clone`]: ../../std/clone/trait.Clone.html
-//! [`Eq`]: ../../std/cmp/trait.Eq.html
-//! [`Ord`]: ../../std/cmp/trait.Ord.html
-//! [`Iter`]: struct.Iter.html
-//! [`Hash`]: ../../std/hash/trait.Hash.html
+//! [`Hash`]: core::hash::Hash
 //! [`.iter`]: ../../std/primitive.slice.html#method.iter
 //! [`.iter_mut`]: ../../std/primitive.slice.html#method.iter_mut
 //! [`.split`]: ../../std/primitive.slice.html#method.split
@@ -560,7 +556,7 @@ impl [u8] {
     ///
     /// To uppercase the value in-place, use [`make_ascii_uppercase`].
     ///
-    /// [`make_ascii_uppercase`]: #method.make_ascii_uppercase
+    /// [`make_ascii_uppercase`]: u8::make_ascii_uppercase
     #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
     #[inline]
     pub fn to_ascii_uppercase(&self) -> Vec<u8> {
@@ -577,7 +573,7 @@ pub fn to_ascii_uppercase(&self) -> Vec<u8> {
     ///
     /// To lowercase the value in-place, use [`make_ascii_lowercase`].
     ///
-    /// [`make_ascii_lowercase`]: #method.make_ascii_lowercase
+    /// [`make_ascii_lowercase`]: u8::make_ascii_lowercase
     #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
     #[inline]
     pub fn to_ascii_lowercase(&self) -> Vec<u8> {
index d7d7b6bd157bc2efc3b9e44bdb8db49c54d1b584..05690e19d23e4175264c706af83bc7d7cdb9b70c 100644 (file)
 ///
 /// Here, there's no need to allocate more memory inside the loop.
 ///
-/// [`str`]: type@str
-/// [`&str`]: type@str
+/// [`str`]: prim@str
+/// [`&str`]: prim@str
 /// [`Deref`]: core::ops::Deref
 /// [`as_str()`]: String::as_str
 #[derive(PartialOrd, Eq, Ord)]
@@ -296,7 +296,7 @@ pub struct String {
 ///
 /// [`Utf8Error`]: core::str::Utf8Error
 /// [`std::str`]: core::str
-/// [`&str`]: str
+/// [`&str`]: prim@str
 /// [`utf8_error`]: Self::utf8_error
 ///
 /// # Examples
@@ -472,7 +472,7 @@ pub fn from_str(_: &str) -> String {
     ///
     /// [`from_utf8_unchecked`]: String::from_utf8_unchecked
     /// [`Vec<u8>`]: crate::vec::Vec
-    /// [`&str`]: str
+    /// [`&str`]: prim@str
     /// [`into_bytes`]: String::into_bytes
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -1576,6 +1576,8 @@ pub fn replace_range<R>(&mut self, range: R, replace_with: &str)
     ///
     /// This will drop any excess capacity.
     ///
+    /// [`str`]: prim@str
+    ///
     /// # Examples
     ///
     /// Basic usage:
@@ -1644,7 +1646,7 @@ pub fn into_bytes(self) -> Vec<u8> {
     /// on using it.
     ///
     /// [`std::str`]: core::str
-    /// [`&str`]: str
+    /// [`&str`]: prim@str
     ///
     /// # Examples
     ///
index b37633031375883844506603a0e2c2872c699a09..73d2fe74826ed0ecbe516112107dad15f40aa7d8 100644 (file)
@@ -2,9 +2,7 @@
 
 //! Thread-safe reference-counting pointers.
 //!
-//! See the [`Arc<T>`][arc] documentation for more details.
-//!
-//! [arc]: struct.Arc.html
+//! See the [`Arc<T>`][Arc] documentation for more details.
 
 use core::any::Any;
 use core::borrow;
@@ -23,7 +21,7 @@
 use core::sync::atomic;
 use core::sync::atomic::Ordering::{Acquire, Relaxed, Release, SeqCst};
 
-use crate::alloc::{box_free, handle_alloc_error, AllocRef, Global, Layout};
+use crate::alloc::{box_free, handle_alloc_error, AllocErr, AllocRef, Global, Layout};
 use crate::borrow::{Cow, ToOwned};
 use crate::boxed::Box;
 use crate::rc::is_dangling;
@@ -100,21 +98,21 @@ macro_rules! acquire {
 /// ## Breaking cycles with `Weak`
 ///
 /// The [`downgrade`][downgrade] method can be used to create a non-owning
-/// [`Weak`][weak] pointer. A [`Weak`][weak] pointer can be [`upgrade`][upgrade]d
+/// [`Weak`] pointer. A [`Weak`] pointer can be [`upgrade`][upgrade]d
 /// to an `Arc`, but this will return [`None`] if the value stored in the allocation has
 /// already been dropped. In other words, `Weak` pointers do not keep the value
 /// inside the allocation alive; however, they *do* keep the allocation
 /// (the backing store for the value) alive.
 ///
 /// A cycle between `Arc` pointers will never be deallocated. For this reason,
-/// [`Weak`][weak] is used to break cycles. For example, a tree could have
-/// strong `Arc` pointers from parent nodes to children, and [`Weak`][weak]
+/// [`Weak`] is used to break cycles. For example, a tree could have
+/// strong `Arc` pointers from parent nodes to children, and [`Weak`]
 /// pointers from children back to their parents.
 ///
 /// # Cloning references
 ///
 /// Creating a new reference from an existing reference counted pointer is done using the
-/// `Clone` trait implemented for [`Arc<T>`][arc] and [`Weak<T>`][weak].
+/// `Clone` trait implemented for [`Arc<T>`][Arc] and [`Weak<T>`][Weak].
 ///
 /// ```
 /// use std::sync::Arc;
@@ -139,23 +137,20 @@ macro_rules! acquire {
 /// Arc::downgrade(&my_arc);
 /// ```
 ///
-/// [`Weak<T>`][weak] does not auto-dereference to `T`, because the inner value may have
+/// [`Weak<T>`][Weak] does not auto-dereference to `T`, because the inner value may have
 /// already been dropped.
 ///
-/// [arc]: struct.Arc.html
-/// [weak]: struct.Weak.html
-/// [`Rc<T>`]: ../../std/rc/struct.Rc.html
-/// [clone]: ../../std/clone/trait.Clone.html#tymethod.clone
+/// [`Rc<T>`]: crate::rc::Rc
+/// [clone]: Clone::clone
 /// [mutex]: ../../std/sync/struct.Mutex.html
 /// [rwlock]: ../../std/sync/struct.RwLock.html
-/// [atomic]: ../../std/sync/atomic/index.html
-/// [`Send`]: ../../std/marker/trait.Send.html
-/// [`Sync`]: ../../std/marker/trait.Sync.html
-/// [deref]: ../../std/ops/trait.Deref.html
-/// [downgrade]: struct.Arc.html#method.downgrade
-/// [upgrade]: struct.Weak.html#method.upgrade
-/// [`None`]: ../../std/option/enum.Option.html#variant.None
-/// [`RefCell<T>`]: ../../std/cell/struct.RefCell.html
+/// [atomic]: core::sync::atomic
+/// [`Send`]: core::marker::Send
+/// [`Sync`]: core::marker::Sync
+/// [deref]: core::ops::Deref
+/// [downgrade]: Arc::downgrade
+/// [upgrade]: Weak::upgrade
+/// [`RefCell<T>`]: core::cell::RefCell
 /// [`std::sync`]: ../../std/sync/index.html
 /// [`Arc::clone(&from)`]: #method.clone
 ///
@@ -184,7 +179,7 @@ macro_rules! acquire {
 ///
 /// Sharing a mutable [`AtomicUsize`]:
 ///
-/// [`AtomicUsize`]: ../../std/sync/atomic/struct.AtomicUsize.html
+/// [`AtomicUsize`]: core::sync::atomic::AtomicUsize
 ///
 /// ```no_run
 /// use std::sync::Arc;
@@ -254,11 +249,7 @@ unsafe fn from_ptr(ptr: *mut ArcInner<T>) -> Self {
 ///
 /// The typical way to obtain a `Weak` pointer is to call [`Arc::downgrade`].
 ///
-/// [`Arc`]: struct.Arc.html
-/// [`Arc::downgrade`]: struct.Arc.html#method.downgrade
-/// [`upgrade`]: struct.Weak.html#method.upgrade
-/// [`Option`]: ../../std/option/enum.Option.html
-/// [`None`]: ../../std/option/enum.Option.html#variant.None
+/// [`upgrade`]: Weak::upgrade
 #[stable(feature = "arc_weak", since = "1.4.0")]
 pub struct Weak<T: ?Sized> {
     // This is a `NonNull` to allow optimizing the size of this type in enums,
@@ -328,6 +319,79 @@ pub fn new(data: T) -> Arc<T> {
         Self::from_inner(Box::leak(x).into())
     }
 
+    /// Constructs a new `Arc<T>` using a weak reference to itself. Attempting
+    /// to upgrade the weak reference before this function returns will result
+    /// in a `None` value. However, the weak reference may be cloned freely and
+    /// stored for use at a later time.
+    ///
+    /// # Examples
+    /// ```
+    /// #![feature(arc_new_cyclic)]
+    /// #![allow(dead_code)]
+    ///
+    /// use std::sync::{Arc, Weak};
+    ///
+    /// struct Foo {
+    ///     me: Weak<Foo>,
+    /// }
+    ///
+    /// let foo = Arc::new_cyclic(|me| Foo {
+    ///     me: me.clone(),
+    /// });
+    /// ```
+    #[inline]
+    #[unstable(feature = "arc_new_cyclic", issue = "75861")]
+    pub fn new_cyclic(data_fn: impl FnOnce(&Weak<T>) -> T) -> Arc<T> {
+        // Construct the inner in the "uninitialized" state with a single
+        // weak reference.
+        let uninit_ptr: NonNull<_> = Box::leak(box ArcInner {
+            strong: atomic::AtomicUsize::new(0),
+            weak: atomic::AtomicUsize::new(1),
+            data: mem::MaybeUninit::<T>::uninit(),
+        })
+        .into();
+        let init_ptr: NonNull<ArcInner<T>> = uninit_ptr.cast();
+
+        let weak = Weak { ptr: init_ptr };
+
+        // It's important we don't give up ownership of the weak pointer, or
+        // else the memory might be freed by the time `data_fn` returns. If
+        // we really wanted to pass ownership, we could create an additional
+        // weak pointer for ourselves, but this would result in additional
+        // updates to the weak reference count which might not be necessary
+        // otherwise.
+        let data = data_fn(&weak);
+
+        // Now we can properly initialize the inner value and turn our weak
+        // reference into a strong reference.
+        unsafe {
+            let inner = init_ptr.as_ptr();
+            ptr::write(&raw mut (*inner).data, data);
+
+            // The above write to the data field must be visible to any threads which
+            // observe a non-zero strong count. Therefore we need at least "Release" ordering
+            // in order to synchronize with the `compare_exchange_weak` in `Weak::upgrade`.
+            //
+            // "Acquire" ordering is not required. When considering the possible behaviours
+            // of `data_fn` we only need to look at what it could do with a reference to a
+            // non-upgradeable `Weak`:
+            // - It can *clone* the `Weak`, increasing the weak reference count.
+            // - It can drop those clones, decreasing the weak reference count (but never to zero).
+            //
+            // These side effects do not impact us in any way, and no other side effects are
+            // possible with safe code alone.
+            let prev_value = (*inner).strong.fetch_add(1, Release);
+            debug_assert_eq!(prev_value, 0, "No prior strong references should exist");
+        }
+
+        let strong = Arc::from_inner(init_ptr);
+
+        // Strong references should collectively own a shared weak reference,
+        // so don't run the destructor for our old weak reference.
+        mem::forget(weak);
+        strong
+    }
+
     /// Constructs a new `Arc` with uninitialized contents.
     ///
     /// # Examples
@@ -352,9 +416,11 @@ pub fn new(data: T) -> Arc<T> {
     #[unstable(feature = "new_uninit", issue = "63291")]
     pub fn new_uninit() -> Arc<mem::MaybeUninit<T>> {
         unsafe {
-            Arc::from_ptr(Arc::allocate_for_layout(Layout::new::<T>(), |mem| {
-                mem as *mut ArcInner<mem::MaybeUninit<T>>
-            }))
+            Arc::from_ptr(Arc::allocate_for_layout(
+                Layout::new::<T>(),
+                |layout| Global.alloc(layout),
+                |mem| mem as *mut ArcInner<mem::MaybeUninit<T>>,
+            ))
         }
     }
 
@@ -381,9 +447,11 @@ pub fn new_uninit() -> Arc<mem::MaybeUninit<T>> {
     #[unstable(feature = "new_uninit", issue = "63291")]
     pub fn new_zeroed() -> Arc<mem::MaybeUninit<T>> {
         unsafe {
-            let mut uninit = Self::new_uninit();
-            ptr::write_bytes::<T>(Arc::get_mut_unchecked(&mut uninit).as_mut_ptr(), 0, 1);
-            uninit
+            Arc::from_ptr(Arc::allocate_for_layout(
+                Layout::new::<T>(),
+                |layout| Global.alloc_zeroed(layout),
+                |mem| mem as *mut ArcInner<mem::MaybeUninit<T>>,
+            ))
         }
     }
 
@@ -396,13 +464,11 @@ pub fn pin(data: T) -> Pin<Arc<T>> {
 
     /// Returns the inner value, if the `Arc` has exactly one strong reference.
     ///
-    /// Otherwise, an [`Err`][result] is returned with the same `Arc` that was
+    /// Otherwise, an [`Err`] is returned with the same `Arc` that was
     /// passed in.
     ///
     /// This will succeed even if there are outstanding weak references.
     ///
-    /// [result]: ../../std/result/enum.Result.html
-    ///
     /// # Examples
     ///
     /// ```
@@ -437,7 +503,7 @@ pub fn try_unwrap(this: Self) -> Result<T, Self> {
 }
 
 impl<T> Arc<[T]> {
-    /// Constructs a new reference-counted slice with uninitialized contents.
+    /// Constructs a new atomically reference-counted slice with uninitialized contents.
     ///
     /// # Examples
     ///
@@ -464,6 +530,40 @@ impl<T> Arc<[T]> {
     pub fn new_uninit_slice(len: usize) -> Arc<[mem::MaybeUninit<T>]> {
         unsafe { Arc::from_ptr(Arc::allocate_for_slice(len)) }
     }
+
+    /// Constructs a new atomically reference-counted slice with uninitialized contents, with the memory being
+    /// filled with `0` bytes.
+    ///
+    /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and
+    /// incorrect usage of this method.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(new_uninit)]
+    ///
+    /// use std::sync::Arc;
+    ///
+    /// let values = Arc::<[u32]>::new_zeroed_slice(3);
+    /// let values = unsafe { values.assume_init() };
+    ///
+    /// assert_eq!(*values, [0, 0, 0])
+    /// ```
+    ///
+    /// [zeroed]: ../../std/mem/union.MaybeUninit.html#method.zeroed
+    #[unstable(feature = "new_uninit", issue = "63291")]
+    pub fn new_zeroed_slice(len: usize) -> Arc<[mem::MaybeUninit<T>]> {
+        unsafe {
+            Arc::from_ptr(Arc::allocate_for_layout(
+                Layout::array::<T>(len).unwrap(),
+                |layout| Global.alloc_zeroed(layout),
+                |mem| {
+                    ptr::slice_from_raw_parts_mut(mem as *mut T, len)
+                        as *mut ArcInner<[mem::MaybeUninit<T>]>
+                },
+            ))
+        }
+    }
 }
 
 impl<T> Arc<mem::MaybeUninit<T>> {
@@ -550,9 +650,7 @@ impl<T: ?Sized> Arc<T> {
     /// Consumes the `Arc`, returning the wrapped pointer.
     ///
     /// To avoid a memory leak the pointer must be converted back to an `Arc` using
-    /// [`Arc::from_raw`][from_raw].
-    ///
-    /// [from_raw]: struct.Arc.html#method.from_raw
+    /// [`Arc::from_raw`].
     ///
     /// # Examples
     ///
@@ -612,8 +710,8 @@ pub fn as_ptr(this: &Self) -> *const T {
     /// This function is unsafe because improper use may lead to memory unsafety,
     /// even if the returned `Arc<T>` is never accessed.
     ///
-    /// [into_raw]: struct.Arc.html#method.into_raw
-    /// [transmute]: ../../std/mem/fn.transmute.html
+    /// [into_raw]: Arc::into_raw
+    /// [transmute]: core::mem::transmute
     ///
     /// # Examples
     ///
@@ -646,9 +744,7 @@ pub unsafe fn from_raw(ptr: *const T) -> Self {
         }
     }
 
-    /// Creates a new [`Weak`][weak] pointer to this allocation.
-    ///
-    /// [weak]: struct.Weak.html
+    /// Creates a new [`Weak`] pointer to this allocation.
     ///
     /// # Examples
     ///
@@ -690,9 +786,7 @@ pub fn downgrade(this: &Self) -> Weak<T> {
         }
     }
 
-    /// Gets the number of [`Weak`][weak] pointers to this allocation.
-    ///
-    /// [weak]: struct.Weak.html
+    /// Gets the number of [`Weak`] pointers to this allocation.
     ///
     /// # Safety
     ///
@@ -861,7 +955,7 @@ unsafe fn drop_slow(&mut self) {
     /// assert!(!Arc::ptr_eq(&five, &other_five));
     /// ```
     ///
-    /// [`ptr::eq`]: ../../std/ptr/fn.eq.html
+    /// [`ptr::eq`]: core::ptr::eq
     pub fn ptr_eq(this: &Self, other: &Self) -> bool {
         this.ptr.as_ptr() == other.ptr.as_ptr()
     }
@@ -875,6 +969,7 @@ impl<T: ?Sized> Arc<T> {
     /// and must return back a (potentially fat)-pointer for the `ArcInner<T>`.
     unsafe fn allocate_for_layout(
         value_layout: Layout,
+        allocate: impl FnOnce(Layout) -> Result<NonNull<[u8]>, AllocErr>,
         mem_to_arcinner: impl FnOnce(*mut u8) -> *mut ArcInner<T>,
     ) -> *mut ArcInner<T> {
         // Calculate layout using the given value layout.
@@ -883,7 +978,7 @@ unsafe fn allocate_for_layout(
         // reference (see #54908).
         let layout = Layout::new::<ArcInner<()>>().extend(value_layout).unwrap().0.pad_to_align();
 
-        let ptr = Global.alloc(layout).unwrap_or_else(|_| handle_alloc_error(layout));
+        let ptr = allocate(layout).unwrap_or_else(|_| handle_alloc_error(layout));
 
         // Initialize the ArcInner
         let inner = mem_to_arcinner(ptr.as_non_null_ptr().as_ptr());
@@ -901,9 +996,11 @@ unsafe fn allocate_for_layout(
     unsafe fn allocate_for_ptr(ptr: *const T) -> *mut ArcInner<T> {
         // Allocate for the `ArcInner<T>` using the given value.
         unsafe {
-            Self::allocate_for_layout(Layout::for_value(&*ptr), |mem| {
-                set_data_ptr(ptr as *mut T, mem) as *mut ArcInner<T>
-            })
+            Self::allocate_for_layout(
+                Layout::for_value(&*ptr),
+                |layout| Global.alloc(layout),
+                |mem| set_data_ptr(ptr as *mut T, mem) as *mut ArcInner<T>,
+            )
         }
     }
 
@@ -934,9 +1031,11 @@ impl<T> Arc<[T]> {
     /// Allocates an `ArcInner<[T]>` with the given length.
     unsafe fn allocate_for_slice(len: usize) -> *mut ArcInner<[T]> {
         unsafe {
-            Self::allocate_for_layout(Layout::array::<T>(len).unwrap(), |mem| {
-                ptr::slice_from_raw_parts_mut(mem as *mut T, len) as *mut ArcInner<[T]>
-            })
+            Self::allocate_for_layout(
+                Layout::array::<T>(len).unwrap(),
+                |layout| Global.alloc(layout),
+                |mem| ptr::slice_from_raw_parts_mut(mem as *mut T, len) as *mut ArcInner<[T]>,
+            )
         }
     }
 }
@@ -1098,7 +1197,7 @@ impl<T: ?Sized> Receiver for Arc<T> {}
 impl<T: Clone> Arc<T> {
     /// Makes a mutable reference into the given `Arc`.
     ///
-    /// If there are other `Arc` or [`Weak`][weak] pointers to the same allocation,
+    /// If there are other `Arc` or [`Weak`] pointers to the same allocation,
     /// then `make_mut` will create a new allocation and invoke [`clone`][clone] on the inner value
     /// to ensure unique ownership. This is also referred to as clone-on-write.
     ///
@@ -1107,10 +1206,9 @@ impl<T: Clone> Arc<T> {
     ///
     /// See also [`get_mut`][get_mut], which will fail rather than cloning.
     ///
-    /// [weak]: struct.Weak.html
-    /// [clone]: ../../std/clone/trait.Clone.html#tymethod.clone
-    /// [get_mut]: struct.Arc.html#method.get_mut
-    /// [`Rc::make_mut`]: ../rc/struct.Rc.html#method.make_mut
+    /// [clone]: Clone::clone
+    /// [get_mut]: Arc::get_mut
+    /// [`Rc::make_mut`]: super::rc::Rc::make_mut
     ///
     /// # Examples
     ///
@@ -1184,18 +1282,16 @@ pub fn make_mut(this: &mut Self) -> &mut T {
 
 impl<T: ?Sized> Arc<T> {
     /// Returns a mutable reference into the given `Arc`, if there are
-    /// no other `Arc` or [`Weak`][weak] pointers to the same allocation.
+    /// no other `Arc` or [`Weak`] pointers to the same allocation.
     ///
-    /// Returns [`None`][option] otherwise, because it is not safe to
+    /// Returns [`None`] otherwise, because it is not safe to
     /// mutate a shared value.
     ///
     /// See also [`make_mut`][make_mut], which will [`clone`][clone]
     /// the inner value when there are other pointers.
     ///
-    /// [weak]: struct.Weak.html
-    /// [option]: ../../std/option/enum.Option.html
-    /// [make_mut]: struct.Arc.html#method.make_mut
-    /// [clone]: ../../std/clone/trait.Clone.html#tymethod.clone
+    /// [make_mut]: Arc::make_mut
+    /// [clone]: Clone::clone
     ///
     /// # Examples
     ///
@@ -1229,7 +1325,7 @@ pub fn get_mut(this: &mut Self) -> Option<&mut T> {
     ///
     /// See also [`get_mut`], which is safe and does appropriate checks.
     ///
-    /// [`get_mut`]: struct.Arc.html#method.get_mut
+    /// [`get_mut`]: Arc::get_mut
     ///
     /// # Safety
     ///
@@ -1315,8 +1411,6 @@ unsafe impl<#[may_dangle] T: ?Sized> Drop for Arc<T> {
     /// drop(foo);    // Doesn't print anything
     /// drop(foo2);   // Prints "dropped!"
     /// ```
-    ///
-    /// [`Weak`]: ../../std/sync/struct.Weak.html
     #[inline]
     fn drop(&mut self) {
         // Because `fetch_sub` is already atomic, we do not need to synchronize
@@ -1401,8 +1495,7 @@ impl<T> Weak<T> {
     /// Constructs a new `Weak<T>`, without allocating any memory.
     /// Calling [`upgrade`] on the return value always gives [`None`].
     ///
-    /// [`upgrade`]: struct.Weak.html#method.upgrade
-    /// [`None`]: ../../std/option/enum.Option.html#variant.None
+    /// [`upgrade`]: Weak::upgrade
     ///
     /// # Examples
     ///
@@ -1441,7 +1534,7 @@ pub fn new() -> Weak<T> {
     /// // assert_eq!("hello", unsafe { &*weak.as_ptr() });
     /// ```
     ///
-    /// [`null`]: ../../std/ptr/fn.null.html
+    /// [`null`]: core::ptr::null
     #[stable(feature = "weak_into_raw", since = "1.45.0")]
     pub fn as_ptr(&self) -> *const T {
         let ptr: *mut ArcInner<T> = NonNull::as_ptr(self.ptr);
@@ -1483,8 +1576,8 @@ pub fn as_ptr(&self) -> *const T {
     /// assert_eq!(0, Arc::weak_count(&strong));
     /// ```
     ///
-    /// [`from_raw`]: struct.Weak.html#method.from_raw
-    /// [`as_ptr`]: struct.Weak.html#method.as_ptr
+    /// [`from_raw`]: Weak::from_raw
+    /// [`as_ptr`]: Weak::as_ptr
     #[stable(feature = "weak_into_raw", since = "1.45.0")]
     pub fn into_raw(self) -> *const T {
         let result = self.as_ptr();
@@ -1530,12 +1623,10 @@ pub fn into_raw(self) -> *const T {
     /// assert!(unsafe { Weak::from_raw(raw_2) }.upgrade().is_none());
     /// ```
     ///
-    /// [`new`]: struct.Weak.html#method.new
-    /// [`into_raw`]: struct.Weak.html#method.into_raw
-    /// [`upgrade`]: struct.Weak.html#method.upgrade
-    /// [`Weak`]: struct.Weak.html
-    /// [`Arc`]: struct.Arc.html
-    /// [`forget`]: ../../std/mem/fn.forget.html
+    /// [`new`]: Weak::new
+    /// [`into_raw`]: Weak::into_raw
+    /// [`upgrade`]: Weak::upgrade
+    /// [`forget`]: std::mem::forget
     #[stable(feature = "weak_into_raw", since = "1.45.0")]
     pub unsafe fn from_raw(ptr: *const T) -> Self {
         if ptr.is_null() {
@@ -1565,9 +1656,6 @@ impl<T: ?Sized> Weak<T> {
     ///
     /// Returns [`None`] if the inner value has since been dropped.
     ///
-    /// [`Arc`]: struct.Arc.html
-    /// [`None`]: ../../std/option/enum.Option.html#variant.None
-    ///
     /// # Examples
     ///
     /// ```
@@ -1589,7 +1677,8 @@ impl<T: ?Sized> Weak<T> {
     #[stable(feature = "arc_weak", since = "1.4.0")]
     pub fn upgrade(&self) -> Option<Arc<T>> {
         // We use a CAS loop to increment the strong count instead of a
-        // fetch_add because once the count hits 0 it must never be above 0.
+        // fetch_add as this function should never take the reference count
+        // from zero to one.
         let inner = self.inner()?;
 
         // Relaxed load because any write of 0 that we can observe
@@ -1608,8 +1697,11 @@ pub fn upgrade(&self) -> Option<Arc<T>> {
                 abort();
             }
 
-            // Relaxed is valid for the same reason it is on Arc's Clone impl
-            match inner.strong.compare_exchange_weak(n, n + 1, Relaxed, Relaxed) {
+            // Relaxed is fine for the failure case because we don't have any expectations about the new state.
+            // Acquire is necessary for the success case to synchronise with `Arc::new_cyclic`, when the inner
+            // value can be initialized after `Weak` references have already been created. In that case, we
+            // expect to observe the fully initialized value.
+            match inner.strong.compare_exchange_weak(n, n + 1, Acquire, Relaxed) {
                 Ok(_) => return Some(Arc::from_inner(self.ptr)), // null checked above
                 Err(old) => n = old,
             }
@@ -1619,8 +1711,6 @@ pub fn upgrade(&self) -> Option<Arc<T>> {
     /// Gets the number of strong (`Arc`) pointers pointing to this allocation.
     ///
     /// If `self` was created using [`Weak::new`], this will return 0.
-    ///
-    /// [`Weak::new`]: #method.new
     #[stable(feature = "weak_counts", since = "1.41.0")]
     pub fn strong_count(&self) -> usize {
         if let Some(inner) = self.inner() { inner.strong.load(SeqCst) } else { 0 }
@@ -1637,8 +1727,6 @@ pub fn strong_count(&self) -> usize {
     /// Due to implementation details, the returned value can be off by 1 in
     /// either direction when other threads are manipulating any `Arc`s or
     /// `Weak`s pointing to the same allocation.
-    ///
-    /// [`Weak::new`]: #method.new
     #[stable(feature = "weak_counts", since = "1.41.0")]
     pub fn weak_count(&self) -> usize {
         self.inner()
@@ -1716,7 +1804,7 @@ fn inner(&self) -> Option<WeakInner<'_>> {
     /// assert!(!first.ptr_eq(&third));
     /// ```
     ///
-    /// [`ptr::eq`]: ../../std/ptr/fn.eq.html
+    /// [`ptr::eq`]: core::ptr::eq
     #[inline]
     #[stable(feature = "weak_ptr_eq", since = "1.39.0")]
     pub fn ptr_eq(&self, other: &Self) -> bool {
@@ -1765,8 +1853,7 @@ impl<T> Default for Weak<T> {
     /// Calling [`upgrade`] on the return value always
     /// gives [`None`].
     ///
-    /// [`None`]: ../../std/option/enum.Option.html#variant.None
-    /// [`upgrade`]: ../../std/sync/struct.Weak.html#method.upgrade
+    /// [`upgrade`]: Weak::upgrade
     ///
     /// # Examples
     ///
index 6f08cd7f123be67c2d036e615f2a5286da21f493..d25171716061d1cff39f7e32583f2a80ce2ebd69 100644 (file)
@@ -492,3 +492,70 @@ fn test_array_from_slice() {
     let a: Result<Arc<[u32; 2]>, _> = r.clone().try_into();
     assert!(a.is_err());
 }
+
+#[test]
+fn test_arc_cyclic_with_zero_refs() {
+    struct ZeroRefs {
+        inner: Weak<ZeroRefs>,
+    }
+    let zero_refs = Arc::new_cyclic(|inner| {
+        assert_eq!(inner.strong_count(), 0);
+        assert!(inner.upgrade().is_none());
+        ZeroRefs { inner: Weak::new() }
+    });
+
+    assert_eq!(Arc::strong_count(&zero_refs), 1);
+    assert_eq!(Arc::weak_count(&zero_refs), 0);
+    assert_eq!(zero_refs.inner.strong_count(), 0);
+    assert_eq!(zero_refs.inner.weak_count(), 0);
+}
+
+#[test]
+fn test_arc_new_cyclic_one_ref() {
+    struct OneRef {
+        inner: Weak<OneRef>,
+    }
+    let one_ref = Arc::new_cyclic(|inner| {
+        assert_eq!(inner.strong_count(), 0);
+        assert!(inner.upgrade().is_none());
+        OneRef { inner: inner.clone() }
+    });
+
+    assert_eq!(Arc::strong_count(&one_ref), 1);
+    assert_eq!(Arc::weak_count(&one_ref), 1);
+
+    let one_ref2 = Weak::upgrade(&one_ref.inner).unwrap();
+    assert!(Arc::ptr_eq(&one_ref, &one_ref2));
+
+    assert_eq!(Arc::strong_count(&one_ref), 2);
+    assert_eq!(Arc::weak_count(&one_ref), 1);
+}
+
+#[test]
+fn test_arc_cyclic_two_refs() {
+    struct TwoRefs {
+        inner1: Weak<TwoRefs>,
+        inner2: Weak<TwoRefs>,
+    }
+    let two_refs = Arc::new_cyclic(|inner| {
+        assert_eq!(inner.strong_count(), 0);
+        assert!(inner.upgrade().is_none());
+
+        let inner1 = inner.clone();
+        let inner2 = inner1.clone();
+
+        TwoRefs { inner1, inner2 }
+    });
+
+    assert_eq!(Arc::strong_count(&two_refs), 1);
+    assert_eq!(Arc::weak_count(&two_refs), 2);
+
+    let two_refs1 = Weak::upgrade(&two_refs.inner1).unwrap();
+    assert!(Arc::ptr_eq(&two_refs, &two_refs1));
+
+    let two_refs2 = Weak::upgrade(&two_refs.inner2).unwrap();
+    assert!(Arc::ptr_eq(&two_refs, &two_refs2));
+
+    assert_eq!(Arc::strong_count(&two_refs), 3);
+    assert_eq!(Arc::weak_count(&two_refs), 2);
+}
index 7129f0f24029187bbb93712012dbf5c232f8501f..a5ddf7619b6dc7c23b9be4d8dd06628fdcfc82a2 100644 (file)
@@ -85,7 +85,7 @@ pub const fn from_size_align(size: usize, align: usize) -> Result<Self, LayoutEr
     /// # Safety
     ///
     /// This function is unsafe as it does not verify the preconditions from
-    /// [`Layout::from_size_align`](#method.from_size_align).
+    /// [`Layout::from_size_align`].
     #[stable(feature = "alloc_layout", since = "1.28.0")]
     #[rustc_const_stable(feature = "alloc_layout", since = "1.28.0")]
     #[inline]
@@ -196,8 +196,7 @@ pub const fn dangling(&self) -> NonNull<u8> {
     /// will *still* have size 16.
     ///
     /// Returns an error if the combination of `self.size()` and the given
-    /// `align` violates the conditions listed in
-    /// [`Layout::from_size_align`](#method.from_size_align).
+    /// `align` violates the conditions listed in [`Layout::from_size_align`].
     #[stable(feature = "alloc_layout_manipulation", since = "1.44.0")]
     #[inline]
     pub fn align_to(&self, align: usize) -> Result<Self, LayoutErr> {
index ad4f8bf1397c2de696b727dc4ab927204ac3cd4d..c1fda2fce641fead20d505a0e293dfb4d10d9b01 100644 (file)
@@ -147,9 +147,8 @@ fn alloc_zeroed(&mut self, layout: Layout) -> Result<NonNull<[u8]>, AllocErr> {
     /// Attempts to extend the memory block.
     ///
     /// Returns a new [`NonNull<[u8]>`] containing a pointer and the actual size of the allocated
-    /// memory. The pointer is suitable for holding data described by a new layout with `layout`’s
-    /// alignment and a size given by `new_size`. To accomplish this, the allocator may extend the
-    /// allocation referenced by `ptr` to fit the new layout.
+    /// memory. The pointer is suitable for holding data described by `new_layout`. To accomplish
+    /// this, the allocator may extend 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 allocator. The memory may or may not have been freed, and should be
@@ -163,11 +162,9 @@ fn alloc_zeroed(&mut self, layout: Layout) -> Result<NonNull<[u8]>, AllocErr> {
     ///
     /// # Safety
     ///
-    /// * `ptr` must denote a block of memory [*currently allocated*] via this allocator,
-    /// * `layout` must [*fit*] that block of memory (The `new_size` argument need not fit it.),
-    /// * `new_size` must be greater than or equal to `layout.size()`, and
-    /// * `new_size`, when rounded up to the nearest multiple of `layout.align()`, must not overflow
-    ///   (i.e., the rounded value must be less than or equal to `usize::MAX`).
+    /// * `ptr` must denote a block of memory [*currently allocated*] via this allocator.
+    /// * `old_layout` must [*fit*] that block of memory (The `new_layout` argument need not fit it.).
+    /// * `new_layout.size()` must be greater than or equal to `old_layout.size()`.
     ///
     /// [*currently allocated*]: #currently-allocated-memory
     /// [*fit*]: #memory-fitting
@@ -188,28 +185,24 @@ fn alloc_zeroed(&mut self, layout: Layout) -> Result<NonNull<[u8]>, AllocErr> {
     unsafe fn grow(
         &mut self,
         ptr: NonNull<u8>,
-        layout: Layout,
-        new_size: usize,
+        old_layout: Layout,
+        new_layout: Layout,
     ) -> Result<NonNull<[u8]>, AllocErr> {
-        let size = layout.size();
         debug_assert!(
-            new_size >= size,
-            "`new_size` must be greater than or equal to `layout.size()`"
+            new_layout.size() >= old_layout.size(),
+            "`new_layout.size()` must be greater than or equal to `old_layout.size()`"
         );
 
-        // SAFETY: the caller must ensure that the `new_size` does not overflow.
-        // `layout.align()` comes from a `Layout` and is thus guaranteed to be valid for a Layout.
-        let new_layout = unsafe { Layout::from_size_align_unchecked(new_size, layout.align()) };
         let new_ptr = self.alloc(new_layout)?;
 
-        // SAFETY: because `new_size` must be greater than or equal to `size`, both the old and new
-        // memory allocation are valid for reads and writes for `size` bytes. Also, because the old
-        // allocation wasn't yet deallocated, it cannot overlap `new_ptr`. Thus, the call to
-        // `copy_nonoverlapping` is safe.
-        // The safety contract for `dealloc` must be upheld by the caller.
+        // SAFETY: because `new_layout.size()` must be greater than or equal to
+        // `old_layout.size()`, both the old and new memory allocation are valid for reads and
+        // writes for `old_layout.size()` bytes. Also, because the old allocation wasn't yet
+        // deallocated, it cannot overlap `new_ptr`. Thus, the call to `copy_nonoverlapping` is
+        // safe. The safety contract for `dealloc` must be upheld by the caller.
         unsafe {
-            ptr::copy_nonoverlapping(ptr.as_ptr(), new_ptr.as_mut_ptr(), size);
-            self.dealloc(ptr, layout);
+            ptr::copy_nonoverlapping(ptr.as_ptr(), new_ptr.as_mut_ptr(), old_layout.size());
+            self.dealloc(ptr, old_layout);
         }
 
         Ok(new_ptr)
@@ -220,21 +213,19 @@ unsafe fn grow(
     ///
     /// The memory block will contain the following contents after a successful call to
     /// `grow_zeroed`:
-    ///   * Bytes `0..layout.size()` are preserved from the original allocation.
-    ///   * Bytes `layout.size()..old_size` will either be preserved or zeroed, depending on the
-    ///     allocator implementation. `old_size` refers to the size of the memory block prior to
-    ///     the `grow_zeroed` call, which may be larger than the size that was originally requested
-    ///     when it was allocated.
+    ///   * Bytes `0..old_layout.size()` are preserved from the original allocation.
+    ///   * Bytes `old_layout.size()..old_size` will either be preserved or zeroed, depending on
+    ///     the allocator implementation. `old_size` refers to the size of the memory block prior
+    ///     to the `grow_zeroed` call, which may be larger than the size that was originally
+    ///     requested when it was allocated.
     ///   * Bytes `old_size..new_size` are zeroed. `new_size` refers to the size of the memory
-    ///     block returned by the `grow` call.
+    ///     block returned by the `grow_zeroed` call.
     ///
     /// # Safety
     ///
-    /// * `ptr` must denote a block of memory [*currently allocated*] via this allocator,
-    /// * `layout` must [*fit*] that block of memory (The `new_size` argument need not fit it.),
-    /// * `new_size` must be greater than or equal to `layout.size()`, and
-    /// * `new_size`, when rounded up to the nearest multiple of `layout.align()`, must not overflow
-    ///   (i.e., the rounded value must be less than or equal to `usize::MAX`).
+    /// * `ptr` must denote a block of memory [*currently allocated*] via this allocator.
+    /// * `old_layout` must [*fit*] that block of memory (The `new_layout` argument need not fit it.).
+    /// * `new_layout.size()` must be greater than or equal to `old_layout.size()`.
     ///
     /// [*currently allocated*]: #currently-allocated-memory
     /// [*fit*]: #memory-fitting
@@ -255,28 +246,24 @@ unsafe fn grow(
     unsafe fn grow_zeroed(
         &mut self,
         ptr: NonNull<u8>,
-        layout: Layout,
-        new_size: usize,
+        old_layout: Layout,
+        new_layout: Layout,
     ) -> Result<NonNull<[u8]>, AllocErr> {
-        let size = layout.size();
         debug_assert!(
-            new_size >= size,
-            "`new_size` must be greater than or equal to `layout.size()`"
+            new_layout.size() >= old_layout.size(),
+            "`new_layout.size()` must be greater than or equal to `old_layout.size()`"
         );
 
-        // SAFETY: the caller must ensure that the `new_size` does not overflow.
-        // `layout.align()` comes from a `Layout` and is thus guaranteed to be valid for a Layout.
-        let new_layout = unsafe { Layout::from_size_align_unchecked(new_size, layout.align()) };
         let new_ptr = self.alloc_zeroed(new_layout)?;
 
-        // SAFETY: because `new_size` must be greater than or equal to `size`, both the old and new
-        // memory allocation are valid for reads and writes for `size` bytes. Also, because the old
-        // allocation wasn't yet deallocated, it cannot overlap `new_ptr`. Thus, the call to
-        // `copy_nonoverlapping` is safe.
-        // The safety contract for `dealloc` must be upheld by the caller.
+        // SAFETY: because `new_layout.size()` must be greater than or equal to
+        // `old_layout.size()`, both the old and new memory allocation are valid for reads and
+        // writes for `old_layout.size()` bytes. Also, because the old allocation wasn't yet
+        // deallocated, it cannot overlap `new_ptr`. Thus, the call to `copy_nonoverlapping` is
+        // safe. The safety contract for `dealloc` must be upheld by the caller.
         unsafe {
-            ptr::copy_nonoverlapping(ptr.as_ptr(), new_ptr.as_mut_ptr(), size);
-            self.dealloc(ptr, layout);
+            ptr::copy_nonoverlapping(ptr.as_ptr(), new_ptr.as_mut_ptr(), old_layout.size());
+            self.dealloc(ptr, old_layout);
         }
 
         Ok(new_ptr)
@@ -285,9 +272,8 @@ unsafe fn grow_zeroed(
     /// Attempts to shrink the memory block.
     ///
     /// Returns a new [`NonNull<[u8]>`] containing a pointer and the actual size of the allocated
-    /// memory. The pointer is suitable for holding data described by a new layout with `layout`’s
-    /// alignment and a size given by `new_size`. To accomplish this, the allocator may shrink the
-    /// allocation referenced by `ptr` to fit the new layout.
+    /// memory. The pointer is suitable for holding data described by `new_layout`. To accomplish
+    /// this, the allocator may 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 allocator. The memory may or may not have been freed, and should be
@@ -301,9 +287,9 @@ unsafe fn grow_zeroed(
     ///
     /// # Safety
     ///
-    /// * `ptr` must denote a block of memory [*currently allocated*] via this allocator,
-    /// * `layout` must [*fit*] that block of memory (The `new_size` argument need not fit it.), and
-    /// * `new_size` must be smaller than or equal to `layout.size()`.
+    /// * `ptr` must denote a block of memory [*currently allocated*] via this allocator.
+    /// * `old_layout` must [*fit*] that block of memory (The `new_layout` argument need not fit it.).
+    /// * `new_layout.size()` must be smaller than or equal to `old_layout.size()`.
     ///
     /// [*currently allocated*]: #currently-allocated-memory
     /// [*fit*]: #memory-fitting
@@ -324,28 +310,24 @@ unsafe fn grow_zeroed(
     unsafe fn shrink(
         &mut self,
         ptr: NonNull<u8>,
-        layout: Layout,
-        new_size: usize,
+        old_layout: Layout,
+        new_layout: Layout,
     ) -> Result<NonNull<[u8]>, AllocErr> {
-        let size = layout.size();
         debug_assert!(
-            new_size <= size,
-            "`new_size` must be smaller than or equal to `layout.size()`"
+            new_layout.size() <= old_layout.size(),
+            "`new_layout.size()` must be smaller than or equal to `old_layout.size()`"
         );
 
-        // SAFETY: the caller must ensure that the `new_size` does not overflow.
-        // `layout.align()` comes from a `Layout` and is thus guaranteed to be valid for a Layout.
-        let new_layout = unsafe { Layout::from_size_align_unchecked(new_size, layout.align()) };
         let new_ptr = self.alloc(new_layout)?;
 
-        // SAFETY: because `new_size` must be lower than or equal to `size`, both the old and new
-        // memory allocation are valid for reads and writes for `new_size` bytes. Also, because the
-        // old allocation wasn't yet deallocated, it cannot overlap `new_ptr`. Thus, the call to
-        // `copy_nonoverlapping` is safe.
-        // The safety contract for `dealloc` must be upheld by the caller.
+        // SAFETY: because `new_layout.size()` must be lower than or equal to
+        // `old_layout.size()`, both the old and new memory allocation are valid for reads and
+        // writes for `new_layout.size()` bytes. Also, because the old allocation wasn't yet
+        // deallocated, it cannot overlap `new_ptr`. Thus, the call to `copy_nonoverlapping` is
+        // safe. The safety contract for `dealloc` must be upheld by the caller.
         unsafe {
-            ptr::copy_nonoverlapping(ptr.as_ptr(), new_ptr.as_mut_ptr(), size);
-            self.dealloc(ptr, layout);
+            ptr::copy_nonoverlapping(ptr.as_ptr(), new_ptr.as_mut_ptr(), new_layout.size());
+            self.dealloc(ptr, old_layout);
         }
 
         Ok(new_ptr)
@@ -385,32 +367,32 @@ unsafe fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout) {
     unsafe fn grow(
         &mut self,
         ptr: NonNull<u8>,
-        layout: Layout,
-        new_size: usize,
+        old_layout: Layout,
+        new_layout: Layout,
     ) -> Result<NonNull<[u8]>, AllocErr> {
         // SAFETY: the safety contract must be upheld by the caller
-        unsafe { (**self).grow(ptr, layout, new_size) }
+        unsafe { (**self).grow(ptr, old_layout, new_layout) }
     }
 
     #[inline]
     unsafe fn grow_zeroed(
         &mut self,
         ptr: NonNull<u8>,
-        layout: Layout,
-        new_size: usize,
+        old_layout: Layout,
+        new_layout: Layout,
     ) -> Result<NonNull<[u8]>, AllocErr> {
         // SAFETY: the safety contract must be upheld by the caller
-        unsafe { (**self).grow_zeroed(ptr, layout, new_size) }
+        unsafe { (**self).grow_zeroed(ptr, old_layout, new_layout) }
     }
 
     #[inline]
     unsafe fn shrink(
         &mut self,
         ptr: NonNull<u8>,
-        layout: Layout,
-        new_size: usize,
+        old_layout: Layout,
+        new_layout: Layout,
     ) -> Result<NonNull<[u8]>, AllocErr> {
         // SAFETY: the safety contract must be upheld by the caller
-        unsafe { (**self).shrink(ptr, layout, new_size) }
+        unsafe { (**self).shrink(ptr, old_layout, new_layout) }
     }
 }
index 6b28ab7d755631f68860ed2cd402f9d1cb20c418..88795d8429d29ff57b91e63f32890936edc47827 100644 (file)
@@ -32,9 +32,6 @@
 /// Note that the traits [`AsRef`] and [`AsMut`] provide similar methods for types that
 /// may not be fixed-size arrays. Implementors should prefer those traits
 /// instead.
-///
-/// [`AsRef`]: ../convert/trait.AsRef.html
-/// [`AsMut`]: ../convert/trait.AsMut.html
 #[unstable(feature = "fixed_size_array", issue = "27778")]
 pub unsafe trait FixedSizeArray<T> {
     /// Converts the array to immutable slice
index 1b4e906e4e47523615759379f91b63c7636db132..7a68de5e6afb8c8cc02476cbb0105ee93ef9afd2 100644 (file)
@@ -94,7 +94,6 @@
 /// Point], but only ones within a certain range. `MAX` is the highest valid
 /// code point that's a valid [Unicode Scalar Value].
 ///
-/// [`char`]: ../../std/primitive.char.html
 /// [Unicode Scalar Value]: http://www.unicode.org/glossary/#unicode_scalar_value
 /// [Code Point]: http://www.unicode.org/glossary/#code_point
 #[stable(feature = "rust1", since = "1.0.0")]
 /// This `struct` is created by the [`escape_unicode`] method on [`char`]. See
 /// its documentation for more.
 ///
-/// [`escape_unicode`]: ../../std/primitive.char.html#method.escape_unicode
-/// [`char`]: ../../std/primitive.char.html
+/// [`escape_unicode`]: char::escape_unicode
 #[derive(Clone, Debug)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct EscapeUnicode {
@@ -236,8 +234,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 /// This `struct` is created by the [`escape_default`] method on [`char`]. See
 /// its documentation for more.
 ///
-/// [`escape_default`]: ../../std/primitive.char.html#method.escape_default
-/// [`char`]: ../../std/primitive.char.html
+/// [`escape_default`]: char::escape_default
 #[derive(Clone, Debug)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct EscapeDefault {
@@ -345,8 +342,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 /// This `struct` is created by the [`escape_debug`] method on [`char`]. See its
 /// documentation for more.
 ///
-/// [`escape_debug`]: ../../std/primitive.char.html#method.escape_debug
-/// [`char`]: ../../std/primitive.char.html
+/// [`escape_debug`]: char::escape_debug
 #[stable(feature = "char_escape_debug", since = "1.20.0")]
 #[derive(Clone, Debug)]
 pub struct EscapeDebug(EscapeDefault);
@@ -380,8 +376,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 /// This `struct` is created by the [`to_lowercase`] method on [`char`]. See
 /// its documentation for more.
 ///
-/// [`to_lowercase`]: ../../std/primitive.char.html#method.to_lowercase
-/// [`char`]: ../../std/primitive.char.html
+/// [`to_lowercase`]: char::to_lowercase
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Debug, Clone)]
 pub struct ToLowercase(CaseMappingIter);
@@ -408,8 +403,7 @@ impl ExactSizeIterator for ToLowercase {}
 /// This `struct` is created by the [`to_uppercase`] method on [`char`]. See
 /// its documentation for more.
 ///
-/// [`to_uppercase`]: ../../std/primitive.char.html#method.to_uppercase
-/// [`char`]: ../../std/primitive.char.html
+/// [`to_uppercase`]: char::to_uppercase
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Debug, Clone)]
 pub struct ToUppercase(CaseMappingIter);
index e775ded60f593e4aaf131e68508eeffa81e26344..3953c73319fe419e5b33d735e68020a2cad20c85 100644 (file)
@@ -25,7 +25,7 @@
 use self::Ordering::*;
 
 /// Trait for equality comparisons which are [partial equivalence
-/// relations](http://en.wikipedia.org/wiki/Partial_equivalence_relation).
+/// relations](https://en.wikipedia.org/wiki/Partial_equivalence_relation).
 ///
 /// This trait allows for partial equality, for types that do not have a full
 /// equivalence relation. For example, in floating point numbers `NaN != NaN`,
@@ -505,7 +505,7 @@ fn cmp(&self, other: &Reverse<T>) -> Ordering {
 ///
 /// This trait can be used with `#[derive]`. When `derive`d on structs, it will produce a
 /// lexicographic ordering based on the top-to-bottom declaration order of the struct's members.
-/// When `derive`d on enums, variants are ordered by their top-to-bottom declaration order.
+/// When `derive`d on enums, variants are ordered by their top-to-bottom discriminant order.
 ///
 /// ## How can I implement `Ord`?
 ///
@@ -694,7 +694,7 @@ fn partial_cmp(&self, other: &Ordering) -> Option<Ordering> {
 ///
 /// This trait can be used with `#[derive]`. When `derive`d on structs, it will produce a
 /// lexicographic ordering based on the top-to-bottom declaration order of the struct's members.
-/// When `derive`d on enums, variants are ordered by their top-to-bottom declaration order.
+/// When `derive`d on enums, variants are ordered by their top-to-bottom discriminant order.
 ///
 /// ## How can I implement `PartialOrd`?
 ///
index e9689af39d51f649b474a8fef71e99936fe12aba..4525ba78ba09548e1f8dd1f89a105a2724dd9376 100644 (file)
@@ -281,8 +281,6 @@ fn deref_mut(&mut self) -> &mut VaListImpl<'f> {
 // improving this.
 mod sealed_trait {
     /// Trait which permits the allowed types to be used with [VaList::arg].
-    ///
-    /// [VaList::arg]: ../struct.VaList.html#method.arg
     #[unstable(
         feature = "c_variadic",
         reason = "the `c_variadic` feature has not been properly tested on \
index 638e83c3b939da6d1996d73cf28fb337c353a242..52f73c03e02d923c201141da94238f8d379156fa 100644 (file)
@@ -117,8 +117,6 @@ pub trait Write {
     ///
     /// This function will return an instance of [`Error`] on error.
     ///
-    /// [`Error`]: struct.Error.html
-    ///
     /// # Examples
     ///
     /// ```
@@ -146,9 +144,6 @@ pub trait Write {
     ///
     /// This function will return an instance of [`Error`] on error.
     ///
-    /// [`char`]: ../../std/primitive.char.html
-    /// [`Error`]: struct.Error.html
-    ///
     /// # Examples
     ///
     /// ```
@@ -218,9 +213,6 @@ fn write_fmt(&mut self, args: Arguments<'_>) -> Result {
 /// To interact with a `Formatter`, you'll call various methods to change the
 /// various options related to formatting. For examples, please see the
 /// documentation of the methods defined on `Formatter` below.
-///
-/// [`Debug`]: trait.Debug.html
-/// [`Display`]: trait.Display.html
 #[allow(missing_debug_implementations)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Formatter<'a> {
@@ -378,7 +370,7 @@ pub fn estimated_capacity(&self) -> usize {
 ///
 /// The [`format_args!`] macro will safely create an instance of this structure.
 /// The macro validates the format string at compile-time so usage of the
-/// [`write`] and [`format`] functions can be safely performed.
+/// [`write()`] and [`format()`] functions can be safely performed.
 ///
 /// You can use the `Arguments<'a>` that [`format_args!`] returns in `Debug`
 /// and `Display` contexts as seen below. The example also shows that `Debug`
@@ -392,9 +384,7 @@ pub fn estimated_capacity(&self) -> usize {
 /// assert_eq!(display, debug);
 /// ```
 ///
-/// [`format_args!`]: ../../std/macro.format_args.html
-/// [`format`]: ../../std/fmt/fn.format.html
-/// [`write`]: ../../std/fmt/fn.write.html
+/// [`format()`]: ../../std/fmt/fn.format.html
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Copy, Clone)]
 pub struct Arguments<'a> {
@@ -472,9 +462,7 @@ fn fmt(&self, fmt: &mut Formatter<'_>) -> Result {
 ///
 /// When used with the alternate format specifier `#?`, the output is pretty-printed.
 ///
-/// For more information on formatters, see [the module-level documentation][module].
-///
-/// [module]: ../../std/fmt/index.html
+/// For more information on formatters, see [the module-level documentation][self].
 ///
 /// This trait can be used with `#[derive]` if all fields implement `Debug`. When
 /// `derive`d for structs, it will use the name of the `struct`, then `{`, then a
@@ -535,8 +523,7 @@ fn fmt(&self, fmt: &mut Formatter<'_>) -> Result {
 /// `Debug` implementations using either `derive` or the debug builder API
 /// on [`Formatter`] support pretty-printing using the alternate flag: `{:#?}`.
 ///
-/// [`debug_struct`]: ../../std/fmt/struct.Formatter.html#method.debug_struct
-/// [`Formatter`]: ../../std/fmt/struct.Formatter.html
+/// [`debug_struct`]: Formatter::debug_struct
 ///
 /// Pretty-printing with `#?`:
 ///
@@ -618,14 +605,10 @@ pub(crate) mod macros {
 
 /// Format trait for an empty format, `{}`.
 ///
-/// `Display` is similar to [`Debug`][debug], but `Display` is for user-facing
+/// `Display` is similar to [`Debug`], but `Display` is for user-facing
 /// output, and so cannot be derived.
 ///
-/// [debug]: trait.Debug.html
-///
-/// For more information on formatters, see [the module-level documentation][module].
-///
-/// [module]: ../../std/fmt/index.html
+/// For more information on formatters, see [the module-level documentation][self].
 ///
 /// # Examples
 ///
@@ -697,9 +680,7 @@ pub trait Display {
 ///
 /// The alternate flag, `#`, adds a `0o` in front of the output.
 ///
-/// For more information on formatters, see [the module-level documentation][module].
-///
-/// [module]: ../../std/fmt/index.html
+/// For more information on formatters, see [the module-level documentation][self].
 ///
 /// # Examples
 ///
@@ -751,7 +732,7 @@ pub trait Octal {
 ///
 /// The alternate flag, `#`, adds a `0b` in front of the output.
 ///
-/// For more information on formatters, see [the module-level documentation][module].
+/// For more information on formatters, see [the module-level documentation][self].
 ///
 /// # Examples
 ///
@@ -790,12 +771,6 @@ pub trait Octal {
 ///     "l as binary is: 0b000000000000000000000001101011"
 /// );
 /// ```
-///
-/// [module]: ../../std/fmt/index.html
-/// [`i8`]: ../../std/primitive.i8.html
-/// [`i128`]: ../../std/primitive.i128.html
-/// [`isize`]: ../../std/primitive.isize.html
-/// [`i32`]: ../../std/primitive.i32.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Binary {
     /// Formats the value using the given formatter.
@@ -813,9 +788,7 @@ pub trait Binary {
 ///
 /// The alternate flag, `#`, adds a `0x` in front of the output.
 ///
-/// For more information on formatters, see [the module-level documentation][module].
-///
-/// [module]: ../../std/fmt/index.html
+/// For more information on formatters, see [the module-level documentation][self].
 ///
 /// # Examples
 ///
@@ -868,9 +841,7 @@ pub trait LowerHex {
 ///
 /// The alternate flag, `#`, adds a `0x` in front of the output.
 ///
-/// For more information on formatters, see [the module-level documentation][module].
-///
-/// [module]: ../../std/fmt/index.html
+/// For more information on formatters, see [the module-level documentation][self].
 ///
 /// # Examples
 ///
@@ -918,9 +889,7 @@ pub trait UpperHex {
 /// The `Pointer` trait should format its output as a memory location. This is commonly presented
 /// as hexadecimal.
 ///
-/// For more information on formatters, see [the module-level documentation][module].
-///
-/// [module]: ../../std/fmt/index.html
+/// For more information on formatters, see [the module-level documentation][self].
 ///
 /// # Examples
 ///
@@ -967,9 +936,7 @@ pub trait Pointer {
 ///
 /// The `LowerExp` trait should format its output in scientific notation with a lower-case `e`.
 ///
-/// For more information on formatters, see [the module-level documentation][module].
-///
-/// [module]: ../../std/fmt/index.html
+/// For more information on formatters, see [the module-level documentation][self].
 ///
 /// # Examples
 ///
@@ -1018,9 +985,7 @@ pub trait LowerExp {
 ///
 /// The `UpperExp` trait should format its output in scientific notation with an upper-case `E`.
 ///
-/// For more information on formatters, see [the module-level documentation][module].
-///
-/// [module]: ../../std/fmt/index.html
+/// For more information on formatters, see [the module-level documentation][self].
 ///
 /// # Examples
 ///
@@ -1812,8 +1777,7 @@ fn debug_upper_hex(&self) -> bool {
     /// Creates a [`DebugStruct`] builder designed to assist with creation of
     /// [`fmt::Debug`] implementations for structs.
     ///
-    /// [`DebugStruct`]: ../../std/fmt/struct.DebugStruct.html
-    /// [`fmt::Debug`]: ../../std/fmt/trait.Debug.html
+    /// [`fmt::Debug`]: self::Debug
     ///
     /// # Examples
     ///
index 1399d0c020f16d8f7e86c36deb7fe2a54380f438..25951e2f58235302dbe0da7b4163c68e01813107 100644 (file)
 use crate::marker::DiscriminantKind;
 use crate::mem;
 
+// These imports are used for simplifying intra-doc links
+#[allow(unused_imports)]
+#[cfg(all(target_has_atomic = "8", target_has_atomic = "32", target_has_atomic = "ptr"))]
+use crate::sync::atomic::{self, AtomicBool, AtomicI32, AtomicIsize, AtomicU32, Ordering};
+
 #[stable(feature = "drop_in_place", since = "1.8.0")]
 #[rustc_deprecated(
     reason = "no longer an intrinsic - use `ptr::drop_in_place` directly",
     /// 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)
-    /// as both the `success` and `failure` parameters. For example,
-    /// [`AtomicBool::compare_exchange`][compare_exchange].
-    ///
-    /// [compare_exchange]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange
+    /// [`atomic`] types via the `compare_exchange` method by passing
+    /// [`Ordering::SeqCst`] as both the `success` and `failure` parameters.
+    /// For example, [`AtomicBool::compare_exchange`].
     pub fn atomic_cxchg<T: Copy>(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)
-    /// as both the `success` and `failure` parameters. For example,
-    /// [`AtomicBool::compare_exchange`][compare_exchange].
-    ///
-    /// [compare_exchange]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange
+    /// [`atomic`] types via the `compare_exchange` method by passing
+    /// [`Ordering::Acquire`] as both the `success` and `failure` parameters.
+    /// For example, [`AtomicBool::compare_exchange`].
     pub fn atomic_cxchg_acq<T: Copy>(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)
-    /// as the `success` and
-    /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html)
-    /// as the `failure` parameters. For example,
-    /// [`AtomicBool::compare_exchange`][compare_exchange].
-    ///
-    /// [compare_exchange]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange
+    /// [`atomic`] types via the `compare_exchange` method by passing
+    /// [`Ordering::Release`] as the `success` and [`Ordering::Relaxed`] as the
+    /// `failure` parameters. For example, [`AtomicBool::compare_exchange`].
     pub fn atomic_cxchg_rel<T: Copy>(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)
-    /// as the `success` and
-    /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html)
-    /// as the `failure` parameters. For example,
-    /// [`AtomicBool::compare_exchange`][compare_exchange].
-    ///
-    /// [compare_exchange]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange
+    /// [`atomic`] types via the `compare_exchange` method by passing
+    /// [`Ordering::AcqRel`] as the `success` and [`Ordering::Acquire`] as the
+    /// `failure` parameters. For example, [`AtomicBool::compare_exchange`].
     pub fn atomic_cxchg_acqrel<T: Copy>(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)
-    /// as both the `success` and `failure` parameters. For example,
-    /// [`AtomicBool::compare_exchange`][compare_exchange].
-    ///
-    /// [compare_exchange]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange
+    /// [`atomic`] types via the `compare_exchange` method by passing
+    /// [`Ordering::Relaxed`] as both the `success` and `failure` parameters.
+    /// For example, [`AtomicBool::compare_exchange`].
     pub fn atomic_cxchg_relaxed<T: Copy>(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)
-    /// as the `success` and
-    /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html)
-    /// as the `failure` parameters. For example,
-    /// [`AtomicBool::compare_exchange`][compare_exchange].
-    ///
-    /// [compare_exchange]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange
+    /// [`atomic`] types via the `compare_exchange` method by passing
+    /// [`Ordering::SeqCst`] as the `success` and [`Ordering::Relaxed`] as the
+    /// `failure` parameters. For example, [`AtomicBool::compare_exchange`].
     pub fn atomic_cxchg_failrelaxed<T: Copy>(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)
-    /// as the `success` and
-    /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html)
-    /// as the `failure` parameters. For example,
-    /// [`AtomicBool::compare_exchange`][compare_exchange].
-    ///
-    /// [compare_exchange]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange
+    /// [`atomic`] types via the `compare_exchange` method by passing
+    /// [`Ordering::SeqCst`] as the `success` and [`Ordering::Acquire`] as the
+    /// `failure` parameters. For example, [`AtomicBool::compare_exchange`].
     pub fn atomic_cxchg_failacq<T: Copy>(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)
-    /// as the `success` and
-    /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html)
-    /// as the `failure` parameters. For example,
-    /// [`AtomicBool::compare_exchange`][compare_exchange].
-    ///
-    /// [compare_exchange]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange
+    /// [`atomic`] types via the `compare_exchange` method by passing
+    /// [`Ordering::Acquire`] as the `success` and [`Ordering::Relaxed`] as the
+    /// `failure` parameters. For example, [`AtomicBool::compare_exchange`].
     pub fn atomic_cxchg_acq_failrelaxed<T: Copy>(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)
-    /// as the `success` and
-    /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html)
-    /// as the `failure` parameters. For example,
-    /// [`AtomicBool::compare_exchange`][compare_exchange].
-    ///
-    /// [compare_exchange]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange
+    /// [`atomic`] types via the `compare_exchange` method by passing
+    /// [`Ordering::AcqRel`] as the `success` and [`Ordering::Relaxed`] as the
+    /// `failure` parameters. For example, [`AtomicBool::compare_exchange`].
     pub fn atomic_cxchg_acqrel_failrelaxed<T: Copy>(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)
-    /// as both the `success` and `failure` parameters. For example,
-    /// [`AtomicBool::compare_exchange_weak`][cew].
-    ///
-    /// [cew]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak
+    /// [`atomic`] types via the `compare_exchange_weak` method by passing
+    /// [`Ordering::SeqCst`] as both the `success` and `failure` parameters.
+    /// For example, [`AtomicBool::compare_exchange_weak`].
     pub fn atomic_cxchgweak<T: Copy>(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)
-    /// as both the `success` and `failure` parameters. For example,
-    /// [`AtomicBool::compare_exchange_weak`][cew].
-    ///
-    /// [cew]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak
+    /// [`atomic`] types via the `compare_exchange_weak` method by passing
+    /// [`Ordering::Acquire`] as both the `success` and `failure` parameters.
+    /// For example, [`AtomicBool::compare_exchange_weak`].
     pub fn atomic_cxchgweak_acq<T: Copy>(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)
-    /// as the `success` and
-    /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html)
-    /// as the `failure` parameters. For example,
-    /// [`AtomicBool::compare_exchange_weak`][cew].
-    ///
-    /// [cew]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak
+    /// [`atomic`] types via the `compare_exchange_weak` method by passing
+    /// [`Ordering::Release`] as the `success` and [`Ordering::Relaxed`] as the
+    /// `failure` parameters. For example, [`AtomicBool::compare_exchange_weak`].
     pub fn atomic_cxchgweak_rel<T: Copy>(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)
-    /// as the `success` and
-    /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html)
-    /// as the `failure` parameters. For example,
-    /// [`AtomicBool::compare_exchange_weak`][cew].
-    ///
-    /// [cew]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak
+    /// [`atomic`] types via the `compare_exchange_weak` method by passing
+    /// [`Ordering::AcqRel`] as the `success` and [`Ordering::Acquire`] as the
+    /// `failure` parameters. For example, [`AtomicBool::compare_exchange_weak`].
     pub fn atomic_cxchgweak_acqrel<T: Copy>(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)
-    /// as both the `success` and `failure` parameters. For example,
-    /// [`AtomicBool::compare_exchange_weak`][cew].
-    ///
-    /// [cew]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak
+    /// [`atomic`] types via the `compare_exchange_weak` method by passing
+    /// [`Ordering::Relaxed`] as both the `success` and `failure` parameters.
+    /// For example, [`AtomicBool::compare_exchange_weak`].
     pub fn atomic_cxchgweak_relaxed<T: Copy>(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)
-    /// as the `success` and
-    /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html)
-    /// as the `failure` parameters. For example,
-    /// [`AtomicBool::compare_exchange_weak`][cew].
-    ///
-    /// [cew]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak
+    /// [`atomic`] types via the `compare_exchange_weak` method by passing
+    /// [`Ordering::SeqCst`] as the `success` and [`Ordering::Relaxed`] as the
+    /// `failure` parameters. For example, [`AtomicBool::compare_exchange_weak`].
     pub fn atomic_cxchgweak_failrelaxed<T: Copy>(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)
-    /// as the `success` and
-    /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html)
-    /// as the `failure` parameters. For example,
-    /// [`AtomicBool::compare_exchange_weak`][cew].
-    ///
-    /// [cew]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak
+    /// [`atomic`] types via the `compare_exchange_weak` method by passing
+    /// [`Ordering::SeqCst`] as the `success` and [`Ordering::Acquire`] as the
+    /// `failure` parameters. For example, [`AtomicBool::compare_exchange_weak`].
     pub fn atomic_cxchgweak_failacq<T: Copy>(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)
-    /// as the `success` and
-    /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html)
-    /// as the `failure` parameters. For example,
-    /// [`AtomicBool::compare_exchange_weak`][cew].
-    ///
-    /// [cew]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak
+    /// [`atomic`] types via the `compare_exchange_weak` method by passing
+    /// [`Ordering::Acquire`] as the `success` and [`Ordering::Relaxed`] as the
+    /// `failure` parameters. For example, [`AtomicBool::compare_exchange_weak`].
     pub fn atomic_cxchgweak_acq_failrelaxed<T: Copy>(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)
-    /// as the `success` and
-    /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html)
-    /// as the `failure` parameters. For example,
-    /// [`AtomicBool::compare_exchange_weak`][cew].
-    ///
-    /// [cew]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak
+    /// [`atomic`] types via the `compare_exchange_weak` method by passing
+    /// [`Ordering::AcqRel`] as the `success` and [`Ordering::Relaxed`] as the
+    /// `failure` parameters. For example, [`AtomicBool::compare_exchange_weak`].
     pub fn atomic_cxchgweak_acqrel_failrelaxed<T: Copy>(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)
-    /// as the `order`. For example,
-    /// [`AtomicBool::load`](../../std/sync/atomic/struct.AtomicBool.html#method.load).
+    /// [`atomic`] types via the `load` method by passing
+    /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::load`].
     pub fn atomic_load<T: Copy>(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)
-    /// as the `order`. For example,
-    /// [`AtomicBool::load`](../../std/sync/atomic/struct.AtomicBool.html#method.load).
+    /// [`atomic`] types via the `load` method by passing
+    /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::load`].
     pub fn atomic_load_acq<T: Copy>(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)
-    /// as the `order`. For example,
-    /// [`AtomicBool::load`](../../std/sync/atomic/struct.AtomicBool.html#method.load).
+    /// [`atomic`] types via the `load` method by passing
+    /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicBool::load`].
     pub fn atomic_load_relaxed<T: Copy>(src: *const T) -> T;
     pub fn atomic_load_unordered<T: Copy>(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)
-    /// as the `order`. For example,
-    /// [`AtomicBool::store`](../../std/sync/atomic/struct.AtomicBool.html#method.store).
+    /// [`atomic`] types via the `store` method by passing
+    /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::store`].
     pub fn atomic_store<T: Copy>(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)
-    /// as the `order`. For example,
-    /// [`AtomicBool::store`](../../std/sync/atomic/struct.AtomicBool.html#method.store).
+    /// [`atomic`] types via the `store` method by passing
+    /// [`Ordering::Release`] as the `order`. For example, [`AtomicBool::store`].
     pub fn atomic_store_rel<T: Copy>(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)
-    /// as the `order`. For example,
-    /// [`AtomicBool::store`](../../std/sync/atomic/struct.AtomicBool.html#method.store).
+    /// [`atomic`] types via the `store` method by passing
+    /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicBool::store`].
     pub fn atomic_store_relaxed<T: Copy>(dst: *mut T, val: T);
     pub fn atomic_store_unordered<T: Copy>(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)
-    /// as the `order`. For example,
-    /// [`AtomicBool::swap`](../../std/sync/atomic/struct.AtomicBool.html#method.swap).
+    /// [`atomic`] types via the `swap` method by passing
+    /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::swap`].
     pub fn atomic_xchg<T: Copy>(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)
-    /// as the `order`. For example,
-    /// [`AtomicBool::swap`](../../std/sync/atomic/struct.AtomicBool.html#method.swap).
+    /// [`atomic`] types via the `swap` method by passing
+    /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::swap`].
     pub fn atomic_xchg_acq<T: Copy>(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)
-    /// as the `order`. For example,
-    /// [`AtomicBool::swap`](../../std/sync/atomic/struct.AtomicBool.html#method.swap).
+    /// [`atomic`] types via the `swap` method by passing
+    /// [`Ordering::Release`] as the `order`. For example, [`AtomicBool::swap`].
     pub fn atomic_xchg_rel<T: Copy>(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)
-    /// as the `order`. For example,
-    /// [`AtomicBool::swap`](../../std/sync/atomic/struct.AtomicBool.html#method.swap).
+    /// [`atomic`] types via the `swap` method by passing
+    /// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicBool::swap`].
     pub fn atomic_xchg_acqrel<T: Copy>(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)
-    /// as the `order`. For example,
-    /// [`AtomicBool::swap`](../../std/sync/atomic/struct.AtomicBool.html#method.swap).
+    /// [`atomic`] types via the `swap` method by passing
+    /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicBool::swap`].
     pub fn atomic_xchg_relaxed<T: Copy>(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)
-    /// as the `order`. For example,
-    /// [`AtomicIsize::fetch_add`](../../std/sync/atomic/struct.AtomicIsize.html#method.fetch_add).
+    /// [`atomic`] types via the `fetch_add` method by passing
+    /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicIsize::fetch_add`].
     pub fn atomic_xadd<T: Copy>(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)
-    /// as the `order`. For example,
-    /// [`AtomicIsize::fetch_add`](../../std/sync/atomic/struct.AtomicIsize.html#method.fetch_add).
+    /// [`atomic`] types via the `fetch_add` method by passing
+    /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicIsize::fetch_add`].
     pub fn atomic_xadd_acq<T: Copy>(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)
-    /// as the `order`. For example,
-    /// [`AtomicIsize::fetch_add`](../../std/sync/atomic/struct.AtomicIsize.html#method.fetch_add).
+    /// [`atomic`] types via the `fetch_add` method by passing
+    /// [`Ordering::Release`] as the `order`. For example, [`AtomicIsize::fetch_add`].
     pub fn atomic_xadd_rel<T: Copy>(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)
-    /// as the `order`. For example,
-    /// [`AtomicIsize::fetch_add`](../../std/sync/atomic/struct.AtomicIsize.html#method.fetch_add).
+    /// [`atomic`] types via the `fetch_add` method by passing
+    /// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicIsize::fetch_add`].
     pub fn atomic_xadd_acqrel<T: Copy>(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)
-    /// as the `order`. For example,
-    /// [`AtomicIsize::fetch_add`](../../std/sync/atomic/struct.AtomicIsize.html#method.fetch_add).
+    /// [`atomic`] types via the `fetch_add` method by passing
+    /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicIsize::fetch_add`].
     pub fn atomic_xadd_relaxed<T: Copy>(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)
-    /// as the `order`. For example,
-    /// [`AtomicIsize::fetch_sub`](../../std/sync/atomic/struct.AtomicIsize.html#method.fetch_sub).
+    /// [`atomic`] types via the `fetch_sub` method by passing
+    /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicIsize::fetch_sub`].
     pub fn atomic_xsub<T: Copy>(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)
-    /// as the `order`. For example,
-    /// [`AtomicIsize::fetch_sub`](../../std/sync/atomic/struct.AtomicIsize.html#method.fetch_sub).
+    /// [`atomic`] types via the `fetch_sub` method by passing
+    /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicIsize::fetch_sub`].
     pub fn atomic_xsub_acq<T: Copy>(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)
-    /// as the `order`. For example,
-    /// [`AtomicIsize::fetch_sub`](../../std/sync/atomic/struct.AtomicIsize.html#method.fetch_sub).
+    /// [`atomic`] types via the `fetch_sub` method by passing
+    /// [`Ordering::Release`] as the `order`. For example, [`AtomicIsize::fetch_sub`].
     pub fn atomic_xsub_rel<T: Copy>(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)
-    /// as the `order`. For example,
-    /// [`AtomicIsize::fetch_sub`](../../std/sync/atomic/struct.AtomicIsize.html#method.fetch_sub).
+    /// [`atomic`] types via the `fetch_sub` method by passing
+    /// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicIsize::fetch_sub`].
     pub fn atomic_xsub_acqrel<T: Copy>(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)
-    /// as the `order`. For example,
-    /// [`AtomicIsize::fetch_sub`](../../std/sync/atomic/struct.AtomicIsize.html#method.fetch_sub).
+    /// [`atomic`] types via the `fetch_sub` method by passing
+    /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicIsize::fetch_sub`].
     pub fn atomic_xsub_relaxed<T: Copy>(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)
-    /// as the `order`. For example,
-    /// [`AtomicBool::fetch_and`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_and).
+    /// [`atomic`] types via the `fetch_and` method by passing
+    /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::fetch_and`].
     pub fn atomic_and<T: Copy>(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)
-    /// as the `order`. For example,
-    /// [`AtomicBool::fetch_and`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_and).
+    /// [`atomic`] types via the `fetch_and` method by passing
+    /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::fetch_and`].
     pub fn atomic_and_acq<T: Copy>(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)
-    /// as the `order`. For example,
-    /// [`AtomicBool::fetch_and`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_and).
+    /// [`atomic`] types via the `fetch_and` method by passing
+    /// [`Ordering::Release`] as the `order`. For example, [`AtomicBool::fetch_and`].
     pub fn atomic_and_rel<T: Copy>(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)
-    /// as the `order`. For example,
-    /// [`AtomicBool::fetch_and`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_and).
+    /// [`atomic`] types via the `fetch_and` method by passing
+    /// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicBool::fetch_and`].
     pub fn atomic_and_acqrel<T: Copy>(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)
-    /// as the `order`. For example,
-    /// [`AtomicBool::fetch_and`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_and).
+    /// [`atomic`] types via the `fetch_and` method by passing
+    /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicBool::fetch_and`].
     pub fn atomic_and_relaxed<T: Copy>(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)
-    /// as the `order`. For example,
-    /// [`AtomicBool::fetch_nand`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_nand).
+    /// [`AtomicBool`] type via the `fetch_nand` method by passing
+    /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::fetch_nand`].
     pub fn atomic_nand<T: Copy>(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)
-    /// as the `order`. For example,
-    /// [`AtomicBool::fetch_nand`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_nand).
+    /// [`AtomicBool`] type via the `fetch_nand` method by passing
+    /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::fetch_nand`].
     pub fn atomic_nand_acq<T: Copy>(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)
-    /// as the `order`. For example,
-    /// [`AtomicBool::fetch_nand`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_nand).
+    /// [`AtomicBool`] type via the `fetch_nand` method by passing
+    /// [`Ordering::Release`] as the `order`. For example, [`AtomicBool::fetch_nand`].
     pub fn atomic_nand_rel<T: Copy>(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)
-    /// as the `order`. For example,
-    /// [`AtomicBool::fetch_nand`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_nand).
+    /// [`AtomicBool`] type via the `fetch_nand` method by passing
+    /// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicBool::fetch_nand`].
     pub fn atomic_nand_acqrel<T: Copy>(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)
-    /// as the `order`. For example,
-    /// [`AtomicBool::fetch_nand`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_nand).
+    /// [`AtomicBool`] type via the `fetch_nand` method by passing
+    /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicBool::fetch_nand`].
     pub fn atomic_nand_relaxed<T: Copy>(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)
-    /// as the `order`. For example,
-    /// [`AtomicBool::fetch_or`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_or).
+    /// [`atomic`] types via the `fetch_or` method by passing
+    /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::fetch_or`].
     pub fn atomic_or<T: Copy>(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)
-    /// as the `order`. For example,
-    /// [`AtomicBool::fetch_or`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_or).
+    /// [`atomic`] types via the `fetch_or` method by passing
+    /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::fetch_or`].
     pub fn atomic_or_acq<T: Copy>(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)
-    /// as the `order`. For example,
-    /// [`AtomicBool::fetch_or`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_or).
+    /// [`atomic`] types via the `fetch_or` method by passing
+    /// [`Ordering::Release`] as the `order`. For example, [`AtomicBool::fetch_or`].
     pub fn atomic_or_rel<T: Copy>(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)
-    /// as the `order`. For example,
-    /// [`AtomicBool::fetch_or`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_or).
+    /// [`atomic`] types via the `fetch_or` method by passing
+    /// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicBool::fetch_or`].
     pub fn atomic_or_acqrel<T: Copy>(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)
-    /// as the `order`. For example,
-    /// [`AtomicBool::fetch_or`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_or).
+    /// [`atomic`] types via the `fetch_or` method by passing
+    /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicBool::fetch_or`].
     pub fn atomic_or_relaxed<T: Copy>(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)
-    /// as the `order`. For example,
-    /// [`AtomicBool::fetch_xor`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_xor).
+    /// [`atomic`] types via the `fetch_xor` method by passing
+    /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::fetch_xor`].
     pub fn atomic_xor<T: Copy>(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)
-    /// as the `order`. For example,
-    /// [`AtomicBool::fetch_xor`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_xor).
+    /// [`atomic`] types via the `fetch_xor` method by passing
+    /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::fetch_xor`].
     pub fn atomic_xor_acq<T: Copy>(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)
-    /// as the `order`. For example,
-    /// [`AtomicBool::fetch_xor`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_xor).
+    /// [`atomic`] types via the `fetch_xor` method by passing
+    /// [`Ordering::Release`] as the `order`. For example, [`AtomicBool::fetch_xor`].
     pub fn atomic_xor_rel<T: Copy>(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)
-    /// as the `order`. For example,
-    /// [`AtomicBool::fetch_xor`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_xor).
+    /// [`atomic`] types via the `fetch_xor` method by passing
+    /// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicBool::fetch_xor`].
     pub fn atomic_xor_acqrel<T: Copy>(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)
-    /// as the `order`. For example,
-    /// [`AtomicBool::fetch_xor`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_xor).
+    /// [`atomic`] types via the `fetch_xor` method by passing
+    /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicBool::fetch_xor`].
     pub fn atomic_xor_relaxed<T: Copy>(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).
+    /// [`atomic`] signed integer types via the `fetch_max` method by passing
+    /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicI32::fetch_max`].
     pub fn atomic_max<T: Copy>(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).
+    /// [`atomic`] signed integer types via the `fetch_max` method by passing
+    /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicI32::fetch_max`].
     pub fn atomic_max_acq<T: Copy>(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).
+    /// [`atomic`] signed integer types via the `fetch_max` method by passing
+    /// [`Ordering::Release`] as the `order`. For example, [`AtomicI32::fetch_max`].
     pub fn atomic_max_rel<T: Copy>(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).
+    /// [`atomic`] signed integer types via the `fetch_max` method by passing
+    /// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicI32::fetch_max`].
     pub fn atomic_max_acqrel<T: Copy>(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).
+    /// [`atomic`] signed integer types via the `fetch_max` method by passing
+    /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicI32::fetch_max`].
     pub fn atomic_max_relaxed<T: Copy>(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).
+    /// [`atomic`] signed integer types via the `fetch_min` method by passing
+    /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicI32::fetch_min`].
     pub fn atomic_min<T: Copy>(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).
+    /// [`atomic`] signed integer types via the `fetch_min` method by passing
+    /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicI32::fetch_min`].
     pub fn atomic_min_acq<T: Copy>(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).
+    /// [`atomic`] signed integer types via the `fetch_min` method by passing
+    /// [`Ordering::Release`] as the `order`. For example, [`AtomicI32::fetch_min`].
     pub fn atomic_min_rel<T: Copy>(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).
+    /// [`atomic`] signed integer types via the `fetch_min` method by passing
+    /// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicI32::fetch_min`].
     pub fn atomic_min_acqrel<T: Copy>(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).
+    /// [`atomic`] signed integer types via the `fetch_min` method by passing
+    /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicI32::fetch_min`].
     pub fn atomic_min_relaxed<T: Copy>(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).
+    /// [`atomic`] unsigned integer types via the `fetch_min` method by passing
+    /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicU32::fetch_min`].
     pub fn atomic_umin<T: Copy>(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).
+    /// [`atomic`] unsigned integer types via the `fetch_min` method by passing
+    /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicU32::fetch_min`].
     pub fn atomic_umin_acq<T: Copy>(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).
+    /// [`atomic`] unsigned integer types via the `fetch_min` method by passing
+    /// [`Ordering::Release`] as the `order`. For example, [`AtomicU32::fetch_min`].
     pub fn atomic_umin_rel<T: Copy>(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).
+    /// [`atomic`] unsigned integer types via the `fetch_min` method by passing
+    /// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicU32::fetch_min`].
     pub fn atomic_umin_acqrel<T: Copy>(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).
+    /// [`atomic`] unsigned integer types via the `fetch_min` method by passing
+    /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicU32::fetch_min`].
     pub fn atomic_umin_relaxed<T: Copy>(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).
+    /// [`atomic`] unsigned integer types via the `fetch_max` method by passing
+    /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicU32::fetch_max`].
     pub fn atomic_umax<T: Copy>(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).
+    /// [`atomic`] unsigned integer types via the `fetch_max` method by passing
+    /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicU32::fetch_max`].
     pub fn atomic_umax_acq<T: Copy>(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).
+    /// [`atomic`] unsigned integer types via the `fetch_max` method by passing
+    /// [`Ordering::Release`] as the `order`. For example, [`AtomicU32::fetch_max`].
     pub fn atomic_umax_rel<T: Copy>(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).
+    /// [`atomic`] unsigned integer types via the `fetch_max` method by passing
+    /// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicU32::fetch_max`].
     pub fn atomic_umax_acqrel<T: Copy>(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).
+    /// [`atomic`] unsigned integer types via the `fetch_max` method by passing
+    /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicU32::fetch_max`].
     pub fn atomic_umax_relaxed<T: Copy>(dst: *mut T, src: T) -> T;
 
     /// The `prefetch` intrinsic is a hint to the code generator to insert a prefetch instruction
     /// 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)
+    /// [`atomic::fence`] by passing [`Ordering::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)
+    /// [`atomic::fence`] by passing [`Ordering::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)
+    /// [`atomic::fence`] by passing [`Ordering::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)
+    /// [`atomic::fence`] by passing [`Ordering::AcqRel`]
     /// as the `order`.
     pub fn atomic_fence_acqrel();
 
     /// 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)
+    /// [`atomic::compiler_fence`] by passing [`Ordering::SeqCst`]
     /// as the `order`.
     pub fn atomic_singlethreadfence();
     /// A compiler-only memory barrier.
     /// 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)
+    /// [`atomic::compiler_fence`] by passing [`Ordering::Acquire`]
     /// as the `order`.
     pub fn atomic_singlethreadfence_acq();
     /// A compiler-only memory barrier.
     /// 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)
+    /// [`atomic::compiler_fence`] by passing [`Ordering::Release`]
     /// as the `order`.
     pub fn atomic_singlethreadfence_rel();
     /// A compiler-only memory barrier.
     /// 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)
+    /// [`atomic::compiler_fence`] by passing [`Ordering::AcqRel`]
     /// as the `order`.
     pub fn atomic_singlethreadfence_acqrel();
 
     /// macro, which panics when it is executed, it is *undefined behavior* to
     /// reach code marked with this function.
     ///
-    /// The stabilized version of this intrinsic is
-    /// [`std::hint::unreachable_unchecked`](../../std/hint/fn.unreachable_unchecked.html).
+    /// The stabilized version of this intrinsic is [`crate::hint::unreachable_unchecked`].
     #[rustc_const_unstable(feature = "const_unreachable_unchecked", issue = "53188")]
     pub fn unreachable() -> !;
 
     /// More specifically, this is the offset in bytes between successive
     /// items of the same type, including alignment padding.
     ///
-    /// The stabilized version of this intrinsic is
-    /// [`std::mem::size_of`](../../std/mem/fn.size_of.html).
+    /// The stabilized version of this intrinsic is [`size_of`].
     #[rustc_const_stable(feature = "const_size_of", since = "1.40.0")]
     pub fn size_of<T>() -> usize;
 
     ///
     /// Drop glue is not run on the destination.
     ///
-    /// The stabilized version of this intrinsic is
-    /// [`std::ptr::write`](../../std/ptr/fn.write.html).
+    /// The stabilized version of this intrinsic is [`crate::ptr::write`].
     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).
+    /// The stabilized version of this intrinsic is [`crate::mem::align_of`].
     #[rustc_const_stable(feature = "const_min_align_of", since = "1.40.0")]
     pub fn min_align_of<T>() -> usize;
     /// The preferred alignment of a type.
 
     /// The size of the referenced value in bytes.
     ///
-    /// The stabilized version of this intrinsic is
-    /// [`std::mem::size_of_val`](../../std/mem/fn.size_of_val.html).
+    /// The stabilized version of this intrinsic is [`size_of_val`].
     #[rustc_const_unstable(feature = "const_size_of_val", issue = "46571")]
     pub fn size_of_val<T: ?Sized>(_: *const T) -> usize;
     /// The required alignment of the referenced value.
     ///
-    /// The stabilized version of this intrinsic is
-    /// [`std::mem::align_of_val`](../../std/mem/fn.align_of_val.html).
+    /// The stabilized version of this intrinsic is [`crate::mem::align_of_val`].
     #[rustc_const_unstable(feature = "const_align_of_val", issue = "46571")]
     pub fn min_align_of_val<T: ?Sized>(_: *const 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)
+    /// The stabilized version of this intrinsic is [`crate::any::type_name`].
     #[rustc_const_unstable(feature = "const_type_name", issue = "63084")]
     pub fn type_name<T: ?Sized>() -> &'static str;
 
     /// 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)
+    /// The stabilized version of this intrinsic is [`crate::any::TypeId::of`].
     #[rustc_const_stable(feature = "const_type_id", since = "1.46.0")]
     pub fn type_id<T: ?Sized + 'static>() -> u64;
 
 
     /// Gets a reference to a static `Location` indicating where it was called.
     ///
-    /// Consider using [`std::panic::Location::caller`](../../std/panic/struct.Location.html#method.caller)
-    /// instead.
+    /// Consider using [`crate::panic::Location::caller`] instead.
     #[rustc_const_unstable(feature = "const_caller_location", issue = "47809")]
     pub fn caller_location() -> &'static crate::panic::Location<'static>;
 
     /// Moves a value out of scope without running drop glue.
     ///
-    /// This exists solely for [`mem::forget_unsized`](../../std/mem/fn.forget_unsized.html);
-    /// normal `forget` uses `ManuallyDrop` instead.
+    /// 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.
     /// If the actual type neither requires drop glue nor implements
     /// `Copy`, then the return value of this function is unspecified.
     ///
-    /// The stabilized version of this intrinsic is
-    /// [`std::mem::needs_drop`](../../std/mem/fn.needs_drop.html).
+    /// The stabilized version of this intrinsic is [`needs_drop`].
     #[rustc_const_stable(feature = "const_needs_drop", since = "1.40.0")]
     pub fn needs_drop<T>() -> bool;
 
 
     /// 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).
+    /// The stabilized version of this intrinsic is [`crate::ptr::read_volatile`].
     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).
+    /// The stabilized version of this intrinsic is [`crate::ptr::write_volatile`].
     pub fn volatile_store<T>(dst: *mut T, val: T);
 
     /// Performs a volatile load from the `src` pointer
     /// Returns the minimum of two `f32` values.
     ///
     /// The stabilized version of this intrinsic is
-    /// [`std::f32::min`](../../std/primitive.f32.html#method.min)
+    /// [`f32::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)
+    /// [`f64::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)
+    /// [`f32::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)
+    /// [`f64::max`]
     pub fn maxnumf64(x: f64, y: f64) -> f64;
 
     /// Copies the sign from `y` to `x` for `f32` values.
     /// Convert with LLVM’s fptoui/fptosi, which may return undef for values out of range
     /// (<https://github.com/rust-lang/rust/issues/10184>)
     ///
-    /// Stabilized as [`f32::to_int_unchecked`](../../std/primitive.f32.html#method.to_int_unchecked)
-    /// and [`f64::to_int_unchecked`](../../std/primitive.f64.html#method.to_int_unchecked).
+    /// Stabilized as [`f32::to_int_unchecked`] and [`f64::to_int_unchecked`].
     pub fn float_to_int_unchecked<Float: Copy, Int: Copy>(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)
+    /// [`u32::count_ones`]
     #[rustc_const_stable(feature = "const_ctpop", since = "1.40.0")]
     pub fn ctpop<T: Copy>(x: T) -> 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)
+    /// [`u32::leading_zeros`]
     ///
     /// # Examples
     ///
     ///
     /// 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)
+    /// [`u32::trailing_zeros`]
     ///
     /// # Examples
     ///
     ///
     /// 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)
+    /// [`u32::swap_bytes`]
     #[rustc_const_stable(feature = "const_bswap", since = "1.40.0")]
     pub fn bswap<T: Copy>(x: T) -> 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)
+    /// [`u32::reverse_bits`]
     #[rustc_const_stable(feature = "const_bitreverse", since = "1.40.0")]
     pub fn bitreverse<T: Copy>(x: T) -> T;
 
     ///
     /// 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)
+    /// [`u32::overflowing_add`]
     #[rustc_const_stable(feature = "const_int_overflow", since = "1.40.0")]
     pub fn add_with_overflow<T: Copy>(x: T, y: T) -> (T, bool);
 
     ///
     /// 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)
+    /// [`u32::overflowing_sub`]
     #[rustc_const_stable(feature = "const_int_overflow", since = "1.40.0")]
     pub fn sub_with_overflow<T: Copy>(x: T, y: T) -> (T, bool);
 
     ///
     /// 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)
+    /// [`u32::overflowing_mul`]
     #[rustc_const_stable(feature = "const_int_overflow", since = "1.40.0")]
     pub fn mul_with_overflow<T: Copy>(x: T, y: T) -> (T, bool);
 
     ///
     /// Safe wrappers for 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)
+    /// [`u32::checked_div`]
     #[rustc_const_unstable(feature = "const_int_unchecked_arith", issue = "none")]
     pub fn unchecked_div<T: Copy>(x: T, y: T) -> T;
     /// Returns the remainder of an unchecked division, resulting in
     ///
     /// Safe wrappers for 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)
+    /// [`u32::checked_rem`]
     #[rustc_const_unstable(feature = "const_int_unchecked_arith", issue = "none")]
     pub fn unchecked_rem<T: Copy>(x: T, y: T) -> T;
 
     ///
     /// Safe wrappers for 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)
+    /// [`u32::checked_shl`]
     #[rustc_const_stable(feature = "const_int_unchecked", since = "1.40.0")]
     pub fn unchecked_shl<T: Copy>(x: T, y: T) -> T;
     /// Performs an unchecked right shift, resulting in undefined behavior when
     ///
     /// Safe wrappers for 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)
+    /// [`u32::checked_shr`]
     #[rustc_const_stable(feature = "const_int_unchecked", since = "1.40.0")]
     pub fn unchecked_shr<T: Copy>(x: T, y: T) -> T;
 
     ///
     /// 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)
+    /// [`u32::rotate_left`]
     #[rustc_const_stable(feature = "const_int_rotate", since = "1.40.0")]
     pub fn rotate_left<T: Copy>(x: T, y: T) -> T;
 
     ///
     /// 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)
+    /// [`u32::rotate_right`]
     #[rustc_const_stable(feature = "const_int_rotate", since = "1.40.0")]
     pub fn rotate_right<T: Copy>(x: T, y: T) -> T;
 
     ///
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `checked_add` method. For example,
-    /// [`std::u32::checked_add`](../../std/primitive.u32.html#method.checked_add)
+    /// [`u32::checked_add`]
     #[rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0")]
     pub fn wrapping_add<T: Copy>(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 `checked_sub` method. For example,
-    /// [`std::u32::checked_sub`](../../std/primitive.u32.html#method.checked_sub)
+    /// [`u32::checked_sub`]
     #[rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0")]
     pub fn wrapping_sub<T: Copy>(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 `checked_mul` method. For example,
-    /// [`std::u32::checked_mul`](../../std/primitive.u32.html#method.checked_mul)
+    /// [`u32::checked_mul`]
     #[rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0")]
     pub fn wrapping_mul<T: Copy>(a: T, b: T) -> T;
 
     ///
     /// 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)
+    /// [`u32::saturating_add`]
     #[rustc_const_stable(feature = "const_int_saturating", since = "1.40.0")]
     pub fn saturating_add<T: Copy>(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)
+    /// [`u32::saturating_sub`]
     #[rustc_const_stable(feature = "const_int_saturating", since = "1.40.0")]
     pub fn saturating_sub<T: Copy>(a: T, b: T) -> T;
 
     /// 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)
+    /// The stabilized version of this intrinsic is [`crate::mem::discriminant`].
     #[rustc_const_unstable(feature = "const_discriminant", issue = "69821")]
     pub fn discriminant_value<T>(v: &T) -> <T as DiscriminantKind>::Discriminant;
 
     /// Returns the number of variants of the type `T` cast to a `usize`;
     /// if `T` has no variants, returns 0. Uninhabited variants will be counted.
     ///
-    /// The to-be-stabilized version of this intrinsic is
-    /// [`std::mem::variant_count`](../../std/mem/fn.variant_count.html)
+    /// The to-be-stabilized version of this intrinsic is [`variant_count`].
     #[rustc_const_unstable(feature = "variant_count", issue = "73662")]
     pub fn variant_count<T>() -> usize;
 
@@ -1989,7 +1763,6 @@ pub(crate) fn is_nonoverlapping<T>(src: *const T, dst: *const T, count: usize) -
 /// `copy_nonoverlapping` is semantically equivalent to C's [`memcpy`], but
 /// with the argument order swapped.
 ///
-/// [`copy`]: ./fn.copy.html
 /// [`memcpy`]: https://en.cppreference.com/w/c/string/byte/memcpy
 ///
 /// # Safety
@@ -2014,10 +1787,9 @@ pub(crate) fn is_nonoverlapping<T>(src: *const T, dst: *const T, count: usize) -
 /// Note that even if the effectively copied size (`count * size_of::<T>()`) is
 /// `0`, the pointers must be non-NULL and properly aligned.
 ///
-/// [`Copy`]: ../marker/trait.Copy.html
-/// [`read`]: ../ptr/fn.read.html
-/// [read-ownership]: ../ptr/fn.read.html#ownership-of-the-returned-value
-/// [valid]: ../ptr/index.html#safety
+/// [`read`]: crate::ptr::read
+/// [read-ownership]: crate::ptr::read#ownership-of-the-returned-value
+/// [valid]: crate::ptr#safety
 ///
 /// # Examples
 ///
@@ -2096,7 +1868,6 @@ pub unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize) {
 /// order swapped. Copying takes place as if the bytes were copied from `src`
 /// to a temporary array and then copied from the array to `dst`.
 ///
-/// [`copy_nonoverlapping`]: ./fn.copy_nonoverlapping.html
 /// [`memmove`]: https://en.cppreference.com/w/c/string/byte/memmove
 ///
 /// # Safety
@@ -2117,10 +1888,9 @@ pub unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize) {
 /// Note that even if the effectively copied size (`count * size_of::<T>()`) is
 /// `0`, the pointers must be non-NULL and properly aligned.
 ///
-/// [`Copy`]: ../marker/trait.Copy.html
-/// [`read`]: ../ptr/fn.read.html
-/// [read-ownership]: ../ptr/fn.read.html#ownership-of-the-returned-value
-/// [valid]: ../ptr/index.html#safety
+/// [`read`]: crate::ptr::read
+/// [read-ownership]: crate::ptr::read#ownership-of-the-returned-value
+/// [valid]: crate::ptr#safety
 ///
 /// # Examples
 ///
@@ -2178,7 +1948,7 @@ pub unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
 /// Note that even if the effectively copied size (`count * size_of::<T>()`) is
 /// `0`, the pointer must be non-NULL and properly aligned.
 ///
-/// [valid]: ../ptr/index.html#safety
+/// [valid]: crate::ptr#safety
 ///
 /// # Examples
 ///
index 19cd05de2a7581efa1d1ce4d547e2b3a3dc3a753..99f8cc66638f3f7ff084fa4f3815a9491ba02f4d 100644 (file)
@@ -73,6 +73,8 @@
 #![feature(const_discriminant)]
 #![feature(const_checked_int_methods)]
 #![feature(const_euclidean_int_methods)]
+#![feature(const_float_classify)]
+#![feature(const_float_bits_conv)]
 #![feature(const_overflowing_int_methods)]
 #![feature(const_int_unchecked_arith)]
 #![feature(const_int_pow)]
index 3b9057b7e8377911feec5d30b98e163a787d0fab..d26f2124f15fd46ccb83d054919f83e02d709bc8 100644 (file)
@@ -28,9 +28,6 @@ macro_rules! panic {
 /// Like [`assert!`], this macro has a second form, where a custom
 /// panic message can be provided.
 ///
-/// [`PartialEq`]: cmp/trait.PartialEq.html
-/// [`assert!`]: macro.assert.html
-///
 /// # Examples
 ///
 /// ```
@@ -85,9 +82,6 @@ macro_rules! assert_eq {
 /// Like [`assert!`], this macro has a second form, where a custom
 /// panic message can be provided.
 ///
-/// [`PartialEq`]: cmp/trait.PartialEq.html
-/// [`assert!`]: macro.assert.html
-///
 /// # Examples
 ///
 /// ```
@@ -158,9 +152,6 @@ macro_rules! assert_ne {
 /// with `debug_assert!` is thus only encouraged after thorough profiling, and
 /// more importantly, only in safe code!
 ///
-/// [`panic!`]: macro.panic.html
-/// [`assert!`]: macro.assert.html
-///
 /// # Examples
 ///
 /// ```
@@ -196,8 +187,6 @@ macro_rules! debug_assert {
 /// expensive to be present in a release build but may be helpful during
 /// development. The result of expanding `debug_assert_eq!` is always type checked.
 ///
-/// [`assert_eq!`]: ../std/macro.assert_eq.html
-///
 /// # Examples
 ///
 /// ```
@@ -223,8 +212,6 @@ macro_rules! debug_assert_eq {
 /// expensive to be present in a release build but may be helpful during
 /// development. The result of expanding `debug_assert_ne!` is always type checked.
 ///
-/// [`assert_ne!`]: ../std/macro.assert_ne.html
-///
 /// # Examples
 ///
 /// ```
@@ -282,8 +269,6 @@ macro_rules! matches {
 /// Because of the early return, `try!` can only be used in functions that
 /// return [`Result`].
 ///
-/// [`Result`]: ../std/result/enum.Result.html
-///
 /// # Examples
 ///
 /// ```
@@ -354,10 +339,10 @@ macro_rules! r#try {
 ///
 /// See [`std::fmt`] for more information on the format string syntax.
 ///
-/// [`std::fmt`]: ../std/fmt/index.html
-/// [`std::fmt::Write`]: ../std/fmt/trait.Write.html
+/// [`std::fmt`]: crate::fmt
+/// [`std::fmt::Write`]: crate::fmt::Write
 /// [`std::io::Write`]: ../std/io/trait.Write.html
-/// [`std::fmt::Result`]: ../std/fmt/type.Result.html
+/// [`std::fmt::Result`]: crate::fmt::Result
 /// [`io::Result`]: ../std/io/type.Result.html
 ///
 /// # Examples
@@ -426,9 +411,7 @@ macro_rules! write {
 /// For more information, see [`write!`]. For information on the format string syntax, see
 /// [`std::fmt`].
 ///
-/// [`write!`]: macro.write.html
-/// [`std::fmt`]: ../std/fmt/index.html
-///
+/// [`std::fmt`]: crate::fmt
 ///
 /// # Examples
 ///
@@ -494,16 +477,12 @@ macro_rules! writeln {
 /// The unsafe counterpart of this macro is the [`unreachable_unchecked`] function, which
 /// will cause undefined behavior if the code is reached.
 ///
-/// [`panic!`]: ../std/macro.panic.html
-/// [`unreachable_unchecked`]: ../std/hint/fn.unreachable_unchecked.html
-/// [`std::hint`]: ../std/hint/index.html
+/// [`unreachable_unchecked`]: crate::hint::unreachable_unchecked
 ///
 /// # Panics
 ///
 /// This will always [`panic!`]
 ///
-/// [`panic!`]: ../std/macro.panic.html
-///
 /// # Examples
 ///
 /// Match arms:
@@ -637,8 +616,6 @@ macro_rules! unimplemented {
 /// implemented", `unimplemented!` makes no such claims. Its message is "not implemented".
 /// Also some IDEs will mark `todo!`s.
 ///
-/// [`unimplemented!`]: macro.unimplemented.html
-///
 /// # Panics
 ///
 /// This will always [panic!](macro.panic.html)
@@ -730,8 +707,6 @@ pub(crate) mod builtin {
     /// #[cfg(not(any(feature = "foo", feature = "bar")))]
     /// compile_error!("Either feature \"foo\" or \"bar\" must be enabled for this crate.");
     /// ```
-    ///
-    /// [`panic!`]: ../std/macro.panic.html
     #[stable(feature = "compile_error_macro", since = "1.20.0")]
     #[rustc_builtin_macro]
     #[macro_export]
@@ -769,12 +744,11 @@ macro_rules! compile_error {
     ///
     /// For more information, see the documentation in [`std::fmt`].
     ///
-    /// [`Display`]: ../std/fmt/trait.Display.html
-    /// [`Debug`]: ../std/fmt/trait.Debug.html
-    /// [`fmt::Arguments`]: ../std/fmt/struct.Arguments.html
-    /// [`std::fmt`]: ../std/fmt/index.html
+    /// [`Display`]: crate::fmt::Display
+    /// [`Debug`]: crate::fmt::Debug
+    /// [`fmt::Arguments`]: crate::fmt::Arguments
+    /// [`std::fmt`]: crate::fmt
     /// [`format!`]: ../std/macro.format.html
-    /// [`write!`]: ../std/macro.write.html
     /// [`println!`]: ../std/macro.println.html
     ///
     /// # Examples
@@ -818,8 +792,6 @@ macro_rules! format_args_nl {
     /// will be emitted. To not emit a compile error, use the [`option_env!`]
     /// macro instead.
     ///
-    /// [`option_env!`]: ../std/macro.option_env.html
-    ///
     /// # Examples
     ///
     /// ```
@@ -854,13 +826,11 @@ macro_rules! env {
     /// expand into an expression of type `Option<&'static str>` whose value is
     /// `Some` of the value of the environment variable. If the environment
     /// variable is not present, then this will expand to `None`. See
-    /// [`Option<T>`][option] for more information on this type.
+    /// [`Option<T>`][Option] for more information on this type.
     ///
     /// A compile time error is never emitted when using this macro regardless
     /// of whether the environment variable is present or not.
     ///
-    /// [option]: ../std/option/enum.Option.html
-    ///
     /// # Examples
     ///
     /// ```
@@ -946,9 +916,6 @@ macro_rules! concat {
     /// but rather the first macro invocation leading up to the invocation
     /// of the `line!` macro.
     ///
-    /// [`column!`]: macro.column.html
-    /// [`file!`]: macro.file.html
-    ///
     /// # Examples
     ///
     /// ```
@@ -976,9 +943,6 @@ macro_rules! line {
     /// but rather the first macro invocation leading up to the invocation
     /// of the `column!` macro.
     ///
-    /// [`line!`]: macro.line.html
-    /// [`file!`]: macro.file.html
-    ///
     /// # Examples
     ///
     /// ```
@@ -999,15 +963,11 @@ macro_rules! column {
     /// With [`line!`] and [`column!`], these macros provide debugging information for
     /// developers about the location within the source.
     ///
-    ///
     /// The expanded expression has type `&'static str`, and the returned file
     /// is not the invocation of the `file!` macro itself, but rather the
     /// first macro invocation leading up to the invocation of the `file!`
     /// macro.
     ///
-    /// [`line!`]: macro.line.html
-    /// [`column!`]: macro.column.html
-    ///
     /// # Examples
     ///
     /// ```
@@ -1258,9 +1218,7 @@ macro_rules! include {
     /// be provided with or without arguments for formatting. See [`std::fmt`]
     /// for syntax for this form.
     ///
-    /// [`panic!`]: macro.panic.html
-    /// [`debug_assert!`]: macro.debug_assert.html
-    /// [`std::fmt`]: ../std/fmt/index.html
+    /// [`std::fmt`]: crate::fmt
     ///
     /// # Examples
     ///
index e45aa86c0795a915d7f5b079e4189d8a7999e3a7..aab0e96d83ab98c6a5b6faf6635bc4bf16580c69 100644 (file)
@@ -74,8 +74,12 @@ impl<T> ManuallyDrop<T> {
     ///
     /// ```rust
     /// use std::mem::ManuallyDrop;
-    /// ManuallyDrop::new(Box::new(()));
+    /// let mut x = ManuallyDrop::new(String::from("Hello World!"));
+    /// x.truncate(5); // You can still safely operate on the value
+    /// assert_eq!(*x, "Hello");
+    /// // But `Drop` will not be run here
     /// ```
+    #[must_use = "if you don't need the wrapper, you can use `mem::forget` instead"]
     #[stable(feature = "manually_drop", since = "1.20.0")]
     #[rustc_const_stable(feature = "const_manually_drop", since = "1.36.0")]
     #[inline(always)]
index 9107c570a897097bf542773ae5c58c402a020805..6d8ed2f4ffb1a158e9e62f845259d185e57f11d5 100644 (file)
 #[rustc_const_stable(feature = "const_forget", since = "1.46.0")]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub const fn forget<T>(t: T) {
-    ManuallyDrop::new(t);
+    let _ = ManuallyDrop::new(t);
 }
 
 /// Like [`forget`], but also accepts unsized values.
index 9fb7296ce31cc32d873d7eb0e91ff21fe9929318..043f0b14f249f70ed671340d27d2999b7e336492 100644 (file)
@@ -381,8 +381,9 @@ impl f32 {
     /// assert!(!f.is_nan());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
     #[inline]
-    pub fn is_nan(self) -> bool {
+    pub const fn is_nan(self) -> bool {
         self != self
     }
 
@@ -390,7 +391,8 @@ pub fn is_nan(self) -> bool {
     // concerns about portability, so this implementation is for
     // private use internally.
     #[inline]
-    fn abs_private(self) -> f32 {
+    #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
+    const fn abs_private(self) -> f32 {
         f32::from_bits(self.to_bits() & 0x7fff_ffff)
     }
 
@@ -410,8 +412,9 @@ fn abs_private(self) -> f32 {
     /// assert!(neg_inf.is_infinite());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
     #[inline]
-    pub fn is_infinite(self) -> bool {
+    pub const fn is_infinite(self) -> bool {
         self.abs_private() == Self::INFINITY
     }
 
@@ -430,8 +433,9 @@ pub fn is_infinite(self) -> bool {
     /// assert!(!neg_inf.is_finite());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
     #[inline]
-    pub fn is_finite(self) -> bool {
+    pub const fn is_finite(self) -> bool {
         // There's no need to handle NaN separately: if self is NaN,
         // the comparison is not true, exactly as desired.
         self.abs_private() < Self::INFINITY
@@ -457,9 +461,10 @@ pub fn is_finite(self) -> bool {
     /// ```
     /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
     #[inline]
-    pub fn is_normal(self) -> bool {
-        self.classify() == FpCategory::Normal
+    pub const fn is_normal(self) -> bool {
+        matches!(self.classify(), FpCategory::Normal)
     }
 
     /// Returns the floating point category of the number. If only one property
@@ -476,7 +481,8 @@ pub fn is_normal(self) -> bool {
     /// assert_eq!(inf.classify(), FpCategory::Infinite);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn classify(self) -> FpCategory {
+    #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
+    pub const fn classify(self) -> FpCategory {
         const EXP_MASK: u32 = 0x7f800000;
         const MAN_MASK: u32 = 0x007fffff;
 
@@ -501,8 +507,9 @@ pub fn classify(self) -> FpCategory {
     /// assert!(!g.is_sign_positive());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
     #[inline]
-    pub fn is_sign_positive(self) -> bool {
+    pub const fn is_sign_positive(self) -> bool {
         !self.is_sign_negative()
     }
 
@@ -517,8 +524,9 @@ pub fn is_sign_positive(self) -> bool {
     /// assert!(g.is_sign_negative());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
     #[inline]
-    pub fn is_sign_negative(self) -> bool {
+    pub const fn is_sign_negative(self) -> bool {
         // IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus
         // applies to zeros and NaNs as well.
         self.to_bits() & 0x8000_0000 != 0
@@ -652,8 +660,9 @@ pub unsafe fn to_int_unchecked<Int>(self) -> Int
     ///
     /// ```
     #[stable(feature = "float_bits_conv", since = "1.20.0")]
+    #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
     #[inline]
-    pub fn to_bits(self) -> u32 {
+    pub const fn to_bits(self) -> u32 {
         // SAFETY: `u32` is a plain old datatype so we can always transmute to it
         unsafe { mem::transmute(self) }
     }
@@ -695,8 +704,9 @@ pub fn to_bits(self) -> u32 {
     /// assert_eq!(v, 12.5);
     /// ```
     #[stable(feature = "float_bits_conv", since = "1.20.0")]
+    #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
     #[inline]
-    pub fn from_bits(v: u32) -> Self {
+    pub const fn from_bits(v: u32) -> Self {
         // SAFETY: `u32` is a plain old datatype so we can always transmute from it
         // It turns out the safety issues with sNaN were overblown! Hooray!
         unsafe { mem::transmute(v) }
@@ -712,8 +722,9 @@ pub fn from_bits(v: u32) -> Self {
     /// assert_eq!(bytes, [0x41, 0x48, 0x00, 0x00]);
     /// ```
     #[stable(feature = "float_to_from_bytes", since = "1.40.0")]
+    #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
     #[inline]
-    pub fn to_be_bytes(self) -> [u8; 4] {
+    pub const fn to_be_bytes(self) -> [u8; 4] {
         self.to_bits().to_be_bytes()
     }
 
@@ -727,8 +738,9 @@ pub fn from_bits(v: u32) -> Self {
     /// assert_eq!(bytes, [0x00, 0x00, 0x48, 0x41]);
     /// ```
     #[stable(feature = "float_to_from_bytes", since = "1.40.0")]
+    #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
     #[inline]
-    pub fn to_le_bytes(self) -> [u8; 4] {
+    pub const fn to_le_bytes(self) -> [u8; 4] {
         self.to_bits().to_le_bytes()
     }
 
@@ -755,8 +767,9 @@ pub fn from_bits(v: u32) -> Self {
     /// );
     /// ```
     #[stable(feature = "float_to_from_bytes", since = "1.40.0")]
+    #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
     #[inline]
-    pub fn to_ne_bytes(self) -> [u8; 4] {
+    pub const fn to_ne_bytes(self) -> [u8; 4] {
         self.to_bits().to_ne_bytes()
     }
 
@@ -769,8 +782,9 @@ pub fn from_bits(v: u32) -> Self {
     /// assert_eq!(value, 12.5);
     /// ```
     #[stable(feature = "float_to_from_bytes", since = "1.40.0")]
+    #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
     #[inline]
-    pub fn from_be_bytes(bytes: [u8; 4]) -> Self {
+    pub const fn from_be_bytes(bytes: [u8; 4]) -> Self {
         Self::from_bits(u32::from_be_bytes(bytes))
     }
 
@@ -783,8 +797,9 @@ pub fn from_bits(v: u32) -> Self {
     /// assert_eq!(value, 12.5);
     /// ```
     #[stable(feature = "float_to_from_bytes", since = "1.40.0")]
+    #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
     #[inline]
-    pub fn from_le_bytes(bytes: [u8; 4]) -> Self {
+    pub const fn from_le_bytes(bytes: [u8; 4]) -> Self {
         Self::from_bits(u32::from_le_bytes(bytes))
     }
 
@@ -808,8 +823,9 @@ pub fn from_bits(v: u32) -> Self {
     /// assert_eq!(value, 12.5);
     /// ```
     #[stable(feature = "float_to_from_bytes", since = "1.40.0")]
+    #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
     #[inline]
-    pub fn from_ne_bytes(bytes: [u8; 4]) -> Self {
+    pub const fn from_ne_bytes(bytes: [u8; 4]) -> Self {
         Self::from_bits(u32::from_ne_bytes(bytes))
     }
 
index a5b1eb3f1fd67c61adcc65d041319bc7b88f6f29..24624b88d59f698e46e890702e225d7c4d7cf5fd 100644 (file)
@@ -380,8 +380,9 @@ impl f64 {
     /// assert!(!f.is_nan());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
     #[inline]
-    pub fn is_nan(self) -> bool {
+    pub const fn is_nan(self) -> bool {
         self != self
     }
 
@@ -389,7 +390,8 @@ pub fn is_nan(self) -> bool {
     // concerns about portability, so this implementation is for
     // private use internally.
     #[inline]
-    fn abs_private(self) -> f64 {
+    #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
+    const fn abs_private(self) -> f64 {
         f64::from_bits(self.to_bits() & 0x7fff_ffff_ffff_ffff)
     }
 
@@ -409,8 +411,9 @@ fn abs_private(self) -> f64 {
     /// assert!(neg_inf.is_infinite());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
     #[inline]
-    pub fn is_infinite(self) -> bool {
+    pub const fn is_infinite(self) -> bool {
         self.abs_private() == Self::INFINITY
     }
 
@@ -429,8 +432,9 @@ pub fn is_infinite(self) -> bool {
     /// assert!(!neg_inf.is_finite());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
     #[inline]
-    pub fn is_finite(self) -> bool {
+    pub const fn is_finite(self) -> bool {
         // There's no need to handle NaN separately: if self is NaN,
         // the comparison is not true, exactly as desired.
         self.abs_private() < Self::INFINITY
@@ -456,9 +460,10 @@ pub fn is_finite(self) -> bool {
     /// ```
     /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
     #[inline]
-    pub fn is_normal(self) -> bool {
-        self.classify() == FpCategory::Normal
+    pub const fn is_normal(self) -> bool {
+        matches!(self.classify(), FpCategory::Normal)
     }
 
     /// Returns the floating point category of the number. If only one property
@@ -475,7 +480,8 @@ pub fn is_normal(self) -> bool {
     /// assert_eq!(inf.classify(), FpCategory::Infinite);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn classify(self) -> FpCategory {
+    #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
+    pub const fn classify(self) -> FpCategory {
         const EXP_MASK: u64 = 0x7ff0000000000000;
         const MAN_MASK: u64 = 0x000fffffffffffff;
 
@@ -500,8 +506,9 @@ pub fn classify(self) -> FpCategory {
     /// assert!(!g.is_sign_positive());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
     #[inline]
-    pub fn is_sign_positive(self) -> bool {
+    pub const fn is_sign_positive(self) -> bool {
         !self.is_sign_negative()
     }
 
@@ -524,8 +531,9 @@ pub fn is_positive(self) -> bool {
     /// assert!(g.is_sign_negative());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
     #[inline]
-    pub fn is_sign_negative(self) -> bool {
+    pub const fn is_sign_negative(self) -> bool {
         self.to_bits() & 0x8000_0000_0000_0000 != 0
     }
 
@@ -666,8 +674,9 @@ pub unsafe fn to_int_unchecked<Int>(self) -> Int
     ///
     /// ```
     #[stable(feature = "float_bits_conv", since = "1.20.0")]
+    #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
     #[inline]
-    pub fn to_bits(self) -> u64 {
+    pub const fn to_bits(self) -> u64 {
         // SAFETY: `u64` is a plain old datatype so we can always transmute to it
         unsafe { mem::transmute(self) }
     }
@@ -709,8 +718,9 @@ pub fn to_bits(self) -> u64 {
     /// assert_eq!(v, 12.5);
     /// ```
     #[stable(feature = "float_bits_conv", since = "1.20.0")]
+    #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
     #[inline]
-    pub fn from_bits(v: u64) -> Self {
+    pub const fn from_bits(v: u64) -> Self {
         // SAFETY: `u64` is a plain old datatype so we can always transmute from it
         // It turns out the safety issues with sNaN were overblown! Hooray!
         unsafe { mem::transmute(v) }
@@ -726,8 +736,9 @@ pub fn from_bits(v: u64) -> Self {
     /// assert_eq!(bytes, [0x40, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
     /// ```
     #[stable(feature = "float_to_from_bytes", since = "1.40.0")]
+    #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
     #[inline]
-    pub fn to_be_bytes(self) -> [u8; 8] {
+    pub const fn to_be_bytes(self) -> [u8; 8] {
         self.to_bits().to_be_bytes()
     }
 
@@ -741,8 +752,9 @@ pub fn from_bits(v: u64) -> Self {
     /// assert_eq!(bytes, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x40]);
     /// ```
     #[stable(feature = "float_to_from_bytes", since = "1.40.0")]
+    #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
     #[inline]
-    pub fn to_le_bytes(self) -> [u8; 8] {
+    pub const fn to_le_bytes(self) -> [u8; 8] {
         self.to_bits().to_le_bytes()
     }
 
@@ -769,8 +781,9 @@ pub fn from_bits(v: u64) -> Self {
     /// );
     /// ```
     #[stable(feature = "float_to_from_bytes", since = "1.40.0")]
+    #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
     #[inline]
-    pub fn to_ne_bytes(self) -> [u8; 8] {
+    pub const fn to_ne_bytes(self) -> [u8; 8] {
         self.to_bits().to_ne_bytes()
     }
 
@@ -783,8 +796,9 @@ pub fn from_bits(v: u64) -> Self {
     /// assert_eq!(value, 12.5);
     /// ```
     #[stable(feature = "float_to_from_bytes", since = "1.40.0")]
+    #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
     #[inline]
-    pub fn from_be_bytes(bytes: [u8; 8]) -> Self {
+    pub const fn from_be_bytes(bytes: [u8; 8]) -> Self {
         Self::from_bits(u64::from_be_bytes(bytes))
     }
 
@@ -797,8 +811,9 @@ pub fn from_bits(v: u64) -> Self {
     /// assert_eq!(value, 12.5);
     /// ```
     #[stable(feature = "float_to_from_bytes", since = "1.40.0")]
+    #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
     #[inline]
-    pub fn from_le_bytes(bytes: [u8; 8]) -> Self {
+    pub const fn from_le_bytes(bytes: [u8; 8]) -> Self {
         Self::from_bits(u64::from_le_bytes(bytes))
     }
 
@@ -822,8 +837,9 @@ pub fn from_bits(v: u64) -> Self {
     /// assert_eq!(value, 12.5);
     /// ```
     #[stable(feature = "float_to_from_bytes", since = "1.40.0")]
+    #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
     #[inline]
-    pub fn from_ne_bytes(bytes: [u8; 8]) -> Self {
+    pub const fn from_ne_bytes(bytes: [u8; 8]) -> Self {
         Self::from_bits(u64::from_ne_bytes(bytes))
     }
 
index 68937176270356a031ac23cf1fed6053f5edff5a..7a88cfbb74dd45472486d181c20fd3d5cb94ca4b 100644 (file)
@@ -1573,7 +1573,7 @@ pub const fn wrapping_shr(self, rhs: u32) -> Self {
 the boundary of the type.
 
 The only case where such wrapping can occur is when one takes the absolute value of the negative
-minimal value for the type this is a positive value that is too large to represent in the type. In
+minimal value for the type; this is a positive value that is too large to represent in the type. In
 such a case, this function returns `MIN` itself.
 
 # Examples
index 3faeb170b0637626090dcdb9dd1fba9c0b999cb3..d6c097eee17bf96ff18540667972043d8b1e86c8 100644 (file)
@@ -28,7 +28,6 @@
 /// [method resolution] and [type coercions].
 ///
 /// [book]: ../../book/ch15-02-deref.html
-/// [`DerefMut`]: trait.DerefMut.html
 /// [more]: #more-on-deref-coercion
 /// [ref-deref-op]: ../../reference/expressions/operator-expr.html#the-dereference-operator
 /// [method resolution]: ../../reference/expressions/method-call-expr.html
@@ -125,7 +124,6 @@ fn deref(&self) -> &T {
 /// [method resolution] and [type coercions].
 ///
 /// [book]: ../../book/ch15-02-deref.html
-/// [`Deref`]: trait.Deref.html
 /// [more]: #more-on-deref-coercion
 /// [ref-deref-op]: ../../reference/expressions/operator-expr.html#the-dereference-operator
 /// [method resolution]: ../../reference/expressions/method-call-expr.html
index 06cfc36363615ee56515bcb64e439bea37676484..ce7d1c3d06ddc5dea1dfb68a152a7551c4d7e4af 100644 (file)
@@ -78,9 +78,9 @@
 ///
 /// In other words, if you tried to explicitly call `Drop::drop` in the above example, you'd get a compiler error.
 ///
-/// If you'd like explicitly call the destructor of a value, [`std::mem::drop`] can be used instead.
+/// If you'd like explicitly call the destructor of a value, [`mem::drop`] can be used instead.
 ///
-/// [`std::mem::drop`]: ../../std/mem/fn.drop.html
+/// [`mem::drop`]: drop
 ///
 /// ## Drop order
 ///
 /// are `Copy` get implicitly duplicated by the compiler, making it very
 /// hard to predict when, and how often destructors will be executed. As such,
 /// these types cannot have destructors.
-///
-/// [`Copy`]: ../../std/marker/trait.Copy.html
 #[lang = "drop"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Drop {
@@ -141,7 +139,7 @@ pub trait Drop {
     ///
     /// This method is called implicitly when the value goes out of scope,
     /// and cannot be called explicitly (this is compiler error [E0040]).
-    /// However, the [`std::mem::drop`] function in the prelude can be
+    /// However, the [`mem::drop`] function in the prelude can be
     /// used to call the argument's `Drop` implementation.
     ///
     /// When this method has been called, `self` has not yet been deallocated.
@@ -156,12 +154,12 @@ pub trait Drop {
     /// Note that even if this panics, the value is considered to be dropped;
     /// you must not cause `drop` to be called again. This is normally automatically
     /// handled by the compiler, but when using unsafe code, can sometimes occur
-    /// unintentionally, particularly when using [`std::ptr::drop_in_place`].
+    /// unintentionally, particularly when using [`ptr::drop_in_place`].
     ///
     /// [E0040]: ../../error-index.html#E0040
-    /// [`panic!`]: ../macro.panic.html
-    /// [`std::mem::drop`]: ../../std/mem/fn.drop.html
-    /// [`std::ptr::drop_in_place`]: ../../std/ptr/fn.drop_in_place.html
+    /// [`panic!`]: crate::panic!
+    /// [`mem::drop`]: drop
+    /// [`ptr::drop_in_place`]: crate::ptr::drop_in_place
     #[stable(feature = "rust1", since = "1.0.0")]
     fn drop(&mut self);
 }
index 3e5cad2b185a14b252e5e2854e9ebfddc0cbfcce..bfdec43f7d80b3c211669655f1f54ae9f5ad6d48 100644 (file)
@@ -28,8 +28,6 @@
 /// this can refer to [the relevant section in the *Rustonomicon*][nomicon].
 ///
 /// [book]: ../../book/ch13-01-closures.html
-/// [`FnMut`]: trait.FnMut.html
-/// [`FnOnce`]: trait.FnOnce.html
 /// [function pointers]: ../../std/primitive.fn.html
 /// [nomicon]: ../../nomicon/hrtb.html
 ///
@@ -99,8 +97,6 @@ pub trait Fn<Args>: FnMut<Args> {
 /// this can refer to [the relevant section in the *Rustonomicon*][nomicon].
 ///
 /// [book]: ../../book/ch13-01-closures.html
-/// [`Fn`]: trait.Fn.html
-/// [`FnOnce`]: trait.FnOnce.html
 /// [function pointers]: ../../std/primitive.fn.html
 /// [nomicon]: ../../nomicon/hrtb.html
 ///
@@ -180,8 +176,6 @@ pub trait FnMut<Args>: FnOnce<Args> {
 /// this can refer to [the relevant section in the *Rustonomicon*][nomicon].
 ///
 /// [book]: ../../book/ch13-01-closures.html
-/// [`Fn`]: trait.Fn.html
-/// [`FnMut`]: trait.FnMut.html
 /// [function pointers]: ../../std/primitive.fn.html
 /// [nomicon]: ../../nomicon/hrtb.html
 ///
index 763b33606fe88b18c044359c74dec2c3bf6172e1..3c2ada57612337e0d865168bc7dc8b4d07af634b 100644 (file)
@@ -5,9 +5,6 @@
 /// [`IndexMut`] is used instead. This allows nice things such as
 /// `let value = v[index]` if the type of `value` implements [`Copy`].
 ///
-/// [`IndexMut`]: ../../std/ops/trait.IndexMut.html
-/// [`Copy`]: ../../std/marker/trait.Copy.html
-///
 /// # Examples
 ///
 /// The following example implements `Index` on a read-only `NucleotideCount`
@@ -76,8 +73,6 @@ pub trait Index<Idx: ?Sized> {
 /// an immutable value is requested, the [`Index`] trait is used instead. This
 /// allows nice things such as `v[index] = value`.
 ///
-/// [`Index`]: ../../std/ops/trait.Index.html
-///
 /// # Examples
 ///
 /// A very simple implementation of a `Balance` struct that has two sides, where
index e3e5934b44be1f0732913ce89568a556dc3d4e19..c19bd6e441e695950f5d258eabe83a816cdd9be3 100644 (file)
 //! // `consume_and_return_x` can no longer be invoked at this point
 //! ```
 //!
-//! [`Fn`]: trait.Fn.html
-//! [`FnMut`]: trait.FnMut.html
-//! [`FnOnce`]: trait.FnOnce.html
-//! [`Add`]: trait.Add.html
-//! [`Sub`]: trait.Sub.html
-//! [`Mul`]: trait.Mul.html
-//! [`clone`]: ../clone/trait.Clone.html#tymethod.clone
+//! [`clone`]: Clone::clone
 //! [operator precedence]: ../../reference/expressions.html#expression-precedence
 
 #![stable(feature = "rust1", since = "1.0.0")]
index e9ab82b5398496d2996d8355b55090db6e0f33d9..d10829832dd169f3779b74528b5be99fcee3fb32 100644 (file)
@@ -35,9 +35,7 @@
 /// assert_eq!(arr[1..=3], [  1,2,3  ]);
 /// ```
 ///
-/// [`IntoIterator`]: ../iter/trait.Iterator.html
-/// [`Iterator`]: ../iter/trait.IntoIterator.html
-/// [slicing index]: ../slice/trait.SliceIndex.html
+/// [slicing index]: crate::slice::SliceIndex
 #[cfg_attr(not(bootstrap), lang = "RangeFull")]
 #[doc(alias = "..")]
 #[derive(Copy, Clone, Default, PartialEq, Eq, Hash)]
@@ -127,8 +125,6 @@ pub fn contains<U>(&self, item: &U) -> bool
     /// # Examples
     ///
     /// ```
-    /// #![feature(range_is_empty)]
-    ///
     /// assert!(!(3..5).is_empty());
     /// assert!( (3..3).is_empty());
     /// assert!( (3..2).is_empty());
@@ -137,13 +133,11 @@ pub fn contains<U>(&self, item: &U) -> bool
     /// The range is empty if either side is incomparable:
     ///
     /// ```
-    /// #![feature(range_is_empty)]
-    ///
     /// assert!(!(3.0..5.0).is_empty());
     /// assert!( (3.0..f32::NAN).is_empty());
     /// assert!( (f32::NAN..5.0).is_empty());
     /// ```
-    #[unstable(feature = "range_is_empty", reason = "recently added", issue = "48111")]
+    #[stable(feature = "range_is_empty", since = "1.47.0")]
     pub fn is_empty(&self) -> bool {
         !(self.start < self.end)
     }
@@ -178,8 +172,6 @@ pub fn is_empty(&self) -> bool {
 /// assert_eq!(arr[1.. 3], [  1,2    ]);
 /// assert_eq!(arr[1..=3], [  1,2,3  ]);
 /// ```
-///
-/// [`Iterator`]: ../iter/trait.IntoIterator.html
 #[cfg_attr(not(bootstrap), lang = "RangeFrom")]
 #[doc(alias = "..")]
 #[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186
@@ -260,9 +252,7 @@ pub fn contains<U>(&self, item: &U) -> bool
 /// assert_eq!(arr[1..=3], [  1,2,3  ]);
 /// ```
 ///
-/// [`IntoIterator`]: ../iter/trait.Iterator.html
-/// [`Iterator`]: ../iter/trait.IntoIterator.html
-/// [slicing index]: ../slice/trait.SliceIndex.html
+/// [slicing index]: crate::slice::SliceIndex
 #[cfg_attr(not(bootstrap), lang = "RangeTo")]
 #[doc(alias = "..")]
 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
@@ -315,8 +305,8 @@ pub fn contains<U>(&self, item: &U) -> bool
 /// iteration has finished are **unspecified** other than that [`.is_empty()`]
 /// will return `true` once no more values will be produced.
 ///
-/// [fused]: ../iter/trait.FusedIterator.html
-/// [`.is_empty()`]: #method.is_empty
+/// [fused]: crate::iter::FusedIterator
+/// [`.is_empty()`]: RangeInclusive::is_empty
 ///
 /// # Examples
 ///
@@ -383,8 +373,8 @@ pub const fn new(start: Idx, end: Idx) -> Self {
     /// Note: the value returned by this method is unspecified after the range
     /// has been iterated to exhaustion.
     ///
-    /// [`end()`]: #method.end
-    /// [`is_empty()`]: #method.is_empty
+    /// [`end()`]: RangeInclusive::end
+    /// [`is_empty()`]: RangeInclusive::is_empty
     ///
     /// # Examples
     ///
@@ -408,8 +398,8 @@ pub const fn start(&self) -> &Idx {
     /// Note: the value returned by this method is unspecified after the range
     /// has been iterated to exhaustion.
     ///
-    /// [`start()`]: #method.start
-    /// [`is_empty()`]: #method.is_empty
+    /// [`start()`]: RangeInclusive::start
+    /// [`is_empty()`]: RangeInclusive::is_empty
     ///
     /// # Examples
     ///
@@ -487,8 +477,6 @@ pub fn contains<U>(&self, item: &U) -> bool
     /// # Examples
     ///
     /// ```
-    /// #![feature(range_is_empty)]
-    ///
     /// assert!(!(3..=5).is_empty());
     /// assert!(!(3..=3).is_empty());
     /// assert!( (3..=2).is_empty());
@@ -497,8 +485,6 @@ pub fn contains<U>(&self, item: &U) -> bool
     /// The range is empty if either side is incomparable:
     ///
     /// ```
-    /// #![feature(range_is_empty)]
-    ///
     /// assert!(!(3.0..=5.0).is_empty());
     /// assert!( (3.0..=f32::NAN).is_empty());
     /// assert!( (f32::NAN..=5.0).is_empty());
@@ -507,14 +493,12 @@ pub fn contains<U>(&self, item: &U) -> bool
     /// This method returns `true` after iteration has finished:
     ///
     /// ```
-    /// #![feature(range_is_empty)]
-    ///
     /// let mut r = 3..=5;
     /// for _ in r.by_ref() {}
     /// // Precise field values are unspecified here
     /// assert!(r.is_empty());
     /// ```
-    #[unstable(feature = "range_is_empty", reason = "recently added", issue = "48111")]
+    #[stable(feature = "range_is_empty", since = "1.47.0")]
     #[inline]
     pub fn is_empty(&self) -> bool {
         self.exhausted || !(self.start <= self.end)
@@ -558,9 +542,7 @@ pub fn is_empty(&self) -> bool {
 /// assert_eq!(arr[1..=3], [  1,2,3  ]);
 /// ```
 ///
-/// [`IntoIterator`]: ../iter/trait.Iterator.html
-/// [`Iterator`]: ../iter/trait.IntoIterator.html
-/// [slicing index]: ../slice/trait.SliceIndex.html
+/// [slicing index]: crate::slice::SliceIndex
 #[cfg_attr(not(bootstrap), lang = "RangeToInclusive")]
 #[doc(alias = "..=")]
 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
index 95a4393592be911f6565f5a434063f535818903e..483362023b22c77bc5f340260804f825c2766080 100644 (file)
@@ -29,7 +29,7 @@
 /// pointers. It is implemented automatically by the compiler.
 ///
 /// [dst-coerce]: https://github.com/rust-lang/rfcs/blob/master/text/0982-dst-coercion.md
-/// [unsize]: ../marker/trait.Unsize.html
+/// [unsize]: crate::marker::Unsize
 /// [nomicon-coerce]: ../../nomicon/coercions.html
 #[unstable(feature = "coerce_unsized", issue = "27732")]
 #[lang = "coerce_unsized"]
index b63219a440392bce543484660b133655f4c4a564..290aa797fd964971df6a2aebfbe3160b366a9978 100644 (file)
 //! mutable reference even when you just have [`Pin`]`<&mut Self>` (such as in your own
 //! [`poll`] implementation).
 //!
-//! [`Pin<P>`]: struct.Pin.html
-//! [`Unpin`]: ../marker/trait.Unpin.html
-//! [`Deref`]: ../ops/trait.Deref.html
-//! [`DerefMut`]: ../ops/trait.DerefMut.html
-//! [`mem::swap`]: ../mem/fn.swap.html
-//! [`mem::forget`]: ../mem/fn.forget.html
+//! [`Pin<P>`]: Pin
+//! [`Deref`]: crate::ops::Deref
+//! [`DerefMut`]: crate::ops::DerefMut
+//! [`mem::swap`]: crate::mem::swap
+//! [`mem::forget`]: crate::mem::forget
 //! [`Box<T>`]: ../../std/boxed/struct.Box.html
 //! [`Vec<T>`]: ../../std/vec/struct.Vec.html
 //! [`Vec::set_len`]: ../../std/vec/struct.Vec.html#method.set_len
-//! [`Pin`]: struct.Pin.html
 //! [`Box`]: ../../std/boxed/struct.Box.html
 //! [Vec::pop]: ../../std/vec/struct.Vec.html#method.pop
 //! [Vec::push]: ../../std/vec/struct.Vec.html#method.push
 //! [`Rc`]: ../../std/rc/struct.Rc.html
-//! [`RefCell<T>`]: ../../std/cell/struct.RefCell.html
-//! [`Drop`]: ../../std/ops/trait.Drop.html
-//! [`drop`]: ../../std/ops/trait.Drop.html#tymethod.drop
+//! [`RefCell<T>`]: crate::cell::RefCell
+//! [`drop`]: Drop::drop
 //! [`VecDeque<T>`]: ../../std/collections/struct.VecDeque.html
-//! [`Option<T>`]: ../../std/option/enum.Option.html
-//! [`VecDeque<T>`]: ../../std/collections/struct.VecDeque.html
-//! [`RefCell<T>`]: ../cell/struct.RefCell.html
-//! [`None`]: ../option/enum.Option.html#variant.None
-//! [`Some(v)`]: ../option/enum.Option.html#variant.Some
-//! [`ptr::write`]: ../ptr/fn.write.html
-//! [`Future`]: ../future/trait.Future.html
+//! [`Option<T>`]: Option
+//! [`Some(v)`]: Some
+//! [`ptr::write`]: crate::ptr::write
+//! [`Future`]: crate::future::Future
 //! [drop-impl]: #drop-implementation
 //! [drop-guarantee]: #drop-guarantee
-//! [`poll`]: ../../std/future/trait.Future.html#tymethod.poll
-//! [`Pin::get_unchecked_mut`]: struct.Pin.html#method.get_unchecked_mut
-//! [`bool`]: ../../std/primitive.bool.html
-//! [`i32`]: ../../std/primitive.i32.html
+//! [`poll`]: crate::future::Future::poll
 
 #![stable(feature = "pin", since = "1.33.0")]
 
 ///
 /// *See the [`pin` module] documentation for an explanation of pinning.*
 ///
-/// [`Unpin`]: ../../std/marker/trait.Unpin.html
-/// [`pin` module]: ../../std/pin/index.html
+/// [`pin` module]: self
 //
 // Note: the `Clone` derive below causes unsoundness as it's possible to implement
 // `Clone` for mutable references.
@@ -481,8 +471,6 @@ impl<P: Deref<Target: Unpin>> Pin<P> {
     ///
     /// Unlike `Pin::new_unchecked`, this method is safe because the pointer
     /// `P` dereferences to an [`Unpin`] type, which cancels the pinning guarantees.
-    ///
-    /// [`Unpin`]: ../../std/marker/trait.Unpin.html
     #[stable(feature = "pin", since = "1.33.0")]
     #[inline(always)]
     pub fn new(pointer: P) -> Pin<P> {
@@ -495,8 +483,6 @@ pub fn new(pointer: P) -> Pin<P> {
     ///
     /// This requires that the data inside this `Pin` is [`Unpin`] so that we
     /// can ignore the pinning invariants when unwrapping it.
-    ///
-    /// [`Unpin`]: ../../std/marker/trait.Unpin.html
     #[stable(feature = "pin_into_inner", since = "1.39.0")]
     #[inline(always)]
     pub fn into_inner(pin: Pin<P>) -> P {
@@ -568,7 +554,7 @@ impl<P: Deref> Pin<P> {
     ///  }
     ///  ```
     ///
-    /// [`mem::swap`]: ../../std/mem/fn.swap.html
+    /// [`mem::swap`]: crate::mem::swap
     #[cfg_attr(not(bootstrap), lang = "new_unchecked")]
     #[stable(feature = "pin", since = "1.33.0")]
     #[inline(always)]
@@ -603,9 +589,6 @@ pub fn as_ref(&self) -> Pin<&P::Target> {
     ///
     /// If the underlying data is [`Unpin`], [`Pin::into_inner`] should be used
     /// instead.
-    ///
-    /// [`Unpin`]: ../../std/marker/trait.Unpin.html
-    /// [`Pin::into_inner`]: #method.into_inner
     #[stable(feature = "pin_into_inner", since = "1.39.0")]
     #[inline(always)]
     pub unsafe fn into_inner_unchecked(pin: Pin<P>) -> P {
index 7d7306574a6e87f80cff7884f9637ff38e4aeb12..fc70dec16f618aeea80e257ebc4e5ae4055c49f6 100644 (file)
@@ -240,8 +240,8 @@ pub unsafe fn as_uninit_ref<'a>(self) -> Option<&'a MaybeUninit<T>>
     /// different allocated object. Note that in Rust,
     /// every (stack-allocated) variable is considered a separate allocated object.
     ///
-    /// In other words, `x.wrapping_offset(y.wrapping_offset_from(x))` is
-    /// *not* the same as `y`, and dereferencing it is undefined behavior
+    /// In other words, `x.wrapping_offset((y as usize).wrapping_sub(x as usize) / size_of::<T>())`
+    /// is *not* the same as `y`, and dereferencing it is undefined behavior
     /// unless `x` and `y` point into the same allocated object.
     ///
     /// Compared to [`offset`], this method basically delays the requirement of staying
@@ -292,7 +292,6 @@ pub const fn wrapping_offset(self, count: isize) -> *const T
     /// This function is the inverse of [`offset`].
     ///
     /// [`offset`]: #method.offset
-    /// [`wrapping_offset_from`]: #method.wrapping_offset_from
     ///
     /// # Safety
     ///
@@ -303,6 +302,9 @@ pub const fn wrapping_offset(self, count: isize) -> *const T
     ///   byte past the end of the same allocated object. Note that in Rust,
     ///   every (stack-allocated) variable is considered a separate allocated object.
     ///
+    /// * Both pointers must be *derived from* a pointer to the same object.
+    ///   (See below for an example.)
+    ///
     /// * The distance between the pointers, **in bytes**, cannot overflow an `isize`.
     ///
     /// * The distance between the pointers, in bytes, must be an exact multiple
@@ -323,10 +325,6 @@ pub const fn wrapping_offset(self, count: isize) -> *const T
     /// Extension. As such, memory acquired directly from allocators or memory
     /// mapped files *may* be too large to handle with this function.
     ///
-    /// Consider using [`wrapping_offset_from`] instead if these constraints are
-    /// difficult to satisfy. The only advantage of this method is that it
-    /// enables more aggressive compiler optimizations.
-    ///
     /// # Panics
     ///
     /// This function panics if `T` is a Zero-Sized Type ("ZST").
@@ -336,8 +334,6 @@ pub const fn wrapping_offset(self, count: isize) -> *const T
     /// Basic usage:
     ///
     /// ```
-    /// #![feature(ptr_offset_from)]
-    ///
     /// let a = [0; 5];
     /// let ptr1: *const i32 = &a[1];
     /// let ptr2: *const i32 = &a[3];
@@ -348,7 +344,24 @@ pub const fn wrapping_offset(self, count: isize) -> *const T
     ///     assert_eq!(ptr2.offset(-2), ptr1);
     /// }
     /// ```
-    #[unstable(feature = "ptr_offset_from", issue = "41079")]
+    ///
+    /// *Incorrect* usage:
+    ///
+    /// ```rust,no_run
+    /// let ptr1 = Box::into_raw(Box::new(0u8)) as *const u8;
+    /// let ptr2 = Box::into_raw(Box::new(1u8)) as *const u8;
+    /// let diff = (ptr2 as isize).wrapping_sub(ptr1 as isize);
+    /// // Make ptr2_other an "alias" of ptr2, but derived from ptr1.
+    /// let ptr2_other = (ptr1 as *const u8).wrapping_offset(diff);
+    /// assert_eq!(ptr2 as usize, ptr2_other as usize);
+    /// // Since ptr2_other and ptr2 are derived from pointers to different objects,
+    /// // computing their offset is undefined behavior, even though
+    /// // they point to the same address!
+    /// unsafe {
+    ///     let zero = ptr2_other.offset_from(ptr2); // Undefined Behavior
+    /// }
+    /// ```
+    #[stable(feature = "ptr_offset_from", since = "1.47.0")]
     #[rustc_const_unstable(feature = "const_ptr_offset_from", issue = "41079")]
     #[inline]
     pub const unsafe fn offset_from(self, origin: *const T) -> isize
@@ -423,59 +436,6 @@ pub const fn guaranteed_ne(self, other: *const T) -> bool
         intrinsics::ptr_guaranteed_ne(self, other)
     }
 
-    /// Calculates the distance between two pointers. The returned value is in
-    /// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
-    ///
-    /// If the address different between the two pointers is not a multiple of
-    /// `mem::size_of::<T>()` then the result of the division is rounded towards
-    /// zero.
-    ///
-    /// Though this method is safe for any two pointers, note that its result
-    /// will be mostly useless if the two pointers aren't into the same allocated
-    /// object, for example if they point to two different local variables.
-    ///
-    /// # Panics
-    ///
-    /// This function panics if `T` is a zero-sized type.
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// #![feature(ptr_wrapping_offset_from)]
-    ///
-    /// let a = [0; 5];
-    /// let ptr1: *const i32 = &a[1];
-    /// let ptr2: *const i32 = &a[3];
-    /// assert_eq!(ptr2.wrapping_offset_from(ptr1), 2);
-    /// assert_eq!(ptr1.wrapping_offset_from(ptr2), -2);
-    /// assert_eq!(ptr1.wrapping_offset(2), ptr2);
-    /// assert_eq!(ptr2.wrapping_offset(-2), ptr1);
-    ///
-    /// let ptr1: *const i32 = 3 as _;
-    /// let ptr2: *const i32 = 13 as _;
-    /// assert_eq!(ptr2.wrapping_offset_from(ptr1), 2);
-    /// ```
-    #[unstable(feature = "ptr_wrapping_offset_from", issue = "41079")]
-    #[rustc_deprecated(
-        since = "1.46.0",
-        reason = "Pointer distances across allocation \
-        boundaries are not typically meaningful. \
-        Use integer subtraction if you really need this."
-    )]
-    #[inline]
-    pub fn wrapping_offset_from(self, origin: *const T) -> isize
-    where
-        T: Sized,
-    {
-        let pointee_size = mem::size_of::<T>();
-        assert!(0 < pointee_size && pointee_size <= isize::MAX as usize);
-
-        let d = isize::wrapping_sub(self as _, origin as _);
-        d.wrapping_div(pointee_size as _)
-    }
-
     /// Calculates the offset from a pointer (convenience for `.offset(count as isize)`).
     ///
     /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
index 3daeec3604185b1bfbece98b9649ce445b08cd4c..2d25f21e55c761a5321765d8712fedabf2e2be38 100644 (file)
@@ -246,8 +246,8 @@ pub unsafe fn as_uninit_ref<'a>(self) -> Option<&'a MaybeUninit<T>>
     /// different allocated object. Note that in Rust,
     /// every (stack-allocated) variable is considered a separate allocated object.
     ///
-    /// In other words, `x.wrapping_offset(y.wrapping_offset_from(x))` is
-    /// *not* the same as `y`, and dereferencing it is undefined behavior
+    /// In other words, `x.wrapping_offset((y as usize).wrapping_sub(x as usize) / size_of::<T>())`
+    /// is *not* the same as `y`, and dereferencing it is undefined behavior
     /// unless `x` and `y` point into the same allocated object.
     ///
     /// Compared to [`offset`], this method basically delays the requirement of staying
@@ -463,7 +463,6 @@ pub const fn guaranteed_eq(self, other: *mut T) -> bool
     /// This function is the inverse of [`offset`].
     ///
     /// [`offset`]: #method.offset-1
-    /// [`wrapping_offset_from`]: #method.wrapping_offset_from-1
     ///
     /// # Safety
     ///
@@ -474,6 +473,9 @@ pub const fn guaranteed_eq(self, other: *mut T) -> bool
     ///   byte past the end of the same allocated object. Note that in Rust,
     ///   every (stack-allocated) variable is considered a separate allocated object.
     ///
+    /// * Both pointers must be *derived from* a pointer to the same object.
+    ///   (See below for an example.)
+    ///
     /// * The distance between the pointers, **in bytes**, cannot overflow an `isize`.
     ///
     /// * The distance between the pointers, in bytes, must be an exact multiple
@@ -494,10 +496,6 @@ pub const fn guaranteed_eq(self, other: *mut T) -> bool
     /// Extension. As such, memory acquired directly from allocators or memory
     /// mapped files *may* be too large to handle with this function.
     ///
-    /// Consider using [`wrapping_offset_from`] instead if these constraints are
-    /// difficult to satisfy. The only advantage of this method is that it
-    /// enables more aggressive compiler optimizations.
-    ///
     /// # Panics
     ///
     /// This function panics if `T` is a Zero-Sized Type ("ZST").
@@ -507,8 +505,6 @@ pub const fn guaranteed_eq(self, other: *mut T) -> bool
     /// Basic usage:
     ///
     /// ```
-    /// #![feature(ptr_offset_from)]
-    ///
     /// let mut a = [0; 5];
     /// let ptr1: *mut i32 = &mut a[1];
     /// let ptr2: *mut i32 = &mut a[3];
@@ -519,7 +515,24 @@ pub const fn guaranteed_eq(self, other: *mut T) -> bool
     ///     assert_eq!(ptr2.offset(-2), ptr1);
     /// }
     /// ```
-    #[unstable(feature = "ptr_offset_from", issue = "41079")]
+    ///
+    /// *Incorrect* usage:
+    ///
+    /// ```rust,no_run
+    /// let ptr1 = Box::into_raw(Box::new(0u8));
+    /// let ptr2 = Box::into_raw(Box::new(1u8));
+    /// let diff = (ptr2 as isize).wrapping_sub(ptr1 as isize);
+    /// // Make ptr2_other an "alias" of ptr2, but derived from ptr1.
+    /// let ptr2_other = (ptr1 as *mut u8).wrapping_offset(diff);
+    /// assert_eq!(ptr2 as usize, ptr2_other as usize);
+    /// // Since ptr2_other and ptr2 are derived from pointers to different objects,
+    /// // computing their offset is undefined behavior, even though
+    /// // they point to the same address!
+    /// unsafe {
+    ///     let zero = ptr2_other.offset_from(ptr2); // Undefined Behavior
+    /// }
+    /// ```
+    #[stable(feature = "ptr_offset_from", since = "1.47.0")]
     #[rustc_const_unstable(feature = "const_ptr_offset_from", issue = "41079")]
     #[inline]
     pub const unsafe fn offset_from(self, origin: *const T) -> isize
@@ -530,56 +543,6 @@ pub const fn guaranteed_eq(self, other: *mut T) -> bool
         unsafe { (self as *const T).offset_from(origin) }
     }
 
-    /// Calculates the distance between two pointers. The returned value is in
-    /// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
-    ///
-    /// If the address different between the two pointers is not a multiple of
-    /// `mem::size_of::<T>()` then the result of the division is rounded towards
-    /// zero.
-    ///
-    /// Though this method is safe for any two pointers, note that its result
-    /// will be mostly useless if the two pointers aren't into the same allocated
-    /// object, for example if they point to two different local variables.
-    ///
-    /// # Panics
-    ///
-    /// This function panics if `T` is a zero-sized type.
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// #![feature(ptr_wrapping_offset_from)]
-    ///
-    /// let mut a = [0; 5];
-    /// let ptr1: *mut i32 = &mut a[1];
-    /// let ptr2: *mut i32 = &mut a[3];
-    /// assert_eq!(ptr2.wrapping_offset_from(ptr1), 2);
-    /// assert_eq!(ptr1.wrapping_offset_from(ptr2), -2);
-    /// assert_eq!(ptr1.wrapping_offset(2), ptr2);
-    /// assert_eq!(ptr2.wrapping_offset(-2), ptr1);
-    ///
-    /// let ptr1: *mut i32 = 3 as _;
-    /// let ptr2: *mut i32 = 13 as _;
-    /// assert_eq!(ptr2.wrapping_offset_from(ptr1), 2);
-    /// ```
-    #[unstable(feature = "ptr_wrapping_offset_from", issue = "41079")]
-    #[rustc_deprecated(
-        since = "1.46.0",
-        reason = "Pointer distances across allocation \
-        boundaries are not typically meaningful. \
-        Use integer subtraction if you really need this."
-    )]
-    #[inline]
-    pub fn wrapping_offset_from(self, origin: *const T) -> isize
-    where
-        T: Sized,
-    {
-        #[allow(deprecated_in_future, deprecated)]
-        (self as *const T).wrapping_offset_from(origin)
-    }
-
     /// Calculates the offset from a pointer (convenience for `.offset(count as isize)`).
     ///
     /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
index 741a9dc8797becd6351f4599905e7f1b9139f1a3..1227d9b01f011105a316b693704d63e22802caa0 100644 (file)
@@ -26,7 +26,7 @@
 /// [`std::mem::transmute`][transmute]. Similarly, the only way to create a true
 /// trait object from a `TraitObject` value is with `transmute`.
 ///
-/// [transmute]: ../intrinsics/fn.transmute.html
+/// [transmute]: crate::intrinsics::transmute
 ///
 /// Synthesizing a trait object with mismatched types—one where the
 /// vtable does not correspond to the type of the value to which the
index 5eddcb2172abe7ac6ba91fffdd2255edf18f4bca..ade5472717dde4d9c9228321bacc8cdebba8d549 100644 (file)
 //! [`?`] can only be used in functions that return [`Result`] because of the
 //! early return of [`Err`] that it provides.
 //!
-//! [`expect`]: enum.Result.html#method.expect
+//! [`expect`]: Result::expect
 //! [`Write`]: ../../std/io/trait.Write.html
 //! [`write_all`]: ../../std/io/trait.Write.html#method.write_all
 //! [`io::Result`]: ../../std/io/type.Result.html
-//! [`?`]: ../../std/macro.try.html
-//! [`Result`]: enum.Result.html
-//! [`Ok(T)`]: enum.Result.html#variant.Ok
-//! [`Err(E)`]: enum.Result.html#variant.Err
+//! [`?`]: crate::ops::Try
+//! [`Ok(T)`]: Ok
+//! [`Err(E)`]: Err
 //! [`io::Error`]: ../../std/io/struct.Error.html
-//! [`Ok`]: enum.Result.html#variant.Ok
-//! [`Err`]: enum.Result.html#variant.Err
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
 /// `Result` is a type that represents either success ([`Ok`]) or failure ([`Err`]).
 ///
 /// See the [`std::result`](index.html) module documentation for details.
-///
-/// [`Ok`]: enum.Result.html#variant.Ok
-/// [`Err`]: enum.Result.html#variant.Err
 #[derive(Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
 #[must_use = "this `Result` may be an `Err` variant, which should be handled"]
 #[rustc_diagnostic_item = "result_type"]
@@ -267,8 +261,6 @@ impl<T, E> Result<T, E> {
 
     /// Returns `true` if the result is [`Ok`].
     ///
-    /// [`Ok`]: enum.Result.html#variant.Ok
-    ///
     /// # Examples
     ///
     /// Basic usage:
@@ -290,8 +282,6 @@ pub const fn is_ok(&self) -> bool {
 
     /// Returns `true` if the result is [`Err`].
     ///
-    /// [`Err`]: enum.Result.html#variant.Err
-    ///
     /// # Examples
     ///
     /// Basic usage:
@@ -378,7 +368,7 @@ pub fn contains_err<F>(&self, f: &F) -> bool
     /// Converts `self` into an [`Option<T>`], consuming `self`,
     /// and discarding the error, if any.
     ///
-    /// [`Option<T>`]: ../../std/option/enum.Option.html
+    /// [`Option<T>`]: Option
     ///
     /// # Examples
     ///
@@ -405,7 +395,7 @@ pub fn ok(self) -> Option<T> {
     /// Converts `self` into an [`Option<E>`], consuming `self`,
     /// and discarding the success value, if any.
     ///
-    /// [`Option<E>`]: ../../std/option/enum.Option.html
+    /// [`Option<E>`]: Option
     ///
     /// # Examples
     ///
@@ -497,9 +487,6 @@ pub fn as_mut(&mut self) -> Result<&mut T, &mut E> {
     ///
     /// This function can be used to compose the results of two functions.
     ///
-    /// [`Ok`]: enum.Result.html#variant.Ok
-    /// [`Err`]: enum.Result.html#variant.Err
-    ///
     /// # Examples
     ///
     /// Print the numbers on each line of a string multiplied by two.
@@ -530,9 +517,7 @@ pub fn map<U, F: FnOnce(T) -> U>(self, op: F) -> Result<U, E> {
     /// the result of a function call, it is recommended to use [`map_or_else`],
     /// which is lazily evaluated.
     ///
-    /// [`map_or_else`]: #method.map_or_else
-    /// [`Ok`]: enum.Result.html#variant.Ok
-    /// [`Err`]: enum.Result.html#variant.Err
+    /// [`map_or_else`]: Result::map_or_else
     ///
     /// # Examples
     ///
@@ -559,8 +544,6 @@ pub fn map_or<U, F: FnOnce(T) -> U>(self, default: U, f: F) -> U {
     /// This function can be used to unpack a successful result
     /// while handling an error.
     ///
-    /// [`Ok`]: enum.Result.html#variant.Ok
-    /// [`Err`]: enum.Result.html#variant.Err
     ///
     /// # Examples
     ///
@@ -590,8 +573,6 @@ pub fn map_or_else<U, D: FnOnce(E) -> U, F: FnOnce(T) -> U>(self, default: D, f:
     /// This function can be used to pass through a successful result while handling
     /// an error.
     ///
-    /// [`Ok`]: enum.Result.html#variant.Ok
-    /// [`Err`]: enum.Result.html#variant.Err
     ///
     /// # Examples
     ///
@@ -671,8 +652,6 @@ pub fn iter_mut(&mut self) -> IterMut<'_, T> {
 
     /// Returns `res` if the result is [`Ok`], otherwise returns the [`Err`] value of `self`.
     ///
-    /// [`Ok`]: enum.Result.html#variant.Ok
-    /// [`Err`]: enum.Result.html#variant.Err
     ///
     /// # Examples
     ///
@@ -706,8 +685,6 @@ pub fn and<U>(self, res: Result<U, E>) -> Result<U, E> {
 
     /// Calls `op` if the result is [`Ok`], otherwise returns the [`Err`] value of `self`.
     ///
-    /// [`Ok`]: enum.Result.html#variant.Ok
-    /// [`Err`]: enum.Result.html#variant.Err
     ///
     /// This function can be used for control flow based on `Result` values.
     ///
@@ -739,9 +716,7 @@ pub fn and_then<U, F: FnOnce(T) -> Result<U, E>>(self, op: F) -> Result<U, E> {
     /// result of a function call, it is recommended to use [`or_else`], which is
     /// lazily evaluated.
     ///
-    /// [`Ok`]: enum.Result.html#variant.Ok
-    /// [`Err`]: enum.Result.html#variant.Err
-    /// [`or_else`]: #method.or_else
+    /// [`or_else`]: Result::or_else
     ///
     /// # Examples
     ///
@@ -777,8 +752,6 @@ pub fn or<F>(self, res: Result<T, F>) -> Result<T, F> {
     ///
     /// This function can be used for control flow based on result values.
     ///
-    /// [`Ok`]: enum.Result.html#variant.Ok
-    /// [`Err`]: enum.Result.html#variant.Err
     ///
     /// # Examples
     ///
@@ -808,9 +781,7 @@ pub fn or_else<F, O: FnOnce(E) -> Result<T, F>>(self, op: O) -> Result<T, F> {
     /// the result of a function call, it is recommended to use [`unwrap_or_else`],
     /// which is lazily evaluated.
     ///
-    /// [`Ok`]: enum.Result.html#variant.Ok
-    /// [`Err`]: enum.Result.html#variant.Err
-    /// [`unwrap_or_else`]: #method.unwrap_or_else
+    /// [`unwrap_or_else`]: Result::unwrap_or_else
     ///
     /// # Examples
     ///
@@ -835,7 +806,6 @@ pub fn unwrap_or(self, default: T) -> T {
 
     /// Returns the contained [`Ok`] value or computes it from a closure.
     ///
-    /// [`Ok`]: enum.Result.html#variant.Ok
     ///
     /// # Examples
     ///
@@ -945,8 +915,6 @@ impl<T, E: fmt::Debug> Result<T, E> {
     /// Panics if the value is an [`Err`], with a panic message including the
     /// passed message, and the content of the [`Err`].
     ///
-    /// [`Ok`]: enum.Result.html#variant.Ok
-    /// [`Err`]: enum.Result.html#variant.Err
     ///
     /// # Examples
     ///
@@ -973,17 +941,15 @@ pub fn expect(self, msg: &str) -> T {
     /// case explicitly, or call [`unwrap_or`], [`unwrap_or_else`], or
     /// [`unwrap_or_default`].
     ///
-    /// [`unwrap_or`]: #method.unwrap_or
-    /// [`unwrap_or_else`]: #method.unwrap_or_else
-    /// [`unwrap_or_default`]: #method.unwrap_or_default
+    /// [`unwrap_or`]: Result::unwrap_or
+    /// [`unwrap_or_else`]: Result::unwrap_or_else
+    /// [`unwrap_or_default`]: Result::unwrap_or_default
     ///
     /// # Panics
     ///
     /// Panics if the value is an [`Err`], with a panic message provided by the
     /// [`Err`]'s value.
     ///
-    /// [`Ok`]: enum.Result.html#variant.Ok
-    /// [`Err`]: enum.Result.html#variant.Err
     ///
     /// # Examples
     ///
@@ -1017,8 +983,6 @@ impl<T: fmt::Debug, E> Result<T, E> {
     /// Panics if the value is an [`Ok`], with a panic message including the
     /// passed message, and the content of the [`Ok`].
     ///
-    /// [`Ok`]: enum.Result.html#variant.Ok
-    /// [`Err`]: enum.Result.html#variant.Err
     ///
     /// # Examples
     ///
@@ -1045,8 +1009,6 @@ pub fn expect_err(self, msg: &str) -> E {
     /// Panics if the value is an [`Ok`], with a custom panic message provided
     /// by the [`Ok`]'s value.
     ///
-    /// [`Ok`]: enum.Result.html#variant.Ok
-    /// [`Err`]: enum.Result.html#variant.Err
     ///
     ///
     /// # Examples
@@ -1095,10 +1057,8 @@ impl<T: Default, E> Result<T, E> {
     /// assert_eq!(0, bad_year);
     /// ```
     ///
-    /// [`parse`]: ../../std/primitive.str.html#method.parse
-    /// [`FromStr`]: ../../std/str/trait.FromStr.html
-    /// [`Ok`]: enum.Result.html#variant.Ok
-    /// [`Err`]: enum.Result.html#variant.Err
+    /// [`parse`]: str::parse
+    /// [`FromStr`]: crate::str::FromStr
     #[inline]
     #[stable(feature = "result_unwrap_or_default", since = "1.16.0")]
     pub fn unwrap_or_default(self) -> T {
@@ -1119,9 +1079,7 @@ impl<T, E: Into<!>> Result<T, E> {
     /// to compile if the error type of the `Result` is later changed
     /// to an error that can actually occur.
     ///
-    /// [`Ok`]: enum.Result.html#variant.Ok
-    /// [`Err`]: enum.Result.html#variant.Err
-    /// [`unwrap`]: enum.Result.html#method.unwrap
+    /// [`unwrap`]: Result::unwrap
     ///
     /// # Examples
     ///
@@ -1343,10 +1301,6 @@ fn into_iter(self) -> IterMut<'a, T> {
 /// The iterator yields one value if the result is [`Ok`], otherwise none.
 ///
 /// Created by [`Result::iter`].
-///
-/// [`Ok`]: enum.Result.html#variant.Ok
-/// [`Result`]: enum.Result.html
-/// [`Result::iter`]: enum.Result.html#method.iter
 #[derive(Debug)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Iter<'a, T: 'a> {
@@ -1396,10 +1350,6 @@ fn clone(&self) -> Self {
 /// An iterator over a mutable reference to the [`Ok`] variant of a [`Result`].
 ///
 /// Created by [`Result::iter_mut`].
-///
-/// [`Ok`]: enum.Result.html#variant.Ok
-/// [`Result`]: enum.Result.html
-/// [`Result::iter_mut`]: enum.Result.html#method.iter_mut
 #[derive(Debug)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct IterMut<'a, T: 'a> {
@@ -1445,10 +1395,7 @@ unsafe impl<A> TrustedLen for IterMut<'_, A> {}
 /// This struct is created by the [`into_iter`] method on
 /// [`Result`] (provided by the [`IntoIterator`] trait).
 ///
-/// [`Ok`]: enum.Result.html#variant.Ok
-/// [`Result`]: enum.Result.html
-/// [`into_iter`]: ../iter/trait.IntoIterator.html#tymethod.into_iter
-/// [`IntoIterator`]: ../iter/trait.IntoIterator.html
+/// [`into_iter`]: IntoIterator::into_iter
 #[derive(Clone, Debug)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct IntoIter<T> {
index 7c1027f60babb6ef4db4c3d484f81465163b9e09..ab9afeb25e0cec7d0e6191ac65c33c0361173113 100644 (file)
@@ -476,6 +476,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 /// This struct is created by the [`chars`] method on [`str`].
 /// See its documentation for more.
 ///
+/// [`char`]: prim@char
 /// [`chars`]: str::chars
 #[derive(Clone)]
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -673,6 +674,7 @@ pub fn as_str(&self) -> &'a str {
 /// This struct is created by the [`char_indices`] method on [`str`].
 /// See its documentation for more.
 ///
+/// [`char`]: prim@char
 /// [`char_indices`]: str::char_indices
 #[derive(Clone, Debug)]
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -2270,6 +2272,8 @@ impl str {
     /// This length is in bytes, not [`char`]s or graphemes. In other words,
     /// it may not be what a human considers the length of the string.
     ///
+    /// [`char`]: prim@char
+    ///
     /// # Examples
     ///
     /// Basic usage:
@@ -2791,7 +2795,9 @@ pub fn split_at_mut(&mut self, mid: usize) -> (&mut str, &mut str) {
     /// assert_eq!(None, chars.next());
     /// ```
     ///
-    /// Remember, [`char`]s may not match your human intuition about characters:
+    /// Remember, [`char`]s may not match your intuition about characters:
+    ///
+    /// [`char`]: prim@char
     ///
     /// ```
     /// let y = "y̆";
@@ -2842,7 +2848,9 @@ pub fn chars(&self) -> Chars<'_> {
     /// assert_eq!(None, char_indices.next());
     /// ```
     ///
-    /// Remember, [`char`]s may not match your human intuition about characters:
+    /// Remember, [`char`]s may not match your intuition about characters:
+    ///
+    /// [`char`]: prim@char
     ///
     /// ```
     /// let yes = "y̆es";
@@ -3053,6 +3061,7 @@ pub fn encode_utf16(&self) -> EncodeUtf16<'_> {
     /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a
     /// function or closure that determines if a character matches.
     ///
+    /// [`char`]: prim@char
     /// [pattern]: self::pattern
     ///
     /// # Examples
@@ -3079,6 +3088,7 @@ pub fn contains<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool {
     /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a
     /// function or closure that determines if a character matches.
     ///
+    /// [`char`]: prim@char
     /// [pattern]: self::pattern
     ///
     /// # Examples
@@ -3104,6 +3114,7 @@ pub fn starts_with<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool {
     /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a
     /// function or closure that determines if a character matches.
     ///
+    /// [`char`]: prim@char
     /// [pattern]: self::pattern
     ///
     /// # Examples
@@ -3132,6 +3143,7 @@ pub fn ends_with<'a, P>(&'a self, pat: P) -> bool
     /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a
     /// function or closure that determines if a character matches.
     ///
+    /// [`char`]: prim@char
     /// [pattern]: self::pattern
     ///
     /// # Examples
@@ -3179,6 +3191,7 @@ pub fn find<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize> {
     /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a
     /// function or closure that determines if a character matches.
     ///
+    /// [`char`]: prim@char
     /// [pattern]: self::pattern
     ///
     /// # Examples
@@ -3225,6 +3238,7 @@ pub fn rfind<'a, P>(&'a self, pat: P) -> Option<usize>
     /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a
     /// function or closure that determines if a character matches.
     ///
+    /// [`char`]: prim@char
     /// [pattern]: self::pattern
     ///
     /// # Iterator behavior
@@ -3344,6 +3358,7 @@ pub fn split<'a, P: Pattern<'a>>(&'a self, pat: P) -> Split<'a, P> {
     /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a
     /// function or closure that determines if a character matches.
     ///
+    /// [`char`]: prim@char
     /// [pattern]: self::pattern
     ///
     /// # Examples
@@ -3383,6 +3398,7 @@ pub fn split_inclusive<'a, P: Pattern<'a>>(&'a self, pat: P) -> SplitInclusive<'
     /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a
     /// function or closure that determines if a character matches.
     ///
+    /// [`char`]: prim@char
     /// [pattern]: self::pattern
     ///
     /// # Iterator behavior
@@ -3434,6 +3450,7 @@ pub fn rsplit<'a, P>(&'a self, pat: P) -> RSplit<'a, P>
     /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a
     /// function or closure that determines if a character matches.
     ///
+    /// [`char`]: prim@char
     /// [pattern]: self::pattern
     ///
     /// Equivalent to [`split`], except that the trailing substring
@@ -3478,6 +3495,7 @@ pub fn split_terminator<'a, P: Pattern<'a>>(&'a self, pat: P) -> SplitTerminator
     /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a
     /// function or closure that determines if a character matches.
     ///
+    /// [`char`]: prim@char
     /// [pattern]: self::pattern
     ///
     /// Equivalent to [`split`], except that the trailing substring is
@@ -3526,6 +3544,7 @@ pub fn rsplit_terminator<'a, P>(&'a self, pat: P) -> RSplitTerminator<'a, P>
     /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a
     /// function or closure that determines if a character matches.
     ///
+    /// [`char`]: prim@char
     /// [pattern]: self::pattern
     ///
     /// # Iterator behavior
@@ -3578,6 +3597,7 @@ pub fn splitn<'a, P: Pattern<'a>>(&'a self, n: usize, pat: P) -> SplitN<'a, P> {
     /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a
     /// function or closure that determines if a character matches.
     ///
+    /// [`char`]: prim@char
     /// [pattern]: self::pattern
     ///
     /// # Iterator behavior
@@ -3666,6 +3686,7 @@ pub fn rsplit_once<'a, P>(&'a self, delimiter: P) -> Option<(&'a str, &'a str)>
     /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a
     /// function or closure that determines if a character matches.
     ///
+    /// [`char`]: prim@char
     /// [pattern]: self::pattern
     ///
     /// # Iterator behavior
@@ -3702,6 +3723,7 @@ pub fn matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> Matches<'a, P> {
     /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a
     /// function or closure that determines if a character matches.
     ///
+    /// [`char`]: prim@char
     /// [pattern]: self::pattern
     ///
     /// # Iterator behavior
@@ -3743,6 +3765,7 @@ pub fn rmatches<'a, P>(&'a self, pat: P) -> RMatches<'a, P>
     /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a
     /// function or closure that determines if a character matches.
     ///
+    /// [`char`]: prim@char
     /// [pattern]: self::pattern
     ///
     /// # Iterator behavior
@@ -3785,6 +3808,7 @@ pub fn match_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> MatchIndices<'a, P
     /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a
     /// function or closure that determines if a character matches.
     ///
+    /// [`char`]: prim@char
     /// [pattern]: self::pattern
     ///
     /// # Iterator behavior
@@ -4003,6 +4027,7 @@ pub fn trim_right(&self) -> &str {
     /// The [pattern] can be a [`char`], a slice of [`char`]s, or a function
     /// or closure that determines if a character matches.
     ///
+    /// [`char`]: prim@char
     /// [pattern]: self::pattern
     ///
     /// # Examples
@@ -4050,6 +4075,7 @@ pub fn trim_matches<'a, P>(&'a self, pat: P) -> &'a str
     /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a
     /// function or closure that determines if a character matches.
     ///
+    /// [`char`]: prim@char
     /// [pattern]: self::pattern
     ///
     /// # Text directionality
@@ -4094,6 +4120,7 @@ pub fn trim_start_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str {
     /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a
     /// function or closure that determines if a character matches.
     ///
+    /// [`char`]: prim@char
     /// [pattern]: self::pattern
     ///
     /// # Examples
@@ -4121,6 +4148,7 @@ pub fn strip_prefix<'a, P: Pattern<'a>>(&'a self, prefix: P) -> Option<&'a str>
     /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a
     /// function or closure that determines if a character matches.
     ///
+    /// [`char`]: prim@char
     /// [pattern]: self::pattern
     ///
     /// # Examples
@@ -4147,6 +4175,7 @@ pub fn strip_suffix<'a, P>(&'a self, suffix: P) -> Option<&'a str>
     /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a
     /// function or closure that determines if a character matches.
     ///
+    /// [`char`]: prim@char
     /// [pattern]: self::pattern
     ///
     /// # Text directionality
@@ -4195,6 +4224,7 @@ pub fn trim_end_matches<'a, P>(&'a self, pat: P) -> &'a str
     /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a
     /// function or closure that determines if a character matches.
     ///
+    /// [`char`]: prim@char
     /// [pattern]: self::pattern
     ///
     /// # Text directionality
@@ -4231,6 +4261,7 @@ pub fn trim_left_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str {
     /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a
     /// function or closure that determines if a character matches.
     ///
+    /// [`char`]: prim@char
     /// [pattern]: self::pattern
     ///
     /// # Text directionality
index 14f1f293d40d68716fd09e8ba5c6dd04db715114..1cc2de5b8756a8bdc8cc06e2fd26374aa1c45f90 100644 (file)
@@ -12,7 +12,7 @@
 //! # Examples
 //!
 //! [`Pattern`] is [implemented][pattern-impls] in the stable API for
-//! [`&str`], [`char`], slices of [`char`], and functions and closures
+//! [`&str`][`str`], [`char`], slices of [`char`], and functions and closures
 //! implementing `FnMut(char) -> bool`.
 //!
 //! ```
 //! assert_eq!(s.find(|c: char| c.is_ascii_punctuation()), Some(35));
 //! ```
 //!
-//! [`&str`]: ../../../std/primitive.str.html
-//! [`char`]: ../../../std/primitive.char.html
-//! [`str`]: ../../../std/primitive.str.html
-//! [`DoubleEndedSearcher`]: trait.DoubleEndedSearcher.html
-//! [`Pattern`]: trait.Pattern.html
-//! [`ReverseSearcher`]: trait.ReverseSearcher.html
-//! [`Searcher`]: trait.Searcher.html
 //! [pattern-impls]: trait.Pattern.html#implementors
 
 #![unstable(
 /// A string pattern.
 ///
 /// A `Pattern<'a>` expresses that the implementing type
-/// can be used as a string pattern for searching in a `&'a str`.
+/// can be used as a string pattern for searching in a [`&'a str`][str].
 ///
 /// For example, both `'a'` and `"aa"` are patterns that
 /// would match at index `1` in the string `"baaaab"`.
 ///
 /// The trait itself acts as a builder for an associated
-/// `Searcher` type, which does the actual work of finding
+/// [`Searcher`] type, which does the actual work of finding
 /// occurrences of the pattern in a string.
 ///
 /// Depending on the type of the pattern, the behaviour of methods like
@@ -75,6 +68,7 @@
 /// | `&String`                | is substring                              |
 ///
 /// # Examples
+///
 /// ```
 /// // &str
 /// assert_eq!("abaaa".find("ba"), Some(1));
@@ -94,9 +88,6 @@
 /// assert_eq!("abcdef_z".find(|ch| ch > 'd' && ch < 'y'), Some(4));
 /// assert_eq!("abcddd_z".find(|ch| ch > 'd' && ch < 'y'), None);
 /// ```
-///
-/// [`str::find`]: ../../../std/primitive.str.html#method.find
-/// [`str::contains`]: ../../../std/primitive.str.html#method.contains
 pub trait Pattern<'a>: Sized {
     /// Associated searcher for this pattern
     type Searcher: Searcher<'a>;
@@ -165,7 +156,7 @@ fn strip_suffix_of(self, haystack: &'a str) -> Option<&'a str>
 
 // Searcher
 
-/// Result of calling `Searcher::next()` or `ReverseSearcher::next_back()`.
+/// Result of calling [`Searcher::next()`] or [`ReverseSearcher::next_back()`].
 #[derive(Copy, Clone, Eq, PartialEq, Debug)]
 pub enum SearchStep {
     /// Expresses that a match of the pattern has been found at
@@ -188,44 +179,47 @@ pub enum SearchStep {
 /// matches of a pattern starting from the front (left) of a string.
 ///
 /// It will be implemented by associated `Searcher`
-/// types of the `Pattern` trait.
+/// types of the [`Pattern`] trait.
 ///
 /// The trait is marked unsafe because the indices returned by the
-/// `next()` methods are required to lie on valid utf8 boundaries in
-/// the haystack. This enables consumers of this trait to
+/// [`next()`][Searcher::next] methods are required to lie on valid utf8
+/// boundaries in the haystack. This enables consumers of this trait to
 /// slice the haystack without additional runtime checks.
 pub unsafe trait Searcher<'a> {
     /// Getter for the underlying string to be searched in
     ///
-    /// Will always return the same `&str`
+    /// Will always return the same [`&str`][str].
     fn haystack(&self) -> &'a str;
 
     /// Performs the next search step starting from the front.
     ///
-    /// - Returns `Match(a, b)` if `haystack[a..b]` matches the pattern.
-    /// - Returns `Reject(a, b)` if `haystack[a..b]` can not match the
-    ///   pattern, even partially.
-    /// - Returns `Done` if every byte of the haystack has been visited
+    /// - Returns [`Match(a, b)`][SearchStep::Match] if `haystack[a..b]` matches
+    ///   the pattern.
+    /// - Returns [`Reject(a, b)`][SearchStep::Reject] if `haystack[a..b]` can
+    ///   not match the pattern, even partially.
+    /// - Returns [`Done`][SearchStep::Done] if every byte of the haystack has
+    ///   been visited.
     ///
-    /// The stream of `Match` and `Reject` values up to a `Done`
+    /// The stream of [`Match`][SearchStep::Match] and
+    /// [`Reject`][SearchStep::Reject] values up to a [`Done`][SearchStep::Done]
     /// will contain index ranges that are adjacent, non-overlapping,
     /// covering the whole haystack, and laying on utf8 boundaries.
     ///
-    /// A `Match` result needs to contain the whole matched pattern,
-    /// however `Reject` results may be split up into arbitrary
-    /// many adjacent fragments. Both ranges may have zero length.
+    /// A [`Match`][SearchStep::Match] result needs to contain the whole matched
+    /// pattern, however [`Reject`][SearchStep::Reject] results may be split up
+    /// into arbitrary many adjacent fragments. Both ranges may have zero length.
     ///
     /// As an example, the pattern `"aaa"` and the haystack `"cbaaaaab"`
     /// might produce the stream
     /// `[Reject(0, 1), Reject(1, 2), Match(2, 5), Reject(5, 8)]`
     fn next(&mut self) -> SearchStep;
 
-    /// Finds the next `Match` result. See `next()`
+    /// Finds the next [`Match`][SearchStep::Match] result. See [`next()`][Searcher::next].
     ///
-    /// Unlike next(), there is no guarantee that the returned ranges
-    /// of this and next_reject will overlap. This will return (start_match, end_match),
-    /// where start_match is the index of where the match begins, and end_match is
-    /// the index after the end of the match.
+    /// Unlike [`next()`][Searcher::next], there is no guarantee that the returned ranges
+    /// of this and [`next_reject`][Searcher::next_reject] will overlap. This will return
+    /// `(start_match, end_match)`, where start_match is the index of where
+    /// the match begins, and end_match is the index after the end of the match.
     #[inline]
     fn next_match(&mut self) -> Option<(usize, usize)> {
         loop {
@@ -237,10 +231,11 @@ fn next_match(&mut self) -> Option<(usize, usize)> {
         }
     }
 
-    /// Finds the next `Reject` result. See `next()` and `next_match()`
+    /// Finds the next [`Reject`][SearchStep::Reject] result. See [`next()`][Searcher::next]
+    /// and [`next_match()`][Searcher::next_match].
     ///
-    /// Unlike next(), there is no guarantee that the returned ranges
-    /// of this and next_match will overlap.
+    /// Unlike [`next()`][Searcher::next], there is no guarantee that the returned ranges
+    /// of this and [`next_match`][Searcher::next_match] will overlap.
     #[inline]
     fn next_reject(&mut self) -> Option<(usize, usize)> {
         loop {
@@ -258,37 +253,41 @@ fn next_reject(&mut self) -> Option<(usize, usize)> {
 /// This trait provides methods for searching for non-overlapping
 /// matches of a pattern starting from the back (right) of a string.
 ///
-/// It will be implemented by associated `Searcher`
-/// types of the `Pattern` trait if the pattern supports searching
+/// It will be implemented by associated [`Searcher`]
+/// types of the [`Pattern`] trait if the pattern supports searching
 /// for it from the back.
 ///
 /// The index ranges returned by this trait are not required
 /// to exactly match those of the forward search in reverse.
 ///
 /// For the reason why this trait is marked unsafe, see them
-/// parent trait `Searcher`.
+/// parent trait [`Searcher`].
 pub unsafe trait ReverseSearcher<'a>: Searcher<'a> {
     /// Performs the next search step starting from the back.
     ///
-    /// - Returns `Match(a, b)` if `haystack[a..b]` matches the pattern.
-    /// - Returns `Reject(a, b)` if `haystack[a..b]` can not match the
-    ///   pattern, even partially.
-    /// - Returns `Done` if every byte of the haystack has been visited
+    /// - Returns [`Match(a, b)`][SearchStep::Match] if `haystack[a..b]`
+    ///   matches the pattern.
+    /// - Returns [`Reject(a, b)`][SearchStep::Reject] if `haystack[a..b]`
+    ///   can not match the pattern, even partially.
+    /// - Returns [`Done`][SearchStep::Done] if every byte of the haystack
+    ///   has been visited
     ///
-    /// The stream of `Match` and `Reject` values up to a `Done`
+    /// The stream of [`Match`][SearchStep::Match] and
+    /// [`Reject`][SearchStep::Reject] values up to a [`Done`][SearchStep::Done]
     /// will contain index ranges that are adjacent, non-overlapping,
     /// covering the whole haystack, and laying on utf8 boundaries.
     ///
-    /// A `Match` result needs to contain the whole matched pattern,
-    /// however `Reject` results may be split up into arbitrary
-    /// many adjacent fragments. Both ranges may have zero length.
+    /// A [`Match`][SearchStep::Match] result needs to contain the whole matched
+    /// pattern, however [`Reject`][SearchStep::Reject] results may be split up
+    /// into arbitrary many adjacent fragments. Both ranges may have zero length.
     ///
     /// As an example, the pattern `"aaa"` and the haystack `"cbaaaaab"`
     /// might produce the stream
-    /// `[Reject(7, 8), Match(4, 7), Reject(1, 4), Reject(0, 1)]`
+    /// `[Reject(7, 8), Match(4, 7), Reject(1, 4), Reject(0, 1)]`.
     fn next_back(&mut self) -> SearchStep;
 
-    /// Finds the next `Match` result. See `next_back()`
+    /// Finds the next [`Match`][SearchStep::Match] result.
+    /// See [`next_back()`][ReverseSearcher::next_back].
     #[inline]
     fn next_match_back(&mut self) -> Option<(usize, usize)> {
         loop {
@@ -300,7 +299,8 @@ fn next_match_back(&mut self) -> Option<(usize, usize)> {
         }
     }
 
-    /// Finds the next `Reject` result. See `next_back()`
+    /// Finds the next [`Reject`][SearchStep::Reject] result.
+    /// See [`next_back()`][ReverseSearcher::next_back].
     #[inline]
     fn next_reject_back(&mut self) -> Option<(usize, usize)> {
         loop {
@@ -313,10 +313,10 @@ fn next_reject_back(&mut self) -> Option<(usize, usize)> {
     }
 }
 
-/// A marker trait to express that a `ReverseSearcher`
-/// can be used for a `DoubleEndedIterator` implementation.
+/// A marker trait to express that a [`ReverseSearcher`]
+/// can be used for a [`DoubleEndedIterator`] implementation.
 ///
-/// For this, the impl of `Searcher` and `ReverseSearcher` need
+/// For this, the impl of [`Searcher`] and [`ReverseSearcher`] need
 /// to follow these conditions:
 ///
 /// - All results of `next()` need to be identical
@@ -328,7 +328,7 @@ fn next_reject_back(&mut self) -> Option<(usize, usize)> {
 /// # Examples
 ///
 /// `char::Searcher` is a `DoubleEndedSearcher` because searching for a
-/// `char` only requires looking at one at a time, which behaves the same
+/// [`char`] only requires looking at one at a time, which behaves the same
 /// from both ends.
 ///
 /// `(&str)::Searcher` is not a `DoubleEndedSearcher` because
@@ -355,13 +355,13 @@ pub struct CharSearcher<'a> {
     /// `finger_back` is the current byte index of the reverse search.
     /// Imagine that it exists after the byte at its index, i.e.
     /// haystack[finger_back - 1] is the last byte of the slice we must inspect during
-    /// forward searching (and thus the first byte to be inspected when calling next_back())
+    /// forward searching (and thus the first byte to be inspected when calling next_back()).
     finger_back: usize,
     /// The character being searched for
     needle: char,
 
     // safety invariant: `utf8_size` must be less than 5
-    /// The number of bytes `needle` takes up when encoded in utf8
+    /// The number of bytes `needle` takes up when encoded in utf8.
     utf8_size: usize,
     /// A utf8 encoded copy of the `needle`
     utf8_encoded: [u8; 4],
@@ -521,7 +521,7 @@ fn next_match_back(&mut self) -> Option<(usize, usize)> {
 
 impl<'a> DoubleEndedSearcher<'a> for CharSearcher<'a> {}
 
-/// Searches for chars that are equal to a given `char`.
+/// Searches for chars that are equal to a given [`char`].
 ///
 /// # Examples
 ///
@@ -772,7 +772,7 @@ unsafe impl<'a, 'b> ReverseSearcher<'a> for CharSliceSearcher<'a, 'b> {
 
 impl<'a, 'b> DoubleEndedSearcher<'a> for CharSliceSearcher<'a, 'b> {}
 
-/// Searches for chars that are equal to any of the chars in the slice.
+/// Searches for chars that are equal to any of the [`char`]s in the slice.
 ///
 /// # Examples
 ///
@@ -821,7 +821,7 @@ unsafe impl<'a, F> ReverseSearcher<'a> for CharPredicateSearcher<'a, F>
 
 impl<'a, F> DoubleEndedSearcher<'a> for CharPredicateSearcher<'a, F> where F: FnMut(char) -> bool {}
 
-/// Searches for chars that match the given predicate.
+/// Searches for [`char`]s that match the given predicate.
 ///
 /// # Examples
 ///
index 57f2de16b2b37522b78d8785b6b5fd6d5f9e7908..0b97508394789d9628e1a1d4866f29c8fb8502cb 100644 (file)
@@ -361,10 +361,8 @@ fn repeat_concat(b0: u8, b1: u8, l: usize) -> Vec<u8> {
         repeat(b0).take(l).chain(repeat(b1).take(l)).collect()
     }
 
-    // Miri is too slow for much of this, and in miri `align_offset` always
-    // returns `usize::max_value()` anyway (at the moment), so we just test
-    // lightly.
-    let iter = if cfg!(miri) { 0..5 } else { 0..100 };
+    // Miri is too slow
+    let iter = if cfg!(miri) { 0..20 } else { 0..100 };
 
     for i in iter {
         #[cfg(not(miri))]
@@ -379,7 +377,7 @@ fn repeat_concat(b0: u8, b1: u8, l: usize) -> Vec<u8> {
         ];
 
         #[cfg(miri)]
-        let cases = &[repeat_concat(b'a', 0x80u8, i)];
+        let cases = &[b"a".repeat(i), b"\x80".repeat(i), repeat_concat(b'a', 0x80u8, i)];
 
         for case in cases {
             for pos in 0..=case.len() {
index 904e3f7284049b982ae68af411759276dc6eb3b4..81e621318e14184b3903e7ea6011338ae4a2a4e9 100644 (file)
@@ -17,7 +17,6 @@
 #![feature(try_find)]
 #![feature(is_sorted)]
 #![feature(pattern)]
-#![feature(range_is_empty)]
 #![feature(raw)]
 #![feature(sort_internals)]
 #![feature(slice_partition_at_index)]
index 9fea34d668fcc77d2e841e2487c2380f23ea4fbf..bf977c141cbf861e0f0e64dff04beea4c5aa54c7 100644 (file)
@@ -300,7 +300,6 @@ fn drop(&mut self) {
 }
 
 #[test]
-#[cfg_attr(miri, ignore)] // Miri does not compute a maximal `mid` for `align_offset`
 fn align_offset_zst() {
     // For pointers of stride = 0, the pointer is already aligned or it cannot be aligned at
     // all, because no amount of elements will align the pointer.
@@ -315,7 +314,6 @@ fn align_offset_zst() {
 }
 
 #[test]
-#[cfg_attr(miri, ignore)] // Miri does not compute a maximal `mid` for `align_offset`
 fn align_offset_stride1() {
     // For pointers of stride = 1, the pointer can always be aligned. The offset is equal to
     // number of bytes.
@@ -337,7 +335,6 @@ fn align_offset_stride1() {
 }
 
 #[test]
-#[cfg_attr(miri, ignore)] // Miri is too slow
 fn align_offset_weird_strides() {
     #[repr(packed)]
     struct A3(u16, u8);
@@ -384,7 +381,9 @@ unsafe fn test_weird_stride<T>(ptr: *const T, align: usize) -> bool {
     // implementation
     let mut align = 1;
     let mut x = false;
-    while align < 1024 {
+    // Miri is too slow
+    let limit = if cfg!(miri) { 32 } else { 1024 };
+    while align < limit {
         for ptr in 1usize..4 * align {
             unsafe {
                 x |= test_weird_stride::<A3>(ptr as *const A3, align);
index 42b483f33ba44a2dc1c123d5a070697589bcb8f1..5650c98f9c7407ef5ac32e7aef5ce823b9c3d351 100644 (file)
@@ -1630,7 +1630,6 @@ fn each_alignment_reversed() {
 }
 
 #[test]
-#[cfg_attr(miri, ignore)] // Miri does not compute a maximal `mid` for `align_offset`
 fn test_align_to_simple() {
     let bytes = [1u8, 2, 3, 4, 5, 6, 7];
     let (prefix, aligned, suffix) = unsafe { bytes.align_to::<u16>() };
@@ -1660,7 +1659,6 @@ fn test_align_to_zst() {
 }
 
 #[test]
-#[cfg_attr(miri, ignore)] // Miri does not compute a maximal `mid` for `align_offset`
 fn test_align_to_non_trivial() {
     #[repr(align(8))]
     struct U64(u64, u64);
index cf52091f609edc90498e9e75bd5dd2954d485d1c..ccc067a3c943d2db477da89d238542d095dc08ed 100644 (file)
@@ -17,6 +17,7 @@
 #![feature(panic_runtime)]
 #![feature(staged_api)]
 #![feature(rustc_attrs)]
+#![feature(llvm_asm)]
 
 use core::any::Any;
 
     unreachable!()
 }
 
-// "Leak" the payload and shim to the relevant abort on the platform in
-// question.
-//
-// For Unix we just use `abort` from libc as it'll trigger debuggers, core
-// dumps, etc, as one might expect. On Windows, however, the best option we have
-// is the `__fastfail` intrinsics, but that's unfortunately not defined in LLVM,
-// and the `RaiseFailFastException` function isn't available until Windows 7
-// which would break compat with XP. For now just use `intrinsics::abort` which
-// will kill us with an illegal instruction, which will do a good enough job for
-// now hopefully.
+// "Leak" the payload and shim to the relevant abort on the platform in question.
 #[rustc_std_internal_symbol]
 pub unsafe extern "C" fn __rust_start_panic(_payload: usize) -> u32 {
     abort();
@@ -55,6 +47,21 @@ unsafe fn abort() -> ! {
                 }
                 __rust_abort();
             }
+        } else if #[cfg(all(windows, any(target_arch = "x86", target_arch = "x86_64")))] {
+            // On Windows, use the processor-specific __fastfail mechanism. In Windows 8
+            // and later, this will terminate the process immediately without running any
+            // in-process exception handlers. In earlier versions of Windows, this
+            // sequence of instructions will be treated as an access violation,
+            // terminating the process but without necessarily bypassing all exception
+            // handlers.
+            //
+            // https://docs.microsoft.com/en-us/cpp/intrinsics/fastfail
+            //
+            // Note: this is the same implementation as in libstd's `abort_internal`
+            unsafe fn abort() -> ! {
+                llvm_asm!("int $$0x29" :: "{ecx}"(7) ::: volatile); // 7 is FAST_FAIL_FATAL_APP_EXIT
+                core::intrinsics::unreachable();
+            }
         } else {
             unsafe fn abort() -> ! {
                 core::intrinsics::abort();
index de3866d92fc3f181ee192baa930917031b51bef0..c5a871e09a6ea61aeab55cb964d9fc14388d917a 100644 (file)
@@ -451,7 +451,7 @@ impl SourceFile {
     /// Also note that even if `is_real` returns `true`, if `--remap-path-prefix` was passed on
     /// the command line, the path as given may not actually be valid.
     ///
-    /// [`is_real`]: #method.is_real
+    /// [`is_real`]: Self::is_real
     #[unstable(feature = "proc_macro_span", issue = "54725")]
     pub fn path(&self) -> PathBuf {
         PathBuf::from(self.0.path())
index 0605ca4d94f31ac01e237e99fea31885e0bffa5f..b674f73ebf3906440277c5217e78907a9593a485 100644 (file)
@@ -65,7 +65,7 @@ fn main() {
     // This should be a pretty good heuristic for when to set
     // COMPILER_RT_HAS_ATOMICS
     if env::var_os("CARGO_CFG_TARGET_HAS_ATOMIC")
-        .map(|features| features.to_string_lossy().to_lowercase().contains("cas"))
+        .map(|features| features.to_string_lossy().to_lowercase().contains("ptr"))
         .unwrap_or(false)
     {
         cfg.define("COMPILER_RT_HAS_ATOMICS", Some("1"));
index b4009c86419d5148e3fb6f79a17e6d43b1d692e0..64d8edf33bd3bcf393e9d94e028f3ea07849a8e0 100644 (file)
@@ -154,36 +154,45 @@ fn alloc_impl(&mut self, layout: Layout, zeroed: bool) -> Result<NonNull<[u8]>,
     unsafe fn grow_impl(
         &mut self,
         ptr: NonNull<u8>,
-        layout: Layout,
-        new_size: usize,
+        old_layout: Layout,
+        new_layout: Layout,
         zeroed: bool,
     ) -> Result<NonNull<[u8]>, AllocErr> {
         debug_assert!(
-            new_size >= layout.size(),
-            "`new_size` must be greater than or equal to `layout.size()`"
+            new_layout.size() >= old_layout.size(),
+            "`new_layout.size()` must be greater than or equal to `old_layout.size()`"
         );
 
-        match layout.size() {
-            // SAFETY: the caller must ensure that the `new_size` does not overflow.
-            // `layout.align()` comes from a `Layout` and is thus guaranteed to be valid for a Layout.
-            0 => unsafe {
-                let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
-                self.alloc_impl(new_layout, zeroed)
-            },
+        match old_layout.size() {
+            0 => self.alloc_impl(new_layout, zeroed),
 
             // SAFETY: `new_size` is non-zero as `old_size` is greater than or equal to `new_size`
             // as required by safety conditions. Other conditions must be upheld by the caller
-            old_size => unsafe {
-                // `realloc` probably checks for `new_size >= size` or something similar.
-                intrinsics::assume(new_size >= layout.size());
+            old_size if old_layout.align() == new_layout.align() => unsafe {
+                let new_size = new_layout.size();
+
+                // `realloc` probably checks for `new_size >= old_layout.size()` or something similar.
+                intrinsics::assume(new_size >= old_layout.size());
 
-                let raw_ptr = GlobalAlloc::realloc(self, ptr.as_ptr(), layout, new_size);
+                let raw_ptr = GlobalAlloc::realloc(self, ptr.as_ptr(), old_layout, new_size);
                 let ptr = NonNull::new(raw_ptr).ok_or(AllocErr)?;
                 if zeroed {
                     raw_ptr.add(old_size).write_bytes(0, new_size - old_size);
                 }
                 Ok(NonNull::slice_from_raw_parts(ptr, new_size))
             },
+
+            // SAFETY: because `new_layout.size()` must be greater than or equal to `old_size`,
+            // both the old and new memory allocation are valid for reads and writes for `old_size`
+            // bytes. Also, because the old allocation wasn't yet deallocated, it cannot overlap
+            // `new_ptr`. Thus, the call to `copy_nonoverlapping` is safe. The safety contract
+            // for `dealloc` must be upheld by the caller.
+            old_size => unsafe {
+                let new_ptr = self.alloc_impl(new_layout, zeroed)?;
+                ptr::copy_nonoverlapping(ptr.as_ptr(), new_ptr.as_mut_ptr(), old_size);
+                self.dealloc(ptr, old_layout);
+                Ok(new_ptr)
+            },
         }
     }
 }
@@ -215,52 +224,64 @@ unsafe fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout) {
     unsafe fn grow(
         &mut self,
         ptr: NonNull<u8>,
-        layout: Layout,
-        new_size: usize,
+        old_layout: Layout,
+        new_layout: Layout,
     ) -> Result<NonNull<[u8]>, AllocErr> {
         // SAFETY: all conditions must be upheld by the caller
-        unsafe { self.grow_impl(ptr, layout, new_size, false) }
+        unsafe { self.grow_impl(ptr, old_layout, new_layout, false) }
     }
 
     #[inline]
     unsafe fn grow_zeroed(
         &mut self,
         ptr: NonNull<u8>,
-        layout: Layout,
-        new_size: usize,
+        old_layout: Layout,
+        new_layout: Layout,
     ) -> Result<NonNull<[u8]>, AllocErr> {
         // SAFETY: all conditions must be upheld by the caller
-        unsafe { self.grow_impl(ptr, layout, new_size, true) }
+        unsafe { self.grow_impl(ptr, old_layout, new_layout, true) }
     }
 
     #[inline]
     unsafe fn shrink(
         &mut self,
         ptr: NonNull<u8>,
-        layout: Layout,
-        new_size: usize,
+        old_layout: Layout,
+        new_layout: Layout,
     ) -> Result<NonNull<[u8]>, AllocErr> {
         debug_assert!(
-            new_size <= layout.size(),
-            "`new_size` must be smaller than or equal to `layout.size()`"
+            new_layout.size() <= old_layout.size(),
+            "`new_layout.size()` must be smaller than or equal to `old_layout.size()`"
         );
 
-        match new_size {
+        match new_layout.size() {
             // SAFETY: conditions must be upheld by the caller
             0 => unsafe {
-                self.dealloc(ptr, layout);
-                Ok(NonNull::slice_from_raw_parts(layout.dangling(), 0))
+                self.dealloc(ptr, old_layout);
+                Ok(NonNull::slice_from_raw_parts(new_layout.dangling(), 0))
             },
 
             // SAFETY: `new_size` is non-zero. Other conditions must be upheld by the caller
-            new_size => unsafe {
-                // `realloc` probably checks for `new_size <= size` or something similar.
-                intrinsics::assume(new_size <= layout.size());
+            new_size if old_layout.align() == new_layout.align() => unsafe {
+                // `realloc` probably checks for `new_size <= old_layout.size()` or something similar.
+                intrinsics::assume(new_size <= old_layout.size());
 
-                let raw_ptr = GlobalAlloc::realloc(self, ptr.as_ptr(), layout, new_size);
+                let raw_ptr = GlobalAlloc::realloc(self, ptr.as_ptr(), old_layout, new_size);
                 let ptr = NonNull::new(raw_ptr).ok_or(AllocErr)?;
                 Ok(NonNull::slice_from_raw_parts(ptr, new_size))
             },
+
+            // SAFETY: because `new_size` must be smaller than or equal to `old_layout.size()`,
+            // both the old and new memory allocation are valid for reads and writes for `new_size`
+            // bytes. Also, because the old allocation wasn't yet deallocated, it cannot overlap
+            // `new_ptr`. Thus, the call to `copy_nonoverlapping` is safe. The safety contract
+            // for `dealloc` must be upheld by the caller.
+            new_size => unsafe {
+                let new_ptr = self.alloc(new_layout)?;
+                ptr::copy_nonoverlapping(ptr.as_ptr(), new_ptr.as_mut_ptr(), new_size);
+                self.dealloc(ptr, old_layout);
+                Ok(new_ptr)
+            },
         }
     }
 }
index b6488ae61b153ee2c1cb6ffeb0184f7d70dbace5..a1aab767eb26f779870cc625449edfaaee2f44d5 100644 (file)
 //! assert_eq!(map.keys().next().unwrap().b, "baz");
 //! ```
 //!
-//! [`Vec`]: ../../std/vec/struct.Vec.html
-//! [`HashMap`]: ../../std/collections/struct.HashMap.html
-//! [`VecDeque`]: ../../std/collections/struct.VecDeque.html
-//! [`LinkedList`]: ../../std/collections/struct.LinkedList.html
-//! [`BTreeMap`]: ../../std/collections/struct.BTreeMap.html
-//! [`HashSet`]: ../../std/collections/struct.HashSet.html
-//! [`BTreeSet`]: ../../std/collections/struct.BTreeSet.html
-//! [`BinaryHeap`]: ../../std/collections/struct.BinaryHeap.html
-//! [`IntoIterator`]: ../../std/iter/trait.IntoIterator.html
+//! [`IntoIterator`]: crate::iter::IntoIterator
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
index 1b7681bd4bb1de0cc282b2efdc972b81bb842659..84e686c2fef818ae7211a3eb5689600db05eaf52 100644 (file)
@@ -296,6 +296,8 @@ fn from(str_err: String) -> Box<dyn Error> {
 impl<'a> From<&str> for Box<dyn Error + Send + Sync + 'a> {
     /// Converts a [`str`] into a box of dyn [`Error`] + [`Send`] + [`Sync`].
     ///
+    /// [`str`]: prim@str
+    ///
     /// # Examples
     ///
     /// ```
@@ -317,6 +319,8 @@ fn from(err: &str) -> Box<dyn Error + Send + Sync + 'a> {
 impl From<&str> for Box<dyn Error> {
     /// Converts a [`str`] into a box of dyn [`Error`].
     ///
+    /// [`str`]: prim@str
+    ///
     /// # Examples
     ///
     /// ```
index 11b3f22503e83c6c6c8a474efb6519e94884ebd5..717967fb7687fa27ede34e9718bb085fabcf0d90 100644 (file)
@@ -69,7 +69,7 @@
 /// extern functions. See the documentation for that function for a
 /// discussion on ensuring the lifetime of the raw pointer.
 ///
-/// [`&str`]: str
+/// [`&str`]: prim@str
 /// [slice.as_ptr]: ../primitive.slice.html#method.as_ptr
 /// [slice.len]: ../primitive.slice.html#method.len
 /// [`Deref`]: ops::Deref
@@ -180,7 +180,7 @@ pub struct CString {
 /// println!("string: {}", my_string_safe());
 /// ```
 ///
-/// [`&str`]: str
+/// [`&str`]: prim@str
 #[derive(Hash)]
 #[stable(feature = "rust1", since = "1.0.0")]
 // FIXME:
@@ -1351,7 +1351,7 @@ pub fn to_bytes_with_nul(&self) -> &[u8] {
     /// function will return the corresponding [`&str`] slice. Otherwise,
     /// it will return an error with details of where UTF-8 validation failed.
     ///
-    /// [`&str`]: str
+    /// [`&str`]: prim@str
     ///
     /// # Examples
     ///
@@ -1379,6 +1379,7 @@ pub fn to_str(&self) -> Result<&str, str::Utf8Error> {
     /// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD] and return a
     /// [`Cow`]`::`[`Owned`]`(`[`String`]`)` with the result.
     ///
+    /// [`str`]: prim@str
     /// [`Borrowed`]: Cow::Borrowed
     /// [`Owned`]: Cow::Owned
     /// [U+FFFD]: crate::char::REPLACEMENT_CHARACTER
index 2767675ff9258a81768145b96aa8ef58ac7e8e12..b1630f8f5494c7334a0283831ae27668558b2bcc 100644 (file)
@@ -1921,7 +1921,7 @@ pub fn create_dir_all<P: AsRef<Path>>(path: P) -> io::Result<()> {
     DirBuilder::new().recursive(true).create(path.as_ref())
 }
 
-/// Removes an existing, empty directory.
+/// Removes an empty directory.
 ///
 /// # Platform-specific behavior
 ///
@@ -1936,6 +1936,8 @@ pub fn create_dir_all<P: AsRef<Path>>(path: P) -> io::Result<()> {
 /// This function will return an error in the following situations, but is not
 /// limited to just these cases:
 ///
+/// * `path` doesn't exist.
+/// * `path` isn't a directory.
 /// * The user lacks permissions to remove the directory at the provided `path`.
 /// * The directory isn't empty.
 ///
index 324562948382890d5ba99d7fd91bc617d8d75c7e..462b696db40cf8ac6dbad7b6e8ae785ed721e7f2 100644 (file)
@@ -480,7 +480,7 @@ pub(crate) fn default_write_vectored<F>(write: F, bufs: &[IoSlice<'_>]) -> Resul
 /// ```
 ///
 /// [`read()`]: Read::read
-/// [`&str`]: str
+/// [`&str`]: prim@str
 /// [`std::io`]: self
 /// [`File`]: crate::fs::File
 /// [slice]: ../../std/primitive.slice.html
index 286eb92915e49381a0dd1c42d870cfa28da28b6e..3943c66aad53a1ec9ecffd946c6c3401470bc7c7 100644 (file)
@@ -50,8 +50,9 @@
 /// handles is **not** available to raw handles returned from this function.
 ///
 /// The returned handle has no external synchronization or buffering.
-fn stdin_raw() -> io::Result<StdinRaw> {
-    stdio::Stdin::new().map(StdinRaw)
+#[unstable(feature = "libstd_sys_internals", issue = "none")]
+const fn stdin_raw() -> StdinRaw {
+    StdinRaw(stdio::Stdin::new())
 }
 
 /// Constructs a new raw handle to the standard output stream of this process.
@@ -63,8 +64,9 @@ fn stdin_raw() -> io::Result<StdinRaw> {
 ///
 /// The returned handle has no external synchronization or buffering layered on
 /// top.
-fn stdout_raw() -> io::Result<StdoutRaw> {
-    stdio::Stdout::new().map(StdoutRaw)
+#[unstable(feature = "libstd_sys_internals", issue = "none")]
+const fn stdout_raw() -> StdoutRaw {
+    StdoutRaw(stdio::Stdout::new())
 }
 
 /// Constructs a new raw handle to the standard error stream of this process.
@@ -74,17 +76,18 @@ fn stdout_raw() -> io::Result<StdoutRaw> {
 ///
 /// The returned handle has no external synchronization or buffering layered on
 /// top.
-fn stderr_raw() -> io::Result<StderrRaw> {
-    stdio::Stderr::new().map(StderrRaw)
+#[unstable(feature = "libstd_sys_internals", issue = "none")]
+const fn stderr_raw() -> StderrRaw {
+    StderrRaw(stdio::Stderr::new())
 }
 
 impl Read for StdinRaw {
     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
-        self.0.read(buf)
+        handle_ebadf(self.0.read(buf), 0)
     }
 
     fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
-        self.0.read_vectored(bufs)
+        handle_ebadf(self.0.read_vectored(bufs), 0)
     }
 
     #[inline]
@@ -98,25 +101,22 @@ unsafe fn initializer(&self) -> Initializer {
     }
 
     fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
-        self.0.read_to_end(buf)
+        handle_ebadf(self.0.read_to_end(buf), 0)
     }
 
     fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
-        self.0.read_to_string(buf)
-    }
-
-    fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
-        self.0.read_exact(buf)
+        handle_ebadf(self.0.read_to_string(buf), 0)
     }
 }
 
 impl Write for StdoutRaw {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        self.0.write(buf)
+        handle_ebadf(self.0.write(buf), buf.len())
     }
 
     fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
-        self.0.write_vectored(bufs)
+        let total = bufs.iter().map(|b| b.len()).sum();
+        handle_ebadf(self.0.write_vectored(bufs), total)
     }
 
     #[inline]
@@ -125,29 +125,30 @@ fn is_write_vectored(&self) -> bool {
     }
 
     fn flush(&mut self) -> io::Result<()> {
-        self.0.flush()
+        handle_ebadf(self.0.flush(), ())
     }
 
     fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
-        self.0.write_all(buf)
+        handle_ebadf(self.0.write_all(buf), ())
     }
 
     fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
-        self.0.write_all_vectored(bufs)
+        handle_ebadf(self.0.write_all_vectored(bufs), ())
     }
 
     fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> {
-        self.0.write_fmt(fmt)
+        handle_ebadf(self.0.write_fmt(fmt), ())
     }
 }
 
 impl Write for StderrRaw {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        self.0.write(buf)
+        handle_ebadf(self.0.write(buf), buf.len())
     }
 
     fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
-        self.0.write_vectored(bufs)
+        let total = bufs.iter().map(|b| b.len()).sum();
+        handle_ebadf(self.0.write_vectored(bufs), total)
     }
 
     #[inline]
@@ -156,80 +157,19 @@ fn is_write_vectored(&self) -> bool {
     }
 
     fn flush(&mut self) -> io::Result<()> {
-        self.0.flush()
+        handle_ebadf(self.0.flush(), ())
     }
 
     fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
-        self.0.write_all(buf)
+        handle_ebadf(self.0.write_all(buf), ())
     }
 
     fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
-        self.0.write_all_vectored(bufs)
+        handle_ebadf(self.0.write_all_vectored(bufs), ())
     }
 
     fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> {
-        self.0.write_fmt(fmt)
-    }
-}
-
-enum Maybe<T> {
-    Real(T),
-    Fake,
-}
-
-impl<W: io::Write> io::Write for Maybe<W> {
-    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        match *self {
-            Maybe::Real(ref mut w) => handle_ebadf(w.write(buf), buf.len()),
-            Maybe::Fake => Ok(buf.len()),
-        }
-    }
-
-    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
-        let total = bufs.iter().map(|b| b.len()).sum();
-        match self {
-            Maybe::Real(w) => handle_ebadf(w.write_vectored(bufs), total),
-            Maybe::Fake => Ok(total),
-        }
-    }
-
-    #[inline]
-    fn is_write_vectored(&self) -> bool {
-        match self {
-            Maybe::Real(w) => w.is_write_vectored(),
-            Maybe::Fake => true,
-        }
-    }
-
-    fn flush(&mut self) -> io::Result<()> {
-        match *self {
-            Maybe::Real(ref mut w) => handle_ebadf(w.flush(), ()),
-            Maybe::Fake => Ok(()),
-        }
-    }
-}
-
-impl<R: io::Read> io::Read for Maybe<R> {
-    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
-        match *self {
-            Maybe::Real(ref mut r) => handle_ebadf(r.read(buf), 0),
-            Maybe::Fake => Ok(0),
-        }
-    }
-
-    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
-        match self {
-            Maybe::Real(r) => handle_ebadf(r.read_vectored(bufs), 0),
-            Maybe::Fake => Ok(0),
-        }
-    }
-
-    #[inline]
-    fn is_read_vectored(&self) -> bool {
-        match self {
-            Maybe::Real(w) => w.is_read_vectored(),
-            Maybe::Fake => true,
-        }
+        handle_ebadf(self.0.write_fmt(fmt), ())
     }
 }
 
@@ -274,7 +214,7 @@ fn handle_ebadf<T>(r: io::Result<T>, default: T) -> io::Result<T> {
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Stdin {
-    inner: Arc<Mutex<BufReader<Maybe<StdinRaw>>>>,
+    inner: Arc<Mutex<BufReader<StdinRaw>>>,
 }
 
 /// A locked reference to the `Stdin` handle.
@@ -305,7 +245,7 @@ pub struct Stdin {
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct StdinLock<'a> {
-    inner: MutexGuard<'a, BufReader<Maybe<StdinRaw>>>,
+    inner: MutexGuard<'a, BufReader<StdinRaw>>,
 }
 
 /// Constructs a new handle to the standard input of the current process.
@@ -349,18 +289,14 @@ pub struct StdinLock<'a> {
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn stdin() -> Stdin {
-    static INSTANCE: Lazy<Mutex<BufReader<Maybe<StdinRaw>>>> = Lazy::new();
+    static INSTANCE: Lazy<Mutex<BufReader<StdinRaw>>> = Lazy::new();
     return Stdin {
         inner: unsafe { INSTANCE.get(stdin_init).expect("cannot access stdin during shutdown") },
     };
 
-    fn stdin_init() -> Arc<Mutex<BufReader<Maybe<StdinRaw>>>> {
+    fn stdin_init() -> Arc<Mutex<BufReader<StdinRaw>>> {
         // This must not reentrantly access `INSTANCE`
-        let stdin = match stdin_raw() {
-            Ok(stdin) => Maybe::Real(stdin),
-            _ => Maybe::Fake,
-        };
-
+        let stdin = stdin_raw();
         Arc::new(Mutex::new(BufReader::with_capacity(stdio::STDIN_BUF_SIZE, stdin)))
     }
 }
@@ -537,7 +473,7 @@ pub struct Stdout {
     // FIXME: this should be LineWriter or BufWriter depending on the state of
     //        stdout (tty or not). Note that if this is not line buffered it
     //        should also flush-on-panic or some form of flush-on-abort.
-    inner: Arc<ReentrantMutex<RefCell<LineWriter<Maybe<StdoutRaw>>>>>,
+    inner: Arc<ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>>,
 }
 
 /// A locked reference to the `Stdout` handle.
@@ -551,7 +487,7 @@ pub struct Stdout {
 /// an error.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct StdoutLock<'a> {
-    inner: ReentrantMutexGuard<'a, RefCell<LineWriter<Maybe<StdoutRaw>>>>,
+    inner: ReentrantMutexGuard<'a, RefCell<LineWriter<StdoutRaw>>>,
 }
 
 /// Constructs a new handle to the standard output of the current process.
@@ -595,17 +531,14 @@ pub struct StdoutLock<'a> {
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn stdout() -> Stdout {
-    static INSTANCE: Lazy<ReentrantMutex<RefCell<LineWriter<Maybe<StdoutRaw>>>>> = Lazy::new();
+    static INSTANCE: Lazy<ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>> = Lazy::new();
     return Stdout {
         inner: unsafe { INSTANCE.get(stdout_init).expect("cannot access stdout during shutdown") },
     };
 
-    fn stdout_init() -> Arc<ReentrantMutex<RefCell<LineWriter<Maybe<StdoutRaw>>>>> {
+    fn stdout_init() -> Arc<ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>> {
         // This must not reentrantly access `INSTANCE`
-        let stdout = match stdout_raw() {
-            Ok(stdout) => Maybe::Real(stdout),
-            _ => Maybe::Fake,
-        };
+        let stdout = stdout_raw();
         unsafe {
             let ret = Arc::new(ReentrantMutex::new(RefCell::new(LineWriter::new(stdout))));
             ret.init();
@@ -715,7 +648,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 /// an error.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Stderr {
-    inner: &'static ReentrantMutex<RefCell<Maybe<StderrRaw>>>,
+    inner: &'static ReentrantMutex<RefCell<StderrRaw>>,
 }
 
 /// A locked reference to the `Stderr` handle.
@@ -729,7 +662,7 @@ pub struct Stderr {
 /// an error.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct StderrLock<'a> {
-    inner: ReentrantMutexGuard<'a, RefCell<Maybe<StderrRaw>>>,
+    inner: ReentrantMutexGuard<'a, RefCell<StderrRaw>>,
 }
 
 /// Constructs a new handle to the standard error of the current process.
@@ -778,19 +711,14 @@ pub fn stderr() -> Stderr {
     //
     // This has the added benefit of allowing `stderr` to be usable during
     // process shutdown as well!
-    static INSTANCE: ReentrantMutex<RefCell<Maybe<StderrRaw>>> =
-        unsafe { ReentrantMutex::new(RefCell::new(Maybe::Fake)) };
+    static INSTANCE: ReentrantMutex<RefCell<StderrRaw>> =
+        unsafe { ReentrantMutex::new(RefCell::new(stderr_raw())) };
 
     // When accessing stderr we need one-time initialization of the reentrant
-    // mutex, followed by one-time detection of whether we actually have a
-    // stderr handle or not. Afterwards we can just always use the now-filled-in
-    // `INSTANCE` value.
+    // mutex. Afterwards we can just always use the now-filled-in `INSTANCE` value.
     static INIT: Once = Once::new();
     INIT.call_once(|| unsafe {
         INSTANCE.init();
-        if let Ok(stderr) = stderr_raw() {
-            *INSTANCE.lock().borrow_mut() = Maybe::Real(stderr);
-        }
     });
     Stderr { inner: &INSTANCE }
 }
index f0548582d2f5d0bab4ee461616ba84ab190779ae..d0f27df51850533dd3578b9352e4e01981154cb1 100644 (file)
@@ -293,7 +293,7 @@ pub fn into_inner(mut self) -> Option<T> {
 
         // Don't drop this `SyncOnceCell`. We just moved out one of the fields, but didn't set
         // the state to uninitialized.
-        mem::ManuallyDrop::new(self);
+        mem::forget(self);
         inner
     }
 
index 1144a13b52c30b377a806a4e075891bd82711355..1142b74ff0dc4b8a3691766594ad8d205edcea8f 100644 (file)
 //! [`Vec<T>`]: vec::Vec
 //! [`atomic`]: sync::atomic
 //! [`for`]: ../book/ch03-05-control-flow.html#looping-through-a-collection-with-for
+//! [`str`]: prim@str
 //! [`mpsc`]: sync::mpsc
 //! [`std::cmp`]: cmp
 //! [`std::slice`]: slice
 #![cfg_attr(test, feature(print_internals, set_stdio, update_panic_count))]
 #![cfg_attr(
     all(target_vendor = "fortanix", target_env = "sgx"),
-    feature(slice_index_methods, coerce_unsized, sgx_platform, ptr_wrapping_offset_from)
+    feature(slice_index_methods, coerce_unsized, sgx_platform)
 )]
 #![cfg_attr(all(test, target_vendor = "fortanix", target_env = "sgx"), feature(fixed_size_array))]
 // std is implemented with unstable features, many of which are internal
index 724dbada9305cad502449cf5722baf661b47b464..e8898d98ff35f3de52613408dd75cd6f37b81ffd 100644 (file)
@@ -1,6 +1,6 @@
 //! Standard library macros
 //!
-//! This modules contains a set of macros which are exported from the standard
+//! This module contains a set of macros which are exported from the standard
 //! library. Each macro is available for use when linking against the standard
 //! library.
 
@@ -29,9 +29,7 @@ macro_rules! panic {
 /// Use `print!` only for the primary output of your program. Use
 /// [`eprint!`] instead to print error and progress messages.
 ///
-/// [`println!`]: ../std/macro.println.html
-/// [flush]: ../std/io/trait.Write.html#tymethod.flush
-/// [`eprint!`]: ../std/macro.eprint.html
+/// [flush]: crate::io::Write::flush
 ///
 /// # Panics
 ///
@@ -74,12 +72,13 @@ macro_rules! print {
 /// Use `println!` only for the primary output of your program. Use
 /// [`eprintln!`] instead to print error and progress messages.
 ///
-/// [`format!`]: ../std/macro.format.html
-/// [`std::fmt`]: ../std/fmt/index.html
-/// [`eprintln!`]: ../std/macro.eprintln.html
+/// [`std::fmt`]: crate::fmt
+///
 /// # Panics
 ///
-/// Panics if writing to `io::stdout` fails.
+/// Panics if writing to [`io::stdout`] fails.
+///
+/// [`io::stdout`]: crate::io::stdout
 ///
 /// # Examples
 ///
@@ -101,14 +100,14 @@ macro_rules! println {
 /// Prints to the standard error.
 ///
 /// Equivalent to the [`print!`] macro, except that output goes to
-/// [`io::stderr`] instead of `io::stdout`. See [`print!`] for
+/// [`io::stderr`] instead of [`io::stdout`]. See [`print!`] for
 /// example usage.
 ///
 /// Use `eprint!` only for error and progress messages. Use `print!`
 /// instead for the primary output of your program.
 ///
-/// [`io::stderr`]: ../std/io/struct.Stderr.html
-/// [`print!`]: ../std/macro.print.html
+/// [`io::stderr`]: crate::io::stderr
+/// [`io::stdout`]: crate::io::stdout
 ///
 /// # Panics
 ///
@@ -129,14 +128,14 @@ macro_rules! eprint {
 /// Prints to the standard error, with a newline.
 ///
 /// Equivalent to the [`println!`] macro, except that output goes to
-/// [`io::stderr`] instead of `io::stdout`. See [`println!`] for
+/// [`io::stderr`] instead of [`io::stdout`]. See [`println!`] for
 /// example usage.
 ///
 /// Use `eprintln!` only for error and progress messages. Use `println!`
 /// instead for the primary output of your program.
 ///
-/// [`io::stderr`]: ../std/io/struct.Stderr.html
-/// [`println!`]: ../std/macro.println.html
+/// [`io::stderr`]: crate::io::stderr
+/// [`io::stdout`]: crate::io::stdout
 ///
 /// # Panics
 ///
index c11049fb98152e0696675f077293c4c3ed287867..d7d96862b2116c0d6706d885b8878c4e3ab21d16 100644 (file)
@@ -268,7 +268,7 @@ pub fn new(ip: Ipv4Addr, port: u16) -> SocketAddrV4 {
             inner: c::sockaddr_in {
                 sin_family: c::AF_INET as c::sa_family_t,
                 sin_port: htons(port),
-                sin_addr: *ip.as_inner(),
+                sin_addr: ip.into_inner(),
                 ..unsafe { mem::zeroed() }
             },
         }
@@ -286,6 +286,8 @@ pub fn new(ip: Ipv4Addr, port: u16) -> SocketAddrV4 {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn ip(&self) -> &Ipv4Addr {
+        // SAFETY: `Ipv4Addr` is `#[repr(C)] struct { _: in_addr; }`.
+        // It is safe to cast from `&in_addr` to `&Ipv4Addr`.
         unsafe { &*(&self.inner.sin_addr as *const c::in_addr as *const Ipv4Addr) }
     }
 
@@ -302,7 +304,7 @@ pub fn ip(&self) -> &Ipv4Addr {
     /// ```
     #[stable(feature = "sockaddr_setters", since = "1.9.0")]
     pub fn set_ip(&mut self, new_ip: Ipv4Addr) {
-        self.inner.sin_addr = *new_ip.as_inner()
+        self.inner.sin_addr = new_ip.into_inner()
     }
 
     /// Returns the port number associated with this socket address.
index de28268ea368212ee8593e01a7f087dc20b103c4..85bb6b60e6829da3d872348c3dc78a0904dba746 100644 (file)
@@ -12,7 +12,7 @@
 use crate::io::Write as IoWrite;
 use crate::mem::transmute;
 use crate::sys::net::netc as c;
-use crate::sys_common::{AsInner, FromInner};
+use crate::sys_common::{AsInner, FromInner, IntoInner};
 
 /// An IP address, either IPv4 or IPv6.
 ///
@@ -909,7 +909,10 @@ impl Eq for Ipv4Addr {}
 #[stable(feature = "rust1", since = "1.0.0")]
 impl hash::Hash for Ipv4Addr {
     fn hash<H: hash::Hasher>(&self, s: &mut H) {
-        // `inner` is #[repr(packed)], so we need to copy `s_addr`.
+        // NOTE:
+        // * hash in big endian order
+        // * in netbsd, `in_addr` has `repr(packed)`, we need to
+        //   copy `s_addr` to avoid unsafe borrowing
         { self.inner.s_addr }.hash(s)
     }
 }
@@ -944,13 +947,14 @@ fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl Ord for Ipv4Addr {
     fn cmp(&self, other: &Ipv4Addr) -> Ordering {
+        // Compare as native endian
         u32::from_be(self.inner.s_addr).cmp(&u32::from_be(other.inner.s_addr))
     }
 }
 
-impl AsInner<c::in_addr> for Ipv4Addr {
-    fn as_inner(&self) -> &c::in_addr {
-        &self.inner
+impl IntoInner<c::in_addr> for Ipv4Addr {
+    fn into_inner(self) -> c::in_addr {
+        self.inner
     }
 }
 
@@ -2019,6 +2023,7 @@ fn test_from_str_socket_addr() {
 
     #[test]
     fn ipv4_addr_to_string() {
+        assert_eq!(Ipv4Addr::new(127, 0, 0, 1).to_string(), "127.0.0.1");
         // Short address
         assert_eq!(Ipv4Addr::new(1, 1, 1, 1).to_string(), "1.1.1.1");
         // Long address
index eb8589eb58f4757df52d53c6c5c3248bb7f2964c..1950ffcb21b6755187362b71568a692b26d8674f 100644 (file)
@@ -170,63 +170,63 @@ pub struct stat {
 
 #[cfg(target_arch = "hexagon")]
 mod arch {
-    use crate::os::raw::{c_int, c_long, c_longlong, c_ulonglong};
+    use crate::os::raw::{c_int, c_long, c_uint};
 
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub type blkcnt_t = c_longlong;
+    pub type blkcnt_t = i64;
     #[stable(feature = "raw_ext", since = "1.1.0")]
     pub type blksize_t = c_long;
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub type ino_t = c_ulonglong;
+    pub type ino_t = u64;
     #[stable(feature = "raw_ext", since = "1.1.0")]
     pub type nlink_t = c_uint;
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub type off_t = c_longlong;
+    pub type off_t = i64;
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub type time_t = c_long;
+    pub type time_t = i64;
 
     #[repr(C)]
     #[derive(Clone)]
     #[stable(feature = "raw_ext", since = "1.1.0")]
     pub struct stat {
         #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_dev: ::dev_t,
+        pub st_dev: u64,
         #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_ino: ::c_ulonglong,
+        pub st_ino: u64,
         #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_mode: ::c_uint,
+        pub st_mode: u32,
         #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_nlink: ::c_uint,
+        pub st_nlink: u32,
         #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_uid: ::c_uint,
+        pub st_uid: u32,
         #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_gid: ::c_uint,
+        pub st_gid: u32,
         #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_rdev: ::c_ulonglong,
+        pub st_rdev: u64,
         #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub __pad1: ::c_ulong,
+        pub __pad1: u32,
         #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_size: ::c_longlong,
+        pub st_size: i64,
         #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_blksize: ::blksize_t,
+        pub st_blksize: i32,
         #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub __pad2: ::c_int,
+        pub __pad2: i32,
         #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_blocks: ::blkcnt_t,
+        pub st_blocks: i64,
         #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_atime: ::time_t,
+        pub st_atime: i64,
         #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_atime_nsec: ::c_long,
+        pub st_atime_nsec: c_long,
         #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_mtime: ::time_t,
+        pub st_mtime: i64,
         #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_mtime_nsec: ::c_long,
+        pub st_mtime_nsec: c_long,
         #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_ctime: ::time_t,
+        pub st_ctime: i64,
         #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_ctime_nsec: ::c_long,
+        pub st_ctime_nsec: c_long,
         #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub __pad3: [::c_int; 2],
+        pub __pad3: [c_int; 2],
     }
 }
 
index bca1732b84d95677af4fbb4742c3b7d11beea5ab..be7fd0dd6c4479cbf909ee66b3a78896a1684463 100644 (file)
@@ -587,6 +587,20 @@ mod prim_array {}
 /// x[1] = 7;
 /// assert_eq!(x, &[1, 7, 3]);
 /// ```
+///
+/// As slices store the length of the sequence they refer to, they have twice
+/// the size of pointers to [`Sized`](marker/trait.Sized.html) types.
+/// Also see the reference on
+/// [dynamically sized types](../reference/dynamically-sized-types.html).
+///
+/// ```
+/// # use std::rc::Rc;
+/// let pointer_size = std::mem::size_of::<&u8>();
+/// assert_eq!(2 * pointer_size, std::mem::size_of::<&[u8]>());
+/// assert_eq!(2 * pointer_size, std::mem::size_of::<*const [u8]>());
+/// assert_eq!(2 * pointer_size, std::mem::size_of::<Box<[u8]>>());
+/// assert_eq!(2 * pointer_size, std::mem::size_of::<Rc<[u8]>>());
+/// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_slice {}
 
index 6d94fa9ebfe6d7316dd5149e7c0068a249f42ab7..c42bc1096528b7266507ce755737bd5535e16234 100644 (file)
 ///
 /// # Warning
 ///
-/// On some system, calling [`wait`] or similar is necessary for the OS to
+/// On some systems, calling [`wait`] or similar is necessary for the OS to
 /// release resources. A process that terminated but has not been waited on is
 /// still around as a "zombie". Leaving too many zombies around may exhaust
 /// global resources (for example process IDs).
index 01314370ce3994842a625c213a233ef3cb3b5414..23c989fd2fdfb78cee8678a22addb8b61886788d 100644 (file)
@@ -131,7 +131,7 @@ pub fn wait(&self) -> BarrierWaitResult {
         lock.count += 1;
         if lock.count < self.num_threads {
             // We need a while loop to guard against spurious wakeups.
-            // http://en.wikipedia.org/wiki/Spurious_wakeup
+            // https://en.wikipedia.org/wiki/Spurious_wakeup
             while local_gen == lock.generation_id && lock.count < self.num_threads {
                 lock = self.cvar.wait(lock).unwrap();
             }
index 9b90bfd68b50f3047ec1ee6e01245efe98311a11..4efd86aa3ede8c3e7c99c2f845f3c164a3cd57b4 100644 (file)
@@ -11,7 +11,7 @@
 ///
 /// It is returned by the [`wait_timeout`] method.
 ///
-/// [`wait_timeout`]: struct.Condvar.html#method.wait_timeout
+/// [`wait_timeout`]: Condvar::wait_timeout
 #[derive(Debug, PartialEq, Eq, Copy, Clone)]
 #[stable(feature = "wait_timeout", since = "1.5.0")]
 pub struct WaitTimeoutResult(bool);
@@ -161,11 +161,10 @@ pub fn new() -> Condvar {
     /// mutex to ensure defined behavior across platforms. If this functionality
     /// is not desired, then unsafe primitives in `sys` are provided.
     ///
-    /// [`notify_one`]: #method.notify_one
-    /// [`notify_all`]: #method.notify_all
-    /// [poisoning]: ../sync/struct.Mutex.html#poisoning
-    /// [`Mutex`]: ../sync/struct.Mutex.html
-    /// [`panic!`]: ../../std/macro.panic.html
+    /// [`notify_one`]: Self::notify_one
+    /// [`notify_all`]: Self::notify_all
+    /// [poisoning]: super::Mutex#poisoning
+    /// [`Mutex`]: super::Mutex
     ///
     /// # Examples
     ///
@@ -218,10 +217,10 @@ pub fn wait<'a, T>(&self, guard: MutexGuard<'a, T>) -> LockResult<MutexGuard<'a,
     /// poisoned when this thread re-acquires the lock. For more information,
     /// see information about [poisoning] on the [`Mutex`] type.
     ///
-    /// [`notify_one`]: #method.notify_one
-    /// [`notify_all`]: #method.notify_all
-    /// [poisoning]: ../sync/struct.Mutex.html#poisoning
-    /// [`Mutex`]: ../sync/struct.Mutex.html
+    /// [`notify_one`]: Self::notify_one
+    /// [`notify_all`]: Self::notify_all
+    /// [poisoning]: super::Mutex#poisoning
+    /// [`Mutex`]: super::Mutex
     ///
     /// # Examples
     ///
@@ -280,7 +279,7 @@ pub fn wait_while<'a, T, F>(
     /// Like [`wait`], the lock specified will be re-acquired when this function
     /// returns, regardless of whether the timeout elapsed or not.
     ///
-    /// [`wait`]: #method.wait
+    /// [`wait`]: Self::wait
     ///
     /// # Examples
     ///
@@ -350,9 +349,8 @@ pub fn wait_timeout_ms<'a, T>(
     /// Like [`wait`], the lock specified will be re-acquired when this function
     /// returns, regardless of whether the timeout elapsed or not.
     ///
-    /// [`wait`]: #method.wait
-    /// [`wait_timeout_while`]: #method.wait_timeout_while
-    /// [`WaitTimeoutResult`]: struct.WaitTimeoutResult.html
+    /// [`wait`]: Self::wait
+    /// [`wait_timeout_while`]: Self::wait_timeout_while
     ///
     /// # Examples
     ///
@@ -420,9 +418,8 @@ pub fn wait_timeout<'a, T>(
     /// Like [`wait_while`], the lock specified will be re-acquired when this
     /// function returns, regardless of whether the timeout elapsed or not.
     ///
-    /// [`wait_while`]: #method.wait_while
-    /// [`wait_timeout`]: #method.wait_timeout
-    /// [`WaitTimeoutResult`]: struct.WaitTimeoutResult.html
+    /// [`wait_while`]: Self::wait_while
+    /// [`wait_timeout`]: Self::wait_timeout
     ///
     /// # Examples
     ///
@@ -485,9 +482,9 @@ pub fn wait_timeout_while<'a, T, F>(
     ///
     /// To wake up all threads, see [`notify_all`].
     ///
-    /// [`wait`]: #method.wait
-    /// [`wait_timeout`]: #method.wait_timeout
-    /// [`notify_all`]: #method.notify_all
+    /// [`wait`]: Self::wait
+    /// [`wait_timeout`]: Self::wait_timeout
+    /// [`notify_all`]: Self::notify_all
     ///
     /// # Examples
     ///
@@ -527,7 +524,7 @@ pub fn notify_one(&self) {
     ///
     /// To wake up only one thread, see [`notify_one`].
     ///
-    /// [`notify_one`]: #method.notify_one
+    /// [`notify_one`]: Self::notify_one
     ///
     /// # Examples
     ///
index 3ff50e9f213477716e1f39447a5d4451ca2cfc62..ac83017d9e1246d35bd28a34618fae72823976c1 100644 (file)
@@ -1,5 +1,3 @@
-// ignore-tidy-filelength
-
 //! Multi-producer, single-consumer FIFO queue communication primitives.
 //!
 //! This module provides message-based communication over channels, concretely
 //!    that a bound of 0 is allowed, causing the channel to become a "rendezvous"
 //!    channel where each sender atomically hands off a message to a receiver.
 //!
-//! [`Sender`]: ../../../std/sync/mpsc/struct.Sender.html
-//! [`SyncSender`]: ../../../std/sync/mpsc/struct.SyncSender.html
-//! [`Receiver`]: ../../../std/sync/mpsc/struct.Receiver.html
-//! [`send`]: ../../../std/sync/mpsc/struct.Sender.html#method.send
-//! [`channel`]: ../../../std/sync/mpsc/fn.channel.html
-//! [`sync_channel`]: ../../../std/sync/mpsc/fn.sync_channel.html
+//! [`send`]: Sender::send
 //!
 //! ## Disconnection
 //!
@@ -46,9 +39,7 @@
 //! will continue to [`unwrap`] the results returned from this module,
 //! instigating a propagation of failure among threads if one unexpectedly dies.
 //!
-//! [`Result`]: ../../../std/result/enum.Result.html
-//! [`Err`]: ../../../std/result/enum.Result.html#variant.Err
-//! [`unwrap`]: ../../../std/result/enum.Result.html#method.unwrap
+//! [`unwrap`]: Result::unwrap
 //!
 //! # Examples
 //!
 ///
 /// Messages sent to the channel can be retrieved using [`recv`].
 ///
-/// [`channel`]: fn.channel.html
-/// [`sync_channel`]: fn.sync_channel.html
-/// [`recv`]: struct.Receiver.html#method.recv
+/// [`recv`]: Receiver::recv
 ///
 /// # Examples
 ///
@@ -333,10 +322,8 @@ impl<T> !Sync for Receiver<T> {}
 /// waiting for a new message, and [`None`] will be returned
 /// when the corresponding channel has hung up.
 ///
-/// [`iter`]: struct.Receiver.html#method.iter
-/// [`Receiver`]: struct.Receiver.html
-/// [`next`]: ../../../std/iter/trait.Iterator.html#tymethod.next
-/// [`None`]: ../../../std/option/enum.Option.html#variant.None
+/// [`iter`]: Receiver::iter
+/// [`next`]: Iterator::next
 ///
 /// # Examples
 ///
@@ -371,9 +358,7 @@ pub struct Iter<'a, T: 'a> {
 /// This iterator will never block the caller in order to wait for data to
 /// become available. Instead, it will return [`None`].
 ///
-/// [`Receiver`]: struct.Receiver.html
-/// [`try_iter`]: struct.Receiver.html#method.try_iter
-/// [`None`]: ../../../std/option/enum.Option.html#variant.None
+/// [`try_iter`]: Receiver::try_iter
 ///
 /// # Examples
 ///
@@ -414,9 +399,7 @@ pub struct TryIter<'a, T: 'a> {
 /// is called, waiting for a new message, and [`None`] will be
 /// returned if the corresponding channel has hung up.
 ///
-/// [`Receiver`]: struct.Receiver.html
-/// [`next`]: ../../../std/iter/trait.Iterator.html#tymethod.next
-/// [`None`]: ../../../std/option/enum.Option.html#variant.None
+/// [`next`]: Iterator::next
 ///
 /// # Examples
 ///
@@ -447,8 +430,7 @@ pub struct IntoIter<T> {
 ///
 /// Messages can be sent through this channel with [`send`].
 ///
-/// [`channel`]: fn.channel.html
-/// [`send`]: struct.Sender.html#method.send
+/// [`send`]: Sender::send
 ///
 /// # Examples
 ///
@@ -493,9 +475,8 @@ impl<T> !Sync for Sender<T> {}
 ///
 /// [`send`] will block if there is no space in the internal buffer.
 ///
-/// [`sync_channel`]: fn.sync_channel.html
-/// [`send`]: struct.SyncSender.html#method.send
-/// [`try_send`]: struct.SyncSender.html#method.try_send
+/// [`send`]: SyncSender::send
+/// [`try_send`]: SyncSender::try_send
 ///
 /// # Examples
 ///
@@ -549,8 +530,8 @@ unsafe impl<T: Send> Send for SyncSender<T> {}
 /// disconnected, implying that the data could never be received. The error
 /// contains the data being sent as a payload so it can be recovered.
 ///
-/// [`Sender::send`]: struct.Sender.html#method.send
-/// [`SyncSender::send`]: struct.SyncSender.html#method.send
+/// [`Sender::send`]: Sender::send
+/// [`SyncSender::send`]: SyncSender::send
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(PartialEq, Eq, Clone, Copy)]
 pub struct SendError<T>(#[stable(feature = "rust1", since = "1.0.0")] pub T);
@@ -561,10 +542,7 @@ unsafe impl<T: Send> Send for SyncSender<T> {}
 /// [`channel`] (or [`sync_channel`]) is disconnected, implying that no further
 /// messages will ever be received.
 ///
-/// [`recv`]: struct.Receiver.html#method.recv
-/// [`Receiver`]: struct.Receiver.html
-/// [`channel`]: fn.channel.html
-/// [`sync_channel`]: fn.sync_channel.html
+/// [`recv`]: Receiver::recv
 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct RecvError;
@@ -573,9 +551,7 @@ unsafe impl<T: Send> Send for SyncSender<T> {}
 /// not return data when called. This can occur with both a [`channel`] and
 /// a [`sync_channel`].
 ///
-/// [`try_recv`]: struct.Receiver.html#method.try_recv
-/// [`channel`]: fn.channel.html
-/// [`sync_channel`]: fn.sync_channel.html
+/// [`try_recv`]: Receiver::try_recv
 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub enum TryRecvError {
@@ -594,9 +570,7 @@ pub enum TryRecvError {
 /// unable to return data when called. This can occur with both a [`channel`] and
 /// a [`sync_channel`].
 ///
-/// [`recv_timeout`]: struct.Receiver.html#method.recv_timeout
-/// [`channel`]: fn.channel.html
-/// [`sync_channel`]: fn.sync_channel.html
+/// [`recv_timeout`]: Receiver::recv_timeout
 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
 #[stable(feature = "mpsc_recv_timeout", since = "1.12.0")]
 pub enum RecvTimeoutError {
@@ -613,7 +587,7 @@ pub enum RecvTimeoutError {
 /// This enumeration is the list of the possible error outcomes for the
 /// [`try_send`] method.
 ///
-/// [`try_send`]: struct.SyncSender.html#method.try_send
+/// [`try_send`]: SyncSender::try_send
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(PartialEq, Eq, Clone, Copy)]
 pub enum TrySendError<T> {
@@ -623,16 +597,11 @@ pub enum TrySendError<T> {
     /// If this is a buffered channel, then the buffer is full at this time. If
     /// this is not a buffered channel, then there is no [`Receiver`] available to
     /// acquire the data.
-    ///
-    /// [`sync_channel`]: fn.sync_channel.html
-    /// [`Receiver`]: struct.Receiver.html
     #[stable(feature = "rust1", since = "1.0.0")]
     Full(#[stable(feature = "rust1", since = "1.0.0")] T),
 
     /// This [`sync_channel`]'s receiving half has disconnected, so the data could not be
     /// sent. The data is returned back to the callee in this case.
-    ///
-    /// [`sync_channel`]: fn.sync_channel.html
     #[stable(feature = "rust1", since = "1.0.0")]
     Disconnected(#[stable(feature = "rust1", since = "1.0.0")] T),
 }
@@ -680,13 +649,8 @@ fn inner_unsafe(&self) -> &UnsafeCell<Flavor<T>> {
 /// [`Sender`] is disconnected while trying to [`recv`], the [`recv`] method will
 /// return a [`RecvError`].
 ///
-/// [`send`]: struct.Sender.html#method.send
-/// [`recv`]: struct.Receiver.html#method.recv
-/// [`Sender`]: struct.Sender.html
-/// [`Receiver`]: struct.Receiver.html
-/// [`sync_channel`]: fn.sync_channel.html
-/// [`SendError`]: struct.SendError.html
-/// [`RecvError`]: struct.RecvError.html
+/// [`send`]: Sender::send
+/// [`recv`]: Receiver::recv
 ///
 /// # Examples
 ///
@@ -733,13 +697,8 @@ pub fn channel<T>() -> (Sender<T>, Receiver<T>) {
 /// [`SendError`]. Similarly, If the [`SyncSender`] is disconnected while trying
 /// to [`recv`], the [`recv`] method will return a [`RecvError`].
 ///
-/// [`channel`]: fn.channel.html
-/// [`send`]: struct.SyncSender.html#method.send
-/// [`recv`]: struct.Receiver.html#method.recv
-/// [`SyncSender`]: struct.SyncSender.html
-/// [`Receiver`]: struct.Receiver.html
-/// [`SendError`]: struct.SendError.html
-/// [`RecvError`]: struct.RecvError.html
+/// [`send`]: SyncSender::send
+/// [`recv`]: Receiver::recv
 ///
 /// # Examples
 ///
@@ -786,9 +745,6 @@ fn new(inner: Flavor<T>) -> Sender<T> {
     /// will be received. It is possible for the corresponding receiver to
     /// hang up immediately after this function returns [`Ok`].
     ///
-    /// [`Err`]: ../../../std/result/enum.Result.html#variant.Err
-    /// [`Ok`]: ../../../std/result/enum.Result.html#variant.Ok
-    ///
     /// This method will never block the current thread.
     ///
     /// # Examples
@@ -933,9 +889,6 @@ fn new(inner: Arc<sync::Packet<T>>) -> SyncSender<T> {
     /// [`Receiver`] has disconnected and is no longer able to receive
     /// information.
     ///
-    /// [`Err`]: ../../../std/result/enum.Result.html#variant.Err
-    /// [`Receiver`]: ../../../std/sync/mpsc/struct.Receiver.html
-    ///
     /// # Examples
     ///
     /// ```rust
@@ -971,7 +924,7 @@ pub fn send(&self, t: T) -> Result<(), SendError<T>> {
     /// See [`send`] for notes about guarantees of whether the
     /// receiver has received the data or not if this function is successful.
     ///
-    /// [`send`]: ../../../std/sync/mpsc/struct.SyncSender.html#method.send
+    /// [`send`]: Self::send
     ///
     /// # Examples
     ///
@@ -1059,7 +1012,7 @@ fn new(inner: Flavor<T>) -> Receiver<T> {
     /// Compared with [`recv`], this function has two failure cases instead of one
     /// (one for disconnection, one for an empty buffer).
     ///
-    /// [`recv`]: struct.Receiver.html#method.recv
+    /// [`recv`]: Self::recv
     ///
     /// # Examples
     ///
@@ -1117,10 +1070,6 @@ pub fn try_recv(&self) -> Result<T, TryRecvError> {
     /// However, since channels are buffered, messages sent before the disconnect
     /// will still be properly received.
     ///
-    /// [`Sender`]: struct.Sender.html
-    /// [`SyncSender`]: struct.SyncSender.html
-    /// [`Err`]: ../../../std/result/enum.Result.html#variant.Err
-    ///
     /// # Examples
     ///
     /// ```
@@ -1203,10 +1152,6 @@ pub fn recv(&self) -> Result<T, RecvError> {
     /// However, since channels are buffered, messages sent before the disconnect
     /// will still be properly received.
     ///
-    /// [`Sender`]: struct.Sender.html
-    /// [`SyncSender`]: struct.SyncSender.html
-    /// [`Err`]: ../../../std/result/enum.Result.html#variant.Err
-    ///
     /// # Known Issues
     ///
     /// There is currently a known issue (see [`#39364`]) that causes `recv_timeout`
@@ -1304,10 +1249,6 @@ pub fn recv_timeout(&self, timeout: Duration) -> Result<T, RecvTimeoutError> {
     /// However, since channels are buffered, messages sent before the disconnect
     /// will still be properly received.
     ///
-    /// [`Sender`]: struct.Sender.html
-    /// [`SyncSender`]: struct.SyncSender.html
-    /// [`Err`]: ../../../std/result/enum.Result.html#variant.Err
-    ///
     /// # Examples
     ///
     /// Successfully receiving value before reaching deadline:
@@ -1397,9 +1338,6 @@ pub fn recv_deadline(&self, deadline: Instant) -> Result<T, RecvTimeoutError> {
     /// Returns an iterator that will block waiting for messages, but never
     /// [`panic!`]. It will return [`None`] when the channel has hung up.
     ///
-    /// [`panic!`]: ../../../std/macro.panic.html
-    /// [`None`]: ../../../std/option/enum.Option.html#variant.None
-    ///
     /// # Examples
     ///
     /// ```rust
@@ -1430,8 +1368,6 @@ pub fn iter(&self) -> Iter<'_, T> {
     /// channel has hung up. The iterator will never [`panic!`] or block the
     /// user by waiting for values.
     ///
-    /// [`panic!`]: ../../../std/macro.panic.html
-    ///
     /// # Examples
     ///
     /// ```no_run
index 8478457eabfc2e8d0d5e68eeea7ba273e1f0f6bc..d7a4f00305c71a458501a599b3a529652a53bfda 100644 (file)
 /// the guard that would have otherwise been returned on a successful lock. This
 /// allows access to the data, despite the lock being poisoned.
 ///
-/// [`new`]: #method.new
-/// [`lock`]: #method.lock
-/// [`try_lock`]: #method.try_lock
-/// [`Result`]: ../../std/result/enum.Result.html
-/// [`unwrap()`]: ../../std/result/enum.Result.html#method.unwrap
-/// [`PoisonError`]: ../../std/sync/struct.PoisonError.html
-/// [`into_inner`]: ../../std/sync/struct.PoisonError.html#method.into_inner
+/// [`new`]: Self::new
+/// [`lock`]: Self::lock
+/// [`try_lock`]: Self::try_lock
+/// [`unwrap()`]: Result::unwrap
+/// [`PoisonError`]: super::PoisonError
+/// [`into_inner`]: super::PoisonError::into_inner
 ///
 /// # Examples
 ///
@@ -190,11 +189,8 @@ unsafe impl<T: ?Sized + Send> Sync for Mutex<T> {}
 /// This structure is created by the [`lock`] and [`try_lock`] methods on
 /// [`Mutex`].
 ///
-/// [`Deref`]: ../../std/ops/trait.Deref.html
-/// [`DerefMut`]: ../../std/ops/trait.DerefMut.html
-/// [`lock`]: struct.Mutex.html#method.lock
-/// [`try_lock`]: struct.Mutex.html#method.try_lock
-/// [`Mutex`]: struct.Mutex.html
+/// [`lock`]: Mutex::lock
+/// [`try_lock`]: Mutex::try_lock
 #[must_use = "if unused the Mutex will immediately unlock"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct MutexGuard<'a, T: ?Sized + 'a> {
@@ -289,8 +285,6 @@ pub fn lock(&self) -> LockResult<MutexGuard<'_, T>> {
     /// this call will return failure if the mutex would otherwise be
     /// acquired.
     ///
-    /// [`Err`]: ../../std/result/enum.Result.html#variant.Err
-    ///
     /// # Examples
     ///
     /// ```
@@ -432,8 +426,6 @@ fn drop(&mut self) {
 impl<T> From<T> for Mutex<T> {
     /// Creates a new mutex in an unlocked state ready for use.
     /// This is equivalent to [`Mutex::new`].
-    ///
-    /// [`Mutex::new`]: ../../std/sync/struct.Mutex.html#method.new
     fn from(t: T) -> Self {
         Mutex::new(t)
     }
index 50f54dbf14306a1644d0ab77345156d2d968c385..586093c916deabb7f5dfed6626d7a895a7e6d57e 100644 (file)
 /// } // write lock is dropped here
 /// ```
 ///
-/// [`Deref`]: ../../std/ops/trait.Deref.html
-/// [`DerefMut`]: ../../std/ops/trait.DerefMut.html
-/// [`Send`]: ../../std/marker/trait.Send.html
-/// [`Sync`]: ../../std/marker/trait.Sync.html
-/// [`Mutex`]: struct.Mutex.html
+/// [`Mutex`]: super::Mutex
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct RwLock<T: ?Sized> {
     inner: Box<sys::RWLock>,
@@ -81,9 +77,8 @@ unsafe impl<T: ?Sized + Send + Sync> Sync for RwLock<T> {}
 /// This structure is created by the [`read`] and [`try_read`] methods on
 /// [`RwLock`].
 ///
-/// [`read`]: struct.RwLock.html#method.read
-/// [`try_read`]: struct.RwLock.html#method.try_read
-/// [`RwLock`]: struct.RwLock.html
+/// [`read`]: RwLock::read
+/// [`try_read`]: RwLock::try_read
 #[must_use = "if unused the RwLock will immediately unlock"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct RwLockReadGuard<'a, T: ?Sized + 'a> {
@@ -102,9 +97,8 @@ unsafe impl<T: ?Sized + Sync> Sync for RwLockReadGuard<'_, T> {}
 /// This structure is created by the [`write`] and [`try_write`] methods
 /// on [`RwLock`].
 ///
-/// [`write`]: struct.RwLock.html#method.write
-/// [`try_write`]: struct.RwLock.html#method.try_write
-/// [`RwLock`]: struct.RwLock.html
+/// [`write`]: RwLock::write
+/// [`try_write`]: RwLock::try_write
 #[must_use = "if unused the RwLock will immediately unlock"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct RwLockWriteGuard<'a, T: ?Sized + 'a> {
@@ -456,8 +450,6 @@ fn default() -> RwLock<T> {
 impl<T> From<T> for RwLock<T> {
     /// Creates a new instance of an `RwLock<T>` which is unlocked.
     /// This is equivalent to [`RwLock::new`].
-    ///
-    /// [`RwLock::new`]: ../../std/sync/struct.RwLock.html#method.new
     fn from(t: T) -> Self {
         RwLock::new(t)
     }
index 601563c5b1fcbdebe7e5dca84bea6f5432a42f61..7fec4731a462c6b89cb580e43de7e33a2624bf67 100644 (file)
@@ -6,8 +6,8 @@
 pub struct Stderr(());
 
 impl Stdin {
-    pub fn new() -> io::Result<Stdin> {
-        Ok(Stdin(()))
+    pub const fn new() -> Stdin {
+        Stdin(())
     }
 }
 
@@ -18,8 +18,8 @@ fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> {
 }
 
 impl Stdout {
-    pub fn new() -> io::Result<Stdout> {
-        Ok(Stdout(()))
+    pub const fn new() -> Stdout {
+        Stdout(())
     }
 }
 
@@ -37,8 +37,8 @@ fn flush(&mut self) -> io::Result<()> {
 }
 
 impl Stderr {
-    pub fn new() -> io::Result<Stderr> {
-        Ok(Stderr(()))
+    pub const fn new() -> Stderr {
+        Stderr(())
     }
 }
 
@@ -62,5 +62,5 @@ pub fn is_ebadf(err: &io::Error) -> bool {
 pub const STDIN_BUF_SIZE: usize = crate::sys_common::io::DEFAULT_BUF_SIZE;
 
 pub fn panic_output() -> Option<impl io::Write> {
-    Stderr::new().ok()
+    Some(Stderr::new())
 }
index f3654ee38716c7c54ab09e65f0230606465ba556..82304dd6dc2931112c1dedb7913204445f52d0cb 100644 (file)
@@ -7,8 +7,8 @@
 pub struct Stderr;
 
 impl Stdin {
-    pub fn new() -> io::Result<Stdin> {
-        Ok(Stdin)
+    pub const fn new() -> Stdin {
+        Stdin
     }
 }
 
@@ -28,8 +28,8 @@ fn is_read_vectored(&self) -> bool {
 }
 
 impl Stdout {
-    pub fn new() -> io::Result<Stdout> {
-        Ok(Stdout)
+    pub const fn new() -> Stdout {
+        Stdout
     }
 }
 
@@ -69,8 +69,8 @@ fn flush(&mut self) -> io::Result<()> {
 }
 
 impl Stderr {
-    pub fn new() -> io::Result<Stderr> {
-        Ok(Stderr)
+    pub const fn new() -> Stderr {
+        Stderr
     }
 }
 
@@ -116,5 +116,5 @@ pub fn is_ebadf(_err: &io::Error) -> bool {
 }
 
 pub fn panic_output() -> Option<impl io::Write> {
-    Stderr::new().ok()
+    Some(Stderr::new())
 }
index 716c174bd53b65a165231e2c1959603384b2a4d2..49f44f9f498aca1f55eadc62d39122ee346abe71 100644 (file)
@@ -19,8 +19,8 @@ fn with_std_fd<F: FnOnce(&FileDesc) -> R, R>(fd: abi::Fd, f: F) -> R {
 }
 
 impl Stdin {
-    pub fn new() -> io::Result<Stdin> {
-        Ok(Stdin(()))
+    pub const fn new() -> Stdin {
+        Stdin(())
     }
 }
 
@@ -31,8 +31,8 @@ fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
 }
 
 impl Stdout {
-    pub fn new() -> io::Result<Stdout> {
-        Ok(Stdout(()))
+    pub const fn new() -> Stdout {
+        Stdout(())
     }
 }
 
@@ -47,8 +47,8 @@ fn flush(&mut self) -> io::Result<()> {
 }
 
 impl Stderr {
-    pub fn new() -> io::Result<Stderr> {
-        Ok(Stderr(()))
+    pub const fn new() -> Stderr {
+        Stderr(())
     }
 }
 
index f8353214cbca037fa635f342bf6e700a0aabf8e1..a05fe8165cff2f2bc5a2cebe9eff9837427ea5c5 100644 (file)
@@ -7,8 +7,8 @@
 pub struct Stderr(());
 
 impl Stdin {
-    pub fn new() -> io::Result<Stdin> {
-        Ok(Stdin(()))
+    pub const fn new() -> Stdin {
+        Stdin(())
     }
 }
 
@@ -28,8 +28,8 @@ fn is_read_vectored(&self) -> bool {
 }
 
 impl Stdout {
-    pub fn new() -> io::Result<Stdout> {
-        Ok(Stdout(()))
+    pub const fn new() -> Stdout {
+        Stdout(())
     }
 }
 
@@ -53,8 +53,8 @@ fn flush(&mut self) -> io::Result<()> {
 }
 
 impl Stderr {
-    pub fn new() -> io::Result<Stderr> {
-        Ok(Stderr(()))
+    pub const fn new() -> Stderr {
+        Stderr(())
     }
 }
 
@@ -84,5 +84,5 @@ pub fn is_ebadf(err: &io::Error) -> bool {
 pub const STDIN_BUF_SIZE: usize = crate::sys_common::io::DEFAULT_BUF_SIZE;
 
 pub fn panic_output() -> Option<impl io::Write> {
-    Stderr::new().ok()
+    Some(Stderr::new())
 }
index 5a4e4505e93bddce1805a1f163e2df0c66bc7cfd..b5e3f5be9885bc7197bb651111b833cc244a8870 100644 (file)
@@ -5,8 +5,8 @@
 pub struct Stderr;
 
 impl Stdin {
-    pub fn new() -> io::Result<Stdin> {
-        Ok(Stdin)
+    pub const fn new() -> Stdin {
+        Stdin
     }
 }
 
@@ -17,8 +17,8 @@ fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> {
 }
 
 impl Stdout {
-    pub fn new() -> io::Result<Stdout> {
-        Ok(Stdout)
+    pub const fn new() -> Stdout {
+        Stdout
     }
 }
 
@@ -33,8 +33,8 @@ fn flush(&mut self) -> io::Result<()> {
 }
 
 impl Stderr {
-    pub fn new() -> io::Result<Stderr> {
-        Ok(Stderr)
+    pub const fn new() -> Stderr {
+        Stderr
     }
 }
 
index ea186846929be135479736277e31ece1035b4960..d58468ad539ff92ca0a9d4d96fd260c01d7329b2 100644 (file)
@@ -53,7 +53,7 @@ pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
     }
 
     #[inline]
-    fn is_read_vectored(&self) -> bool {
+    pub fn is_read_vectored(&self) -> bool {
         true
     }
 
index bbbd5eda7731411ee6a7ddf39aeebe35ac927426..6473a0c3cec41aa764d824f02a81f1765773b781 100644 (file)
@@ -351,8 +351,7 @@ pub fn new(status: c_int) -> ExitStatus {
     }
 
     fn exited(&self) -> bool {
-        /*unsafe*/
-        { libc::WIFEXITED(self.0) }
+        libc::WIFEXITED(self.0)
     }
 
     pub fn success(&self) -> bool {
@@ -360,19 +359,11 @@ pub fn success(&self) -> bool {
     }
 
     pub fn code(&self) -> Option<i32> {
-        if self.exited() {
-            Some(/*unsafe*/ { libc::WEXITSTATUS(self.0) })
-        } else {
-            None
-        }
+        if self.exited() { Some(libc::WEXITSTATUS(self.0)) } else { None }
     }
 
     pub fn signal(&self) -> Option<i32> {
-        if !self.exited() {
-            Some(/*unsafe*/ { libc::WTERMSIG(self.0) })
-        } else {
-            None
-        }
+        if !self.exited() { Some(libc::WTERMSIG(self.0)) } else { None }
     }
 }
 
index 622444ccafd3cd0d97d4426b8e515951b82d1c77..92e9f205b4e6e2edaf2c7ac85c31f6bed2e00f88 100644 (file)
@@ -6,8 +6,8 @@
 pub struct Stderr(());
 
 impl Stdin {
-    pub fn new() -> io::Result<Stdin> {
-        Ok(Stdin(()))
+    pub const fn new() -> Stdin {
+        Stdin(())
     }
 }
 
@@ -21,8 +21,8 @@ fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
 }
 
 impl Stdout {
-    pub fn new() -> io::Result<Stdout> {
-        Ok(Stdout(()))
+    pub const fn new() -> Stdout {
+        Stdout(())
     }
 }
 
@@ -40,8 +40,8 @@ fn flush(&mut self) -> io::Result<()> {
 }
 
 impl Stderr {
-    pub fn new() -> io::Result<Stderr> {
-        Ok(Stderr(()))
+    pub const fn new() -> Stderr {
+        Stderr(())
     }
 }
 
@@ -65,5 +65,5 @@ pub fn is_ebadf(err: &io::Error) -> bool {
 pub const STDIN_BUF_SIZE: usize = crate::sys_common::io::DEFAULT_BUF_SIZE;
 
 pub fn panic_output() -> Option<impl io::Write> {
-    Stderr::new().ok()
+    Some(Stderr::new())
 }
index 3f73f6c490326fb6d4e8c6c8fd94b55abdc36f08..5391ed83ebc36267e5932ba1723411bdc3e722a6 100644 (file)
@@ -2,6 +2,6 @@
 #![unstable(feature = "thread_local_internals", issue = "none")]
 
 pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) {
-    use crate::sys_common::thread_local::register_dtor_fallback;
+    use crate::sys_common::thread_local_dtor::register_dtor_fallback;
     register_dtor_fallback(t, dtor);
 }
index 78e3911dc4efea33e1edc322a40e54ab7856e2bb..23baafabf7933bd7ad116f0541a3466c687acb77 100644 (file)
@@ -7,8 +7,8 @@
 pub struct Stderr;
 
 impl Stdin {
-    pub fn new() -> io::Result<Stdin> {
-        Ok(Stdin)
+    pub const fn new() -> Stdin {
+        Stdin
     }
 
     #[inline]
@@ -33,8 +33,8 @@ fn is_read_vectored(&self) -> bool {
 }
 
 impl Stdout {
-    pub fn new() -> io::Result<Stdout> {
-        Ok(Stdout)
+    pub const fn new() -> Stdout {
+        Stdout
     }
 
     #[inline]
@@ -62,8 +62,8 @@ fn flush(&mut self) -> io::Result<()> {
 }
 
 impl Stderr {
-    pub fn new() -> io::Result<Stderr> {
-        Ok(Stderr)
+    pub const fn new() -> Stderr {
+        Stderr
     }
 
     #[inline]
@@ -98,5 +98,5 @@ pub fn is_ebadf(err: &io::Error) -> bool {
 }
 
 pub fn panic_output() -> Option<impl io::Write> {
-    Stderr::new().ok()
+    Some(Stderr::new())
 }
index 982ec912c44b710eebdb7d78559e9ea314e6f95b..a0d5a7471d8af67a4a64c94d2a4477db249d7ac2 100644 (file)
@@ -300,14 +300,10 @@ pub fn dur2timeout(dur: Duration) -> c::DWORD {
         .unwrap_or(c::INFINITE)
 }
 
-// On Windows, use the processor-specific __fastfail mechanism.  In Windows 8
-// and later, this will terminate the process immediately without running any
-// in-process exception handlers.  In earlier versions of Windows, this
-// sequence of instructions will be treated as an access violation,
-// terminating the process but without necessarily bypassing all exception
-// handlers.
-//
-// https://docs.microsoft.com/en-us/cpp/intrinsics/fastfail
+/// Use `__fastfail` to abort the process
+///
+/// This is the same implementation as in libpanic_abort's `__rust_start_panic`. See
+/// that function for more information on `__fastfail`
 #[allow(unreachable_code)]
 pub fn abort_internal() -> ! {
     #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
index c84896296ecb930902e09d010d60c85d216c3c60..ff214497166beb8ac953c890312a5f5e29cb689f 100644 (file)
@@ -131,8 +131,8 @@ fn write_u16s(handle: c::HANDLE, data: &[u16]) -> io::Result<usize> {
 }
 
 impl Stdin {
-    pub fn new() -> io::Result<Stdin> {
-        Ok(Stdin { surrogate: 0 })
+    pub const fn new() -> Stdin {
+        Stdin { surrogate: 0 }
     }
 }
 
@@ -255,8 +255,8 @@ fn utf16_to_utf8(utf16: &[u16], utf8: &mut [u8]) -> io::Result<usize> {
 }
 
 impl Stdout {
-    pub fn new() -> io::Result<Stdout> {
-        Ok(Stdout)
+    pub const fn new() -> Stdout {
+        Stdout
     }
 }
 
@@ -271,8 +271,8 @@ fn flush(&mut self) -> io::Result<()> {
 }
 
 impl Stderr {
-    pub fn new() -> io::Result<Stderr> {
-        Ok(Stderr)
+    pub const fn new() -> Stderr {
+        Stderr
     }
 }
 
@@ -291,5 +291,5 @@ pub fn is_ebadf(err: &io::Error) -> bool {
 }
 
 pub fn panic_output() -> Option<impl io::Write> {
-    Stderr::new().ok()
+    Some(Stderr::new())
 }
index 5bdabf6d4b78efdaa81c74e514ce8076e459bf5e..872511af862a72d47ce767a0975fba1083600617 100644 (file)
@@ -30,8 +30,8 @@ fn write(handle_id: c::DWORD, data: &[u8]) -> io::Result<usize> {
 }
 
 impl Stdin {
-    pub fn new() -> io::Result<Stdin> {
-        Ok(Stdin {})
+    pub const fn new() -> Stdin {
+        Stdin {}
     }
 }
 
@@ -44,8 +44,8 @@ fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
 }
 
 impl Stdout {
-    pub fn new() -> io::Result<Stdout> {
-        Ok(Stdout)
+    pub const fn new() -> Stdout {
+        Stdout
     }
 }
 
@@ -60,8 +60,8 @@ fn flush(&mut self) -> io::Result<()> {
 }
 
 impl Stderr {
-    pub fn new() -> io::Result<Stderr> {
-        Ok(Stderr)
+    pub const fn new() -> Stderr {
+        Stderr
     }
 }
 
@@ -80,5 +80,5 @@ pub fn is_ebadf(err: &io::Error) -> bool {
 }
 
 pub fn panic_output() -> Option<impl io::Write> {
-    Stderr::new().ok()
+    Some(Stderr::new())
 }
index 81a5ef95e82dcdc7cc33a230c715385304fdbf84..0bb136078bc95c6539c449adb9bf6ae5be233691 100644 (file)
@@ -585,8 +585,8 @@ pub fn multicast_loop_v6(&self) -> io::Result<bool> {
 
     pub fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
         let mreq = c::ip_mreq {
-            imr_multiaddr: *multiaddr.as_inner(),
-            imr_interface: *interface.as_inner(),
+            imr_multiaddr: multiaddr.into_inner(),
+            imr_interface: interface.into_inner(),
         };
         setsockopt(&self.inner, c::IPPROTO_IP, c::IP_ADD_MEMBERSHIP, mreq)
     }
@@ -601,8 +601,8 @@ pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Res
 
     pub fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
         let mreq = c::ip_mreq {
-            imr_multiaddr: *multiaddr.as_inner(),
-            imr_interface: *interface.as_inner(),
+            imr_multiaddr: multiaddr.into_inner(),
+            imr_interface: interface.into_inner(),
         };
         setsockopt(&self.inner, c::IPPROTO_IP, c::IP_DROP_MEMBERSHIP, mreq)
     }
index 66508f06b2884ccb4de9147d890d3f08fa35e8cb..a4562967f0bcb904ed738f8e8855bfe55acccabd 100644 (file)
@@ -71,9 +71,7 @@
 ///    not guard typically have a synthetic limit after which point no more
 ///    destructors are run.
 ///
-/// [`with`]: ../../std/thread/struct.LocalKey.html#method.with
-/// [`thread_local!`]: ../../std/macro.thread_local.html
-/// [`Drop`]: ../../std/ops/trait.Drop.html
+/// [`with`]: LocalKey::with
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct LocalKey<T: 'static> {
     // This outer `LocalKey<T>` type is what's going to be stored in statics,
@@ -118,10 +116,10 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 /// # fn main() {}
 /// ```
 ///
-/// See [LocalKey documentation][`std::thread::LocalKey`] for more
+/// See [`LocalKey` documentation][`std::thread::LocalKey`] for more
 /// information.
 ///
-/// [`std::thread::LocalKey`]: ../std/thread/struct.LocalKey.html
+/// [`std::thread::LocalKey`]: crate::thread::LocalKey
 #[macro_export]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[allow_internal_unstable(thread_local_internals)]
index 202867258f1e403006c53b07932a67e2dfb9915f..0b9849517c2526bbfb1a9a4fd5881eac7682cf6a 100644 (file)
 //!
 //! Note that the stack size of the main thread is *not* determined by Rust.
 //!
-//! [channels]: ../../std/sync/mpsc/index.html
-//! [`Arc`]: ../../std/sync/struct.Arc.html
-//! [`spawn`]: ../../std/thread/fn.spawn.html
-//! [`JoinHandle`]: ../../std/thread/struct.JoinHandle.html
-//! [`JoinHandle::thread`]: ../../std/thread/struct.JoinHandle.html#method.thread
-//! [`join`]: ../../std/thread/struct.JoinHandle.html#method.join
-//! [`Result`]: ../../std/result/enum.Result.html
-//! [`Ok`]: ../../std/result/enum.Result.html#variant.Ok
-//! [`Err`]: ../../std/result/enum.Result.html#variant.Err
-//! [`panic!`]: ../../std/macro.panic.html
-//! [`Builder`]: ../../std/thread/struct.Builder.html
-//! [`Builder::stack_size`]: ../../std/thread/struct.Builder.html#method.stack_size
-//! [`Builder::name`]: ../../std/thread/struct.Builder.html#method.name
-//! [`thread::current`]: ../../std/thread/fn.current.html
-//! [`thread::Result`]: ../../std/thread/type.Result.html
-//! [`Thread`]: ../../std/thread/struct.Thread.html
-//! [`park`]: ../../std/thread/fn.park.html
-//! [`unpark`]: ../../std/thread/struct.Thread.html#method.unpark
-//! [`Thread::name`]: ../../std/thread/struct.Thread.html#method.name
-//! [`thread::park_timeout`]: ../../std/thread/fn.park_timeout.html
-//! [`Cell`]: ../cell/struct.Cell.html
-//! [`RefCell`]: ../cell/struct.RefCell.html
-//! [`thread_local!`]: ../macro.thread_local.html
-//! [`with`]: struct.LocalKey.html#method.with
+//! [channels]: crate::sync::mpsc
+//! [`join`]: JoinHandle::join
+//! [`Result`]: crate::result::Result
+//! [`Ok`]: crate::result::Result::Ok
+//! [`Err`]: crate::result::Result::Err
+//! [`thread::current`]: current
+//! [`thread::Result`]: Result
+//! [`unpark`]: Thread::unpark
+//! [`Thread::name`]: Thread::name
+//! [`thread::park_timeout`]: park_timeout
+//! [`Cell`]: crate::cell::Cell
+//! [`RefCell`]: crate::cell::RefCell
+//! [`with`]: LocalKey::with
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
 /// handler.join().unwrap();
 /// ```
 ///
-/// [`thread::spawn`]: ../../std/thread/fn.spawn.html
-/// [`stack_size`]: ../../std/thread/struct.Builder.html#method.stack_size
-/// [`name`]: ../../std/thread/struct.Builder.html#method.name
-/// [`spawn`]: ../../std/thread/struct.Builder.html#method.spawn
-/// [`io::Result`]: ../../std/io/type.Result.html
-/// [`unwrap`]: ../../std/result/enum.Result.html#method.unwrap
+/// [`stack_size`]: Builder::stack_size
+/// [`name`]: Builder::name
+/// [`spawn`]: Builder::spawn
+/// [`thread::spawn`]: spawn
+/// [`io::Result`]: crate::io::Result
+/// [`unwrap`]: crate::result::Result::unwrap
 /// [naming-threads]: ./index.html#naming-threads
 /// [stack-size]: ./index.html#stack-size
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -355,9 +344,7 @@ pub fn stack_size(mut self, size: usize) -> Builder {
     /// [`io::Result`] to capture any failure to create the thread at
     /// the OS level.
     ///
-    /// [`spawn`]: ../../std/thread/fn.spawn.html
-    /// [`io::Result`]: ../../std/io/type.Result.html
-    /// [`JoinHandle`]: ../../std/thread/struct.JoinHandle.html
+    /// [`io::Result`]: crate::io::Result
     ///
     /// # Panics
     ///
@@ -443,11 +430,7 @@ pub fn spawn<F, T>(self, f: F) -> io::Result<JoinHandle<T>>
     /// handler.join().unwrap();
     /// ```
     ///
-    /// [`spawn`]: ../../std/thread/fn.spawn.html
-    /// [`Builder::spawn`]: ../../std/thread/struct.Builder.html#method.spawn
-    /// [`io::Result`]: ../../std/io/type.Result.html
-    /// [`JoinHandle`]: ../../std/thread/struct.JoinHandle.html
-    /// [`JoinHandle::join`]: ../../std/thread/struct.JoinHandle.html#method.join
+    /// [`io::Result`]: crate::io::Result
     #[unstable(feature = "thread_spawn_unchecked", issue = "55132")]
     pub unsafe fn spawn_unchecked<'a, F, T>(self, f: F) -> io::Result<JoinHandle<T>>
     where
@@ -513,7 +496,7 @@ pub unsafe fn spawn_unchecked<'a, F, T>(self, f: F) -> io::Result<JoinHandle<T>>
 /// the main thread finishes). Additionally, the join handle provides a [`join`]
 /// method that can be used to join the child thread. If the child thread
 /// panics, [`join`] will return an [`Err`] containing the argument given to
-/// [`panic`].
+/// [`panic!`].
 ///
 /// This will create a thread using default parameters of [`Builder`], if you
 /// want to specify the stack size or the name of the thread, use this API
@@ -600,15 +583,9 @@ pub unsafe fn spawn_unchecked<'a, F, T>(self, f: F) -> io::Result<JoinHandle<T>>
 /// println!("{}", result);
 /// ```
 ///
-/// [`channels`]: ../../std/sync/mpsc/index.html
-/// [`JoinHandle`]: ../../std/thread/struct.JoinHandle.html
-/// [`join`]: ../../std/thread/struct.JoinHandle.html#method.join
-/// [`Err`]: ../../std/result/enum.Result.html#variant.Err
-/// [`panic`]: ../../std/macro.panic.html
-/// [`Builder::spawn`]: ../../std/thread/struct.Builder.html#method.spawn
-/// [`Builder`]: ../../std/thread/struct.Builder.html
-/// [`Send`]: ../../std/marker/trait.Send.html
-/// [`Sync`]: ../../std/marker/trait.Sync.html
+/// [`channels`]: crate::sync::mpsc
+/// [`join`]: JoinHandle::join
+/// [`Err`]: crate::result::Result::Err
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn spawn<F, T>(f: F) -> JoinHandle<T>
 where
@@ -673,11 +650,8 @@ pub fn current() -> Thread {
 /// thread::yield_now();
 /// ```
 ///
-/// [`channel`]: ../../std/sync/mpsc/index.html
-/// [`spawn`]: ../../std/thread/fn.spawn.html
-/// [`join`]: ../../std/thread/struct.JoinHandle.html#method.join
-/// [`Mutex`]: ../../std/sync/struct.Mutex.html
-/// [`Condvar`]: ../../std/sync/struct.Condvar.html
+/// [`channel`]: crate::sync::mpsc
+/// [`join`]: JoinHandle::join
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn yield_now() {
     imp::Thread::yield_now()
@@ -723,8 +697,6 @@ pub fn yield_now() {
 ///     panic!()
 /// }
 /// ```
-///
-/// [Mutex]: ../../std/sync/struct.Mutex.html
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn panicking() -> bool {
@@ -881,10 +853,8 @@ pub fn sleep(dur: Duration) {
 /// parked_thread.join().unwrap();
 /// ```
 ///
-/// [`Thread`]: ../../std/thread/struct.Thread.html
-/// [`park`]: ../../std/thread/fn.park.html
-/// [`unpark`]: ../../std/thread/struct.Thread.html#method.unpark
-/// [`thread::park_timeout`]: ../../std/thread/fn.park_timeout.html
+/// [`unpark`]: Thread::unpark
+/// [`thread::park_timeout`]: park_timeout
 //
 // The implementation currently uses the trivial strategy of a Mutex+Condvar
 // with wakeup flag, which does not actually allow spurious wakeups. In the
@@ -939,9 +909,6 @@ pub fn park() {
 /// amount of time waited to be precisely `ms` long.
 ///
 /// See the [park documentation][`park`] for more detail.
-///
-/// [`park_timeout`]: fn.park_timeout.html
-/// [`park`]: ../../std/thread/fn.park.html
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_deprecated(since = "1.6.0", reason = "replaced by `std::thread::park_timeout`")]
 pub fn park_timeout_ms(ms: u32) {
@@ -986,8 +953,6 @@ pub fn park_timeout_ms(ms: u32) {
 ///     timeout_remaining = timeout - elapsed;
 /// }
 /// ```
-///
-/// [park]: fn.park.html
 #[stable(feature = "park_timeout", since = "1.4.0")]
 pub fn park_timeout(dur: Duration) {
     let thread = current();
@@ -1046,8 +1011,7 @@ pub fn park_timeout(dur: Duration) {
 /// assert!(thread::current().id() != other_thread_id);
 /// ```
 ///
-/// [`id`]: ../../std/thread/struct.Thread.html#method.id
-/// [`Thread`]: ../../std/thread/struct.Thread.html
+/// [`id`]: Thread::id
 #[stable(feature = "thread_id", since = "1.19.0")]
 #[derive(Eq, PartialEq, Clone, Copy, Hash, Debug)]
 pub struct ThreadId(NonZeroU64);
@@ -1124,12 +1088,7 @@ struct Inner {
 /// should instead use a function like `spawn` to create new threads, see the
 /// docs of [`Builder`] and [`spawn`] for more details.
 ///
-/// [`Builder`]: ../../std/thread/struct.Builder.html
-/// [`JoinHandle::thread`]: ../../std/thread/struct.JoinHandle.html#method.thread
-/// [`JoinHandle`]: ../../std/thread/struct.JoinHandle.html
-/// [`thread::current`]: ../../std/thread/fn.current.html
-/// [`spawn`]: ../../std/thread/fn.spawn.html
-
+/// [`thread::current`]: current
 pub struct Thread {
     inner: Arc<Inner>,
 }
@@ -1181,8 +1140,6 @@ pub(crate) fn new(name: Option<String>) -> Thread {
     ///
     /// parked_thread.join().unwrap();
     /// ```
-    ///
-    /// [park]: fn.park.html
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn unpark(&self) {
         // To ensure the unparked thread will observe any writes we made
@@ -1326,7 +1283,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 /// }
 /// ```
 ///
-/// [`Result`]: ../../std/result/enum.Result.html
+/// [`Result`]: crate::result::Result
 #[stable(feature = "rust1", since = "1.0.0")]
 pub type Result<T> = crate::result::Result<T, Box<dyn Any + Send + 'static>>;
 
@@ -1421,9 +1378,8 @@ fn join(&mut self) -> Result<T> {
 /// thread::sleep(Duration::from_millis(1000));
 /// ```
 ///
-/// [`Clone`]: ../../std/clone/trait.Clone.html
-/// [`thread::spawn`]: fn.spawn.html
-/// [`thread::Builder::spawn`]: struct.Builder.html#method.spawn
+/// [`thread::Builder::spawn`]: Builder::spawn
+/// [`thread::spawn`]: spawn
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct JoinHandle<T>(JoinInner<T>);
 
@@ -1462,11 +1418,10 @@ pub fn thread(&self) -> &Thread {
     /// operations that happen after `join` returns.
     ///
     /// If the child thread panics, [`Err`] is returned with the parameter given
-    /// to [`panic`].
+    /// to [`panic!`].
     ///
-    /// [`Err`]: ../../std/result/enum.Result.html#variant.Err
-    /// [`panic`]: ../../std/macro.panic.html
-    /// [atomic memory orderings]: ../../std/sync/atomic/index.html
+    /// [`Err`]: crate::result::Result::Err
+    /// [atomic memory orderings]: crate::sync::atomic
     ///
     /// # Panics
     ///
index 077005371c0cf1c70573a890a510500852aaf9b0..c02f93bf9d42f1ed27d8c13e56a2331075eb064c 100644 (file)
@@ -84,7 +84,7 @@ pub trait Stats {
     /// by the constant `1.4826` to allow its use as a consistent estimator for the standard
     /// deviation.
     ///
-    /// See: <http://en.wikipedia.org/wiki/Median_absolute_deviation>
+    /// See: <https://en.wikipedia.org/wiki/Median_absolute_deviation>
     fn median_abs_dev(&self) -> f64;
 
     /// Median absolute deviation as a percent of the median. See `median_abs_dev` and `median`.
@@ -96,7 +96,7 @@ pub trait Stats {
     ///
     /// Calculated by linear interpolation between closest ranks.
     ///
-    /// See: <http://en.wikipedia.org/wiki/Percentile>
+    /// See: <https://en.wikipedia.org/wiki/Percentile>
     fn percentile(&self, pct: f64) -> f64;
 
     /// Quartiles of the sample: three values that divide the sample into four equal groups, each
@@ -302,7 +302,7 @@ fn percentile_of_sorted(sorted_samples: &[f64], pct: f64) -> f64 {
 /// It differs from trimming in that it does not change the number of samples,
 /// just changes the values of those that are outliers.
 ///
-/// See: <http://en.wikipedia.org/wiki/Winsorising>
+/// See: <https://en.wikipedia.org/wiki/Winsorising>
 pub fn winsorize(samples: &mut [f64], pct: f64) {
     let mut tmp = samples.to_vec();
     local_sort(&mut tmp);
index 7ff00d85dd2f24a0ea0d9bc8552e4d6960aadc11..d50e4cf52697a30bd96338ba12c11e01a852f8cf 100644 (file)
@@ -132,7 +132,8 @@ pub fn find(build: &mut Build) {
             false
         };
 
-        if cxx_configured {
+        // for VxWorks, record CXX compiler which will be used in lib.rs:linker()
+        if cxx_configured || target.contains("vxworks") {
             let compiler = cfg.get_compiler();
             build.cxx.insert(target, compiler);
         }
index 70b1c471ac3f0e6f11efc24d4d0b17a17a081354..8b8b01b11532731342b1413a0adcf86fb219252a 100644 (file)
@@ -527,7 +527,7 @@ pub fn parse(args: &[String]) -> Config {
 
         let build = toml.build.clone().unwrap_or_default();
         // set by bootstrap.py
-        config.hosts.push(config.build.clone());
+        config.hosts.push(config.build);
         for host in build.host.iter().map(|h| TargetSelection::from_user(h)) {
             if !config.hosts.contains(&host) {
                 config.hosts.push(host);
index 01121977f130b66d678070bc1a13b491ead6faa6..f0b2254be9ee9159a057c793aea00e4cd0d9e557 100644 (file)
@@ -226,7 +226,7 @@ fn make_win_dist(
         let idx = line.find(':').unwrap();
         let key = &line[..idx];
         let trim_chars: &[_] = &[' ', '='];
-        let value = line[(idx + 1)..].trim_start_matches(trim_chars).split(';').map(PathBuf::from);
+        let value = env::split_paths(line[(idx + 1)..].trim_start_matches(trim_chars));
 
         if key == "programs" {
             bin_path.extend(value);
index a1b5ca2ea2fa1f18c128645704f1dd329c0e6d79..2a8f43950db3c2faab179cf77c9aeee5f68aefcd 100644 (file)
@@ -96,7 +96,7 @@ fn is_explicit_request(builder: &Builder<'_>, path: &str) -> bool {
         .paths
         .iter()
         .map(components_simplified)
-        .any(|requested| requested.iter().copied().eq(path.split("/")))
+        .any(|requested| requested.iter().copied().eq(path.split('/')))
 }
 
 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
index 56e4f0467cc50967978d2752e7cf99374e460977..38b3a32e3b5fbecd2dc01d9077145e9c0db10f13 100644 (file)
@@ -505,14 +505,11 @@ pub fn parse(args: &[String]) -> Flags {
 
         if let Subcommand::Check { .. } = &cmd {
             if matches.opt_str("stage").is_some() {
-                println!("{}", "--stage not supported for x.py check, always treated as stage 0");
+                println!("--stage not supported for x.py check, always treated as stage 0");
                 process::exit(1);
             }
             if matches.opt_str("keep-stage").is_some() {
-                println!(
-                    "{}",
-                    "--keep-stage not supported for x.py check, only one stage available"
-                );
+                println!("--keep-stage not supported for x.py check, only one stage available");
                 process::exit(1);
             }
         }
index 390b7e96b9a543cecdd806fe2369b10469bd9f50..6f93082e6752f01c559b572dcf85ff95873e8270 100644 (file)
@@ -87,7 +87,7 @@ pub fn format(build: &Build, check: bool) {
                 .lines()
                 .filter(|entry| entry.starts_with("??"))
                 .map(|entry| {
-                    entry.split(" ").nth(1).expect("every git status entry should list a path")
+                    entry.split(' ').nth(1).expect("every git status entry should list a path")
                 });
             for untracked_path in untracked_paths {
                 eprintln!("skip untracked path {} during rustfmt invocations", untracked_path);
index 77820ef87e3b470399217ffcbcb9c33128bcfe76..191cc5b0b64ca85db834c46305059b9de884ab44 100644 (file)
@@ -323,10 +323,7 @@ pub enum Mode {
 
 impl Mode {
     pub fn is_tool(&self) -> bool {
-        match self {
-            Mode::ToolBootstrap | Mode::ToolRustc | Mode::ToolStd => true,
-            _ => false,
-        }
+        matches!(self, Mode::ToolBootstrap | Mode::ToolRustc | Mode::ToolStd)
     }
 }
 
@@ -857,6 +854,10 @@ fn linker(&self, target: TargetSelection, can_use_lld: bool) -> Option<&Path> {
         if let Some(linker) = self.config.target_config.get(&target).and_then(|c| c.linker.as_ref())
         {
             Some(linker)
+        } else if target.contains("vxworks") {
+            // need to use CXX compiler as linker to resolve the exception functions
+            // that are only existed in CXX libraries
+            Some(self.cxx[&target].path())
         } else if target != self.config.build
             && util::use_host_linker(target)
             && !target.contains("msvc")
index eca9ddceae1b5a80c1b7424dfeca07b884e536bd..97d9dbdd63fb2f53809da3824b753c7f1fb74bd7 100644 (file)
@@ -767,7 +767,7 @@ fn supported_sanitizers(
 ) -> Vec<SanitizerRuntime> {
     let darwin_libs = |os: &str, components: &[&str]| -> Vec<SanitizerRuntime> {
         components
-            .into_iter()
+            .iter()
             .map(move |c| SanitizerRuntime {
                 cmake_target: format!("clang_rt.{}_{}_dynamic", c, os),
                 path: out_dir
@@ -779,7 +779,7 @@ fn supported_sanitizers(
 
     let common_libs = |os: &str, arch: &str, components: &[&str]| -> Vec<SanitizerRuntime> {
         components
-            .into_iter()
+            .iter()
             .map(move |c| SanitizerRuntime {
                 cmake_target: format!("clang_rt.{}-{}", c, arch),
                 path: out_dir.join(&format!("build/lib/{}/libclang_rt.{}-{}.a", os, c, arch)),
index ac833a55d4c53bbf2224fa0adf7fffba6b76de73..afa72b5d58c14e8744d5d43e10fe015deeba8b83 100644 (file)
@@ -1754,6 +1754,11 @@ fn run(self, builder: &Builder<'_>) {
             cargo.arg("--quiet");
         }
 
+        if builder.config.cmd.bless() {
+            // Bless `expect!` tests.
+            cargo.env("UPDATE_EXPECT", "1");
+        }
+
         if target.contains("emscripten") {
             cargo.env(
                 format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)),
index 2c00a628a1d350e764dbd51b534167a808e98c00..969443ac0949bf6ab837373bccc03dea2bb6de58 100755 (executable)
@@ -4,7 +4,7 @@ set -ex
 
 source shared.sh
 
-LLVM=llvmorg-9.0.0
+LLVM=llvmorg-10.0.0
 
 mkdir llvm-project
 cd llvm-project
@@ -18,17 +18,7 @@ cd clang-build
 # For whatever reason the default set of include paths for clang is different
 # than that of gcc. As a result we need to manually include our sysroot's
 # include path, /rustroot/include, to clang's default include path.
-#
-# Alsow there's this weird oddity with gcc where there's an 'include-fixed'
-# directory that it generates. It turns out [1] that Centos 5's headers are so
-# old that they're incompatible with modern C semantics. While gcc automatically
-# fixes that clang doesn't account for this. Tell clang to manually include the
-# fixed headers so we can successfully compile code later on.
-#
-# [1]: https://sourceware.org/ml/crossgcc/2008-11/msg00028.html
-INC="/rustroot/include"
-INC="$INC:/rustroot/lib/gcc/x86_64-unknown-linux-gnu/5.5.0/include-fixed"
-INC="$INC:/usr/include"
+INC="/rustroot/include:/usr/include"
 
 hide_output \
     cmake ../llvm \
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-full-bootstrap/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-full-bootstrap/Dockerfile
deleted file mode 100644 (file)
index 8648e5e..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-FROM ubuntu:16.04
-
-RUN apt-get update && apt-get install -y --no-install-recommends \
-  g++ \
-  make \
-  file \
-  curl \
-  ca-certificates \
-  python3 \
-  git \
-  cmake \
-  sudo \
-  gdb \
-  libssl-dev \
-  pkg-config \
-  xz-utils
-
-COPY scripts/sccache.sh /scripts/
-RUN sh /scripts/sccache.sh
-
-ENV RUST_CONFIGURE_ARGS \
-      --build=x86_64-unknown-linux-gnu \
-      --enable-full-bootstrap
-ENV SCRIPT python3 ../x.py --stage 2 build
-
-# In general this just slows down the build and we're just a smoke test that
-# a full bootstrap works in general, so there's not much need to take this
-# penalty in build times.
-ENV NO_LLVM_ASSERTIONS 1
-ENV NO_DEBUG_ASSERTIONS 1
index 165ecc791804472bd79ac03c8e231458bc7a4672..db2def483ac309fe663088451a2ec81adde8a338 100644 (file)
@@ -419,9 +419,6 @@ jobs:
           - name: x86_64-gnu-distcheck
             <<: *job-linux-xl
 
-          - name: x86_64-gnu-full-bootstrap
-            <<: *job-linux-xl
-
           - name: x86_64-gnu-llvm-8
             env:
               RUST_BACKTRACE: 1
index c242f5d4562690ba8f0c310bd86df305cee523ef..a1481f22f509de74548a95cc1041d34dc862649b 100755 (executable)
@@ -8,11 +8,14 @@ IFS=$'\n\t'
 
 source "$(cd "$(dirname "$0")" && pwd)/../shared.sh"
 
+# Update both macOS's and Windows's tarballs when bumping the version here.
+LLVM_VERSION="10.0.0"
+
 if isMacOS; then
-    curl -f "${MIRRORS_BASE}/clang%2Bllvm-9.0.0-x86_64-darwin-apple.tar.xz" | tar xJf -
+    curl -f "${MIRRORS_BASE}/clang%2Bllvm-${LLVM_VERSION}-x86_64-apple-darwin.tar.xz" | tar xJf -
 
-    ciCommandSetEnv CC "$(pwd)/clang+llvm-9.0.0-x86_64-darwin-apple/bin/clang"
-    ciCommandSetEnv CXX "$(pwd)/clang+llvm-9.0.0-x86_64-darwin-apple/bin/clang++"
+    ciCommandSetEnv CC "$(pwd)/clang+llvm-${LLVM_VERSION}-x86_64-apple-darwin/bin/clang"
+    ciCommandSetEnv CXX "$(pwd)/clang+llvm-${LLVM_VERSION}-x86_64-apple-darwin/bin/clang++"
 
     # macOS 10.15 onwards doesn't have libraries in /usr/include anymore: those
     # are now located deep into the filesystem, under Xcode's own files. The
@@ -33,8 +36,10 @@ elif isWindows && [[ ${CUSTOM_MINGW-0} -ne 1 ]]; then
     #
     # Note that the LLVM installer is an NSIS installer
     #
-    # Original downloaded here came from
-    # http://releases.llvm.org/9.0.0/LLVM-9.0.0-win64.exe
+    # Original downloaded here came from:
+    #
+    #   https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.0/LLVM-10.0.0-win64.exe
+    #
     # That installer was run through `wine ./installer.exe /S /NCRC` on Linux
     # and then the resulting installation directory (found in
     # `$HOME/.wine/drive_c/Program Files/LLVM`) was packaged up into a tarball.
@@ -45,7 +50,7 @@ elif isWindows && [[ ${CUSTOM_MINGW-0} -ne 1 ]]; then
 
     mkdir -p citools
     cd citools
-    curl -f "${MIRRORS_BASE}/LLVM-9.0.0-win64.tar.gz" | tar xzf -
+    curl -f "${MIRRORS_BASE}/LLVM-${LLVM_VERSION}-win64.tar.gz" | tar xzf -
     ciCommandSetEnv RUST_CONFIGURE_ARGS \
         "${RUST_CONFIGURE_ARGS} --set llvm.clang-cl=$(pwd)/clang-rust/bin/clang-cl.exe"
 fi
index d16c2a9d0342c71f4512a02c4db1a1dab0d5abea..2f49fc8a41552293af6078f04a9d493996fe3bca 100644 (file)
@@ -81,7 +81,7 @@ impl<T> AsyncReceiver<T> {
 }
 ```
 
-Paths in Rust have three namespaces: type, value, and macro. Items from these namespaces are allowed to overlap. In case of ambiguity, rustdoc will warn about the ambiguity and ask you to disambiguate, which can be done by using a prefix like `struct@`, `enum@`, `type@`, `trait@`, `union@`, `const@`, `static@`, `value@`, `function@`, `mod@`, `fn@`, `module@`, `method@` , `macro@`, or `derive@`:
+Paths in Rust have three namespaces: type, value, and macro. Items from these namespaces are allowed to overlap. In case of ambiguity, rustdoc will warn about the ambiguity and ask you to disambiguate, which can be done by using a prefix like `struct@`, `enum@`, `type@`, `trait@`, `union@`, `const@`, `static@`, `value@`, `function@`, `mod@`, `fn@`, `module@`, `method@`, `prim@`, `primitive@`, `macro@`, or `derive@`:
 
 ```rust
 /// See also: [`Foo`](struct@Foo)
@@ -467,3 +467,36 @@ $ rustdoc src/lib.rs -Z unstable-options --runtool valgrind
 ```
 
 Another use case would be to run a test inside an emulator, or through a Virtual Machine.
+
+### `--show-coverage`: get statistics about code documentation coverage
+
+This option allows you to get a nice overview over your code documentation coverage, including both
+doc-comments and code examples in the doc-comments. Example:
+
+```bash
+$ rustdoc src/lib.rs -Z unstable-options --show-coverage
++-------------------------------------+------------+------------+------------+------------+
+| File                                | Documented | Percentage |   Examples | Percentage |
++-------------------------------------+------------+------------+------------+------------+
+| lib.rs                              |          4 |     100.0% |          1 |      25.0% |
++-------------------------------------+------------+------------+------------+------------+
+| Total                               |          4 |     100.0% |          1 |      25.0% |
++-------------------------------------+------------+------------+------------+------------+
+```
+
+You can also use this option with the `--output-format` one:
+
+```bash
+$ rustdoc src/lib.rs -Z unstable-options --show-coverage --output-format json
+{"lib.rs":{"total":4,"with_docs":4,"total_examples":4,"with_examples":1}}
+```
+
+Calculating code examples follows these rules:
+
+1. These items aren't accounted by default:
+  * struct/union field
+  * enum variant
+  * constant
+  * static
+  * typedef
+2. If one of the previously listed items has a code example, then it'll be counted.
index 4115825e920838947ab4dee93124a1811980daaf..c43d91bf070edd97a878a9acdec8039fe954d4b1 100644 (file)
@@ -6,7 +6,7 @@ The tracking issue for this feature is: [#68793](https://github.com/rust-lang/ru
 
 The rustc flag `-Z control-flow-guard` enables the Windows [Control Flow Guard](https://docs.microsoft.com/en-us/windows/win32/secbp/control-flow-guard) (CFG) platform security feature.
 
-CFG is an exploit mitigation designed to enforce control-flow integrity for software running on supported Windows platforms (Windows 8.1 onwards). Specifically, CFG uses runtime checks to validate the target address of every indirect call/jump before allowing the call to complete. 
+CFG is an exploit mitigation designed to enforce control-flow integrity for software running on supported [Windows platforms (Windows 8.1 onwards)](https://docs.microsoft.com/en-us/windows/win32/secbp/control-flow-guard). Specifically, CFG uses runtime checks to validate the target address of every indirect call/jump before allowing the call to complete. 
 
 During compilation, the compiler identifies all indirect calls/jumps and adds CFG checks. It also emits metadata containing the relative addresses of all address-taken functions. At runtime, if the binary is run on a CFG-aware operating system, the loader uses the CFG metadata to generate a bitmap of the address space and marks those addresses that contain valid targets. On each indirect call, the inserted check determines whether the target address is marked in this bitmap. If the target is not valid, the process is terminated.
 
@@ -19,8 +19,9 @@ CFG functionality is completely implemented in the LLVM backend and is supported
 
 ## When to use Control Flow Guard
 
-The primary motivation for enabling CFG in Rust is to enhance security when linking against non-Rust code, especially C/C++ code. To achieve full CFG protection, all indirect calls (including any from Rust code) must have the appropriate CFG checks, as added by this flag. CFG can also improve security for Rust code that uses the `unsafe` keyword
+The primary motivation for enabling CFG in Rust is to enhance security when linking against non-Rust code, especially C/C++ code. To achieve full CFG protection, all indirect calls (including any from Rust code) must have the appropriate CFG checks, as added by this flag. CFG can also improve security for Rust code that uses the `unsafe` keyword.
 
+Another motivation behind CFG is to harden programs against [return-oriented programming (ROP)](https://en.wikipedia.org/wiki/Return-oriented_programming) attacks. CFG disallows an attacker from taking advantage of the program's own instructions while redirecting control flow in unexpected ways.
 
 ## Overhead of Control Flow Guard
 
index e06881711c4213b504428ac4fc7ea975c6f70c93..127a53cad2b30481776766e72d9058aade43c100 100644 (file)
@@ -1671,6 +1671,7 @@ pub struct MutTy {
 pub struct FnSig {
     pub header: FnHeader,
     pub decl: P<FnDecl>,
+    pub span: Span,
 }
 
 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
index 1e922d3415fdbb7e4d8db0441d152b6b18d59b9a..965571aaa548ee7e0f8e168b581d44e58498733b 100644 (file)
@@ -363,9 +363,10 @@ pub fn visit_bounds<T: MutVisitor>(bounds: &mut GenericBounds, vis: &mut T) {
 }
 
 // No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
-pub fn visit_fn_sig<T: MutVisitor>(FnSig { header, decl }: &mut FnSig, vis: &mut T) {
+pub fn visit_fn_sig<T: MutVisitor>(FnSig { header, decl, span }: &mut FnSig, vis: &mut T) {
     vis.visit_fn_header(header);
     vis.visit_fn_decl(decl);
+    vis.visit_span(span);
 }
 
 // No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
index 46c4be0a33bf76af3b9ae1e8e287ac4792bda563..4a8bf6b4f19b604bc815c12cc869db8cce47d3a9 100644 (file)
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::sync::Lrc;
 use rustc_macros::HashStable_Generic;
+use rustc_span::hygiene::ExpnKind;
+use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::{kw, sym};
 use rustc_span::symbol::{Ident, Symbol};
-use rustc_span::{self, Span, DUMMY_SP};
+use rustc_span::{self, FileName, RealFileName, Span, DUMMY_SP};
 use std::borrow::Cow;
 use std::{fmt, mem};
 
@@ -808,6 +810,31 @@ pub fn pretty_printing_compatibility_hack(&self) -> bool {
         }
         false
     }
+
+    // See issue #74616 for details
+    pub fn ident_name_compatibility_hack(
+        &self,
+        orig_span: Span,
+        source_map: &SourceMap,
+    ) -> Option<(Ident, bool)> {
+        if let NtIdent(ident, is_raw) = self {
+            if let ExpnKind::Macro(_, macro_name) = orig_span.ctxt().outer_expn_data().kind {
+                let filename = source_map.span_to_filename(orig_span);
+                if let FileName::Real(RealFileName::Named(path)) = filename {
+                    if (path.ends_with("time-macros-impl/src/lib.rs")
+                        && macro_name == sym::impl_macros)
+                        || (path.ends_with("js-sys/src/lib.rs") && macro_name == sym::arrays)
+                    {
+                        let snippet = source_map.span_to_snippet(orig_span);
+                        if snippet.as_deref() == Ok("$name") {
+                            return Some((*ident, *is_raw));
+                        }
+                    }
+                }
+            }
+        }
+        None
+    }
 }
 
 impl PartialEq for Nonterminal {
index 473fb7ccc70c4dda877255fc2599582037b5fd1b..f3309afec7d6b01ecd9f4fb600ed04290985d5f3 100644 (file)
@@ -263,7 +263,12 @@ fn lower_item_kind(
                 let (ty, body_id) = self.lower_const_item(t, span, e.as_deref());
                 hir::ItemKind::Const(ty, body_id)
             }
-            ItemKind::Fn(_, FnSig { ref decl, header }, ref generics, ref body) => {
+            ItemKind::Fn(
+                _,
+                FnSig { ref decl, header, span: fn_sig_span },
+                ref generics,
+                ref body,
+            ) => {
                 let fn_def_id = self.resolver.local_def_id(id);
                 self.with_new_scopes(|this| {
                     this.current_item = Some(ident.span);
@@ -290,7 +295,11 @@ fn lower_item_kind(
                             )
                         },
                     );
-                    let sig = hir::FnSig { decl, header: this.lower_fn_header(header) };
+                    let sig = hir::FnSig {
+                        decl,
+                        header: this.lower_fn_header(header),
+                        span: fn_sig_span,
+                    };
                     hir::ItemKind::Fn(sig, generics, body_id)
                 })
             }
@@ -1243,7 +1252,7 @@ fn lower_method_sig(
                 )
             },
         );
-        (generics, hir::FnSig { header, decl })
+        (generics, hir::FnSig { header, decl, span: sig.span })
     }
 
     fn lower_fn_header(&mut self, h: FnHeader) -> hir::FnHeader {
index 31eedeaed0a684ac33e46bade44b4217314cdb4b..586355fe6136e9a62fb1000e5de12d2c70549941 100644 (file)
@@ -2058,7 +2058,7 @@ fn lower_async_fn_output_type_to_future_bound(
 
         hir::GenericBound::LangItemTrait(
             // ::std::future::Future<future_params>
-            hir::LangItem::FutureTraitLangItem,
+            hir::LangItem::Future,
             span,
             self.next_id(),
             future_args,
index b15792dfd4c45ad7c1932ef3faf11d7a5c149164..0ee8ef55e61bff6010fe7a974e46b9c58100478e 100644 (file)
@@ -613,11 +613,14 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
     let spans = sess.parse_sess.gated_spans.spans.borrow();
     macro_rules! gate_all {
         ($gate:ident, $msg:literal) => {
-            for span in spans.get(&sym::$gate).unwrap_or(&vec![]) {
-                gate_feature_post!(&visitor, $gate, *span, $msg);
+            if let Some(spans) = spans.get(&sym::$gate) {
+                for span in spans {
+                    gate_feature_post!(&visitor, $gate, *span, $msg);
+                }
             }
         };
     }
+    gate_all!(if_let_guard, "`if let` guard is not implemented");
     gate_all!(let_chains, "`let` expressions in this position are experimental");
     gate_all!(async_closure, "async closures are unstable");
     gate_all!(generators, "yield syntax is experimental");
index accb0b3c9496514473c065721e99287bf55e9a91..849e8b136e12db756fa49df97920d2c04ade09aa 100644 (file)
@@ -924,6 +924,7 @@ fn create_method(
         let sig = ast::FnSig {
             header: ast::FnHeader { unsafety, ext: ast::Extern::None, ..ast::FnHeader::default() },
             decl: fn_decl,
+            span: trait_.span,
         };
         let def = ast::Defaultness::Final;
 
index c37adb7baa05742d18998dc3eac6034c03506a91..8478fcfbf09a6725f68f647a6c79dd226aebbc6d 100644 (file)
@@ -67,7 +67,7 @@ fn allocator_fn(&self, method: &AllocatorMethod) -> Stmt {
         let (output_ty, output_expr) = self.ret_ty(&method.output, result);
         let decl = self.cx.fn_decl(abi_args, ast::FnRetTy::Ty(output_ty));
         let header = FnHeader { unsafety: Unsafe::Yes(self.span), ..FnHeader::default() };
-        let sig = FnSig { decl, header };
+        let sig = FnSig { decl, header, span: self.span };
         let block = Some(self.cx.block_expr(output_expr));
         let kind = ItemKind::Fn(ast::Defaultness::Final, sig, Generics::default(), block);
         let item = self.cx.item(
index 277cd8389e3e2dbf44480a6a65a6bba256b8e25b..0ea60665d67552bb92346ef402b565a0a016eff5 100644 (file)
@@ -318,7 +318,7 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
     };
 
     let decl = ecx.fn_decl(vec![], ast::FnRetTy::Ty(main_ret_ty));
-    let sig = ast::FnSig { decl, header: ast::FnHeader::default() };
+    let sig = ast::FnSig { decl, header: ast::FnHeader::default(), span: sp };
     let def = ast::Defaultness::Final;
     let main = ast::ItemKind::Fn(def, sig, ast::Generics::default(), Some(main_body));
 
index a6062de6bf8af48a993668019c8ace8b3e994e1f..4fef94dde5f7a3f41dc60a31cceff88262bd3172 100644 (file)
@@ -479,10 +479,13 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'tcx>>)
                         _ => unreachable!(),
                     }
                 } else {
-                    // We use i32 as the type for discarded outputs
-                    's'
+                    // We use i64x2 as the type for discarded outputs
+                    'q'
                 };
                 format!("{{{}{}}}", class, idx)
+            } else if reg == InlineAsmReg::AArch64(AArch64InlineAsmReg::x30) {
+                // LLVM doesn't recognize x30
+                "lr".to_string()
             } else {
                 format!("{{{}}}", reg.name())
             }
index b28cb071de6592d18de7b4708da301bfcc5509cb..77c12c410d5f97cb48dfd06dee64bf971e9cf2fc 100644 (file)
@@ -31,7 +31,7 @@
 use rustc_data_structures::sync::{par_iter, Lock, ParallelIterator};
 use rustc_hir as hir;
 use rustc_hir::def_id::{LocalDefId, LOCAL_CRATE};
-use rustc_hir::lang_items::StartFnLangItem;
+use rustc_hir::lang_items::LangItem;
 use rustc_index::vec::Idx;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
 use rustc_middle::middle::cstore::EncodedMetadata;
@@ -458,7 +458,7 @@ fn create_entry_fn<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
         let (arg_argc, arg_argv) = get_argc_argv(cx, &mut bx);
 
         let (start_fn, args) = if use_start_lang_item {
-            let start_def_id = cx.tcx().require_lang_item(StartFnLangItem, None);
+            let start_def_id = cx.tcx().require_lang_item(LangItem::Start, None);
             let start_fn = cx.get_fn_addr(
                 ty::Instance::resolve(
                     cx.tcx(),
index a4e039de4df587dcc101a7571afbfc4f876cb15b..8048a569f79ea7b369ccc119783210b5bde04298 100644 (file)
@@ -10,7 +10,7 @@
 use crate::MemFlags;
 
 use rustc_ast as ast;
-use rustc_hir::lang_items;
+use rustc_hir::lang_items::LangItem;
 use rustc_index::vec::Idx;
 use rustc_middle::mir;
 use rustc_middle::mir::interpret::{AllocId, ConstValue, Pointer, Scalar};
@@ -420,14 +420,14 @@ fn codegen_assert_terminator(
                 let index = self.codegen_operand(&mut bx, index).immediate();
                 // 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])
+                (LangItem::PanicBoundsCheck, 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])
+                (LangItem::Panic, vec![msg.0, msg.1, location])
             }
         };
 
@@ -492,8 +492,7 @@ enum AssertIntrinsic {
 
                 // 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 def_id = common::langcall(bx.tcx(), Some(span), "", LangItem::Panic);
                 let instance = ty::Instance::mono(bx.tcx(), def_id);
                 let fn_abi = FnAbi::of_instance(bx, instance, &[]);
                 let llfn = bx.get_fn_addr(instance);
index 77e94fe3d0adc150d311e798a8da022a6d2268b1..71f924df119a3ba6ebb47040dd051938e8f3c688 100644 (file)
@@ -8,7 +8,7 @@
 use crate::MemFlags;
 
 use rustc_apfloat::{ieee, Float, Round, Status};
-use rustc_hir::lang_items::ExchangeMallocFnLangItem;
+use rustc_hir::lang_items::LangItem;
 use rustc_middle::mir;
 use rustc_middle::ty::cast::{CastTy, IntTy};
 use rustc_middle::ty::layout::{HasTyCtxt, TyAndLayout};
@@ -507,7 +507,7 @@ pub fn codegen_rvalue_operand(
                 let llty_ptr = bx.cx().backend_type(box_layout);
 
                 // Allocate space:
-                let def_id = match bx.tcx().lang_items().require(ExchangeMallocFnLangItem) {
+                let def_id = match bx.tcx().lang_items().require(LangItem::ExchangeMalloc) {
                     Ok(id) => id,
                     Err(s) => {
                         bx.cx().sess().fatal(&format!("allocation of `{}` {}", box_layout.ty, s));
index e9e6fc5af223089b9c08d6830d4dea348073e2d4..9aed307ec93ae5a78398dd95ced150c549be0e0b 100644 (file)
@@ -61,7 +61,7 @@ fn new(op: KleeneOp, span: Span) -> KleeneToken {
     }
 }
 
-/// A Kleene-style [repetition operator](http://en.wikipedia.org/wiki/Kleene_star)
+/// A Kleene-style [repetition operator](https://en.wikipedia.org/wiki/Kleene_star)
 /// for token sequences.
 #[derive(Clone, PartialEq, Encodable, Decodable, Debug, Copy)]
 enum KleeneOp {
index 33e35cd0404fba4e256702cb948867096aa7459c..409784812f58f46e213989a4ca8163b752c80a90 100644 (file)
@@ -173,13 +173,19 @@ macro_rules! op {
             }
 
             Interpolated(nt) => {
-                let stream = nt_to_tokenstream(&nt, sess, span);
-                TokenTree::Group(Group {
-                    delimiter: Delimiter::None,
-                    stream,
-                    span: DelimSpan::from_single(span),
-                    flatten: nt.pretty_printing_compatibility_hack(),
-                })
+                if let Some((name, is_raw)) =
+                    nt.ident_name_compatibility_hack(span, sess.source_map())
+                {
+                    TokenTree::Ident(Ident::new(sess, name.name, is_raw, name.span))
+                } else {
+                    let stream = nt_to_tokenstream(&nt, sess, span);
+                    TokenTree::Group(Group {
+                        delimiter: Delimiter::None,
+                        stream,
+                        span: DelimSpan::from_single(span),
+                        flatten: nt.pretty_printing_compatibility_hack(),
+                    })
+                }
             }
 
             OpenDelim(..) | CloseDelim(..) => unreachable!(),
index 31aba8aba2515696945d70773b53292fb9220188..e858980738d7118da4317e3a36f72dc53ec72f93 100644 (file)
@@ -582,6 +582,9 @@ pub fn set(&self, features: &mut Features, span: Span) {
     /// The smallest useful subset of `const_generics`.
     (active, min_const_generics, "1.47.0", Some(74878), None),
 
+    /// Allows `if let` guard in match arms.
+    (active, if_let_guard, "1.47.0", Some(51114), None),
+
     // -------------------------------------------------------------------------
     // feature-group-end: actual feature gates
     // -------------------------------------------------------------------------
@@ -591,6 +594,7 @@ pub fn set(&self, features: &mut Features, span: Span) {
 /// unanticipated results, such as compiler crashes. We warn the user about these
 /// to alert them.
 pub const INCOMPLETE_FEATURES: &[Symbol] = &[
+    sym::if_let_guard,
     sym::impl_trait_in_bindings,
     sym::generic_associated_types,
     sym::const_generics,
index 628fc93141114b63fb16ebeb8984f8b907445392..45735ead256a798d246dc0c3067daa7c1dbf542f 100644 (file)
@@ -23,7 +23,7 @@
 /// Internally the `DefPathTable` holds a tree of `DefKey`s, where each `DefKey`
 /// stores the `DefIndex` of its parent.
 /// There is one `DefPathTable` for each crate.
-#[derive(Clone, Default, Decodable, Encodable)]
+#[derive(Clone, Default)]
 pub struct DefPathTable {
     index_to_key: IndexVec<DefIndex, DefKey>,
     def_path_hashes: IndexVec<DefIndex, DefPathHash>,
@@ -42,10 +42,6 @@ fn allocate(&mut self, key: DefKey, def_path_hash: DefPathHash) -> DefIndex {
         index
     }
 
-    pub fn next_id(&self) -> DefIndex {
-        DefIndex::from(self.index_to_key.len())
-    }
-
     #[inline(always)]
     pub fn def_key(&self, index: DefIndex) -> DefKey {
         self.index_to_key[index]
@@ -58,15 +54,25 @@ pub fn def_path_hash(&self, index: DefIndex) -> DefPathHash {
         hash
     }
 
-    pub fn add_def_path_hashes_to(&self, cnum: CrateNum, out: &mut FxHashMap<DefPathHash, DefId>) {
-        out.extend(self.def_path_hashes.iter().enumerate().map(|(index, &hash)| {
-            let def_id = DefId { krate: cnum, index: DefIndex::from(index) };
-            (hash, def_id)
-        }));
+    pub fn num_def_ids(&self) -> usize {
+        self.index_to_key.len()
     }
 
-    pub fn size(&self) -> usize {
-        self.index_to_key.len()
+    pub fn enumerated_keys_and_path_hashes(
+        &self,
+    ) -> impl Iterator<Item = (DefIndex, &DefKey, &DefPathHash)> + '_ {
+        self.index_to_key
+            .iter_enumerated()
+            .map(move |(index, key)| (index, key, &self.def_path_hashes[index]))
+    }
+
+    pub fn all_def_path_hashes_and_def_ids(
+        &self,
+        krate: CrateNum,
+    ) -> impl Iterator<Item = (DefPathHash, DefId)> + '_ {
+        self.def_path_hashes
+            .iter_enumerated()
+            .map(move |(index, hash)| (*hash, DefId { krate, index }))
     }
 }
 
index cf356763130691055f565c50dd2b649f2a094807..cd4185226dce5c767f4d82f3677c5a7b71772c70 100644 (file)
@@ -1851,6 +1851,7 @@ pub struct MutTy<'hir> {
 pub struct FnSig<'hir> {
     pub header: FnHeader,
     pub decl: &'hir FnDecl<'hir>,
+    pub span: Span,
 }
 
 // The bodies for items are stored "out of line", in a separate
index 978f73760ecb5e6eb1cc74e7789acaa527f4947b..acf6847c014f14e6a2461f7be547aa26d5f2d1ed 100644 (file)
@@ -7,8 +7,6 @@
 //! * Traits that represent operators; e.g., `Add`, `Sub`, `Index`.
 //! * Functions called by the compiler itself.
 
-pub use self::LangItem::*;
-
 use crate::def_id::DefId;
 use crate::{MethodKind, Target};
 
@@ -57,14 +55,14 @@ impl LangItem {
             /// that is `#[lang = "eq"]` would result in `sym::eq`.
             pub fn name(self) -> Symbol {
                 match self {
-                    $( $variant => $name, )*
+                    $( LangItem::$variant => $name, )*
                 }
             }
 
             pub fn group(self) -> Option<LangItemGroup> {
                 use LangItemGroup::*;
                 match self {
-                    $( $variant => expand_group!($($group)*), )*
+                    $( LangItem::$variant => expand_group!($($group)*), )*
                 }
             }
         }
@@ -87,7 +85,7 @@ pub fn new() -> Self {
                 fn init_none(_: LangItem) -> Option<DefId> { None }
 
                 Self {
-                    items: vec![$(init_none($variant)),*],
+                    items: vec![$(init_none(LangItem::$variant)),*],
                     missing: Vec::new(),
                     groups: [vec![]; NUM_GROUPS],
                 }
@@ -114,7 +112,7 @@ pub fn group(&self, group: LangItemGroup) -> &[DefId] {
                 /// exists.
                 #[allow(dead_code)]
                 pub fn $method(&self) -> Option<DefId> {
-                    self.items[$variant as usize]
+                    self.items[LangItem::$variant as usize]
                 }
             )*
         }
@@ -123,7 +121,7 @@ pub fn $method(&self) -> Option<DefId> {
             /// A mapping from the name of the lang item to its order and the form it must be of.
             pub static ref ITEM_REFS: FxHashMap<Symbol, (usize, Target)> = {
                 let mut item_refs = FxHashMap::default();
-                $( item_refs.insert($name, ($variant as usize, $target)); )*
+                $( item_refs.insert($name, (LangItem::$variant as usize, $target)); )*
                 item_refs
             };
         }
@@ -161,179 +159,176 @@ pub fn extract<'a, F>(check_name: F, attrs: &'a [ast::Attribute]) -> Option<(Sym
 }
 
 language_item_table! {
-//  Variant name,                  Name,                    Method name,             Target;
-    BoolImplItem,                  sym::bool,               bool_impl,               Target::Impl;
-    CharImplItem,                  sym::char,               char_impl,               Target::Impl;
-    StrImplItem,                   sym::str,                str_impl,                Target::Impl;
-    ArrayImplItem,                 sym::array,              array_impl,              Target::Impl;
-    SliceImplItem,                 sym::slice,              slice_impl,              Target::Impl;
-    SliceU8ImplItem,               sym::slice_u8,           slice_u8_impl,           Target::Impl;
-    StrAllocImplItem,              sym::str_alloc,          str_alloc_impl,          Target::Impl;
-    SliceAllocImplItem,            sym::slice_alloc,        slice_alloc_impl,        Target::Impl;
-    SliceU8AllocImplItem,          sym::slice_u8_alloc,     slice_u8_alloc_impl,     Target::Impl;
-    ConstPtrImplItem,              sym::const_ptr,          const_ptr_impl,          Target::Impl;
-    MutPtrImplItem,                sym::mut_ptr,            mut_ptr_impl,            Target::Impl;
-    ConstSlicePtrImplItem,         sym::const_slice_ptr,    const_slice_ptr_impl,    Target::Impl;
-    MutSlicePtrImplItem,           sym::mut_slice_ptr,      mut_slice_ptr_impl,      Target::Impl;
-    I8ImplItem,                    sym::i8,                 i8_impl,                 Target::Impl;
-    I16ImplItem,                   sym::i16,                i16_impl,                Target::Impl;
-    I32ImplItem,                   sym::i32,                i32_impl,                Target::Impl;
-    I64ImplItem,                   sym::i64,                i64_impl,                Target::Impl;
-    I128ImplItem,                  sym::i128,               i128_impl,               Target::Impl;
-    IsizeImplItem,                 sym::isize,              isize_impl,              Target::Impl;
-    U8ImplItem,                    sym::u8,                 u8_impl,                 Target::Impl;
-    U16ImplItem,                   sym::u16,                u16_impl,                Target::Impl;
-    U32ImplItem,                   sym::u32,                u32_impl,                Target::Impl;
-    U64ImplItem,                   sym::u64,                u64_impl,                Target::Impl;
-    U128ImplItem,                  sym::u128,               u128_impl,               Target::Impl;
-    UsizeImplItem,                 sym::usize,              usize_impl,              Target::Impl;
-    F32ImplItem,                   sym::f32,                f32_impl,                Target::Impl;
-    F64ImplItem,                   sym::f64,                f64_impl,                Target::Impl;
-    F32RuntimeImplItem,            sym::f32_runtime,        f32_runtime_impl,        Target::Impl;
-    F64RuntimeImplItem,            sym::f64_runtime,        f64_runtime_impl,        Target::Impl;
-
-    SizedTraitLangItem,            sym::sized,              sized_trait,             Target::Trait;
-    UnsizeTraitLangItem,           sym::unsize,             unsize_trait,            Target::Trait;
-    // trait injected by #[derive(PartialEq)], (i.e. "Partial EQ").
-    StructuralPeqTraitLangItem,    sym::structural_peq,     structural_peq_trait,    Target::Trait;
-    // trait injected by #[derive(Eq)], (i.e. "Total EQ"; no, I will not apologize).
-    StructuralTeqTraitLangItem,    sym::structural_teq,     structural_teq_trait,    Target::Trait;
-    CopyTraitLangItem,             sym::copy,               copy_trait,              Target::Trait;
-    CloneTraitLangItem,            sym::clone,              clone_trait,             Target::Trait;
-    SyncTraitLangItem,             sym::sync,               sync_trait,              Target::Trait;
-    DiscriminantKindTraitLangItem, sym::discriminant_kind,  discriminant_kind_trait, Target::Trait;
+//  Variant name,            Name,                    Method name,             Target;
+    Bool,                    sym::bool,                bool_impl,                  Target::Impl;
+    Char,                    sym::char,                char_impl,                  Target::Impl;
+    Str,                     sym::str,                 str_impl,                   Target::Impl;
+    Array,                   sym::array,               array_impl,                 Target::Impl;
+    Slice,                   sym::slice,               slice_impl,                 Target::Impl;
+    SliceU8,                 sym::slice_u8,            slice_u8_impl,              Target::Impl;
+    StrAlloc,                sym::str_alloc,           str_alloc_impl,             Target::Impl;
+    SliceAlloc,              sym::slice_alloc,         slice_alloc_impl,           Target::Impl;
+    SliceU8Alloc,            sym::slice_u8_alloc,      slice_u8_alloc_impl,        Target::Impl;
+    ConstPtr,                sym::const_ptr,           const_ptr_impl,             Target::Impl;
+    MutPtr,                  sym::mut_ptr,             mut_ptr_impl,               Target::Impl;
+    ConstSlicePtr,           sym::const_slice_ptr,     const_slice_ptr_impl,       Target::Impl;
+    MutSlicePtr,             sym::mut_slice_ptr,       mut_slice_ptr_impl,         Target::Impl;
+    I8,                      sym::i8,                  i8_impl,                    Target::Impl;
+    I16,                     sym::i16,                 i16_impl,                   Target::Impl;
+    I32,                     sym::i32,                 i32_impl,                   Target::Impl;
+    I64,                     sym::i64,                 i64_impl,                   Target::Impl;
+    I128,                    sym::i128,                i128_impl,                  Target::Impl;
+    Isize,                   sym::isize,               isize_impl,                 Target::Impl;
+    U8,                      sym::u8,                  u8_impl,                    Target::Impl;
+    U16,                     sym::u16,                 u16_impl,                   Target::Impl;
+    U32,                     sym::u32,                 u32_impl,                   Target::Impl;
+    U64,                     sym::u64,                 u64_impl,                   Target::Impl;
+    U128,                    sym::u128,                u128_impl,                  Target::Impl;
+    Usize,                   sym::usize,               usize_impl,                 Target::Impl;
+    F32,                     sym::f32,                 f32_impl,                   Target::Impl;
+    F64,                     sym::f64,                 f64_impl,                   Target::Impl;
+    F32Runtime,              sym::f32_runtime,         f32_runtime_impl,           Target::Impl;
+    F64Runtime,              sym::f64_runtime,         f64_runtime_impl,           Target::Impl;
+
+    Sized,                   sym::sized,               sized_trait,                Target::Trait;
+    Unsize,                  sym::unsize,              unsize_trait,               Target::Trait;
+    // Trait injected by #[derive(PartialEq)], (i.e. "Partial EQ").
+    StructuralPeq,           sym::structural_peq,      structural_peq_trait,       Target::Trait;
+    // Trait injected by #[derive(Eq)], (i.e. "Total EQ"; no, I will not apologize).
+    StructuralTeq,           sym::structural_teq,      structural_teq_trait,       Target::Trait;
+    Copy,                    sym::copy,                copy_trait,                 Target::Trait;
+    Clone,                   sym::clone,               clone_trait,                Target::Trait;
+    Sync,                    sym::sync,                sync_trait,                 Target::Trait;
+    DiscriminantKind,        sym::discriminant_kind,   discriminant_kind_trait,    Target::Trait;
     // The associated item of `trait DiscriminantKind`.
-    DiscriminantTypeLangItem,      sym::discriminant_type,  discriminant_type,       Target::AssocTy;
-
-    FreezeTraitLangItem,           sym::freeze,             freeze_trait,            Target::Trait;
-
-    DropTraitLangItem,             sym::drop,               drop_trait,              Target::Trait;
-
-    CoerceUnsizedTraitLangItem,    sym::coerce_unsized,     coerce_unsized_trait,    Target::Trait;
-    DispatchFromDynTraitLangItem,  sym::dispatch_from_dyn,  dispatch_from_dyn_trait, Target::Trait;
-
-    AddTraitLangItem(Op),          sym::add,                add_trait,               Target::Trait;
-    SubTraitLangItem(Op),          sym::sub,                sub_trait,               Target::Trait;
-    MulTraitLangItem(Op),          sym::mul,                mul_trait,               Target::Trait;
-    DivTraitLangItem(Op),          sym::div,                div_trait,               Target::Trait;
-    RemTraitLangItem(Op),          sym::rem,                rem_trait,               Target::Trait;
-    NegTraitLangItem(Op),          sym::neg,                neg_trait,               Target::Trait;
-    NotTraitLangItem(Op),          sym::not,                not_trait,               Target::Trait;
-    BitXorTraitLangItem(Op),       sym::bitxor,             bitxor_trait,            Target::Trait;
-    BitAndTraitLangItem(Op),       sym::bitand,             bitand_trait,            Target::Trait;
-    BitOrTraitLangItem(Op),        sym::bitor,              bitor_trait,             Target::Trait;
-    ShlTraitLangItem(Op),          sym::shl,                shl_trait,               Target::Trait;
-    ShrTraitLangItem(Op),          sym::shr,                shr_trait,               Target::Trait;
-    AddAssignTraitLangItem(Op),    sym::add_assign,         add_assign_trait,        Target::Trait;
-    SubAssignTraitLangItem(Op),    sym::sub_assign,         sub_assign_trait,        Target::Trait;
-    MulAssignTraitLangItem(Op),    sym::mul_assign,         mul_assign_trait,        Target::Trait;
-    DivAssignTraitLangItem(Op),    sym::div_assign,         div_assign_trait,        Target::Trait;
-    RemAssignTraitLangItem(Op),    sym::rem_assign,         rem_assign_trait,        Target::Trait;
-    BitXorAssignTraitLangItem(Op), sym::bitxor_assign,      bitxor_assign_trait,     Target::Trait;
-    BitAndAssignTraitLangItem(Op), sym::bitand_assign,      bitand_assign_trait,     Target::Trait;
-    BitOrAssignTraitLangItem(Op),  sym::bitor_assign,       bitor_assign_trait,      Target::Trait;
-    ShlAssignTraitLangItem(Op),    sym::shl_assign,         shl_assign_trait,        Target::Trait;
-    ShrAssignTraitLangItem(Op),    sym::shr_assign,         shr_assign_trait,        Target::Trait;
-    IndexTraitLangItem(Op),        sym::index,              index_trait,             Target::Trait;
-    IndexMutTraitLangItem(Op),     sym::index_mut,          index_mut_trait,         Target::Trait;
-
-    UnsafeCellTypeLangItem,        sym::unsafe_cell,        unsafe_cell_type,        Target::Struct;
-    VaListTypeLangItem,            sym::va_list,            va_list,                 Target::Struct;
-
-    DerefTraitLangItem,            sym::deref,              deref_trait,             Target::Trait;
-    DerefMutTraitLangItem,         sym::deref_mut,          deref_mut_trait,         Target::Trait;
-    ReceiverTraitLangItem,         sym::receiver,           receiver_trait,          Target::Trait;
-
-    FnTraitLangItem,               kw::Fn,                  fn_trait,                Target::Trait;
-    FnMutTraitLangItem,            sym::fn_mut,             fn_mut_trait,            Target::Trait;
-    FnOnceTraitLangItem,           sym::fn_once,            fn_once_trait,           Target::Trait;
-
-    FnOnceOutputLangItem,          sym::fn_once_output,     fn_once_output,          Target::AssocTy;
-
-    FutureTraitLangItem,           sym::future_trait,       future_trait,            Target::Trait;
-    GeneratorStateLangItem,        sym::generator_state,    gen_state,               Target::Enum;
-    GeneratorTraitLangItem,        sym::generator,          gen_trait,               Target::Trait;
-    UnpinTraitLangItem,            sym::unpin,              unpin_trait,             Target::Trait;
-    PinTypeLangItem,               sym::pin,                pin_type,                Target::Struct;
-
-    // Don't be fooled by the naming here: this lang item denotes `PartialEq`, not `Eq`.
-    EqTraitLangItem,               sym::eq,                 eq_trait,                Target::Trait;
-    PartialOrdTraitLangItem,       sym::partial_ord,        partial_ord_trait,       Target::Trait;
-
-    // A number of panic-related lang items. The `panic` item corresponds to
-    // divide-by-zero and various panic cases with `match`. The
-    // `panic_bounds_check` item is for indexing arrays.
+    Discriminant,            sym::discriminant_type,   discriminant_type,          Target::AssocTy;
+
+    Freeze,                  sym::freeze,              freeze_trait,               Target::Trait;
+
+    Drop,                    sym::drop,                drop_trait,                 Target::Trait;
+
+    CoerceUnsized,           sym::coerce_unsized,      coerce_unsized_trait,       Target::Trait;
+    DispatchFromDyn,         sym::dispatch_from_dyn,   dispatch_from_dyn_trait,    Target::Trait;
+
+    Add(Op),                 sym::add,                 add_trait,                  Target::Trait;
+    Sub(Op),                 sym::sub,                 sub_trait,                  Target::Trait;
+    Mul(Op),                 sym::mul,                 mul_trait,                  Target::Trait;
+    Div(Op),                 sym::div,                 div_trait,                  Target::Trait;
+    Rem(Op),                 sym::rem,                 rem_trait,                  Target::Trait;
+    Neg(Op),                 sym::neg,                 neg_trait,                  Target::Trait;
+    Not(Op),                 sym::not,                 not_trait,                  Target::Trait;
+    BitXor(Op),              sym::bitxor,              bitxor_trait,               Target::Trait;
+    BitAnd(Op),              sym::bitand,              bitand_trait,               Target::Trait;
+    BitOr(Op),               sym::bitor,               bitor_trait,                Target::Trait;
+    Shl(Op),                 sym::shl,                 shl_trait,                  Target::Trait;
+    Shr(Op),                 sym::shr,                 shr_trait,                  Target::Trait;
+    AddAssign(Op),           sym::add_assign,          add_assign_trait,           Target::Trait;
+    SubAssign(Op),           sym::sub_assign,          sub_assign_trait,           Target::Trait;
+    MulAssign(Op),           sym::mul_assign,          mul_assign_trait,           Target::Trait;
+    DivAssign(Op),           sym::div_assign,          div_assign_trait,           Target::Trait;
+    RemAssign(Op),           sym::rem_assign,          rem_assign_trait,           Target::Trait;
+    BitXorAssign(Op),        sym::bitxor_assign,       bitxor_assign_trait,        Target::Trait;
+    BitAndAssign(Op),        sym::bitand_assign,       bitand_assign_trait,        Target::Trait;
+    BitOrAssign(Op),         sym::bitor_assign,        bitor_assign_trait,         Target::Trait;
+    ShlAssign(Op),           sym::shl_assign,          shl_assign_trait,           Target::Trait;
+    ShrAssign(Op),           sym::shr_assign,          shr_assign_trait,           Target::Trait;
+    Index(Op),               sym::index,               index_trait,                Target::Trait;
+    IndexMut(Op),            sym::index_mut,           index_mut_trait,            Target::Trait;
+
+    UnsafeCell,              sym::unsafe_cell,         unsafe_cell_type,           Target::Struct;
+    VaList,                  sym::va_list,             va_list,                    Target::Struct;
+
+    Deref,                   sym::deref,               deref_trait,                Target::Trait;
+    DerefMut,                sym::deref_mut,           deref_mut_trait,            Target::Trait;
+    Receiver,                sym::receiver,            receiver_trait,             Target::Trait;
+
+    Fn,                      kw::Fn,                   fn_trait,                   Target::Trait;
+    FnMut,                   sym::fn_mut,              fn_mut_trait,               Target::Trait;
+    FnOnce,                  sym::fn_once,             fn_once_trait,              Target::Trait;
+
+    FnOnceOutput,            sym::fn_once_output,      fn_once_output,             Target::AssocTy;
+
+    Future,                  sym::future_trait,        future_trait,               Target::Trait;
+    GeneratorState,          sym::generator_state,     gen_state,                  Target::Enum;
+    Generator,               sym::generator,           gen_trait,                  Target::Trait;
+    Unpin,                   sym::unpin,               unpin_trait,                Target::Trait;
+    Pin,                     sym::pin,                 pin_type,                   Target::Struct;
+
+    PartialEq,               sym::eq,                  eq_trait,                   Target::Trait;
+    PartialOrd,              sym::partial_ord,         partial_ord_trait,          Target::Trait;
+
+    // A number of panic-related lang items. The `panic` item corresponds to divide-by-zero and
+    // various panic cases with `match`. The `panic_bounds_check` item is for indexing arrays.
     //
-    // The `begin_unwind` lang item has a predefined symbol name and is sort of
-    // a "weak lang item" in the sense that a crate is not required to have it
-    // defined to use it, but a final product is required to define it
-    // somewhere. Additionally, there are restrictions on crates that use a weak
-    // lang item, but do not have it defined.
-    PanicFnLangItem,               sym::panic,              panic_fn,                Target::Fn;
-    PanicBoundsCheckFnLangItem,    sym::panic_bounds_check, panic_bounds_check_fn,   Target::Fn;
-    PanicInfoLangItem,             sym::panic_info,         panic_info,              Target::Struct;
-    PanicLocationLangItem,         sym::panic_location,     panic_location,          Target::Struct;
-    PanicImplLangItem,             sym::panic_impl,         panic_impl,              Target::Fn;
-    // Libstd panic entry point. Necessary for const eval to be able to catch it
-    BeginPanicFnLangItem,          sym::begin_panic,        begin_panic_fn,          Target::Fn;
+    // The `begin_unwind` lang item has a predefined symbol name and is sort of a "weak lang item"
+    // in the sense that a crate is not required to have it defined to use it, but a final product
+    // is required to define it somewhere. Additionally, there are restrictions on crates that use
+    // a weak lang item, but do not have it defined.
+    Panic,                   sym::panic,               panic_fn,                   Target::Fn;
+    PanicBoundsCheck,        sym::panic_bounds_check,  panic_bounds_check_fn,      Target::Fn;
+    PanicInfo,               sym::panic_info,          panic_info,                 Target::Struct;
+    PanicLocation,           sym::panic_location,      panic_location,             Target::Struct;
+    PanicImpl,               sym::panic_impl,          panic_impl,                 Target::Fn;
+    // libstd panic entry point. Necessary for const eval to be able to catch it
+    BeginPanic,              sym::begin_panic,         begin_panic_fn,             Target::Fn;
 
-    ExchangeMallocFnLangItem,      sym::exchange_malloc,    exchange_malloc_fn,      Target::Fn;
-    BoxFreeFnLangItem,             sym::box_free,           box_free_fn,             Target::Fn;
-    DropInPlaceFnLangItem,         sym::drop_in_place,      drop_in_place_fn,        Target::Fn;
-    OomLangItem,                   sym::oom,                oom,                     Target::Fn;
-    AllocLayoutLangItem,           sym::alloc_layout,       alloc_layout,            Target::Struct;
+    ExchangeMalloc,          sym::exchange_malloc,     exchange_malloc_fn,         Target::Fn;
+    BoxFree,                 sym::box_free,            box_free_fn,                Target::Fn;
+    DropInPlace,             sym::drop_in_place,       drop_in_place_fn,           Target::Fn;
+    Oom,                     sym::oom,                 oom,                        Target::Fn;
+    AllocLayout,             sym::alloc_layout,        alloc_layout,               Target::Struct;
 
-    StartFnLangItem,               sym::start,              start_fn,                Target::Fn;
+    Start,                   sym::start,               start_fn,                   Target::Fn;
 
-    EhPersonalityLangItem,         sym::eh_personality,     eh_personality,          Target::Fn;
-    EhCatchTypeinfoLangItem,       sym::eh_catch_typeinfo,  eh_catch_typeinfo,       Target::Static;
+    EhPersonality,           sym::eh_personality,      eh_personality,             Target::Fn;
+    EhCatchTypeinfo,         sym::eh_catch_typeinfo,   eh_catch_typeinfo,          Target::Static;
 
-    OwnedBoxLangItem,              sym::owned_box,          owned_box,               Target::Struct;
+    OwnedBox,                sym::owned_box,           owned_box,                  Target::Struct;
 
-    PhantomDataItem,               sym::phantom_data,       phantom_data,            Target::Struct;
+    PhantomData,             sym::phantom_data,        phantom_data,               Target::Struct;
 
-    ManuallyDropItem,              sym::manually_drop,      manually_drop,           Target::Struct;
+    ManuallyDrop,            sym::manually_drop,       manually_drop,              Target::Struct;
 
-    MaybeUninitLangItem,           sym::maybe_uninit,       maybe_uninit,            Target::Union;
+    MaybeUninit,             sym::maybe_uninit,        maybe_uninit,               Target::Union;
 
     // Align offset for stride != 1; must not panic.
-    AlignOffsetLangItem,           sym::align_offset,       align_offset_fn,         Target::Fn;
+    AlignOffset,             sym::align_offset,        align_offset_fn,            Target::Fn;
 
-    TerminationTraitLangItem,      sym::termination,        termination,             Target::Trait;
+    Termination,             sym::termination,         termination,                Target::Trait;
 
-    TryTraitLangItem,              kw::Try,                 try_trait,               Target::Trait;
+    Try,                     kw::Try,                  try_trait,                  Target::Trait;
 
     // Language items from AST lowering
-    TryFromError,                  sym::from_error,         from_error_fn,           Target::Method(MethodKind::Trait { body: false });
-    TryFromOk,                     sym::from_ok,            from_ok_fn,              Target::Method(MethodKind::Trait { body: false });
-    TryIntoResult,                 sym::into_result,        into_result_fn,          Target::Method(MethodKind::Trait { body: false });
+    TryFromError,            sym::from_error,          from_error_fn,              Target::Method(MethodKind::Trait { body: false });
+    TryFromOk,               sym::from_ok,             from_ok_fn,                 Target::Method(MethodKind::Trait { body: false });
+    TryIntoResult,           sym::into_result,         into_result_fn,             Target::Method(MethodKind::Trait { body: false });
 
-    PollReady,                     sym::Ready,              poll_ready_variant,      Target::Variant;
-    PollPending,                   sym::Pending,            poll_pending_variant,    Target::Variant;
+    PollReady,               sym::Ready,               poll_ready_variant,         Target::Variant;
+    PollPending,             sym::Pending,             poll_pending_variant,       Target::Variant;
 
-    FromGenerator,                 sym::from_generator,     from_generator_fn,       Target::Fn;
-    GetContext,                    sym::get_context,        get_context_fn,          Target::Fn;
+    FromGenerator,           sym::from_generator,      from_generator_fn,          Target::Fn;
+    GetContext,              sym::get_context,         get_context_fn,             Target::Fn;
 
-    FuturePoll,                    sym::poll,               future_poll_fn,          Target::Method(MethodKind::Trait { body: false });
+    FuturePoll,              sym::poll,                future_poll_fn,             Target::Method(MethodKind::Trait { body: false });
 
-    FromFrom,                      sym::from,               from_fn,                 Target::Method(MethodKind::Trait { body: false });
+    FromFrom,                sym::from,                from_fn,                    Target::Method(MethodKind::Trait { body: false });
 
-    OptionSome,                    sym::Some,               option_some_variant,     Target::Variant;
-    OptionNone,                    sym::None,               option_none_variant,     Target::Variant;
+    OptionSome,              sym::Some,                option_some_variant,        Target::Variant;
+    OptionNone,              sym::None,                option_none_variant,        Target::Variant;
 
-    ResultOk,                      sym::Ok,                 result_ok_variant,       Target::Variant;
-    ResultErr,                     sym::Err,                result_err_variant,      Target::Variant;
+    ResultOk,                sym::Ok,                  result_ok_variant,          Target::Variant;
+    ResultErr,               sym::Err,                 result_err_variant,         Target::Variant;
 
-    IntoIterIntoIter,              sym::into_iter,          into_iter_fn,            Target::Method(MethodKind::Trait { body: false });
-    IteratorNext,                  sym::next,               next_fn,                 Target::Method(MethodKind::Trait { body: false});
+    IntoIterIntoIter,        sym::into_iter,           into_iter_fn,               Target::Method(MethodKind::Trait { body: false });
+    IteratorNext,            sym::next,                next_fn,                    Target::Method(MethodKind::Trait { body: false});
 
-    PinNewUnchecked,               sym::new_unchecked,      new_unchecked_fn,        Target::Method(MethodKind::Inherent);
+    PinNewUnchecked,         sym::new_unchecked,       new_unchecked_fn,           Target::Method(MethodKind::Inherent);
 
-    RangeFrom,                     sym::RangeFrom,           range_from_struct,          Target::Struct;
-    RangeFull,                     sym::RangeFull,           range_full_struct,          Target::Struct;
-    RangeInclusiveStruct,          sym::RangeInclusive,      range_inclusive_struct,     Target::Struct;
-    RangeInclusiveNew,             sym::range_inclusive_new, range_inclusive_new_method, Target::Method(MethodKind::Inherent);
-    Range,                         sym::Range,               range_struct,               Target::Struct;
-    RangeToInclusive,              sym::RangeToInclusive,    range_to_inclusive_struct,  Target::Struct;
-    RangeTo,                       sym::RangeTo,             range_to_struct,            Target::Struct;
+    RangeFrom,               sym::RangeFrom,           range_from_struct,          Target::Struct;
+    RangeFull,               sym::RangeFull,           range_full_struct,          Target::Struct;
+    RangeInclusiveStruct,    sym::RangeInclusive,      range_inclusive_struct,     Target::Struct;
+    RangeInclusiveNew,       sym::range_inclusive_new, range_inclusive_new_method, Target::Method(MethodKind::Inherent);
+    Range,                   sym::Range,               range_struct,               Target::Struct;
+    RangeToInclusive,        sym::RangeToInclusive,    range_to_inclusive_struct,  Target::Struct;
+    RangeTo,                 sym::RangeTo,             range_to_struct,            Target::Struct;
 }
index 76b95c696f7ca0dcb1e2af38233b467cdfba9cf8..74e2a90262ce60a3cec9c410ff9ba46d5774f0c8 100644 (file)
@@ -15,7 +15,7 @@ macro_rules! weak_lang_items {
 lazy_static! {
     pub static ref WEAK_ITEMS_REFS: FxHashMap<Symbol, LangItem> = {
         let mut map = FxHashMap::default();
-        $(map.insert(sym::$name, lang_items::$item);)*
+        $(map.insert(sym::$name, LangItem::$item);)*
         map
     };
 }
@@ -46,7 +46,7 @@ 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;
-    oom,                OomLangItem,                rust_oom;
+    panic_impl,         PanicImpl,          rust_begin_unwind;
+    eh_personality,     EhPersonality,      rust_eh_personality;
+    oom,                Oom,                rust_oom;
 }
index 2b2c42207e48b6b62117b10b0023ae53a3dfac0b..8212958510a6f88bb5a672b35c5e1cccdb583a69 100644 (file)
@@ -609,6 +609,7 @@ fn note_error_origin(
                 err.span_label(span, "expected due to this");
             }
             ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
+                semi_span,
                 source,
                 ref prior_arms,
                 last_ty,
@@ -663,6 +664,14 @@ fn note_error_origin(
                             format!("this and all prior arms are found to be of type `{}`", t),
                         );
                     }
+                    if let Some(sp) = semi_span {
+                        err.span_suggestion_short(
+                            sp,
+                            "consider removing this semicolon",
+                            String::new(),
+                            Applicability::MachineApplicable,
+                        );
+                    }
                 }
             },
             ObligationCauseCode::IfExpression(box IfExpressionCause { then, outer, semicolon }) => {
index f135bde7f8337a0b12f488f5fd52ec2cfd583233..e05041d88460e3cf40fbd010f42f295fd8a12ec6 100644 (file)
@@ -22,7 +22,6 @@
 #![feature(extend_one)]
 #![feature(never_type)]
 #![feature(or_patterns)]
-#![feature(range_is_empty)]
 #![feature(in_band_lifetimes)]
 #![feature(crate_visibility_modifier)]
 #![recursion_limit = "512"] // For rustdoc
index 950771f0a692710021dc7e29c18736fdbbe3ea0b..28b56f6fef4b80861b86ccc76619f3bd82be76f4 100644 (file)
@@ -19,3 +19,6 @@ name = "rustc_lexer"
 # Note that this crate purposefully does not depend on other rustc crates
 [dependencies]
 unicode-xid = "0.2.0"
+
+[dev-dependencies]
+expect-test = "0.1"
index 2d80ca5a4de10449f99fbe4772dd42dc0c6ef62b..b7d6194cd77cf956d16ede3087c5b8a0a1ae4517 100644 (file)
@@ -35,6 +35,7 @@
 /// Parsed token.
 /// It doesn't contain information about data that has been parsed,
 /// only the type of the token and its size.
+#[derive(Debug)]
 pub struct Token {
     pub kind: TokenKind,
     pub len: usize,
index e6acc26ec2f343e6645755f6032eff88e8e385d3..a1ea5ceb1f61283a2c5a5722f27bd1d9593552be 100644 (file)
-#[cfg(test)]
-mod tests {
-    use crate::*;
-
-    fn check_raw_str(s: &str, expected_hashes: u16, expected_err: Option<RawStrError>) {
-        let s = &format!("r{}", s);
-        let mut cursor = Cursor::new(s);
-        cursor.bump();
-        let (n_hashes, err) = cursor.raw_double_quoted_string(0);
-        assert_eq!(n_hashes, expected_hashes);
-        assert_eq!(err, expected_err);
-    }
-
-    #[test]
-    fn test_naked_raw_str() {
-        check_raw_str(r#""abc""#, 0, None);
-    }
-
-    #[test]
-    fn test_raw_no_start() {
-        check_raw_str(r##""abc"#"##, 0, None);
-    }
-
-    #[test]
-    fn test_too_many_terminators() {
-        // this error is handled in the parser later
-        check_raw_str(r###"#"abc"##"###, 1, None);
-    }
-
-    #[test]
-    fn test_unterminated() {
-        check_raw_str(
-            r#"#"abc"#,
-            1,
-            Some(RawStrError::NoTerminator {
-                expected: 1,
-                found: 0,
-                possible_terminator_offset: None,
-            }),
-        );
-        check_raw_str(
-            r###"##"abc"#"###,
-            2,
-            Some(RawStrError::NoTerminator {
-                expected: 2,
-                found: 1,
-                possible_terminator_offset: Some(7),
-            }),
-        );
-        // We're looking for "# not just any #
-        check_raw_str(
-            r###"##"abc#"###,
-            2,
-            Some(RawStrError::NoTerminator {
-                expected: 2,
-                found: 0,
-                possible_terminator_offset: None,
-            }),
-        )
-    }
-
-    #[test]
-    fn test_invalid_start() {
-        check_raw_str(r##"#~"abc"#"##, 1, Some(RawStrError::InvalidStarter { bad_char: '~' }));
-    }
-
-    #[test]
-    fn test_unterminated_no_pound() {
-        // https://github.com/rust-lang/rust/issues/70677
-        check_raw_str(
-            r#"""#,
-            0,
-            Some(RawStrError::NoTerminator {
-                expected: 0,
-                found: 0,
-                possible_terminator_offset: None,
-            }),
-        );
-    }
-
-    #[test]
-    fn test_valid_shebang() {
-        // https://github.com/rust-lang/rust/issues/70528
-        let input = "#!/usr/bin/rustrun\nlet x = 5;";
-        assert_eq!(strip_shebang(input), Some(18));
-    }
-
-    #[test]
-    fn test_invalid_shebang_valid_rust_syntax() {
-        // https://github.com/rust-lang/rust/issues/70528
-        let input = "#!    [bad_attribute]";
-        assert_eq!(strip_shebang(input), None);
-    }
-
-    #[test]
-    fn test_shebang_second_line() {
-        // Because shebangs are interpreted by the kernel, they must be on the first line
-        let input = "\n#!/bin/bash";
-        assert_eq!(strip_shebang(input), None);
-    }
-
-    #[test]
-    fn test_shebang_space() {
-        let input = "#!    /bin/bash";
-        assert_eq!(strip_shebang(input), Some(input.len()));
-    }
-
-    #[test]
-    fn test_shebang_empty_shebang() {
-        let input = "#!    \n[attribute(foo)]";
-        assert_eq!(strip_shebang(input), None);
-    }
-
-    #[test]
-    fn test_invalid_shebang_comment() {
-        let input = "#!//bin/ami/a/comment\n[";
-        assert_eq!(strip_shebang(input), None)
-    }
-
-    #[test]
-    fn test_invalid_shebang_another_comment() {
-        let input = "#!/*bin/ami/a/comment*/\n[attribute";
-        assert_eq!(strip_shebang(input), None)
-    }
-
-    #[test]
-    fn test_shebang_valid_rust_after() {
-        let input = "#!/*bin/ami/a/comment*/\npub fn main() {}";
-        assert_eq!(strip_shebang(input), Some(23))
-    }
-
-    #[test]
-    fn test_shebang_followed_by_attrib() {
-        let input = "#!/bin/rust-scripts\n#![allow_unused(true)]";
-        assert_eq!(strip_shebang(input), Some(19));
-    }
+use super::*;
+
+use expect_test::{expect, Expect};
+
+fn check_raw_str(s: &str, expected_hashes: u16, expected_err: Option<RawStrError>) {
+    let s = &format!("r{}", s);
+    let mut cursor = Cursor::new(s);
+    cursor.bump();
+    let (n_hashes, err) = cursor.raw_double_quoted_string(0);
+    assert_eq!(n_hashes, expected_hashes);
+    assert_eq!(err, expected_err);
+}
+
+#[test]
+fn test_naked_raw_str() {
+    check_raw_str(r#""abc""#, 0, None);
+}
+
+#[test]
+fn test_raw_no_start() {
+    check_raw_str(r##""abc"#"##, 0, None);
+}
+
+#[test]
+fn test_too_many_terminators() {
+    // this error is handled in the parser later
+    check_raw_str(r###"#"abc"##"###, 1, None);
+}
+
+#[test]
+fn test_unterminated() {
+    check_raw_str(
+        r#"#"abc"#,
+        1,
+        Some(RawStrError::NoTerminator { expected: 1, found: 0, possible_terminator_offset: None }),
+    );
+    check_raw_str(
+        r###"##"abc"#"###,
+        2,
+        Some(RawStrError::NoTerminator {
+            expected: 2,
+            found: 1,
+            possible_terminator_offset: Some(7),
+        }),
+    );
+    // We're looking for "# not just any #
+    check_raw_str(
+        r###"##"abc#"###,
+        2,
+        Some(RawStrError::NoTerminator { expected: 2, found: 0, possible_terminator_offset: None }),
+    )
+}
+
+#[test]
+fn test_invalid_start() {
+    check_raw_str(r##"#~"abc"#"##, 1, Some(RawStrError::InvalidStarter { bad_char: '~' }));
+}
+
+#[test]
+fn test_unterminated_no_pound() {
+    // https://github.com/rust-lang/rust/issues/70677
+    check_raw_str(
+        r#"""#,
+        0,
+        Some(RawStrError::NoTerminator { expected: 0, found: 0, possible_terminator_offset: None }),
+    );
+}
+
+#[test]
+fn test_valid_shebang() {
+    // https://github.com/rust-lang/rust/issues/70528
+    let input = "#!/usr/bin/rustrun\nlet x = 5;";
+    assert_eq!(strip_shebang(input), Some(18));
+}
+
+#[test]
+fn test_invalid_shebang_valid_rust_syntax() {
+    // https://github.com/rust-lang/rust/issues/70528
+    let input = "#!    [bad_attribute]";
+    assert_eq!(strip_shebang(input), None);
+}
+
+#[test]
+fn test_shebang_second_line() {
+    // Because shebangs are interpreted by the kernel, they must be on the first line
+    let input = "\n#!/bin/bash";
+    assert_eq!(strip_shebang(input), None);
+}
+
+#[test]
+fn test_shebang_space() {
+    let input = "#!    /bin/bash";
+    assert_eq!(strip_shebang(input), Some(input.len()));
+}
+
+#[test]
+fn test_shebang_empty_shebang() {
+    let input = "#!    \n[attribute(foo)]";
+    assert_eq!(strip_shebang(input), None);
+}
+
+#[test]
+fn test_invalid_shebang_comment() {
+    let input = "#!//bin/ami/a/comment\n[";
+    assert_eq!(strip_shebang(input), None)
+}
+
+#[test]
+fn test_invalid_shebang_another_comment() {
+    let input = "#!/*bin/ami/a/comment*/\n[attribute";
+    assert_eq!(strip_shebang(input), None)
+}
+
+#[test]
+fn test_shebang_valid_rust_after() {
+    let input = "#!/*bin/ami/a/comment*/\npub fn main() {}";
+    assert_eq!(strip_shebang(input), Some(23))
+}
+
+#[test]
+fn test_shebang_followed_by_attrib() {
+    let input = "#!/bin/rust-scripts\n#![allow_unused(true)]";
+    assert_eq!(strip_shebang(input), Some(19));
+}
+
+fn check_lexing(src: &str, expect: Expect) {
+    let actual: String = tokenize(src).map(|token| format!("{:?}\n", token)).collect();
+    expect.assert_eq(&actual)
+}
+
+#[test]
+fn comment_flavors() {
+    check_lexing(
+        r"
+// line
+//// line as well
+/// outer doc line
+//! inner doc line
+/* block */
+/**/
+/*** also block */
+/** outer doc block */
+/*! inner doc block */
+",
+        expect![[r#"
+                Token { kind: Whitespace, len: 1 }
+                Token { kind: LineComment { doc_style: None }, len: 7 }
+                Token { kind: Whitespace, len: 1 }
+                Token { kind: LineComment { doc_style: None }, len: 17 }
+                Token { kind: Whitespace, len: 1 }
+                Token { kind: LineComment { doc_style: Some(Outer) }, len: 18 }
+                Token { kind: Whitespace, len: 1 }
+                Token { kind: LineComment { doc_style: Some(Inner) }, len: 18 }
+                Token { kind: Whitespace, len: 1 }
+                Token { kind: BlockComment { doc_style: None, terminated: true }, len: 11 }
+                Token { kind: Whitespace, len: 1 }
+                Token { kind: BlockComment { doc_style: None, terminated: true }, len: 4 }
+                Token { kind: Whitespace, len: 1 }
+                Token { kind: BlockComment { doc_style: None, terminated: true }, len: 18 }
+                Token { kind: Whitespace, len: 1 }
+                Token { kind: BlockComment { doc_style: Some(Outer), terminated: true }, len: 22 }
+                Token { kind: Whitespace, len: 1 }
+                Token { kind: BlockComment { doc_style: Some(Inner), terminated: true }, len: 22 }
+                Token { kind: Whitespace, len: 1 }
+            "#]],
+    )
 }
index b337bf0a3f9226f7fecb3ccdfc4375a4791fd1b3..4bcf31ef0bfc5e88f818a84235186b1d8a7d29d4 100644 (file)
@@ -40,7 +40,7 @@
 use rustc_hir::{HirId, HirIdSet, Node};
 use rustc_middle::lint::LintDiagnosticBuilder;
 use rustc_middle::ty::subst::{GenericArgKind, Subst};
-use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::ty::{self, layout::LayoutError, Ty, TyCtxt};
 use rustc_session::lint::FutureIncompatibleInfo;
 use rustc_session::Session;
 use rustc_span::edition::Edition;
@@ -2177,11 +2177,17 @@ fn structurally_same_type_impl<'tcx>(
                 let a_kind = &a.kind;
                 let b_kind = &b.kind;
 
-                let compare_layouts = |a, b| -> bool {
-                    let a_layout = &cx.layout_of(a).unwrap().layout.abi;
-                    let b_layout = &cx.layout_of(b).unwrap().layout.abi;
-                    debug!("{:?} == {:?} = {}", a_layout, b_layout, a_layout == b_layout);
-                    a_layout == b_layout
+                let compare_layouts = |a, b| -> Result<bool, LayoutError<'tcx>> {
+                    debug!("compare_layouts({:?}, {:?})", a, b);
+                    let a_layout = &cx.layout_of(a)?.layout.abi;
+                    let b_layout = &cx.layout_of(b)?.layout.abi;
+                    debug!(
+                        "comparing layouts: {:?} == {:?} = {}",
+                        a_layout,
+                        b_layout,
+                        a_layout == b_layout
+                    );
+                    Ok(a_layout == b_layout)
                 };
 
                 #[allow(rustc::usage_of_ty_tykind)]
@@ -2196,11 +2202,19 @@ fn structurally_same_type_impl<'tcx>(
                             let b = b.subst(cx.tcx, b_substs);
                             debug!("Comparing {:?} and {:?}", a, b);
 
+                            // We can immediately rule out these types as structurally same if
+                            // their layouts differ.
+                            match compare_layouts(a, b) {
+                                Ok(false) => return false,
+                                _ => (), // otherwise, continue onto the full, fields comparison
+                            }
+
                             // Grab a flattened representation of all fields.
                             let a_fields = a_def.variants.iter().flat_map(|v| v.fields.iter());
                             let b_fields = b_def.variants.iter().flat_map(|v| v.fields.iter());
-                            compare_layouts(a, b)
-                            && a_fields.eq_by(
+
+                            // Perform a structural comparison for each field.
+                            a_fields.eq_by(
                                 b_fields,
                                 |&ty::FieldDef { did: a_did, .. },
                                  &ty::FieldDef { did: b_did, .. }| {
@@ -2287,13 +2301,13 @@ fn structurally_same_type_impl<'tcx>(
                             if let Some(ty) = crate::types::repr_nullable_ptr(cx, adt, ckind) {
                                 ty == primitive
                             } else {
-                                compare_layouts(a, b)
+                                compare_layouts(a, b).unwrap_or(false)
                             }
                         }
                         // Otherwise, just compare the layouts. This may fail to lint for some
                         // incompatible types, but at the very least, will stop reads into
                         // uninitialised memory.
-                        _ => compare_layouts(a, b),
+                        _ => compare_layouts(a, b).unwrap_or(false),
                     }
                 })
             }
index 21b8080714c1744ca54130adbb6325ece0082bff..25c0b40c495a0c807f84abc8259ed75be07cc03b 100644 (file)
@@ -151,6 +151,12 @@ fn main() {
             continue;
         }
 
+        // Include path contains host directory, replace it with target
+        if is_crossed && flag.starts_with("-I") {
+            cfg.flag(&flag.replace(&host, &target));
+            continue;
+        }
+
         cfg.flag(flag);
     }
 
@@ -189,6 +195,9 @@ fn main() {
 
     if !is_crossed {
         cmd.arg("--system-libs");
+    } else if target.contains("windows-gnu") {
+        println!("cargo:rustc-link-lib=shell32");
+        println!("cargo:rustc-link-lib=uuid");
     }
     cmd.args(&components);
 
index ce19240a009d091f52de29382790ef80f90500b3..bdb53e3f75a40866d347e3f3c279935eb90f7ae5 100644 (file)
@@ -51,51 +51,90 @@ pub unsafe fn symbol<T>(&self, symbol: &str) -> Result<*mut T, String> {
 
 #[cfg(unix)]
 mod dl {
-    use std::ffi::{CStr, CString, OsStr};
+    use std::ffi::{CString, OsStr};
     use std::os::unix::prelude::*;
-    use std::ptr;
-    use std::str;
 
-    pub(super) fn open(filename: &OsStr) -> Result<*mut u8, String> {
-        check_for_errors_in(|| unsafe {
-            let s = CString::new(filename.as_bytes()).unwrap();
-            libc::dlopen(s.as_ptr(), libc::RTLD_LAZY) as *mut u8
-        })
-    }
+    // As of the 2017 revision of the POSIX standard (IEEE 1003.1-2017), it is
+    // implementation-defined whether `dlerror` is thread-safe (in which case it returns the most
+    // recent error in the calling thread) or not thread-safe (in which case it returns the most
+    // recent error in *any* thread).
+    //
+    // There's no easy way to tell what strategy is used by a given POSIX implementation, so we
+    // lock around all calls that can modify `dlerror` in this module lest we accidentally read an
+    // error from a different thread. This is bulletproof when we are the *only* code using the
+    // dynamic library APIs at a given point in time. However, it's still possible for us to race
+    // with other code (see #74469) on platforms where `dlerror` is not thread-safe.
+    mod error {
+        use std::ffi::CStr;
+        use std::lazy::SyncLazy;
+        use std::sync::{Mutex, MutexGuard};
+
+        pub fn lock() -> MutexGuard<'static, Guard> {
+            static LOCK: SyncLazy<Mutex<Guard>> = SyncLazy::new(|| Mutex::new(Guard { _priv: () }));
+            LOCK.lock().unwrap()
+        }
 
-    fn check_for_errors_in<T, F>(f: F) -> Result<T, String>
-    where
-        F: FnOnce() -> T,
-    {
-        use std::sync::{Mutex, Once};
-        static INIT: Once = Once::new();
-        static mut LOCK: *mut Mutex<()> = ptr::null_mut();
-        unsafe {
-            INIT.call_once(|| {
-                LOCK = Box::into_raw(Box::new(Mutex::new(())));
-            });
-            // dlerror isn't thread safe, so we need to lock around this entire
-            // sequence
-            let _guard = (*LOCK).lock();
-            let _old_error = libc::dlerror();
-
-            let result = f();
-
-            let last_error = libc::dlerror() as *const _;
-            if ptr::null() == last_error {
-                Ok(result)
-            } else {
-                let s = CStr::from_ptr(last_error).to_bytes();
-                Err(str::from_utf8(s).unwrap().to_owned())
+        pub struct Guard {
+            _priv: (),
+        }
+
+        impl Guard {
+            pub fn get(&mut self) -> Result<(), String> {
+                let msg = unsafe { libc::dlerror() };
+                if msg.is_null() {
+                    Ok(())
+                } else {
+                    let msg = unsafe { CStr::from_ptr(msg as *const _) };
+                    Err(msg.to_string_lossy().into_owned())
+                }
+            }
+
+            pub fn clear(&mut self) {
+                let _ = unsafe { libc::dlerror() };
             }
         }
     }
 
+    pub(super) fn open(filename: &OsStr) -> Result<*mut u8, String> {
+        let s = CString::new(filename.as_bytes()).unwrap();
+
+        let mut dlerror = error::lock();
+        let ret = unsafe { libc::dlopen(s.as_ptr(), libc::RTLD_LAZY | libc::RTLD_LOCAL) };
+
+        if !ret.is_null() {
+            return Ok(ret.cast());
+        }
+
+        // A NULL return from `dlopen` indicates that an error has definitely occurred, so if
+        // nothing is in `dlerror`, we are racing with another thread that has stolen our error
+        // message. See the explanation on the `dl::error` module for more information.
+        dlerror.get().and_then(|()| Err("Unknown error".to_string()))
+    }
+
     pub(super) unsafe fn symbol(
         handle: *mut u8,
         symbol: *const libc::c_char,
     ) -> Result<*mut u8, String> {
-        check_for_errors_in(|| libc::dlsym(handle as *mut libc::c_void, symbol) as *mut u8)
+        let mut dlerror = error::lock();
+
+        // Unlike `dlopen`, it's possible for `dlsym` to return NULL without overwriting `dlerror`.
+        // Because of this, we clear `dlerror` before calling `dlsym` to avoid picking up a stale
+        // error message by accident.
+        dlerror.clear();
+
+        let ret = libc::dlsym(handle as *mut libc::c_void, symbol);
+
+        if !ret.is_null() {
+            return Ok(ret.cast());
+        }
+
+        // If `dlsym` returns NULL but there is nothing in `dlerror` it means one of two things:
+        // - We tried to load a symbol mapped to address 0. This is not technically an error but is
+        //   unlikely to occur in practice and equally unlikely to be handled correctly by calling
+        //   code. Therefore we treat it as an error anyway.
+        // - An error has occurred, but we are racing with another thread that has stolen our error
+        //   message. See the explanation on the `dl::error` module for more information.
+        dlerror.get().and_then(|()| Err("Tried to load symbol mapped to address 0".to_string()))
     }
 
     pub(super) unsafe fn close(handle: *mut u8) {
index e50fa34554d51acbed0fc7e135651bc6d912f045..85490f5f6e91ab1e1b956e4753440c7cb343a740 100644 (file)
@@ -5,6 +5,7 @@
 #![feature(drain_filter)]
 #![feature(in_band_lifetimes)]
 #![feature(nll)]
+#![feature(once_cell)]
 #![feature(or_patterns)]
 #![feature(proc_macro_internals)]
 #![feature(min_specialization)]
index 10f5b671748dab99a3efbecdb708a4d4976ccb25..43d76e9fdb4c308cbc256b69307e85599a400aee 100644 (file)
@@ -16,7 +16,6 @@
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
 use rustc_hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
-use rustc_hir::definitions::DefPathTable;
 use rustc_hir::definitions::{DefKey, DefPath, DefPathData, DefPathHash};
 use rustc_hir::lang_items;
 use rustc_index::vec::{Idx, IndexVec};
@@ -29,7 +28,6 @@
 use rustc_middle::mir::{self, Body, Promoted};
 use rustc_middle::ty::codec::TyDecoder;
 use rustc_middle::ty::{self, Ty, TyCtxt};
-use rustc_middle::util::common::record_time;
 use rustc_serialize::{opaque, Decodable, Decoder};
 use rustc_session::Session;
 use rustc_span::hygiene::ExpnDataDecodeMode;
     /// universal (`for<'tcx>`), that is paired up with whichever `TyCtxt`
     /// is being used to decode those values.
     root: CrateRoot<'static>,
-    /// For each definition in this crate, we encode a key. When the
-    /// crate is loaded, we read all the keys and put them in this
-    /// hashmap, which gives the reverse mapping. This allows us to
-    /// quickly retrace a `DefPath`, which is needed for incremental
-    /// compilation support.
-    def_path_table: DefPathTable,
     /// Trait impl data.
     /// FIXME: Used only from queries and can use query cache,
     /// so pre-decoding can probably be avoided.
     /// Do not access the value directly, as it might not have been initialized yet.
     /// The field must always be initialized to `DepNodeIndex::INVALID`.
     dep_node_index: AtomicCell<DepNodeIndex>,
+    /// Caches decoded `DefKey`s.
+    def_key_cache: Lock<FxHashMap<DefIndex, DefKey>>,
+    /// Caches decoded `DefPathHash`es.
+    def_path_hash_cache: Lock<FxHashMap<DefIndex, DefPathHash>>,
 
     // --- Other significant crate properties ---
     /// ID of this crate, from the current compilation session's point of view.
@@ -807,7 +803,7 @@ fn get_trait_def(&self, item_id: DefIndex, sess: &Session) -> ty::TraitDef {
                     data.has_auto_impl,
                     data.is_marker,
                     data.specialization_kind,
-                    self.def_path_table.def_path_hash(item_id),
+                    self.def_path_hash(item_id),
                 )
             }
             EntryKind::TraitAlias => ty::TraitDef::new(
@@ -817,7 +813,7 @@ fn get_trait_def(&self, item_id: DefIndex, sess: &Session) -> ty::TraitDef {
                 false,
                 false,
                 ty::trait_def::TraitSpecializationKind::None,
-                self.def_path_table.def_path_hash(item_id),
+                self.def_path_hash(item_id),
             ),
             _ => bug!("def-index does not refer to trait or trait alias"),
         }
@@ -1509,12 +1505,14 @@ fn fn_sig(&self, id: DefIndex, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> {
 
     #[inline]
     fn def_key(&self, index: DefIndex) -> DefKey {
-        let mut key = self.def_path_table.def_key(index);
-        if self.is_proc_macro(index) {
-            let name = self.raw_proc_macro(index).name();
-            key.disambiguated_data.data = DefPathData::MacroNs(Symbol::intern(name));
-        }
-        key
+        *self.def_key_cache.lock().entry(index).or_insert_with(|| {
+            let mut key = self.root.tables.def_keys.get(self, index).unwrap().decode(self);
+            if self.is_proc_macro(index) {
+                let name = self.raw_proc_macro(index).name();
+                key.disambiguated_data.data = DefPathData::MacroNs(Symbol::intern(name));
+            }
+            key
+        })
     }
 
     // Returns the path leading to the thing with this `id`.
@@ -1523,6 +1521,57 @@ fn def_path(&self, id: DefIndex) -> DefPath {
         DefPath::make(self.cnum, id, |parent| self.def_key(parent))
     }
 
+    fn def_path_hash_unlocked(
+        &self,
+        index: DefIndex,
+        def_path_hashes: &mut FxHashMap<DefIndex, DefPathHash>,
+    ) -> DefPathHash {
+        *def_path_hashes.entry(index).or_insert_with(|| {
+            self.root.tables.def_path_hashes.get(self, index).unwrap().decode(self)
+        })
+    }
+
+    #[inline]
+    fn def_path_hash(&self, index: DefIndex) -> DefPathHash {
+        let mut def_path_hashes = self.def_path_hash_cache.lock();
+        self.def_path_hash_unlocked(index, &mut def_path_hashes)
+    }
+
+    fn all_def_path_hashes_and_def_ids(&self) -> Vec<(DefPathHash, DefId)> {
+        let mut def_path_hashes = self.def_path_hash_cache.lock();
+        (0..self.num_def_ids())
+            .map(|index| {
+                let index = DefIndex::from_usize(index);
+                (self.def_path_hash_unlocked(index, &mut def_path_hashes), self.local_def_id(index))
+            })
+            .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 =
+                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
+    }
+
     /// Imports the source_map from an external crate into the source_map of the crate
     /// currently being compiled (the "local crate").
     ///
@@ -1723,9 +1772,6 @@ impl CrateMetadata {
         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))
@@ -1737,7 +1783,6 @@ impl CrateMetadata {
         CrateMetadata {
             blob,
             root,
-            def_path_table,
             trait_impls,
             raw_proc_macros,
             source_map_import_info: OnceCell::new(),
@@ -1752,6 +1797,8 @@ impl CrateMetadata {
             host_hash,
             extern_crate: Lock::new(None),
             hygiene_context: Default::default(),
+            def_key_cache: Default::default(),
+            def_path_hash_cache: Default::default(),
         }
     }
 
@@ -1828,6 +1875,10 @@ impl CrateMetadata {
         self.root.hash
     }
 
+    fn num_def_ids(&self) -> usize {
+        self.root.tables.def_keys.size()
+    }
+
     fn local_def_id(&self, index: DefIndex) -> DefId {
         DefId { krate: self.cnum, index }
     }
@@ -1843,36 +1894,6 @@ fn reverse_translate_def_id(&self, did: DefId) -> Option<DefId> {
 
         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 50c2ad8148a1421819a24314e586828a6b29de5e..36ff65fc5eb008c5c28b822655e91db4bfb131fb 100644 (file)
@@ -9,7 +9,6 @@
 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_hir::definitions::DefPathTable;
 use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
 use rustc_middle::hir::exports::Export;
 use rustc_middle::middle::cstore::{CrateSource, CrateStore, EncodedMetadata};
@@ -486,8 +485,12 @@ fn def_path_hash(&self, def: DefId) -> DefPathHash {
         self.get_crate_data(def.krate).def_path_hash(def.index)
     }
 
-    fn def_path_table(&self, cnum: CrateNum) -> &DefPathTable {
-        &self.get_crate_data(cnum).cdata.def_path_table
+    fn all_def_path_hashes_and_def_ids(&self, cnum: CrateNum) -> Vec<(DefPathHash, DefId)> {
+        self.get_crate_data(cnum).all_def_path_hashes_and_def_ids()
+    }
+
+    fn num_def_ids(&self, cnum: CrateNum) -> usize {
+        self.get_crate_data(cnum).num_def_ids()
     }
 
     fn crates_untracked(&self) -> Vec<CrateNum> {
index 78abf341e33a9e08b6bb68548dfcc7785ccd1c4b..509ef1caf1a9d10553dff75c46694b8d936f7a75 100644 (file)
@@ -9,7 +9,6 @@
 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::definitions::DefPathTable;
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::itemlikevisit::{ItemLikeVisitor, ParItemLikeVisitor};
 use rustc_hir::lang_items;
@@ -418,9 +417,14 @@ fn encode_info_for_items(&mut self) {
         }
     }
 
-    fn encode_def_path_table(&mut self) -> Lazy<DefPathTable> {
-        let definitions = self.tcx.hir().definitions();
-        self.lazy(definitions.def_path_table())
+    fn encode_def_path_table(&mut self) {
+        let table = self.tcx.hir().definitions().def_path_table();
+        for (def_index, def_key, def_path_hash) in table.enumerated_keys_and_path_hashes() {
+            let def_key = self.lazy(def_key);
+            let def_path_hash = self.lazy(def_path_hash);
+            self.tables.def_keys.set(def_index, def_key);
+            self.tables.def_path_hashes.set(def_index, def_path_hash);
+        }
     }
 
     fn encode_source_map(&mut self) -> Lazy<[rustc_span::SourceFile]> {
@@ -525,7 +529,7 @@ fn encode_crate_root(&mut self) -> Lazy<CrateRoot<'tcx>> {
 
         // Encode DefPathTable
         i = self.position();
-        let def_path_table = self.encode_def_path_table();
+        self.encode_def_path_table();
         let def_path_table_bytes = self.position() - i;
 
         // Encode the def IDs of impls, for coherence checking.
@@ -642,7 +646,6 @@ fn encode_crate_root(&mut self) -> Lazy<CrateRoot<'tcx>> {
             native_libraries,
             foreign_modules,
             source_map,
-            def_path_table,
             impls,
             exported_symbols,
             interpret_alloc_index,
index ac1ac3607017be63ca36c38d67c43102c7537cbc..1ba5962d119e807ac09a1e8e54efa802f02e95cd 100644 (file)
@@ -7,7 +7,8 @@
 use rustc_data_structures::sync::MetadataRef;
 use rustc_hir as hir;
 use rustc_hir::def::CtorKind;
-use rustc_hir::def_id::{DefId, DefIndex};
+use rustc_hir::def_id::{DefId, DefIndex, DefPathHash};
+use rustc_hir::definitions::DefKey;
 use rustc_hir::lang_items;
 use rustc_index::{bit_set::FiniteBitSet, vec::IndexVec};
 use rustc_middle::hir::exports::Export;
@@ -195,7 +196,6 @@ macro_rules! Lazy {
     diagnostic_items: Lazy<[(Symbol, DefIndex)]>,
     native_libraries: Lazy<[NativeLib]>,
     foreign_modules: Lazy<[ForeignModule]>,
-    def_path_table: Lazy<rustc_hir::definitions::DefPathTable>,
     impls: Lazy<[TraitImpls]>,
     interpret_alloc_index: Lazy<[u32]>,
 
@@ -285,6 +285,12 @@ fn encode(&self, buf: &mut Encoder) -> LazyTables<'tcx> {
     mir: Table<DefIndex, Lazy!(mir::Body<'tcx>)>,
     promoted_mir: Table<DefIndex, Lazy!(IndexVec<mir::Promoted, mir::Body<'tcx>>)>,
     unused_generic_params: Table<DefIndex, Lazy<FiniteBitSet<u32>>>,
+    // `def_keys` and `def_path_hashes` represent a lazy version of a
+    // `DefPathTable`. This allows us to avoid deserializing an entire
+    // `DefPathTable` up front, since we may only ever use a few
+    // definitions from any given crate.
+    def_keys: Table<DefIndex, Lazy<DefKey>>,
+    def_path_hashes: Table<DefIndex, Lazy<DefPathHash>>
 }
 
 #[derive(Copy, Clone, MetadataEncodable, MetadataDecodable)]
index 28858e146e48930b8100c26ccc78bdd94f7e07dc..03bd4170ea99039ba1897a5495d599cf01b393fe 100644 (file)
@@ -201,4 +201,9 @@ pub(super) fn get<'a, 'tcx, M: Metadata<'a, 'tcx>>(&self, metadata: M, i: I) ->
         let bytes = &metadata.raw_bytes()[start..start + self.meta];
         <Option<T>>::maybe_read_from_bytes_at(bytes, i.index())?
     }
+
+    /// Size of the table in entries, including possible gaps.
+    pub(super) fn size(&self) -> usize {
+        self.meta / <Option<T>>::BYTE_LEN
+    }
 }
index a6cc7cbc9207cca26f0108360abd8e6d85cb0d03..1e57411f9c54ff1900d11c33ec52f3d2e6d0ccad 100644 (file)
@@ -828,13 +828,24 @@ pub fn attrs(&self, id: HirId) -> &'hir [ast::Attribute] {
         attrs.unwrap_or(&[])
     }
 
+    /// Gets the span of the definition of the specified HIR node.
+    /// This is used by `tcx.get_span`
     pub fn span(&self, hir_id: HirId) -> Span {
         match self.find_entry(hir_id).map(|entry| entry.node) {
             Some(Node::Param(param)) => param.span,
-            Some(Node::Item(item)) => item.span,
+            Some(Node::Item(item)) => match &item.kind {
+                ItemKind::Fn(sig, _, _) => sig.span,
+                _ => item.span,
+            },
             Some(Node::ForeignItem(foreign_item)) => foreign_item.span,
-            Some(Node::TraitItem(trait_method)) => trait_method.span,
-            Some(Node::ImplItem(impl_item)) => impl_item.span,
+            Some(Node::TraitItem(trait_item)) => match &trait_item.kind {
+                TraitItemKind::Fn(sig, _) => sig.span,
+                _ => trait_item.span,
+            },
+            Some(Node::ImplItem(impl_item)) => match &impl_item.kind {
+                ImplItemKind::Fn(sig, _) => sig.span,
+                _ => impl_item.span,
+            },
             Some(Node::Variant(variant)) => variant.span,
             Some(Node::Field(field)) => field.span,
             Some(Node::AnonConst(constant)) => self.body(constant.body).value.span,
@@ -866,6 +877,18 @@ pub fn span(&self, hir_id: HirId) -> Span {
         }
     }
 
+    /// Like `hir.span()`, but includes the body of function items
+    /// (instead of just the function header)
+    pub fn span_with_body(&self, hir_id: HirId) -> Span {
+        match self.find_entry(hir_id).map(|entry| entry.node) {
+            Some(Node::TraitItem(item)) => item.span,
+            Some(Node::ImplItem(impl_item)) => impl_item.span,
+            Some(Node::Item(item)) => item.span,
+            Some(_) => self.span(hir_id),
+            _ => bug!("hir::map::Map::span_with_body: id not in map: {:?}", hir_id),
+        }
+    }
+
     pub fn span_if_local(&self, id: DefId) -> Option<Span> {
         id.as_local().map(|id| self.span(self.local_def_id_to_hir_id(id)))
     }
index ec1dcd29ef2d8180328b85073d5288af75c0253c..1b2dea8a378c33df1bfb1017ce063ba54ee441e3 100644 (file)
@@ -40,7 +40,6 @@
 #![feature(nll)]
 #![feature(option_expect_none)]
 #![feature(or_patterns)]
-#![feature(range_is_empty)]
 #![feature(min_specialization)]
 #![feature(trusted_len)]
 #![feature(stmt_expr_attributes)]
index 6759ad61d3a39e28ef97131afb1a11b233cb348d..1af1d58181760b65aef5ad23f5bc4239e6fc172d 100644 (file)
@@ -9,7 +9,7 @@
 use rustc_data_structures::svh::Svh;
 use rustc_data_structures::sync::{self, MetadataRef};
 use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
-use rustc_hir::definitions::{DefKey, DefPath, DefPathHash, DefPathTable};
+use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
 use rustc_macros::HashStable;
 use rustc_session::search_paths::PathKind;
 use rustc_session::utils::NativeLibKind;
@@ -187,7 +187,8 @@ pub trait CrateStore {
     fn def_key(&self, def: DefId) -> DefKey;
     fn def_path(&self, def: DefId) -> DefPath;
     fn def_path_hash(&self, def: DefId) -> DefPathHash;
-    fn def_path_table(&self, cnum: CrateNum) -> &DefPathTable;
+    fn all_def_path_hashes_and_def_ids(&self, cnum: CrateNum) -> Vec<(DefPathHash, DefId)>;
+    fn num_def_ids(&self, cnum: CrateNum) -> usize;
 
     // "queries" used in resolve that aren't tracked for incremental compilation
     fn crate_name_untracked(&self, cnum: CrateNum) -> Symbol;
index 70c90198276c1700a91850037f0b4a851dab4b57..3e1caa3b5497799ae4dce83812877d04f7e8a318 100644 (file)
@@ -53,7 +53,7 @@ pub fn required(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.
     match tcx.sess.panic_strategy() {
-        PanicStrategy::Abort => lang_item != LangItem::EhPersonalityLangItem,
+        PanicStrategy::Abort => lang_item != LangItem::EhPersonality,
         PanicStrategy::Unwind => true,
     }
 }
index f01c9ae4471d42beb40ec7a2d8c3316951bbe252..7ac7d9b23f172640686813b74489b4352fb7d823 100644 (file)
@@ -1564,10 +1564,10 @@ pub enum ProjectionElem<V, T> {
     /// ```
     ConstantIndex {
         /// index or -index (in Python terms), depending on from_end
-        offset: u32,
+        offset: u64,
         /// The thing being indexed must be at least this long. For arrays this
         /// is always the exact length.
-        min_length: u32,
+        min_length: u64,
         /// Counting backwards from end? This is always false when indexing an
         /// array.
         from_end: bool,
@@ -1578,8 +1578,8 @@ pub enum ProjectionElem<V, T> {
     /// If `from_end` is true `slice[from..slice.len() - to]`.
     /// Otherwise `array[from..to]`.
     Subslice {
-        from: u32,
-        to: u32,
+        from: u64,
+        to: u64,
         /// Whether `to` counts from the start or end of the array/slice.
         /// For `PlaceElem`s this is `true` if and only if the base is a slice.
         /// For `ProjectionKind`, this can also be `true` for arrays.
@@ -1616,7 +1616,7 @@ fn is_indirect(&self) -> bool {
 
 // At least on 64 bit systems, `PlaceElem` should not be larger than two pointers.
 #[cfg(target_arch = "x86_64")]
-static_assert_size!(PlaceElem<'_>, 16);
+static_assert_size!(PlaceElem<'_>, 24);
 
 /// Alias for projections as they appear in `UserTypeProjection`, where we
 /// need neither the `V` parameter for `Index` nor the `T` for `Field`.
@@ -2330,7 +2330,7 @@ pub fn index(self) -> Self {
         self.map_projections(|pat_ty_proj| pat_ty_proj.index())
     }
 
-    pub fn subslice(self, from: u32, to: u32) -> Self {
+    pub fn subslice(self, from: u64, to: u64) -> Self {
         self.map_projections(|pat_ty_proj| pat_ty_proj.subslice(from, to))
     }
 
@@ -2376,7 +2376,7 @@ pub(crate) fn index(mut self) -> Self {
         self
     }
 
-    pub(crate) fn subslice(mut self, from: u32, to: u32) -> Self {
+    pub(crate) fn subslice(mut self, from: u64, to: u64) -> Self {
         self.projs.push(ProjectionElem::Subslice { from, to, from_end: true });
         self
     }
@@ -2452,7 +2452,10 @@ fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
 
 impl<'tcx> Display for Constant<'tcx> {
     fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
-        write!(fmt, "const ")?;
+        match self.literal.ty.kind {
+            ty::FnDef(..) => {}
+            _ => write!(fmt, "const ")?,
+        }
         pretty_print_const(self.literal, fmt, true)
     }
 }
index e8fe3a97a10c76295c72d75cf7f1a87b7e3f7830..fcfd648c2b7aaaa97a182e2639715c05ed513bba 100644 (file)
@@ -103,7 +103,7 @@ pub enum TerminatorKind<'tcx> {
         unwind: Option<BasicBlock>,
     },
 
-    /// Block ends with a call of a converging function.
+    /// Block ends with a call of a function.
     Call {
         /// The function that’s being called.
         func: Operand<'tcx>,
index ea9c8b7a415840b15e2adfedca48baea42093e5b..f86403fa502bb02e225618a7a95949381e331fcf 100644 (file)
@@ -345,6 +345,7 @@ pub fn peel_derives(&self) -> &Self {
 #[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)]
 pub struct MatchExpressionArmCause<'tcx> {
     pub arm_span: Span,
+    pub semi_span: Option<Span>,
     pub source: hir::MatchSource,
     pub prior_arms: Vec<Span>,
     pub last_ty: Ty<'tcx>,
index 0ab07aea426c3c95d217133c567d291e0c0f8cc0..6a9bb8d6c284fc31d09a89c1e12ac8cd283cbfae 100644 (file)
@@ -2,7 +2,7 @@
 use crate::ty::{self, Ty, TyCtxt};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
-use rustc_hir::lang_items::{DerefMutTraitLangItem, DerefTraitLangItem};
+use rustc_hir::lang_items::LangItem;
 use rustc_macros::HashStable;
 
 #[derive(Clone, Copy, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
@@ -118,8 +118,8 @@ pub struct OverloadedDeref<'tcx> {
 impl<'tcx> OverloadedDeref<'tcx> {
     pub fn method_call(&self, tcx: TyCtxt<'tcx>, source: Ty<'tcx>) -> (DefId, SubstsRef<'tcx>) {
         let trait_def_id = match self.mutbl {
-            hir::Mutability::Not => tcx.require_lang_item(DerefTraitLangItem, None),
-            hir::Mutability::Mut => tcx.require_lang_item(DerefMutTraitLangItem, None),
+            hir::Mutability::Not => tcx.require_lang_item(LangItem::Deref, None),
+            hir::Mutability::Mut => tcx.require_lang_item(LangItem::DerefMut, None),
         };
         let method_def_id = tcx
             .associated_items(trait_def_id)
index e6b05fe409438c1bd74d5b2f118d03c70cc1cc77..18ae744cb1ee328792bdf203c039e29155d73a73 100644 (file)
@@ -40,7 +40,7 @@
 use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LOCAL_CRATE};
 use rustc_hir::definitions::{DefPathHash, Definitions};
 use rustc_hir::intravisit::Visitor;
-use rustc_hir::lang_items::{self, PanicLocationLangItem};
+use rustc_hir::lang_items::LangItem;
 use rustc_hir::{HirId, ItemKind, ItemLocalId, ItemLocalMap, ItemLocalSet, Node, TraitCandidate};
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_macros::HashStable;
@@ -1102,20 +1102,13 @@ pub fn create_global_ctxt(
         providers[LOCAL_CRATE] = local_providers;
 
         let def_path_hash_to_def_id = if s.opts.build_dep_graph() {
-            let def_path_tables = crates
-                .iter()
-                .map(|&cnum| (cnum, cstore.def_path_table(cnum)))
-                .chain(iter::once((LOCAL_CRATE, definitions.def_path_table())));
+            let capacity = definitions.def_path_table().num_def_ids()
+                + crates.iter().map(|cnum| cstore.num_def_ids(*cnum)).sum::<usize>();
+            let mut map = FxHashMap::with_capacity_and_hasher(capacity, Default::default());
 
-            // Precompute the capacity of the hashmap so we don't have to
-            // re-allocate when populating it.
-            let capacity = def_path_tables.clone().map(|(_, t)| t.size()).sum::<usize>();
-
-            let mut map: FxHashMap<_, _> =
-                FxHashMap::with_capacity_and_hasher(capacity, ::std::default::Default::default());
-
-            for (cnum, def_path_table) in def_path_tables {
-                def_path_table.add_def_path_hashes_to(cnum, &mut map);
+            map.extend(definitions.def_path_table().all_def_path_hashes_and_def_ids(LOCAL_CRATE));
+            for cnum in &crates {
+                map.extend(cstore.all_def_path_hashes_and_def_ids(*cnum).into_iter());
             }
 
             Some(map)
@@ -1545,7 +1538,7 @@ pub fn has_strict_asm_symbol_naming(&self) -> bool {
     pub fn caller_location_ty(&self) -> Ty<'tcx> {
         self.mk_imm_ref(
             self.lifetimes.re_static,
-            self.type_of(self.require_lang_item(PanicLocationLangItem, None))
+            self.type_of(self.require_lang_item(LangItem::PanicLocation, None))
                 .subst(*self, self.mk_substs([self.lifetimes.re_static.into()].iter())),
         )
     }
@@ -2192,12 +2185,12 @@ fn mk_generic_adt(self, wrapper_def_id: DefId, ty_param: Ty<'tcx>) -> Ty<'tcx> {
 
     #[inline]
     pub fn mk_box(self, ty: Ty<'tcx>) -> Ty<'tcx> {
-        let def_id = self.require_lang_item(lang_items::OwnedBoxLangItem, None);
+        let def_id = self.require_lang_item(LangItem::OwnedBox, None);
         self.mk_generic_adt(def_id, ty)
     }
 
     #[inline]
-    pub fn mk_lang_item(self, ty: Ty<'tcx>, item: lang_items::LangItem) -> Option<Ty<'tcx>> {
+    pub fn mk_lang_item(self, ty: Ty<'tcx>, item: LangItem) -> Option<Ty<'tcx>> {
         let def_id = self.lang_items().require(item).ok()?;
         Some(self.mk_generic_adt(def_id, ty))
     }
@@ -2210,7 +2203,7 @@ pub fn mk_diagnostic_item(self, ty: Ty<'tcx>, name: Symbol) -> Option<Ty<'tcx>>
 
     #[inline]
     pub fn mk_maybe_uninit(self, ty: Ty<'tcx>) -> Ty<'tcx> {
-        let def_id = self.require_lang_item(lang_items::MaybeUninitLangItem, None);
+        let def_id = self.require_lang_item(LangItem::MaybeUninit, None);
         self.mk_generic_adt(def_id, ty)
     }
 
index e6dafd4965bc9fb321568a1af6d9be3e738a7927..8e08fe4b87b8256e2f6677030a00f8403b1b4e77 100644 (file)
@@ -5,7 +5,7 @@
 use rustc_errors::ErrorReported;
 use rustc_hir::def::Namespace;
 use rustc_hir::def_id::{CrateNum, DefId};
-use rustc_hir::lang_items::{DropInPlaceFnLangItem, FnOnceTraitLangItem};
+use rustc_hir::lang_items::LangItem;
 use rustc_macros::HashStable;
 
 use std::fmt;
@@ -408,7 +408,7 @@ pub fn resolve_closure(
     }
 
     pub fn resolve_drop_in_place(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ty::Instance<'tcx> {
-        let def_id = tcx.require_lang_item(DropInPlaceFnLangItem, None);
+        let def_id = tcx.require_lang_item(LangItem::DropInPlace, None);
         let substs = tcx.intern_substs(&[ty.into()]);
         Instance::resolve(tcx, ty::ParamEnv::reveal_all(), def_id, substs).unwrap().unwrap()
     }
@@ -419,7 +419,7 @@ pub fn fn_once_adapter_instance(
         substs: ty::SubstsRef<'tcx>,
     ) -> Instance<'tcx> {
         debug!("fn_once_adapter_shim({:?}, {:?})", closure_did, substs);
-        let fn_once = tcx.require_lang_item(FnOnceTraitLangItem, None);
+        let fn_once = tcx.require_lang_item(LangItem::FnOnce, None);
         let call_once = tcx
             .associated_items(fn_once)
             .in_definition_order()
index 928cba324d5849025aceb7c9303af7ec2c0728cc..08bd131565bfa7b1d0f868331156ac95dd8d7687 100644 (file)
@@ -8,7 +8,7 @@
 use rustc_attr as attr;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_hir as hir;
-use rustc_hir::lang_items::{GeneratorStateLangItem, PinTypeLangItem};
+use rustc_hir::lang_items::LangItem;
 use rustc_index::bit_set::BitSet;
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_session::{DataTypeKind, FieldInfo, SizeKind, VariantInfo};
@@ -2371,13 +2371,13 @@ fn fn_sig_for_fn_abi(&self, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> {
                 let env_region = ty::ReLateBound(ty::INNERMOST, ty::BrEnv);
                 let env_ty = tcx.mk_mut_ref(tcx.mk_region(env_region), ty);
 
-                let pin_did = tcx.require_lang_item(PinTypeLangItem, None);
+                let pin_did = tcx.require_lang_item(LangItem::Pin, None);
                 let pin_adt_ref = tcx.adt_def(pin_did);
                 let pin_substs = tcx.intern_substs(&[env_ty.into()]);
                 let env_ty = tcx.mk_adt(pin_adt_ref, pin_substs);
 
                 sig.map_bound(|sig| {
-                    let state_did = tcx.require_lang_item(GeneratorStateLangItem, None);
+                    let state_did = tcx.require_lang_item(LangItem::GeneratorState, None);
                     let state_adt_ref = tcx.adt_def(state_did);
                     let state_substs =
                         tcx.intern_substs(&[sig.yield_ty.into(), sig.return_ty.into()]);
index 4fa86a91254ce698cffbe64a1a4ee8d000015d57..a961d02f7a2b1e6b153b2920981eaceebe5dc996 100644 (file)
@@ -32,7 +32,7 @@
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, CtorOf, DefKind, Namespace, Res};
 use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, CRATE_DEF_INDEX};
-use rustc_hir::lang_items::{FnMutTraitLangItem, FnOnceTraitLangItem, FnTraitLangItem};
+use rustc_hir::lang_items::LangItem;
 use rustc_hir::{Constness, Node};
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_macros::HashStable;
@@ -2670,9 +2670,9 @@ impl<'tcx> ClosureKind {
 
     pub fn trait_did(&self, tcx: TyCtxt<'tcx>) -> DefId {
         match *self {
-            ClosureKind::Fn => tcx.require_lang_item(FnTraitLangItem, None),
-            ClosureKind::FnMut => tcx.require_lang_item(FnMutTraitLangItem, None),
-            ClosureKind::FnOnce => tcx.require_lang_item(FnOnceTraitLangItem, None),
+            ClosureKind::Fn => tcx.require_lang_item(LangItem::Fn, None),
+            ClosureKind::FnMut => tcx.require_lang_item(LangItem::FnMut, None),
+            ClosureKind::FnOnce => tcx.require_lang_item(LangItem::FnOnce, None),
         }
     }
 
index 0a6e17a43d8db391656472fd14047a2bc48fd954..c1f354c7a15f3fd1cacfbe89b233ff55a2b777fa 100644 (file)
@@ -1264,7 +1264,7 @@ pub fn to_const(self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> &'tcx ty::Const<'tcx>
     /// De Bruijn index of 0, because the innermost binder in that location
     /// is the outer fn.
     ///
-    /// [dbi]: http://en.wikipedia.org/wiki/De_Bruijn_index
+    /// [dbi]: https://en.wikipedia.org/wiki/De_Bruijn_index
     #[derive(HashStable)]
     pub struct DebruijnIndex {
         DEBUG_FORMAT = "DebruijnIndex({})",
index 7a50bdfeef625e0a25a906aa3b917241004d0471..9076dbccb525352f708a325c1d5d67bf8e1de9e9 100644 (file)
@@ -113,23 +113,32 @@ pub(in crate::borrow_check) fn report_use_of_moved_or_uninitialized(
                 }
             }
 
-            let msg = ""; //FIXME: add "partially " or "collaterally "
+            let is_partial_move = move_site_vec.iter().any(|move_site| {
+                let move_out = self.move_data.moves[(*move_site).moi];
+                let moved_place = &self.move_data.move_paths[move_out.path].place;
+                // `*(_1)` where `_1` is a `Box` is actually a move out.
+                let is_box_move = moved_place.as_ref().projection == &[ProjectionElem::Deref]
+                    && self.body.local_decls[moved_place.local].ty.is_box();
+
+                !is_box_move
+                    && used_place != moved_place.as_ref()
+                    && used_place.is_prefix_of(moved_place.as_ref())
+            });
+
+            let partial_str = if is_partial_move { "partial " } else { "" };
+            let partially_str = if is_partial_move { "partially " } else { "" };
 
             let mut err = self.cannot_act_on_moved_value(
                 span,
                 desired_action.as_noun(),
-                msg,
+                partially_str,
                 self.describe_place_with_options(moved_place, IncludingDowncast(true)),
             );
 
             self.add_moved_or_invoked_closure_note(location, used_place, &mut err);
 
             let mut is_loop_move = false;
-            let is_partial_move = move_site_vec.iter().any(|move_site| {
-                let move_out = self.move_data.moves[(*move_site).moi];
-                let moved_place = &self.move_data.move_paths[move_out.path].place;
-                used_place != moved_place.as_ref() && used_place.is_prefix_of(moved_place.as_ref())
-            });
+
             for move_site in &move_site_vec {
                 let move_out = self.move_data.moves[(*move_site).moi];
                 let moved_place = &self.move_data.move_paths[move_out.path].place;
@@ -142,13 +151,19 @@ pub(in crate::borrow_check) fn report_use_of_moved_or_uninitialized(
                 if location == move_out.source {
                     err.span_label(
                         span,
-                        format!("value moved{} here, in previous iteration of loop", move_msg),
+                        format!(
+                            "value {}moved{} here, in previous iteration of loop",
+                            partially_str, move_msg
+                        ),
                     );
                     is_loop_move = true;
                 } else if move_site.traversed_back_edge {
                     err.span_label(
                         move_span,
-                        format!("value moved{} here, in previous iteration of loop", move_msg),
+                        format!(
+                            "value {}moved{} here, in previous iteration of loop",
+                            partially_str, move_msg
+                        ),
                     );
                 } else {
                     if let UseSpans::FnSelfUse { var_span, fn_call_span, fn_span, kind } =
@@ -162,7 +177,10 @@ pub(in crate::borrow_check) fn report_use_of_moved_or_uninitialized(
                             FnSelfUseKind::FnOnceCall => {
                                 err.span_label(
                                     fn_call_span,
-                                    &format!("{} moved due to this call", place_name),
+                                    &format!(
+                                        "{} {}moved due to this call",
+                                        place_name, partially_str
+                                    ),
                                 );
                                 err.span_note(
                                     var_span,
@@ -172,7 +190,10 @@ pub(in crate::borrow_check) fn report_use_of_moved_or_uninitialized(
                             FnSelfUseKind::Operator { self_arg } => {
                                 err.span_label(
                                     fn_call_span,
-                                    &format!("{} moved due to usage in operator", place_name),
+                                    &format!(
+                                        "{} {}moved due to usage in operator",
+                                        place_name, partially_str
+                                    ),
                                 );
                                 if self.fn_self_span_reported.insert(fn_span) {
                                     err.span_note(
@@ -186,14 +207,17 @@ pub(in crate::borrow_check) fn report_use_of_moved_or_uninitialized(
                                     err.span_label(
                                         fn_call_span,
                                         &format!(
-                                            "{} moved due to this implicit call to `.into_iter()`",
-                                            place_name
+                                            "{} {}moved due to this implicit call to `.into_iter()`",
+                                            place_name, partially_str
                                         ),
                                     );
                                 } else {
                                     err.span_label(
                                         fn_call_span,
-                                        &format!("{} moved due to this method call", place_name),
+                                        &format!(
+                                            "{} {}moved due to this method call",
+                                            place_name, partially_str
+                                        ),
                                     );
                                 }
                                 // Avoid pointing to the same function in multiple different
@@ -207,10 +231,17 @@ pub(in crate::borrow_check) fn report_use_of_moved_or_uninitialized(
                             }
                         }
                     } else {
-                        err.span_label(move_span, format!("value moved{} here", move_msg));
+                        err.span_label(
+                            move_span,
+                            format!("value {}moved{} here", partially_str, move_msg),
+                        );
                         move_spans.var_span_label(
                             &mut err,
-                            format!("variable moved due to use{}", move_spans.describe()),
+                            format!(
+                                "variable {}moved due to use{}",
+                                partially_str,
+                                move_spans.describe()
+                            ),
                         );
                     }
                 }
@@ -250,9 +281,9 @@ pub(in crate::borrow_check) fn report_use_of_moved_or_uninitialized(
                 err.span_label(
                     span,
                     format!(
-                        "value {} here {}",
+                        "value {} here after {}move",
                         desired_action.as_verb_in_past_tense(),
-                        if is_partial_move { "after partial move" } else { "after move" },
+                        partial_str
                     ),
                 );
             }
@@ -321,7 +352,7 @@ pub(in crate::borrow_check) fn report_use_of_moved_or_uninitialized(
                 } else {
                     None
                 };
-                self.note_type_does_not_implement_copy(&mut err, &note_msg, ty, span);
+                self.note_type_does_not_implement_copy(&mut err, &note_msg, ty, span, partial_str);
             }
 
             if let Some((_, mut old_err)) =
@@ -1398,8 +1429,12 @@ fn predecessor_locations(
 
                 for moi in &self.move_data.loc_map[location] {
                     debug!("report_use_of_moved_or_uninitialized: moi={:?}", moi);
-                    if mpis.contains(&self.move_data.moves[*moi].path) {
-                        debug!("report_use_of_moved_or_uninitialized: found");
+                    let path = self.move_data.moves[*moi].path;
+                    if mpis.contains(&path) {
+                        debug!(
+                            "report_use_of_moved_or_uninitialized: found {:?}",
+                            move_paths[path].place
+                        );
                         result.push(MoveSite { moi: *moi, traversed_back_edge: is_back_edge });
 
                         // Strictly speaking, we could continue our DFS here. There may be
index daffdec2a83bed72239b89fcfc78aa523b553688..e73a78811d49052196321ad216a8f3c1ec0a267d 100644 (file)
@@ -412,10 +412,11 @@ pub(super) fn note_type_does_not_implement_copy(
         place_desc: &str,
         ty: Ty<'tcx>,
         span: Option<Span>,
+        move_prefix: &str,
     ) {
         let message = format!(
-            "move occurs because {} has type `{}`, which does not implement the `Copy` trait",
-            place_desc, ty,
+            "{}move occurs because {} has type `{}`, which does not implement the `Copy` trait",
+            move_prefix, place_desc, ty,
         );
         if let Some(span) = span {
             err.span_label(span, message);
index bd3e20458b078bb72f8237a908656f02d9f5bf11..1c8da212f108853740a30545914f865f6d07afbb 100644 (file)
@@ -445,7 +445,13 @@ fn add_move_hints(
                         None => "value".to_string(),
                     };
 
-                    self.note_type_does_not_implement_copy(err, &place_desc, place_ty, Some(span));
+                    self.note_type_does_not_implement_copy(
+                        err,
+                        &place_desc,
+                        place_ty,
+                        Some(span),
+                        "",
+                    );
                 } else {
                     binds_to.sort();
                     binds_to.dedup();
@@ -467,7 +473,7 @@ fn add_move_hints(
                     Some(desc) => format!("`{}`", desc),
                     None => "value".to_string(),
                 };
-                self.note_type_does_not_implement_copy(err, &place_desc, place_ty, Some(span));
+                self.note_type_does_not_implement_copy(err, &place_desc, place_ty, Some(span), "");
 
                 use_spans.args_span_label(err, format!("move out of {} occurs here", place_desc));
                 use_spans
@@ -529,6 +535,7 @@ fn add_move_error_details(&self, err: &mut DiagnosticBuilder<'a>, binds_to: &[Lo
                     &format!("`{}`", self.local_names[*local].unwrap()),
                     bind_to.ty,
                     Some(binding_span),
+                    "",
                 );
             }
         }
index 9197a83cdd07a4615d37ff1628410f35d832a538..a775fa59c1b9dce220554c6197a3568f600462eb 100644 (file)
@@ -257,7 +257,7 @@ fn compile_all_suggestions(
         };
 
         // We want this message to appear after other messages on the mir def.
-        let mir_span = mbcx.infcx.tcx.def_span(mbcx.mir_def_id);
+        let mir_span = mbcx.body.span;
         diag.sort_span = mir_span.shrink_to_hi();
 
         // Buffer the diagnostic
index a61af5c3f0523605f2a27e37abe7091aeeb822c5..b486b8b589cfddeba3104056346e55746e9084c0 100644 (file)
@@ -1694,8 +1694,8 @@ fn check_if_subslice_element_is_moved(
         desired_action: InitializationRequiringAction,
         place_span: (PlaceRef<'tcx>, Span),
         maybe_uninits: &BitSet<MovePathIndex>,
-        from: u32,
-        to: u32,
+        from: u64,
+        to: u64,
     ) {
         if let Some(mpi) = self.move_path_for_place(place_span.0) {
             let move_paths = &self.move_data.move_paths;
index 168a352591d0e12b400ff93bede87ef594513303..69c4f633770f2bc8869e786076fbb4aa72f54d0a 100644 (file)
@@ -10,7 +10,7 @@
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_hir::lang_items::{CoerceUnsizedTraitLangItem, CopyTraitLangItem, SizedTraitLangItem};
+use rustc_hir::lang_items::LangItem;
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_infer::infer::canonical::QueryRegionConstraints;
 use rustc_infer::infer::outlives::env::RegionBoundPairs;
@@ -507,7 +507,7 @@ fn sanitize_place(
         if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context {
             let tcx = self.tcx();
             let trait_ref = ty::TraitRef {
-                def_id: tcx.require_lang_item(CopyTraitLangItem, Some(self.last_span)),
+                def_id: tcx.require_lang_item(LangItem::Copy, Some(self.last_span)),
                 substs: tcx.mk_substs_trait(place_ty.ty, &[]),
             };
 
@@ -649,7 +649,7 @@ fn sanitize_projection(
                 PlaceTy::from_ty(match base_ty.kind {
                     ty::Array(inner, _) => {
                         assert!(!from_end, "array subslices should not use from_end");
-                        tcx.mk_array(inner, (to - from) as u64)
+                        tcx.mk_array(inner, to - from)
                     }
                     ty::Slice(..) => {
                         assert!(from_end, "slice subslices should use from_end");
@@ -1474,7 +1474,7 @@ fn check_stmt(&mut self, body: &Body<'tcx>, stmt: &Statement<'tcx>, location: Lo
                 self.check_rvalue(body, rv, location);
                 if !self.tcx().features().unsized_locals {
                     let trait_ref = ty::TraitRef {
-                        def_id: tcx.require_lang_item(SizedTraitLangItem, Some(self.last_span)),
+                        def_id: tcx.require_lang_item(LangItem::Sized, Some(self.last_span)),
                         substs: tcx.mk_substs_trait(place_ty, &[]),
                     };
                     self.prove_trait_ref(
@@ -2025,7 +2025,7 @@ fn check_rvalue(&mut self, body: &Body<'tcx>, rvalue: &Rvalue<'tcx>, location: L
                                     self.param_env,
                                     ty::Binder::bind(ty::TraitRef::new(
                                         self.tcx().require_lang_item(
-                                            CopyTraitLangItem,
+                                            LangItem::Copy,
                                             Some(self.last_span),
                                         ),
                                         tcx.mk_substs_trait(ty, &[]),
@@ -2050,7 +2050,7 @@ fn check_rvalue(&mut self, body: &Body<'tcx>, rvalue: &Rvalue<'tcx>, location: L
                 }
 
                 let trait_ref = ty::TraitRef {
-                    def_id: tcx.require_lang_item(SizedTraitLangItem, Some(self.last_span)),
+                    def_id: tcx.require_lang_item(LangItem::Sized, Some(self.last_span)),
                     substs: tcx.mk_substs_trait(ty, &[]),
                 };
 
@@ -2148,10 +2148,8 @@ fn check_rvalue(&mut self, body: &Body<'tcx>, rvalue: &Rvalue<'tcx>, location: L
                     CastKind::Pointer(PointerCast::Unsize) => {
                         let &ty = ty;
                         let trait_ref = ty::TraitRef {
-                            def_id: tcx.require_lang_item(
-                                CoerceUnsizedTraitLangItem,
-                                Some(self.last_span),
-                            ),
+                            def_id: tcx
+                                .require_lang_item(LangItem::CoerceUnsized, Some(self.last_span)),
                             substs: tcx.mk_substs_trait(op.ty(body, tcx), &[ty.into()]),
                         };
 
index cd6b75cf55602cb7a3150720486190c5e269dd47..9dfc67bcf67aad353376b31fa0baadbd37be3279 100644 (file)
@@ -17,7 +17,7 @@
 use rustc_errors::DiagnosticBuilder;
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_hir::lang_items;
+use rustc_hir::lang_items::LangItem;
 use rustc_hir::{BodyOwnerKind, HirId};
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_infer::infer::{InferCtxt, NLLRegionVariableOrigin};
@@ -456,7 +456,7 @@ fn build(self) -> UniversalRegions<'tcx> {
         if let DefiningTy::FnDef(def_id, _) = defining_ty {
             if self.infcx.tcx.fn_sig(def_id).c_variadic() {
                 let va_list_did = self.infcx.tcx.require_lang_item(
-                    lang_items::VaListTypeLangItem,
+                    LangItem::VaList,
                     Some(self.infcx.tcx.def_span(self.mir_def.did)),
                 );
                 let region = self
index e567063e0d5997db17e1a194c97972e73fae3799..e088dc6a954a3b451975e2a9aa9028bb885632ab 100644 (file)
@@ -480,7 +480,7 @@ fn gather_move(&mut self, place: Place<'tcx>) {
                 }
             };
             let base_ty = base_place.ty(self.builder.body, self.builder.tcx).ty;
-            let len: u32 = match base_ty.kind {
+            let len: u64 = match base_ty.kind {
                 ty::Array(_, size) => {
                     let length = size.eval_usize(self.builder.tcx, self.builder.param_env);
                     length
index fb3a670714b58ad0298612dc5261383d64f27b79..d9be28cf9dbb60c44c5b13234601bcbd050d0198 100644 (file)
@@ -1,6 +1,6 @@
 use std::convert::TryFrom;
 
-use rustc_hir::lang_items::PanicLocationLangItem;
+use rustc_hir::lang_items::LangItem;
 use rustc_middle::mir::TerminatorKind;
 use rustc_middle::ty::subst::Subst;
 use rustc_span::{Span, Symbol};
@@ -63,7 +63,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         // Allocate memory for `CallerLocation` struct.
         let loc_ty = self
             .tcx
-            .type_of(self.tcx.require_lang_item(PanicLocationLangItem, None))
+            .type_of(self.tcx.require_lang_item(LangItem::PanicLocation, None))
             .subst(*self.tcx, self.tcx.mk_substs([self.tcx.lifetimes.re_erased.into()].iter()));
         let loc_layout = self.layout_of(loc_ty).unwrap();
         let location = self.allocate(loc_layout, MemoryKind::CallerLocation);
index 20fd8e43361d6561d9c3cb7c74e52c0d5ee8016b..6ba6103b311a3e3b90d7cf8e694846df382cb634 100644 (file)
@@ -549,17 +549,17 @@ pub(super) fn mplace_projection(
 
             ConstantIndex { offset, min_length, from_end } => {
                 let n = base.len(self)?;
-                if n < u64::from(min_length) {
+                if n < min_length {
                     // This can only be reached in ConstProp and non-rustc-MIR.
                     throw_ub!(BoundsCheckFailed { len: min_length.into(), index: n });
                 }
 
                 let index = if from_end {
                     assert!(0 < offset && offset <= min_length);
-                    n.checked_sub(u64::from(offset)).unwrap()
+                    n.checked_sub(offset).unwrap()
                 } else {
                     assert!(offset < min_length);
-                    u64::from(offset)
+                    offset
                 };
 
                 self.mplace_index(base, index)?
index 3118e7ac3ab17f57ec3e2f7076bd1b03adba385d..2e3b508463540ca5472f407c14abe41394705572 100644 (file)
@@ -22,7 +22,6 @@
 #![feature(try_blocks)]
 #![feature(associated_type_bounds)]
 #![feature(associated_type_defaults)]
-#![feature(range_is_empty)]
 #![feature(stmt_expr_attributes)]
 #![feature(trait_alias)]
 #![feature(option_expect_none)]
index e724180f4d833d588c199cc4bdf46bab1c681410..d379f4ef428a6ce44564c4e6c0596a3e4c17a3e0 100644 (file)
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId, LOCAL_CRATE};
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
-use rustc_hir::lang_items::{ExchangeMallocFnLangItem, StartFnLangItem};
+use rustc_hir::lang_items::LangItem;
 use rustc_index::bit_set::GrowableBitSet;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::mir::interpret::{AllocId, ConstValue};
@@ -594,7 +594,7 @@ fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'tcx>, location: Location) {
             mir::Rvalue::NullaryOp(mir::NullOp::Box, _) => {
                 let tcx = self.tcx;
                 let exchange_malloc_fn_def_id =
-                    tcx.require_lang_item(ExchangeMallocFnLangItem, None);
+                    tcx.require_lang_item(LangItem::ExchangeMalloc, None);
                 let instance = Instance::mono(tcx, exchange_malloc_fn_def_id);
                 if should_codegen_locally(tcx, &instance) {
                     self.output.push(create_fn_mono_item(self.tcx, instance, span));
@@ -1083,7 +1083,7 @@ fn push_extra_entry_roots(&mut self) {
             _ => return,
         };
 
-        let start_def_id = match self.tcx.lang_items().require(StartFnLangItem) {
+        let start_def_id = match self.tcx.lang_items().require(LangItem::Start) {
             Ok(s) => s,
             Err(err) => self.tcx.sess.fatal(&err),
         };
index 15d7b11124071a59b9e0f01eb2abf1791f8ba50f..edafa00a03ad0fd597ba0673d59a6481be745b8d 100644 (file)
@@ -2,7 +2,7 @@
 use rustc_middle::ty::adjustment::CustomCoerceUnsized;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 
-use rustc_hir::lang_items::CoerceUnsizedTraitLangItem;
+use rustc_hir::lang_items::LangItem;
 
 pub mod collector;
 pub mod partitioning;
@@ -13,7 +13,7 @@ pub fn custom_coerce_unsize_info<'tcx>(
     source_ty: Ty<'tcx>,
     target_ty: Ty<'tcx>,
 ) -> CustomCoerceUnsized {
-    let def_id = tcx.require_lang_item(CoerceUnsizedTraitLangItem, None);
+    let def_id = tcx.require_lang_item(LangItem::CoerceUnsized, None);
 
     let trait_ref = ty::Binder::bind(ty::TraitRef {
         def_id,
diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs
deleted file mode 100644 (file)
index 6162651..0000000
+++ /dev/null
@@ -1,1012 +0,0 @@
-//! Partitioning Codegen Units for Incremental Compilation
-//! ======================================================
-//!
-//! The task of this module is to take the complete set of monomorphizations of
-//! a crate and produce a set of codegen units from it, where a codegen unit
-//! is a named set of (mono-item, linkage) pairs. That is, this module
-//! decides which monomorphization appears in which codegen units with which
-//! linkage. The following paragraphs describe some of the background on the
-//! partitioning scheme.
-//!
-//! The most important opportunity for saving on compilation time with
-//! incremental compilation is to avoid re-codegenning and re-optimizing code.
-//! Since the unit of codegen and optimization for LLVM is "modules" or, how
-//! we call them "codegen units", the particulars of how much time can be saved
-//! by incremental compilation are tightly linked to how the output program is
-//! partitioned into these codegen units prior to passing it to LLVM --
-//! especially because we have to treat codegen units as opaque entities once
-//! they are created: There is no way for us to incrementally update an existing
-//! LLVM module and so we have to build any such module from scratch if it was
-//! affected by some change in the source code.
-//!
-//! From that point of view it would make sense to maximize the number of
-//! codegen units by, for example, putting each function into its own module.
-//! That way only those modules would have to be re-compiled that were actually
-//! affected by some change, minimizing the number of functions that could have
-//! been re-used but just happened to be located in a module that is
-//! re-compiled.
-//!
-//! However, since LLVM optimization does not work across module boundaries,
-//! using such a highly granular partitioning would lead to very slow runtime
-//! code since it would effectively prohibit inlining and other inter-procedure
-//! optimizations. We want to avoid that as much as possible.
-//!
-//! Thus we end up with a trade-off: The bigger the codegen units, the better
-//! LLVM's optimizer can do its work, but also the smaller the compilation time
-//! reduction we get from incremental compilation.
-//!
-//! Ideally, we would create a partitioning such that there are few big codegen
-//! units with few interdependencies between them. For now though, we use the
-//! following heuristic to determine the partitioning:
-//!
-//! - There are two codegen units for every source-level module:
-//! - One for "stable", that is non-generic, code
-//! - One for more "volatile" code, i.e., monomorphized instances of functions
-//!   defined in that module
-//!
-//! In order to see why this heuristic makes sense, let's take a look at when a
-//! codegen unit can get invalidated:
-//!
-//! 1. The most straightforward case is when the BODY of a function or global
-//! changes. Then any codegen unit containing the code for that item has to be
-//! re-compiled. Note that this includes all codegen units where the function
-//! has been inlined.
-//!
-//! 2. The next case is when the SIGNATURE of a function or global changes. In
-//! this case, all codegen units containing a REFERENCE to that item have to be
-//! re-compiled. This is a superset of case 1.
-//!
-//! 3. The final and most subtle case is when a REFERENCE to a generic function
-//! is added or removed somewhere. Even though the definition of the function
-//! might be unchanged, a new REFERENCE might introduce a new monomorphized
-//! instance of this function which has to be placed and compiled somewhere.
-//! Conversely, when removing a REFERENCE, it might have been the last one with
-//! that particular set of generic arguments and thus we have to remove it.
-//!
-//! From the above we see that just using one codegen unit per source-level
-//! module is not such a good idea, since just adding a REFERENCE to some
-//! generic item somewhere else would invalidate everything within the module
-//! containing the generic item. The heuristic above reduces this detrimental
-//! side-effect of references a little by at least not touching the non-generic
-//! code of the module.
-//!
-//! A Note on Inlining
-//! ------------------
-//! As briefly mentioned above, in order for LLVM to be able to inline a
-//! function call, the body of the function has to be available in the LLVM
-//! module where the call is made. This has a few consequences for partitioning:
-//!
-//! - The partitioning algorithm has to take care of placing functions into all
-//!   codegen units where they should be available for inlining. It also has to
-//!   decide on the correct linkage for these functions.
-//!
-//! - The partitioning algorithm has to know which functions are likely to get
-//!   inlined, so it can distribute function instantiations accordingly. Since
-//!   there is no way of knowing for sure which functions LLVM will decide to
-//!   inline in the end, we apply a heuristic here: Only functions marked with
-//!   `#[inline]` are considered for inlining by the partitioner. The current
-//!   implementation will not try to determine if a function is likely to be
-//!   inlined by looking at the functions definition.
-//!
-//! Note though that as a side-effect of creating a codegen units per
-//! source-level module, functions from the same module will be available for
-//! inlining, even when they are not marked `#[inline]`.
-
-use std::cmp;
-use std::collections::hash_map::Entry;
-
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_data_structures::sync;
-use rustc_hir::def::DefKind;
-use rustc_hir::def_id::{CrateNum, DefId, DefIdSet, CRATE_DEF_INDEX, LOCAL_CRATE};
-use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
-use rustc_middle::middle::exported_symbols::SymbolExportLevel;
-use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, Linkage, Visibility};
-use rustc_middle::mir::mono::{InstantiationMode, MonoItem};
-use rustc_middle::ty::print::characteristic_def_id_of_type;
-use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::{self, DefIdTree, InstanceDef, TyCtxt};
-use rustc_span::symbol::{Symbol, SymbolStr};
-
-use crate::monomorphize::collector::InliningMap;
-use crate::monomorphize::collector::{self, MonoItemCollectionMode};
-
-// Anything we can't find a proper codegen unit for goes into this.
-fn fallback_cgu_name(name_builder: &mut CodegenUnitNameBuilder<'_>) -> Symbol {
-    name_builder.build_cgu_name(LOCAL_CRATE, &["fallback"], Some("cgu"))
-}
-
-pub fn partition<'tcx, I>(
-    tcx: TyCtxt<'tcx>,
-    mono_items: I,
-    max_cgu_count: usize,
-    inlining_map: &InliningMap<'tcx>,
-) -> Vec<CodegenUnit<'tcx>>
-where
-    I: Iterator<Item = MonoItem<'tcx>>,
-{
-    let _prof_timer = tcx.prof.generic_activity("cgu_partitioning");
-
-    // In the first step, we place all regular monomorphizations into their
-    // respective 'home' codegen unit. Regular monomorphizations are all
-    // functions and statics defined in the local crate.
-    let mut initial_partitioning = {
-        let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_place_roots");
-        place_root_mono_items(tcx, mono_items)
-    };
-
-    initial_partitioning.codegen_units.iter_mut().for_each(|cgu| cgu.estimate_size(tcx));
-
-    debug_dump(tcx, "INITIAL PARTITIONING:", initial_partitioning.codegen_units.iter());
-
-    // Merge until we have at most `max_cgu_count` codegen units.
-    {
-        let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_merge_cgus");
-        merge_codegen_units(tcx, &mut initial_partitioning, max_cgu_count);
-        debug_dump(tcx, "POST MERGING:", initial_partitioning.codegen_units.iter());
-    }
-
-    // In the next step, we use the inlining map to determine which additional
-    // monomorphizations have to go into each codegen unit. These additional
-    // monomorphizations can be drop-glue, functions from external crates, and
-    // local functions the definition of which is marked with `#[inline]`.
-    let mut post_inlining = {
-        let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_place_inline_items");
-        place_inlined_mono_items(initial_partitioning, inlining_map)
-    };
-
-    post_inlining.codegen_units.iter_mut().for_each(|cgu| cgu.estimate_size(tcx));
-
-    debug_dump(tcx, "POST INLINING:", post_inlining.codegen_units.iter());
-
-    // Next we try to make as many symbols "internal" as possible, so LLVM has
-    // more freedom to optimize.
-    if tcx.sess.opts.cg.link_dead_code != Some(true) {
-        let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_internalize_symbols");
-        internalize_symbols(tcx, &mut post_inlining, inlining_map);
-    }
-
-    // Finally, sort by codegen unit name, so that we get deterministic results.
-    let PostInliningPartitioning {
-        codegen_units: mut result,
-        mono_item_placements: _,
-        internalization_candidates: _,
-    } = post_inlining;
-
-    result.sort_by_cached_key(|cgu| cgu.name().as_str());
-
-    result
-}
-
-struct PreInliningPartitioning<'tcx> {
-    codegen_units: Vec<CodegenUnit<'tcx>>,
-    roots: FxHashSet<MonoItem<'tcx>>,
-    internalization_candidates: FxHashSet<MonoItem<'tcx>>,
-}
-
-/// For symbol internalization, we need to know whether a symbol/mono-item is
-/// accessed from outside the codegen unit it is defined in. This type is used
-/// to keep track of that.
-#[derive(Clone, PartialEq, Eq, Debug)]
-enum MonoItemPlacement {
-    SingleCgu { cgu_name: Symbol },
-    MultipleCgus,
-}
-
-struct PostInliningPartitioning<'tcx> {
-    codegen_units: Vec<CodegenUnit<'tcx>>,
-    mono_item_placements: FxHashMap<MonoItem<'tcx>, MonoItemPlacement>,
-    internalization_candidates: FxHashSet<MonoItem<'tcx>>,
-}
-
-fn place_root_mono_items<'tcx, I>(tcx: TyCtxt<'tcx>, mono_items: I) -> PreInliningPartitioning<'tcx>
-where
-    I: Iterator<Item = MonoItem<'tcx>>,
-{
-    let mut roots = FxHashSet::default();
-    let mut codegen_units = FxHashMap::default();
-    let is_incremental_build = tcx.sess.opts.incremental.is_some();
-    let mut internalization_candidates = FxHashSet::default();
-
-    // Determine if monomorphizations instantiated in this crate will be made
-    // available to downstream crates. This depends on whether we are in
-    // share-generics mode and whether the current crate can even have
-    // downstream crates.
-    let export_generics = tcx.sess.opts.share_generics() && tcx.local_crate_exports_generics();
-
-    let cgu_name_builder = &mut CodegenUnitNameBuilder::new(tcx);
-    let cgu_name_cache = &mut FxHashMap::default();
-
-    for mono_item in mono_items {
-        match mono_item.instantiation_mode(tcx) {
-            InstantiationMode::GloballyShared { .. } => {}
-            InstantiationMode::LocalCopy => continue,
-        }
-
-        let characteristic_def_id = characteristic_def_id_of_mono_item(tcx, mono_item);
-        let is_volatile = is_incremental_build && mono_item.is_generic_fn();
-
-        let codegen_unit_name = match characteristic_def_id {
-            Some(def_id) => compute_codegen_unit_name(
-                tcx,
-                cgu_name_builder,
-                def_id,
-                is_volatile,
-                cgu_name_cache,
-            ),
-            None => fallback_cgu_name(cgu_name_builder),
-        };
-
-        let codegen_unit = codegen_units
-            .entry(codegen_unit_name)
-            .or_insert_with(|| CodegenUnit::new(codegen_unit_name));
-
-        let mut can_be_internalized = true;
-        let (linkage, visibility) = mono_item_linkage_and_visibility(
-            tcx,
-            &mono_item,
-            &mut can_be_internalized,
-            export_generics,
-        );
-        if visibility == Visibility::Hidden && can_be_internalized {
-            internalization_candidates.insert(mono_item);
-        }
-
-        codegen_unit.items_mut().insert(mono_item, (linkage, visibility));
-        roots.insert(mono_item);
-    }
-
-    // Always ensure we have at least one CGU; otherwise, if we have a
-    // crate with just types (for example), we could wind up with no CGU.
-    if codegen_units.is_empty() {
-        let codegen_unit_name = fallback_cgu_name(cgu_name_builder);
-        codegen_units.insert(codegen_unit_name, CodegenUnit::new(codegen_unit_name));
-    }
-
-    PreInliningPartitioning {
-        codegen_units: codegen_units.into_iter().map(|(_, codegen_unit)| codegen_unit).collect(),
-        roots,
-        internalization_candidates,
-    }
-}
-
-fn mono_item_linkage_and_visibility(
-    tcx: TyCtxt<'tcx>,
-    mono_item: &MonoItem<'tcx>,
-    can_be_internalized: &mut bool,
-    export_generics: bool,
-) -> (Linkage, Visibility) {
-    if let Some(explicit_linkage) = mono_item.explicit_linkage(tcx) {
-        return (explicit_linkage, Visibility::Default);
-    }
-    let vis = mono_item_visibility(tcx, mono_item, can_be_internalized, export_generics);
-    (Linkage::External, vis)
-}
-
-fn mono_item_visibility(
-    tcx: TyCtxt<'tcx>,
-    mono_item: &MonoItem<'tcx>,
-    can_be_internalized: &mut bool,
-    export_generics: bool,
-) -> Visibility {
-    let instance = match mono_item {
-        // This is pretty complicated; see below.
-        MonoItem::Fn(instance) => instance,
-
-        // Misc handling for generics and such, but otherwise:
-        MonoItem::Static(def_id) => {
-            return if tcx.is_reachable_non_generic(*def_id) {
-                *can_be_internalized = false;
-                default_visibility(tcx, *def_id, false)
-            } else {
-                Visibility::Hidden
-            };
-        }
-        MonoItem::GlobalAsm(hir_id) => {
-            let def_id = tcx.hir().local_def_id(*hir_id);
-            return if tcx.is_reachable_non_generic(def_id) {
-                *can_be_internalized = false;
-                default_visibility(tcx, def_id.to_def_id(), false)
-            } else {
-                Visibility::Hidden
-            };
-        }
-    };
-
-    let def_id = match instance.def {
-        InstanceDef::Item(def) => def.did,
-        InstanceDef::DropGlue(def_id, Some(_)) => def_id,
-
-        // These are all compiler glue and such, never exported, always hidden.
-        InstanceDef::VtableShim(..)
-        | InstanceDef::ReifyShim(..)
-        | InstanceDef::FnPtrShim(..)
-        | InstanceDef::Virtual(..)
-        | InstanceDef::Intrinsic(..)
-        | InstanceDef::ClosureOnceShim { .. }
-        | InstanceDef::DropGlue(..)
-        | InstanceDef::CloneShim(..) => return Visibility::Hidden,
-    };
-
-    // The `start_fn` lang item is actually a monomorphized instance of a
-    // function in the standard library, used for the `main` function. We don't
-    // want to export it so we tag it with `Hidden` visibility but this symbol
-    // is only referenced from the actual `main` symbol which we unfortunately
-    // don't know anything about during partitioning/collection. As a result we
-    // forcibly keep this symbol out of the `internalization_candidates` set.
-    //
-    // FIXME: eventually we don't want to always force this symbol to have
-    //        hidden visibility, it should indeed be a candidate for
-    //        internalization, but we have to understand that it's referenced
-    //        from the `main` symbol we'll generate later.
-    //
-    //        This may be fixable with a new `InstanceDef` perhaps? Unsure!
-    if tcx.lang_items().start_fn() == Some(def_id) {
-        *can_be_internalized = false;
-        return Visibility::Hidden;
-    }
-
-    let is_generic = instance.substs.non_erasable_generics().next().is_some();
-
-    // Upstream `DefId` instances get different handling than local ones.
-    if !def_id.is_local() {
-        return if export_generics && is_generic {
-            // If it is a upstream monomorphization and we export generics, we must make
-            // it available to downstream crates.
-            *can_be_internalized = false;
-            default_visibility(tcx, def_id, true)
-        } else {
-            Visibility::Hidden
-        };
-    }
-
-    if is_generic {
-        if export_generics {
-            if tcx.is_unreachable_local_definition(def_id) {
-                // This instance cannot be used from another crate.
-                Visibility::Hidden
-            } else {
-                // This instance might be useful in a downstream crate.
-                *can_be_internalized = false;
-                default_visibility(tcx, def_id, true)
-            }
-        } else {
-            // We are not exporting generics or the definition is not reachable
-            // for downstream crates, we can internalize its instantiations.
-            Visibility::Hidden
-        }
-    } else {
-        // If this isn't a generic function then we mark this a `Default` if
-        // this is a reachable item, meaning that it's a symbol other crates may
-        // access when they link to us.
-        if tcx.is_reachable_non_generic(def_id) {
-            *can_be_internalized = false;
-            debug_assert!(!is_generic);
-            return default_visibility(tcx, def_id, false);
-        }
-
-        // If this isn't reachable then we're gonna tag this with `Hidden`
-        // visibility. In some situations though we'll want to prevent this
-        // symbol from being internalized.
-        //
-        // There's two categories of items here:
-        //
-        // * First is weak lang items. These are basically mechanisms for
-        //   libcore to forward-reference symbols defined later in crates like
-        //   the standard library or `#[panic_handler]` definitions. The
-        //   definition of these weak lang items needs to be referenceable by
-        //   libcore, so we're no longer a candidate for internalization.
-        //   Removal of these functions can't be done by LLVM but rather must be
-        //   done by the linker as it's a non-local decision.
-        //
-        // * Second is "std internal symbols". Currently this is primarily used
-        //   for allocator symbols. Allocators are a little weird in their
-        //   implementation, but the idea is that the compiler, at the last
-        //   minute, defines an allocator with an injected object file. The
-        //   `alloc` crate references these symbols (`__rust_alloc`) and the
-        //   definition doesn't get hooked up until a linked crate artifact is
-        //   generated.
-        //
-        //   The symbols synthesized by the compiler (`__rust_alloc`) are thin
-        //   veneers around the actual implementation, some other symbol which
-        //   implements the same ABI. These symbols (things like `__rg_alloc`,
-        //   `__rdl_alloc`, `__rde_alloc`, etc), are all tagged with "std
-        //   internal symbols".
-        //
-        //   The std-internal symbols here **should not show up in a dll as an
-        //   exported interface**, so they return `false` from
-        //   `is_reachable_non_generic` above and we'll give them `Hidden`
-        //   visibility below. Like the weak lang items, though, we can't let
-        //   LLVM internalize them as this decision is left up to the linker to
-        //   omit them, so prevent them from being internalized.
-        let attrs = tcx.codegen_fn_attrs(def_id);
-        if attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) {
-            *can_be_internalized = false;
-        }
-
-        Visibility::Hidden
-    }
-}
-
-fn default_visibility(tcx: TyCtxt<'_>, id: DefId, is_generic: bool) -> Visibility {
-    if !tcx.sess.target.target.options.default_hidden_visibility {
-        return Visibility::Default;
-    }
-
-    // Generic functions never have export-level C.
-    if is_generic {
-        return Visibility::Hidden;
-    }
-
-    // Things with export level C don't get instantiated in
-    // downstream crates.
-    if !id.is_local() {
-        return Visibility::Hidden;
-    }
-
-    // C-export level items remain at `Default`, all other internal
-    // items become `Hidden`.
-    match tcx.reachable_non_generics(id.krate).get(&id) {
-        Some(SymbolExportLevel::C) => Visibility::Default,
-        _ => Visibility::Hidden,
-    }
-}
-
-fn merge_codegen_units<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    initial_partitioning: &mut PreInliningPartitioning<'tcx>,
-    target_cgu_count: usize,
-) {
-    assert!(target_cgu_count >= 1);
-    let codegen_units = &mut initial_partitioning.codegen_units;
-
-    // Note that at this point in time the `codegen_units` here may not be in a
-    // deterministic order (but we know they're deterministically the same set).
-    // We want this merging to produce a deterministic ordering of codegen units
-    // from the input.
-    //
-    // Due to basically how we've implemented the merging below (merge the two
-    // smallest into each other) we're sure to start off with a deterministic
-    // order (sorted by name). This'll mean that if two cgus have the same size
-    // the stable sort below will keep everything nice and deterministic.
-    codegen_units.sort_by_cached_key(|cgu| cgu.name().as_str());
-
-    // This map keeps track of what got merged into what.
-    let mut cgu_contents: FxHashMap<Symbol, Vec<SymbolStr>> =
-        codegen_units.iter().map(|cgu| (cgu.name(), vec![cgu.name().as_str()])).collect();
-
-    // Merge the two smallest codegen units until the target size is reached.
-    while codegen_units.len() > target_cgu_count {
-        // Sort small cgus to the back
-        codegen_units.sort_by_cached_key(|cgu| cmp::Reverse(cgu.size_estimate()));
-        let mut smallest = codegen_units.pop().unwrap();
-        let second_smallest = codegen_units.last_mut().unwrap();
-
-        // Move the mono-items from `smallest` to `second_smallest`
-        second_smallest.modify_size_estimate(smallest.size_estimate());
-        for (k, v) in smallest.items_mut().drain() {
-            second_smallest.items_mut().insert(k, v);
-        }
-
-        // Record that `second_smallest` now contains all the stuff that was in
-        // `smallest` before.
-        let mut consumed_cgu_names = cgu_contents.remove(&smallest.name()).unwrap();
-        cgu_contents.get_mut(&second_smallest.name()).unwrap().extend(consumed_cgu_names.drain(..));
-
-        debug!(
-            "CodegenUnit {} merged into CodegenUnit {}",
-            smallest.name(),
-            second_smallest.name()
-        );
-    }
-
-    let cgu_name_builder = &mut CodegenUnitNameBuilder::new(tcx);
-
-    if tcx.sess.opts.incremental.is_some() {
-        // If we are doing incremental compilation, we want CGU names to
-        // reflect the path of the source level module they correspond to.
-        // For CGUs that contain the code of multiple modules because of the
-        // merging done above, we use a concatenation of the names of
-        // all contained CGUs.
-        let new_cgu_names: FxHashMap<Symbol, String> = cgu_contents
-            .into_iter()
-            // This `filter` makes sure we only update the name of CGUs that
-            // were actually modified by merging.
-            .filter(|(_, cgu_contents)| cgu_contents.len() > 1)
-            .map(|(current_cgu_name, cgu_contents)| {
-                let mut cgu_contents: Vec<&str> = cgu_contents.iter().map(|s| &s[..]).collect();
-
-                // Sort the names, so things are deterministic and easy to
-                // predict.
-                cgu_contents.sort();
-
-                (current_cgu_name, cgu_contents.join("--"))
-            })
-            .collect();
-
-        for cgu in codegen_units.iter_mut() {
-            if let Some(new_cgu_name) = new_cgu_names.get(&cgu.name()) {
-                if tcx.sess.opts.debugging_opts.human_readable_cgu_names {
-                    cgu.set_name(Symbol::intern(&new_cgu_name));
-                } else {
-                    // If we don't require CGU names to be human-readable, we
-                    // use a fixed length hash of the composite CGU name
-                    // instead.
-                    let new_cgu_name = CodegenUnit::mangle_name(&new_cgu_name);
-                    cgu.set_name(Symbol::intern(&new_cgu_name));
-                }
-            }
-        }
-    } else {
-        // If we are compiling non-incrementally we just generate simple CGU
-        // names containing an index.
-        for (index, cgu) in codegen_units.iter_mut().enumerate() {
-            cgu.set_name(numbered_codegen_unit_name(cgu_name_builder, index));
-        }
-    }
-}
-
-fn place_inlined_mono_items<'tcx>(
-    initial_partitioning: PreInliningPartitioning<'tcx>,
-    inlining_map: &InliningMap<'tcx>,
-) -> PostInliningPartitioning<'tcx> {
-    let mut new_partitioning = Vec::new();
-    let mut mono_item_placements = FxHashMap::default();
-
-    let PreInliningPartitioning { codegen_units: initial_cgus, roots, internalization_candidates } =
-        initial_partitioning;
-
-    let single_codegen_unit = initial_cgus.len() == 1;
-
-    for old_codegen_unit in initial_cgus {
-        // Collect all items that need to be available in this codegen unit.
-        let mut reachable = FxHashSet::default();
-        for root in old_codegen_unit.items().keys() {
-            follow_inlining(*root, inlining_map, &mut reachable);
-        }
-
-        let mut new_codegen_unit = CodegenUnit::new(old_codegen_unit.name());
-
-        // Add all monomorphizations that are not already there.
-        for mono_item in reachable {
-            if let Some(linkage) = old_codegen_unit.items().get(&mono_item) {
-                // This is a root, just copy it over.
-                new_codegen_unit.items_mut().insert(mono_item, *linkage);
-            } else {
-                if roots.contains(&mono_item) {
-                    bug!(
-                        "GloballyShared mono-item inlined into other CGU: \
-                          {:?}",
-                        mono_item
-                    );
-                }
-
-                // This is a CGU-private copy.
-                new_codegen_unit
-                    .items_mut()
-                    .insert(mono_item, (Linkage::Internal, Visibility::Default));
-            }
-
-            if !single_codegen_unit {
-                // If there is more than one codegen unit, we need to keep track
-                // in which codegen units each monomorphization is placed.
-                match mono_item_placements.entry(mono_item) {
-                    Entry::Occupied(e) => {
-                        let placement = e.into_mut();
-                        debug_assert!(match *placement {
-                            MonoItemPlacement::SingleCgu { cgu_name } => {
-                                cgu_name != new_codegen_unit.name()
-                            }
-                            MonoItemPlacement::MultipleCgus => true,
-                        });
-                        *placement = MonoItemPlacement::MultipleCgus;
-                    }
-                    Entry::Vacant(e) => {
-                        e.insert(MonoItemPlacement::SingleCgu {
-                            cgu_name: new_codegen_unit.name(),
-                        });
-                    }
-                }
-            }
-        }
-
-        new_partitioning.push(new_codegen_unit);
-    }
-
-    return PostInliningPartitioning {
-        codegen_units: new_partitioning,
-        mono_item_placements,
-        internalization_candidates,
-    };
-
-    fn follow_inlining<'tcx>(
-        mono_item: MonoItem<'tcx>,
-        inlining_map: &InliningMap<'tcx>,
-        visited: &mut FxHashSet<MonoItem<'tcx>>,
-    ) {
-        if !visited.insert(mono_item) {
-            return;
-        }
-
-        inlining_map.with_inlining_candidates(mono_item, |target| {
-            follow_inlining(target, inlining_map, visited);
-        });
-    }
-}
-
-fn internalize_symbols<'tcx>(
-    _tcx: TyCtxt<'tcx>,
-    partitioning: &mut PostInliningPartitioning<'tcx>,
-    inlining_map: &InliningMap<'tcx>,
-) {
-    if partitioning.codegen_units.len() == 1 {
-        // Fast path for when there is only one codegen unit. In this case we
-        // can internalize all candidates, since there is nowhere else they
-        // could be accessed from.
-        for cgu in &mut partitioning.codegen_units {
-            for candidate in &partitioning.internalization_candidates {
-                cgu.items_mut().insert(*candidate, (Linkage::Internal, Visibility::Default));
-            }
-        }
-
-        return;
-    }
-
-    // Build a map from every monomorphization to all the monomorphizations that
-    // reference it.
-    let mut accessor_map: FxHashMap<MonoItem<'tcx>, Vec<MonoItem<'tcx>>> = Default::default();
-    inlining_map.iter_accesses(|accessor, accessees| {
-        for accessee in accessees {
-            accessor_map.entry(*accessee).or_default().push(accessor);
-        }
-    });
-
-    let mono_item_placements = &partitioning.mono_item_placements;
-
-    // For each internalization candidates in each codegen unit, check if it is
-    // accessed from outside its defining codegen unit.
-    for cgu in &mut partitioning.codegen_units {
-        let home_cgu = MonoItemPlacement::SingleCgu { cgu_name: cgu.name() };
-
-        for (accessee, linkage_and_visibility) in cgu.items_mut() {
-            if !partitioning.internalization_candidates.contains(accessee) {
-                // This item is no candidate for internalizing, so skip it.
-                continue;
-            }
-            debug_assert_eq!(mono_item_placements[accessee], home_cgu);
-
-            if let Some(accessors) = accessor_map.get(accessee) {
-                if accessors
-                    .iter()
-                    .filter_map(|accessor| {
-                        // Some accessors might not have been
-                        // instantiated. We can safely ignore those.
-                        mono_item_placements.get(accessor)
-                    })
-                    .any(|placement| *placement != home_cgu)
-                {
-                    // Found an accessor from another CGU, so skip to the next
-                    // item without marking this one as internal.
-                    continue;
-                }
-            }
-
-            // If we got here, we did not find any accesses from other CGUs,
-            // so it's fine to make this monomorphization internal.
-            *linkage_and_visibility = (Linkage::Internal, Visibility::Default);
-        }
-    }
-}
-
-fn characteristic_def_id_of_mono_item<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    mono_item: MonoItem<'tcx>,
-) -> Option<DefId> {
-    match mono_item {
-        MonoItem::Fn(instance) => {
-            let def_id = match instance.def {
-                ty::InstanceDef::Item(def) => def.did,
-                ty::InstanceDef::VtableShim(..)
-                | ty::InstanceDef::ReifyShim(..)
-                | ty::InstanceDef::FnPtrShim(..)
-                | ty::InstanceDef::ClosureOnceShim { .. }
-                | ty::InstanceDef::Intrinsic(..)
-                | ty::InstanceDef::DropGlue(..)
-                | ty::InstanceDef::Virtual(..)
-                | ty::InstanceDef::CloneShim(..) => return None,
-            };
-
-            // If this is a method, we want to put it into the same module as
-            // its self-type. If the self-type does not provide a characteristic
-            // DefId, we use the location of the impl after all.
-
-            if tcx.trait_of_item(def_id).is_some() {
-                let self_ty = instance.substs.type_at(0);
-                // This is a default implementation of a trait method.
-                return characteristic_def_id_of_type(self_ty).or(Some(def_id));
-            }
-
-            if let Some(impl_def_id) = tcx.impl_of_method(def_id) {
-                if tcx.sess.opts.incremental.is_some()
-                    && tcx.trait_id_of_impl(impl_def_id) == tcx.lang_items().drop_trait()
-                {
-                    // Put `Drop::drop` into the same cgu as `drop_in_place`
-                    // since `drop_in_place` is the only thing that can
-                    // call it.
-                    return None;
-                }
-                // This is a method within an impl, find out what the self-type is:
-                let impl_self_ty = tcx.subst_and_normalize_erasing_regions(
-                    instance.substs,
-                    ty::ParamEnv::reveal_all(),
-                    &tcx.type_of(impl_def_id),
-                );
-                if let Some(def_id) = characteristic_def_id_of_type(impl_self_ty) {
-                    return Some(def_id);
-                }
-            }
-
-            Some(def_id)
-        }
-        MonoItem::Static(def_id) => Some(def_id),
-        MonoItem::GlobalAsm(hir_id) => Some(tcx.hir().local_def_id(hir_id).to_def_id()),
-    }
-}
-
-type CguNameCache = FxHashMap<(DefId, bool), Symbol>;
-
-fn compute_codegen_unit_name(
-    tcx: TyCtxt<'_>,
-    name_builder: &mut CodegenUnitNameBuilder<'_>,
-    def_id: DefId,
-    volatile: bool,
-    cache: &mut CguNameCache,
-) -> Symbol {
-    // Find the innermost module that is not nested within a function.
-    let mut current_def_id = def_id;
-    let mut cgu_def_id = None;
-    // Walk backwards from the item we want to find the module for.
-    loop {
-        if current_def_id.index == CRATE_DEF_INDEX {
-            if cgu_def_id.is_none() {
-                // If we have not found a module yet, take the crate root.
-                cgu_def_id = Some(DefId { krate: def_id.krate, index: CRATE_DEF_INDEX });
-            }
-            break;
-        } else if tcx.def_kind(current_def_id) == DefKind::Mod {
-            if cgu_def_id.is_none() {
-                cgu_def_id = Some(current_def_id);
-            }
-        } else {
-            // If we encounter something that is not a module, throw away
-            // any module that we've found so far because we now know that
-            // it is nested within something else.
-            cgu_def_id = None;
-        }
-
-        current_def_id = tcx.parent(current_def_id).unwrap();
-    }
-
-    let cgu_def_id = cgu_def_id.unwrap();
-
-    *cache.entry((cgu_def_id, volatile)).or_insert_with(|| {
-        let def_path = tcx.def_path(cgu_def_id);
-
-        let components = def_path.data.iter().map(|part| part.data.as_symbol());
-
-        let volatile_suffix = volatile.then_some("volatile");
-
-        name_builder.build_cgu_name(def_path.krate, components, volatile_suffix)
-    })
-}
-
-fn numbered_codegen_unit_name(
-    name_builder: &mut CodegenUnitNameBuilder<'_>,
-    index: usize,
-) -> Symbol {
-    name_builder.build_cgu_name_no_mangle(LOCAL_CRATE, &["cgu"], Some(index))
-}
-
-fn debug_dump<'a, 'tcx, I>(tcx: TyCtxt<'tcx>, label: &str, cgus: I)
-where
-    I: Iterator<Item = &'a CodegenUnit<'tcx>>,
-    'tcx: 'a,
-{
-    if cfg!(debug_assertions) {
-        debug!("{}", label);
-        for cgu in cgus {
-            debug!("CodegenUnit {} estimated size {} :", cgu.name(), cgu.size_estimate());
-
-            for (mono_item, linkage) in cgu.items() {
-                let symbol_name = mono_item.symbol_name(tcx).name;
-                let symbol_hash_start = symbol_name.rfind('h');
-                let symbol_hash =
-                    symbol_hash_start.map(|i| &symbol_name[i..]).unwrap_or("<no hash>");
-
-                debug!(
-                    " - {} [{:?}] [{}] estimated size {}",
-                    mono_item.to_string(tcx, true),
-                    linkage,
-                    symbol_hash,
-                    mono_item.size_estimate(tcx)
-                );
-            }
-
-            debug!("");
-        }
-    }
-}
-
-#[inline(never)] // give this a place in the profiler
-fn assert_symbols_are_distinct<'a, 'tcx, I>(tcx: TyCtxt<'tcx>, mono_items: I)
-where
-    I: Iterator<Item = &'a MonoItem<'tcx>>,
-    'tcx: 'a,
-{
-    let _prof_timer = tcx.prof.generic_activity("assert_symbols_are_distinct");
-
-    let mut symbols: Vec<_> =
-        mono_items.map(|mono_item| (mono_item, mono_item.symbol_name(tcx))).collect();
-
-    symbols.sort_by_key(|sym| sym.1);
-
-    for pair in symbols.windows(2) {
-        let sym1 = &pair[0].1;
-        let sym2 = &pair[1].1;
-
-        if sym1 == sym2 {
-            let mono_item1 = pair[0].0;
-            let mono_item2 = pair[1].0;
-
-            let span1 = mono_item1.local_span(tcx);
-            let span2 = mono_item2.local_span(tcx);
-
-            // Deterministically select one of the spans for error reporting
-            let span = match (span1, span2) {
-                (Some(span1), Some(span2)) => {
-                    Some(if span1.lo().0 > span2.lo().0 { span1 } else { span2 })
-                }
-                (span1, span2) => span1.or(span2),
-            };
-
-            let error_message = format!("symbol `{}` is already defined", sym1);
-
-            if let Some(span) = span {
-                tcx.sess.span_fatal(span, &error_message)
-            } else {
-                tcx.sess.fatal(&error_message)
-            }
-        }
-    }
-}
-
-fn collect_and_partition_mono_items(
-    tcx: TyCtxt<'tcx>,
-    cnum: CrateNum,
-) -> (&'tcx DefIdSet, &'tcx [CodegenUnit<'tcx>]) {
-    assert_eq!(cnum, LOCAL_CRATE);
-
-    let collection_mode = match tcx.sess.opts.debugging_opts.print_mono_items {
-        Some(ref s) => {
-            let mode_string = s.to_lowercase();
-            let mode_string = mode_string.trim();
-            if mode_string == "eager" {
-                MonoItemCollectionMode::Eager
-            } else {
-                if mode_string != "lazy" {
-                    let message = format!(
-                        "Unknown codegen-item collection mode '{}'. \
-                                           Falling back to 'lazy' mode.",
-                        mode_string
-                    );
-                    tcx.sess.warn(&message);
-                }
-
-                MonoItemCollectionMode::Lazy
-            }
-        }
-        None => {
-            if tcx.sess.opts.cg.link_dead_code == Some(true) {
-                MonoItemCollectionMode::Eager
-            } else {
-                MonoItemCollectionMode::Lazy
-            }
-        }
-    };
-
-    let (items, inlining_map) = collector::collect_crate_mono_items(tcx, collection_mode);
-
-    tcx.sess.abort_if_errors();
-
-    let (codegen_units, _) = tcx.sess.time("partition_and_assert_distinct_symbols", || {
-        sync::join(
-            || {
-                &*tcx.arena.alloc_from_iter(partition(
-                    tcx,
-                    items.iter().cloned(),
-                    tcx.sess.codegen_units(),
-                    &inlining_map,
-                ))
-            },
-            || assert_symbols_are_distinct(tcx, items.iter()),
-        )
-    });
-
-    let mono_items: DefIdSet = items
-        .iter()
-        .filter_map(|mono_item| match *mono_item {
-            MonoItem::Fn(ref instance) => Some(instance.def_id()),
-            MonoItem::Static(def_id) => Some(def_id),
-            _ => None,
-        })
-        .collect();
-
-    if tcx.sess.opts.debugging_opts.print_mono_items.is_some() {
-        let mut item_to_cgus: FxHashMap<_, Vec<_>> = Default::default();
-
-        for cgu in codegen_units {
-            for (&mono_item, &linkage) in cgu.items() {
-                item_to_cgus.entry(mono_item).or_default().push((cgu.name(), linkage));
-            }
-        }
-
-        let mut item_keys: Vec<_> = items
-            .iter()
-            .map(|i| {
-                let mut output = i.to_string(tcx, false);
-                output.push_str(" @@");
-                let mut empty = Vec::new();
-                let cgus = item_to_cgus.get_mut(i).unwrap_or(&mut empty);
-                cgus.sort_by_key(|(name, _)| *name);
-                cgus.dedup();
-                for &(ref cgu_name, (linkage, _)) in cgus.iter() {
-                    output.push_str(" ");
-                    output.push_str(&cgu_name.as_str());
-
-                    let linkage_abbrev = match linkage {
-                        Linkage::External => "External",
-                        Linkage::AvailableExternally => "Available",
-                        Linkage::LinkOnceAny => "OnceAny",
-                        Linkage::LinkOnceODR => "OnceODR",
-                        Linkage::WeakAny => "WeakAny",
-                        Linkage::WeakODR => "WeakODR",
-                        Linkage::Appending => "Appending",
-                        Linkage::Internal => "Internal",
-                        Linkage::Private => "Private",
-                        Linkage::ExternalWeak => "ExternalWeak",
-                        Linkage::Common => "Common",
-                    };
-
-                    output.push_str("[");
-                    output.push_str(linkage_abbrev);
-                    output.push_str("]");
-                }
-                output
-            })
-            .collect();
-
-        item_keys.sort();
-
-        for item in item_keys {
-            println!("MONO_ITEM {}", item);
-        }
-    }
-
-    (tcx.arena.alloc(mono_items), codegen_units)
-}
-
-pub fn provide(providers: &mut Providers) {
-    providers.collect_and_partition_mono_items = collect_and_partition_mono_items;
-
-    providers.is_codegened_item = |tcx, def_id| {
-        let (all_mono_items, _) = tcx.collect_and_partition_mono_items(LOCAL_CRATE);
-        all_mono_items.contains(&def_id)
-    };
-
-    providers.codegen_unit = |tcx, name| {
-        let (_, all) = tcx.collect_and_partition_mono_items(LOCAL_CRATE);
-        all.iter()
-            .find(|cgu| cgu.name() == name)
-            .unwrap_or_else(|| panic!("failed to find cgu with name {:?}", name))
-    };
-}
diff --git a/src/librustc_mir/monomorphize/partitioning/default.rs b/src/librustc_mir/monomorphize/partitioning/default.rs
new file mode 100644 (file)
index 0000000..b48bae8
--- /dev/null
@@ -0,0 +1,552 @@
+use std::collections::hash_map::Entry;
+
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_hir::def::DefKind;
+use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
+use rustc_middle::middle::exported_symbols::SymbolExportLevel;
+use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, Linkage, Visibility};
+use rustc_middle::mir::mono::{InstantiationMode, MonoItem};
+use rustc_middle::ty::print::characteristic_def_id_of_type;
+use rustc_middle::ty::{self, DefIdTree, InstanceDef, TyCtxt};
+use rustc_span::symbol::Symbol;
+
+use crate::monomorphize::collector::InliningMap;
+use crate::monomorphize::partitioning::merging;
+use crate::monomorphize::partitioning::{
+    MonoItemPlacement, Partitioner, PostInliningPartitioning, PreInliningPartitioning,
+};
+
+pub struct DefaultPartitioning;
+
+impl<'tcx> Partitioner<'tcx> for DefaultPartitioning {
+    fn place_root_mono_items(
+        &mut self,
+        tcx: TyCtxt<'tcx>,
+        mono_items: &mut dyn Iterator<Item = MonoItem<'tcx>>,
+    ) -> PreInliningPartitioning<'tcx> {
+        let mut roots = FxHashSet::default();
+        let mut codegen_units = FxHashMap::default();
+        let is_incremental_build = tcx.sess.opts.incremental.is_some();
+        let mut internalization_candidates = FxHashSet::default();
+
+        // Determine if monomorphizations instantiated in this crate will be made
+        // available to downstream crates. This depends on whether we are in
+        // share-generics mode and whether the current crate can even have
+        // downstream crates.
+        let export_generics = tcx.sess.opts.share_generics() && tcx.local_crate_exports_generics();
+
+        let cgu_name_builder = &mut CodegenUnitNameBuilder::new(tcx);
+        let cgu_name_cache = &mut FxHashMap::default();
+
+        for mono_item in mono_items {
+            match mono_item.instantiation_mode(tcx) {
+                InstantiationMode::GloballyShared { .. } => {}
+                InstantiationMode::LocalCopy => continue,
+            }
+
+            let characteristic_def_id = characteristic_def_id_of_mono_item(tcx, mono_item);
+            let is_volatile = is_incremental_build && mono_item.is_generic_fn();
+
+            let codegen_unit_name = match characteristic_def_id {
+                Some(def_id) => compute_codegen_unit_name(
+                    tcx,
+                    cgu_name_builder,
+                    def_id,
+                    is_volatile,
+                    cgu_name_cache,
+                ),
+                None => fallback_cgu_name(cgu_name_builder),
+            };
+
+            let codegen_unit = codegen_units
+                .entry(codegen_unit_name)
+                .or_insert_with(|| CodegenUnit::new(codegen_unit_name));
+
+            let mut can_be_internalized = true;
+            let (linkage, visibility) = mono_item_linkage_and_visibility(
+                tcx,
+                &mono_item,
+                &mut can_be_internalized,
+                export_generics,
+            );
+            if visibility == Visibility::Hidden && can_be_internalized {
+                internalization_candidates.insert(mono_item);
+            }
+
+            codegen_unit.items_mut().insert(mono_item, (linkage, visibility));
+            roots.insert(mono_item);
+        }
+
+        // Always ensure we have at least one CGU; otherwise, if we have a
+        // crate with just types (for example), we could wind up with no CGU.
+        if codegen_units.is_empty() {
+            let codegen_unit_name = fallback_cgu_name(cgu_name_builder);
+            codegen_units.insert(codegen_unit_name, CodegenUnit::new(codegen_unit_name));
+        }
+
+        PreInliningPartitioning {
+            codegen_units: codegen_units
+                .into_iter()
+                .map(|(_, codegen_unit)| codegen_unit)
+                .collect(),
+            roots,
+            internalization_candidates,
+        }
+    }
+
+    fn merge_codegen_units(
+        &mut self,
+        tcx: TyCtxt<'tcx>,
+        initial_partitioning: &mut PreInliningPartitioning<'tcx>,
+        target_cgu_count: usize,
+    ) {
+        merging::merge_codegen_units(tcx, initial_partitioning, target_cgu_count);
+    }
+
+    fn place_inlined_mono_items(
+        &mut self,
+        initial_partitioning: PreInliningPartitioning<'tcx>,
+        inlining_map: &InliningMap<'tcx>,
+    ) -> PostInliningPartitioning<'tcx> {
+        let mut new_partitioning = Vec::new();
+        let mut mono_item_placements = FxHashMap::default();
+
+        let PreInliningPartitioning {
+            codegen_units: initial_cgus,
+            roots,
+            internalization_candidates,
+        } = initial_partitioning;
+
+        let single_codegen_unit = initial_cgus.len() == 1;
+
+        for old_codegen_unit in initial_cgus {
+            // Collect all items that need to be available in this codegen unit.
+            let mut reachable = FxHashSet::default();
+            for root in old_codegen_unit.items().keys() {
+                follow_inlining(*root, inlining_map, &mut reachable);
+            }
+
+            let mut new_codegen_unit = CodegenUnit::new(old_codegen_unit.name());
+
+            // Add all monomorphizations that are not already there.
+            for mono_item in reachable {
+                if let Some(linkage) = old_codegen_unit.items().get(&mono_item) {
+                    // This is a root, just copy it over.
+                    new_codegen_unit.items_mut().insert(mono_item, *linkage);
+                } else {
+                    if roots.contains(&mono_item) {
+                        bug!(
+                            "GloballyShared mono-item inlined into other CGU: \
+                              {:?}",
+                            mono_item
+                        );
+                    }
+
+                    // This is a CGU-private copy.
+                    new_codegen_unit
+                        .items_mut()
+                        .insert(mono_item, (Linkage::Internal, Visibility::Default));
+                }
+
+                if !single_codegen_unit {
+                    // If there is more than one codegen unit, we need to keep track
+                    // in which codegen units each monomorphization is placed.
+                    match mono_item_placements.entry(mono_item) {
+                        Entry::Occupied(e) => {
+                            let placement = e.into_mut();
+                            debug_assert!(match *placement {
+                                MonoItemPlacement::SingleCgu { cgu_name } => {
+                                    cgu_name != new_codegen_unit.name()
+                                }
+                                MonoItemPlacement::MultipleCgus => true,
+                            });
+                            *placement = MonoItemPlacement::MultipleCgus;
+                        }
+                        Entry::Vacant(e) => {
+                            e.insert(MonoItemPlacement::SingleCgu {
+                                cgu_name: new_codegen_unit.name(),
+                            });
+                        }
+                    }
+                }
+            }
+
+            new_partitioning.push(new_codegen_unit);
+        }
+
+        return PostInliningPartitioning {
+            codegen_units: new_partitioning,
+            mono_item_placements,
+            internalization_candidates,
+        };
+
+        fn follow_inlining<'tcx>(
+            mono_item: MonoItem<'tcx>,
+            inlining_map: &InliningMap<'tcx>,
+            visited: &mut FxHashSet<MonoItem<'tcx>>,
+        ) {
+            if !visited.insert(mono_item) {
+                return;
+            }
+
+            inlining_map.with_inlining_candidates(mono_item, |target| {
+                follow_inlining(target, inlining_map, visited);
+            });
+        }
+    }
+
+    fn internalize_symbols(
+        &mut self,
+        _tcx: TyCtxt<'tcx>,
+        partitioning: &mut PostInliningPartitioning<'tcx>,
+        inlining_map: &InliningMap<'tcx>,
+    ) {
+        if partitioning.codegen_units.len() == 1 {
+            // Fast path for when there is only one codegen unit. In this case we
+            // can internalize all candidates, since there is nowhere else they
+            // could be accessed from.
+            for cgu in &mut partitioning.codegen_units {
+                for candidate in &partitioning.internalization_candidates {
+                    cgu.items_mut().insert(*candidate, (Linkage::Internal, Visibility::Default));
+                }
+            }
+
+            return;
+        }
+
+        // Build a map from every monomorphization to all the monomorphizations that
+        // reference it.
+        let mut accessor_map: FxHashMap<MonoItem<'tcx>, Vec<MonoItem<'tcx>>> = Default::default();
+        inlining_map.iter_accesses(|accessor, accessees| {
+            for accessee in accessees {
+                accessor_map.entry(*accessee).or_default().push(accessor);
+            }
+        });
+
+        let mono_item_placements = &partitioning.mono_item_placements;
+
+        // For each internalization candidates in each codegen unit, check if it is
+        // accessed from outside its defining codegen unit.
+        for cgu in &mut partitioning.codegen_units {
+            let home_cgu = MonoItemPlacement::SingleCgu { cgu_name: cgu.name() };
+
+            for (accessee, linkage_and_visibility) in cgu.items_mut() {
+                if !partitioning.internalization_candidates.contains(accessee) {
+                    // This item is no candidate for internalizing, so skip it.
+                    continue;
+                }
+                debug_assert_eq!(mono_item_placements[accessee], home_cgu);
+
+                if let Some(accessors) = accessor_map.get(accessee) {
+                    if accessors
+                        .iter()
+                        .filter_map(|accessor| {
+                            // Some accessors might not have been
+                            // instantiated. We can safely ignore those.
+                            mono_item_placements.get(accessor)
+                        })
+                        .any(|placement| *placement != home_cgu)
+                    {
+                        // Found an accessor from another CGU, so skip to the next
+                        // item without marking this one as internal.
+                        continue;
+                    }
+                }
+
+                // If we got here, we did not find any accesses from other CGUs,
+                // so it's fine to make this monomorphization internal.
+                *linkage_and_visibility = (Linkage::Internal, Visibility::Default);
+            }
+        }
+    }
+}
+
+fn characteristic_def_id_of_mono_item<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    mono_item: MonoItem<'tcx>,
+) -> Option<DefId> {
+    match mono_item {
+        MonoItem::Fn(instance) => {
+            let def_id = match instance.def {
+                ty::InstanceDef::Item(def) => def.did,
+                ty::InstanceDef::VtableShim(..)
+                | ty::InstanceDef::ReifyShim(..)
+                | ty::InstanceDef::FnPtrShim(..)
+                | ty::InstanceDef::ClosureOnceShim { .. }
+                | ty::InstanceDef::Intrinsic(..)
+                | ty::InstanceDef::DropGlue(..)
+                | ty::InstanceDef::Virtual(..)
+                | ty::InstanceDef::CloneShim(..) => return None,
+            };
+
+            // If this is a method, we want to put it into the same module as
+            // its self-type. If the self-type does not provide a characteristic
+            // DefId, we use the location of the impl after all.
+
+            if tcx.trait_of_item(def_id).is_some() {
+                let self_ty = instance.substs.type_at(0);
+                // This is a default implementation of a trait method.
+                return characteristic_def_id_of_type(self_ty).or(Some(def_id));
+            }
+
+            if let Some(impl_def_id) = tcx.impl_of_method(def_id) {
+                if tcx.sess.opts.incremental.is_some()
+                    && tcx.trait_id_of_impl(impl_def_id) == tcx.lang_items().drop_trait()
+                {
+                    // Put `Drop::drop` into the same cgu as `drop_in_place`
+                    // since `drop_in_place` is the only thing that can
+                    // call it.
+                    return None;
+                }
+                // This is a method within an impl, find out what the self-type is:
+                let impl_self_ty = tcx.subst_and_normalize_erasing_regions(
+                    instance.substs,
+                    ty::ParamEnv::reveal_all(),
+                    &tcx.type_of(impl_def_id),
+                );
+                if let Some(def_id) = characteristic_def_id_of_type(impl_self_ty) {
+                    return Some(def_id);
+                }
+            }
+
+            Some(def_id)
+        }
+        MonoItem::Static(def_id) => Some(def_id),
+        MonoItem::GlobalAsm(hir_id) => Some(tcx.hir().local_def_id(hir_id).to_def_id()),
+    }
+}
+
+fn compute_codegen_unit_name(
+    tcx: TyCtxt<'_>,
+    name_builder: &mut CodegenUnitNameBuilder<'_>,
+    def_id: DefId,
+    volatile: bool,
+    cache: &mut CguNameCache,
+) -> Symbol {
+    // Find the innermost module that is not nested within a function.
+    let mut current_def_id = def_id;
+    let mut cgu_def_id = None;
+    // Walk backwards from the item we want to find the module for.
+    loop {
+        if current_def_id.index == CRATE_DEF_INDEX {
+            if cgu_def_id.is_none() {
+                // If we have not found a module yet, take the crate root.
+                cgu_def_id = Some(DefId { krate: def_id.krate, index: CRATE_DEF_INDEX });
+            }
+            break;
+        } else if tcx.def_kind(current_def_id) == DefKind::Mod {
+            if cgu_def_id.is_none() {
+                cgu_def_id = Some(current_def_id);
+            }
+        } else {
+            // If we encounter something that is not a module, throw away
+            // any module that we've found so far because we now know that
+            // it is nested within something else.
+            cgu_def_id = None;
+        }
+
+        current_def_id = tcx.parent(current_def_id).unwrap();
+    }
+
+    let cgu_def_id = cgu_def_id.unwrap();
+
+    *cache.entry((cgu_def_id, volatile)).or_insert_with(|| {
+        let def_path = tcx.def_path(cgu_def_id);
+
+        let components = def_path.data.iter().map(|part| part.data.as_symbol());
+
+        let volatile_suffix = volatile.then_some("volatile");
+
+        name_builder.build_cgu_name(def_path.krate, components, volatile_suffix)
+    })
+}
+
+// Anything we can't find a proper codegen unit for goes into this.
+fn fallback_cgu_name(name_builder: &mut CodegenUnitNameBuilder<'_>) -> Symbol {
+    name_builder.build_cgu_name(LOCAL_CRATE, &["fallback"], Some("cgu"))
+}
+
+fn mono_item_linkage_and_visibility(
+    tcx: TyCtxt<'tcx>,
+    mono_item: &MonoItem<'tcx>,
+    can_be_internalized: &mut bool,
+    export_generics: bool,
+) -> (Linkage, Visibility) {
+    if let Some(explicit_linkage) = mono_item.explicit_linkage(tcx) {
+        return (explicit_linkage, Visibility::Default);
+    }
+    let vis = mono_item_visibility(tcx, mono_item, can_be_internalized, export_generics);
+    (Linkage::External, vis)
+}
+
+type CguNameCache = FxHashMap<(DefId, bool), Symbol>;
+
+fn mono_item_visibility(
+    tcx: TyCtxt<'tcx>,
+    mono_item: &MonoItem<'tcx>,
+    can_be_internalized: &mut bool,
+    export_generics: bool,
+) -> Visibility {
+    let instance = match mono_item {
+        // This is pretty complicated; see below.
+        MonoItem::Fn(instance) => instance,
+
+        // Misc handling for generics and such, but otherwise:
+        MonoItem::Static(def_id) => {
+            return if tcx.is_reachable_non_generic(*def_id) {
+                *can_be_internalized = false;
+                default_visibility(tcx, *def_id, false)
+            } else {
+                Visibility::Hidden
+            };
+        }
+        MonoItem::GlobalAsm(hir_id) => {
+            let def_id = tcx.hir().local_def_id(*hir_id);
+            return if tcx.is_reachable_non_generic(def_id) {
+                *can_be_internalized = false;
+                default_visibility(tcx, def_id.to_def_id(), false)
+            } else {
+                Visibility::Hidden
+            };
+        }
+    };
+
+    let def_id = match instance.def {
+        InstanceDef::Item(def) => def.did,
+        InstanceDef::DropGlue(def_id, Some(_)) => def_id,
+
+        // These are all compiler glue and such, never exported, always hidden.
+        InstanceDef::VtableShim(..)
+        | InstanceDef::ReifyShim(..)
+        | InstanceDef::FnPtrShim(..)
+        | InstanceDef::Virtual(..)
+        | InstanceDef::Intrinsic(..)
+        | InstanceDef::ClosureOnceShim { .. }
+        | InstanceDef::DropGlue(..)
+        | InstanceDef::CloneShim(..) => return Visibility::Hidden,
+    };
+
+    // The `start_fn` lang item is actually a monomorphized instance of a
+    // function in the standard library, used for the `main` function. We don't
+    // want to export it so we tag it with `Hidden` visibility but this symbol
+    // is only referenced from the actual `main` symbol which we unfortunately
+    // don't know anything about during partitioning/collection. As a result we
+    // forcibly keep this symbol out of the `internalization_candidates` set.
+    //
+    // FIXME: eventually we don't want to always force this symbol to have
+    //        hidden visibility, it should indeed be a candidate for
+    //        internalization, but we have to understand that it's referenced
+    //        from the `main` symbol we'll generate later.
+    //
+    //        This may be fixable with a new `InstanceDef` perhaps? Unsure!
+    if tcx.lang_items().start_fn() == Some(def_id) {
+        *can_be_internalized = false;
+        return Visibility::Hidden;
+    }
+
+    let is_generic = instance.substs.non_erasable_generics().next().is_some();
+
+    // Upstream `DefId` instances get different handling than local ones.
+    if !def_id.is_local() {
+        return if export_generics && is_generic {
+            // If it is a upstream monomorphization and we export generics, we must make
+            // it available to downstream crates.
+            *can_be_internalized = false;
+            default_visibility(tcx, def_id, true)
+        } else {
+            Visibility::Hidden
+        };
+    }
+
+    if is_generic {
+        if export_generics {
+            if tcx.is_unreachable_local_definition(def_id) {
+                // This instance cannot be used from another crate.
+                Visibility::Hidden
+            } else {
+                // This instance might be useful in a downstream crate.
+                *can_be_internalized = false;
+                default_visibility(tcx, def_id, true)
+            }
+        } else {
+            // We are not exporting generics or the definition is not reachable
+            // for downstream crates, we can internalize its instantiations.
+            Visibility::Hidden
+        }
+    } else {
+        // If this isn't a generic function then we mark this a `Default` if
+        // this is a reachable item, meaning that it's a symbol other crates may
+        // access when they link to us.
+        if tcx.is_reachable_non_generic(def_id) {
+            *can_be_internalized = false;
+            debug_assert!(!is_generic);
+            return default_visibility(tcx, def_id, false);
+        }
+
+        // If this isn't reachable then we're gonna tag this with `Hidden`
+        // visibility. In some situations though we'll want to prevent this
+        // symbol from being internalized.
+        //
+        // There's two categories of items here:
+        //
+        // * First is weak lang items. These are basically mechanisms for
+        //   libcore to forward-reference symbols defined later in crates like
+        //   the standard library or `#[panic_handler]` definitions. The
+        //   definition of these weak lang items needs to be referenceable by
+        //   libcore, so we're no longer a candidate for internalization.
+        //   Removal of these functions can't be done by LLVM but rather must be
+        //   done by the linker as it's a non-local decision.
+        //
+        // * Second is "std internal symbols". Currently this is primarily used
+        //   for allocator symbols. Allocators are a little weird in their
+        //   implementation, but the idea is that the compiler, at the last
+        //   minute, defines an allocator with an injected object file. The
+        //   `alloc` crate references these symbols (`__rust_alloc`) and the
+        //   definition doesn't get hooked up until a linked crate artifact is
+        //   generated.
+        //
+        //   The symbols synthesized by the compiler (`__rust_alloc`) are thin
+        //   veneers around the actual implementation, some other symbol which
+        //   implements the same ABI. These symbols (things like `__rg_alloc`,
+        //   `__rdl_alloc`, `__rde_alloc`, etc), are all tagged with "std
+        //   internal symbols".
+        //
+        //   The std-internal symbols here **should not show up in a dll as an
+        //   exported interface**, so they return `false` from
+        //   `is_reachable_non_generic` above and we'll give them `Hidden`
+        //   visibility below. Like the weak lang items, though, we can't let
+        //   LLVM internalize them as this decision is left up to the linker to
+        //   omit them, so prevent them from being internalized.
+        let attrs = tcx.codegen_fn_attrs(def_id);
+        if attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) {
+            *can_be_internalized = false;
+        }
+
+        Visibility::Hidden
+    }
+}
+
+fn default_visibility(tcx: TyCtxt<'_>, id: DefId, is_generic: bool) -> Visibility {
+    if !tcx.sess.target.target.options.default_hidden_visibility {
+        return Visibility::Default;
+    }
+
+    // Generic functions never have export-level C.
+    if is_generic {
+        return Visibility::Hidden;
+    }
+
+    // Things with export level C don't get instantiated in
+    // downstream crates.
+    if !id.is_local() {
+        return Visibility::Hidden;
+    }
+
+    // C-export level items remain at `Default`, all other internal
+    // items become `Hidden`.
+    match tcx.reachable_non_generics(id.krate).get(&id) {
+        Some(SymbolExportLevel::C) => Visibility::Default,
+        _ => Visibility::Hidden,
+    }
+}
diff --git a/src/librustc_mir/monomorphize/partitioning/merging.rs b/src/librustc_mir/monomorphize/partitioning/merging.rs
new file mode 100644 (file)
index 0000000..1787e6d
--- /dev/null
@@ -0,0 +1,110 @@
+use std::cmp;
+
+use rustc_data_structures::fx::FxHashMap;
+use rustc_hir::def_id::LOCAL_CRATE;
+use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder};
+use rustc_middle::ty::TyCtxt;
+use rustc_span::symbol::{Symbol, SymbolStr};
+
+use crate::monomorphize::partitioning::PreInliningPartitioning;
+
+pub fn merge_codegen_units<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    initial_partitioning: &mut PreInliningPartitioning<'tcx>,
+    target_cgu_count: usize,
+) {
+    assert!(target_cgu_count >= 1);
+    let codegen_units = &mut initial_partitioning.codegen_units;
+
+    // Note that at this point in time the `codegen_units` here may not be in a
+    // deterministic order (but we know they're deterministically the same set).
+    // We want this merging to produce a deterministic ordering of codegen units
+    // from the input.
+    //
+    // Due to basically how we've implemented the merging below (merge the two
+    // smallest into each other) we're sure to start off with a deterministic
+    // order (sorted by name). This'll mean that if two cgus have the same size
+    // the stable sort below will keep everything nice and deterministic.
+    codegen_units.sort_by_cached_key(|cgu| cgu.name().as_str());
+
+    // This map keeps track of what got merged into what.
+    let mut cgu_contents: FxHashMap<Symbol, Vec<SymbolStr>> =
+        codegen_units.iter().map(|cgu| (cgu.name(), vec![cgu.name().as_str()])).collect();
+
+    // Merge the two smallest codegen units until the target size is reached.
+    while codegen_units.len() > target_cgu_count {
+        // Sort small cgus to the back
+        codegen_units.sort_by_cached_key(|cgu| cmp::Reverse(cgu.size_estimate()));
+        let mut smallest = codegen_units.pop().unwrap();
+        let second_smallest = codegen_units.last_mut().unwrap();
+
+        // Move the mono-items from `smallest` to `second_smallest`
+        second_smallest.modify_size_estimate(smallest.size_estimate());
+        for (k, v) in smallest.items_mut().drain() {
+            second_smallest.items_mut().insert(k, v);
+        }
+
+        // Record that `second_smallest` now contains all the stuff that was in
+        // `smallest` before.
+        let mut consumed_cgu_names = cgu_contents.remove(&smallest.name()).unwrap();
+        cgu_contents.get_mut(&second_smallest.name()).unwrap().extend(consumed_cgu_names.drain(..));
+
+        debug!(
+            "CodegenUnit {} merged into CodegenUnit {}",
+            smallest.name(),
+            second_smallest.name()
+        );
+    }
+
+    let cgu_name_builder = &mut CodegenUnitNameBuilder::new(tcx);
+
+    if tcx.sess.opts.incremental.is_some() {
+        // If we are doing incremental compilation, we want CGU names to
+        // reflect the path of the source level module they correspond to.
+        // For CGUs that contain the code of multiple modules because of the
+        // merging done above, we use a concatenation of the names of
+        // all contained CGUs.
+        let new_cgu_names: FxHashMap<Symbol, String> = cgu_contents
+            .into_iter()
+            // This `filter` makes sure we only update the name of CGUs that
+            // were actually modified by merging.
+            .filter(|(_, cgu_contents)| cgu_contents.len() > 1)
+            .map(|(current_cgu_name, cgu_contents)| {
+                let mut cgu_contents: Vec<&str> = cgu_contents.iter().map(|s| &s[..]).collect();
+
+                // Sort the names, so things are deterministic and easy to
+                // predict.
+                cgu_contents.sort();
+
+                (current_cgu_name, cgu_contents.join("--"))
+            })
+            .collect();
+
+        for cgu in codegen_units.iter_mut() {
+            if let Some(new_cgu_name) = new_cgu_names.get(&cgu.name()) {
+                if tcx.sess.opts.debugging_opts.human_readable_cgu_names {
+                    cgu.set_name(Symbol::intern(&new_cgu_name));
+                } else {
+                    // If we don't require CGU names to be human-readable, we
+                    // use a fixed length hash of the composite CGU name
+                    // instead.
+                    let new_cgu_name = CodegenUnit::mangle_name(&new_cgu_name);
+                    cgu.set_name(Symbol::intern(&new_cgu_name));
+                }
+            }
+        }
+    } else {
+        // If we are compiling non-incrementally we just generate simple CGU
+        // names containing an index.
+        for (index, cgu) in codegen_units.iter_mut().enumerate() {
+            cgu.set_name(numbered_codegen_unit_name(cgu_name_builder, index));
+        }
+    }
+}
+
+fn numbered_codegen_unit_name(
+    name_builder: &mut CodegenUnitNameBuilder<'_>,
+    index: usize,
+) -> Symbol {
+    name_builder.build_cgu_name_no_mangle(LOCAL_CRATE, &["cgu"], Some(index))
+}
diff --git a/src/librustc_mir/monomorphize/partitioning/mod.rs b/src/librustc_mir/monomorphize/partitioning/mod.rs
new file mode 100644 (file)
index 0000000..9dfbd65
--- /dev/null
@@ -0,0 +1,433 @@
+//! Partitioning Codegen Units for Incremental Compilation
+//! ======================================================
+//!
+//! The task of this module is to take the complete set of monomorphizations of
+//! a crate and produce a set of codegen units from it, where a codegen unit
+//! is a named set of (mono-item, linkage) pairs. That is, this module
+//! decides which monomorphization appears in which codegen units with which
+//! linkage. The following paragraphs describe some of the background on the
+//! partitioning scheme.
+//!
+//! The most important opportunity for saving on compilation time with
+//! incremental compilation is to avoid re-codegenning and re-optimizing code.
+//! Since the unit of codegen and optimization for LLVM is "modules" or, how
+//! we call them "codegen units", the particulars of how much time can be saved
+//! by incremental compilation are tightly linked to how the output program is
+//! partitioned into these codegen units prior to passing it to LLVM --
+//! especially because we have to treat codegen units as opaque entities once
+//! they are created: There is no way for us to incrementally update an existing
+//! LLVM module and so we have to build any such module from scratch if it was
+//! affected by some change in the source code.
+//!
+//! From that point of view it would make sense to maximize the number of
+//! codegen units by, for example, putting each function into its own module.
+//! That way only those modules would have to be re-compiled that were actually
+//! affected by some change, minimizing the number of functions that could have
+//! been re-used but just happened to be located in a module that is
+//! re-compiled.
+//!
+//! However, since LLVM optimization does not work across module boundaries,
+//! using such a highly granular partitioning would lead to very slow runtime
+//! code since it would effectively prohibit inlining and other inter-procedure
+//! optimizations. We want to avoid that as much as possible.
+//!
+//! Thus we end up with a trade-off: The bigger the codegen units, the better
+//! LLVM's optimizer can do its work, but also the smaller the compilation time
+//! reduction we get from incremental compilation.
+//!
+//! Ideally, we would create a partitioning such that there are few big codegen
+//! units with few interdependencies between them. For now though, we use the
+//! following heuristic to determine the partitioning:
+//!
+//! - There are two codegen units for every source-level module:
+//! - One for "stable", that is non-generic, code
+//! - One for more "volatile" code, i.e., monomorphized instances of functions
+//!   defined in that module
+//!
+//! In order to see why this heuristic makes sense, let's take a look at when a
+//! codegen unit can get invalidated:
+//!
+//! 1. The most straightforward case is when the BODY of a function or global
+//! changes. Then any codegen unit containing the code for that item has to be
+//! re-compiled. Note that this includes all codegen units where the function
+//! has been inlined.
+//!
+//! 2. The next case is when the SIGNATURE of a function or global changes. In
+//! this case, all codegen units containing a REFERENCE to that item have to be
+//! re-compiled. This is a superset of case 1.
+//!
+//! 3. The final and most subtle case is when a REFERENCE to a generic function
+//! is added or removed somewhere. Even though the definition of the function
+//! might be unchanged, a new REFERENCE might introduce a new monomorphized
+//! instance of this function which has to be placed and compiled somewhere.
+//! Conversely, when removing a REFERENCE, it might have been the last one with
+//! that particular set of generic arguments and thus we have to remove it.
+//!
+//! From the above we see that just using one codegen unit per source-level
+//! module is not such a good idea, since just adding a REFERENCE to some
+//! generic item somewhere else would invalidate everything within the module
+//! containing the generic item. The heuristic above reduces this detrimental
+//! side-effect of references a little by at least not touching the non-generic
+//! code of the module.
+//!
+//! A Note on Inlining
+//! ------------------
+//! As briefly mentioned above, in order for LLVM to be able to inline a
+//! function call, the body of the function has to be available in the LLVM
+//! module where the call is made. This has a few consequences for partitioning:
+//!
+//! - The partitioning algorithm has to take care of placing functions into all
+//!   codegen units where they should be available for inlining. It also has to
+//!   decide on the correct linkage for these functions.
+//!
+//! - The partitioning algorithm has to know which functions are likely to get
+//!   inlined, so it can distribute function instantiations accordingly. Since
+//!   there is no way of knowing for sure which functions LLVM will decide to
+//!   inline in the end, we apply a heuristic here: Only functions marked with
+//!   `#[inline]` are considered for inlining by the partitioner. The current
+//!   implementation will not try to determine if a function is likely to be
+//!   inlined by looking at the functions definition.
+//!
+//! Note though that as a side-effect of creating a codegen units per
+//! source-level module, functions from the same module will be available for
+//! inlining, even when they are not marked `#[inline]`.
+
+mod default;
+mod merging;
+
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::sync;
+use rustc_hir::def_id::{CrateNum, DefIdSet, LOCAL_CRATE};
+use rustc_middle::mir::mono::MonoItem;
+use rustc_middle::mir::mono::{CodegenUnit, Linkage};
+use rustc_middle::ty::query::Providers;
+use rustc_middle::ty::TyCtxt;
+use rustc_span::symbol::Symbol;
+
+use crate::monomorphize::collector::InliningMap;
+use crate::monomorphize::collector::{self, MonoItemCollectionMode};
+
+trait Partitioner<'tcx> {
+    fn place_root_mono_items(
+        &mut self,
+        tcx: TyCtxt<'tcx>,
+        mono_items: &mut dyn Iterator<Item = MonoItem<'tcx>>,
+    ) -> PreInliningPartitioning<'tcx>;
+
+    fn merge_codegen_units(
+        &mut self,
+        tcx: TyCtxt<'tcx>,
+        initial_partitioning: &mut PreInliningPartitioning<'tcx>,
+        target_cgu_count: usize,
+    );
+
+    fn place_inlined_mono_items(
+        &mut self,
+        initial_partitioning: PreInliningPartitioning<'tcx>,
+        inlining_map: &InliningMap<'tcx>,
+    ) -> PostInliningPartitioning<'tcx>;
+
+    fn internalize_symbols(
+        &mut self,
+        tcx: TyCtxt<'tcx>,
+        partitioning: &mut PostInliningPartitioning<'tcx>,
+        inlining_map: &InliningMap<'tcx>,
+    );
+}
+
+fn get_partitioner<'tcx>(tcx: TyCtxt<'tcx>) -> Box<dyn Partitioner<'tcx>> {
+    let strategy = match &tcx.sess.opts.debugging_opts.cgu_partitioning_strategy {
+        None => "default",
+        Some(s) => &s[..],
+    };
+
+    match strategy {
+        "default" => Box::new(default::DefaultPartitioning),
+        _ => tcx.sess.fatal("unknown partitioning strategy"),
+    }
+}
+
+pub fn partition<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    mono_items: &mut dyn Iterator<Item = MonoItem<'tcx>>,
+    max_cgu_count: usize,
+    inlining_map: &InliningMap<'tcx>,
+) -> Vec<CodegenUnit<'tcx>> {
+    let _prof_timer = tcx.prof.generic_activity("cgu_partitioning");
+
+    let mut partitioner = get_partitioner(tcx);
+    // In the first step, we place all regular monomorphizations into their
+    // respective 'home' codegen unit. Regular monomorphizations are all
+    // functions and statics defined in the local crate.
+    let mut initial_partitioning = {
+        let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_place_roots");
+        partitioner.place_root_mono_items(tcx, mono_items)
+    };
+
+    initial_partitioning.codegen_units.iter_mut().for_each(|cgu| cgu.estimate_size(tcx));
+
+    debug_dump(tcx, "INITIAL PARTITIONING:", initial_partitioning.codegen_units.iter());
+
+    // Merge until we have at most `max_cgu_count` codegen units.
+    {
+        let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_merge_cgus");
+        partitioner.merge_codegen_units(tcx, &mut initial_partitioning, max_cgu_count);
+        debug_dump(tcx, "POST MERGING:", initial_partitioning.codegen_units.iter());
+    }
+
+    // In the next step, we use the inlining map to determine which additional
+    // monomorphizations have to go into each codegen unit. These additional
+    // monomorphizations can be drop-glue, functions from external crates, and
+    // local functions the definition of which is marked with `#[inline]`.
+    let mut post_inlining = {
+        let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_place_inline_items");
+        partitioner.place_inlined_mono_items(initial_partitioning, inlining_map)
+    };
+
+    post_inlining.codegen_units.iter_mut().for_each(|cgu| cgu.estimate_size(tcx));
+
+    debug_dump(tcx, "POST INLINING:", post_inlining.codegen_units.iter());
+
+    // Next we try to make as many symbols "internal" as possible, so LLVM has
+    // more freedom to optimize.
+    if tcx.sess.opts.cg.link_dead_code != Some(true) {
+        let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_internalize_symbols");
+        partitioner.internalize_symbols(tcx, &mut post_inlining, inlining_map);
+    }
+
+    // Finally, sort by codegen unit name, so that we get deterministic results.
+    let PostInliningPartitioning {
+        codegen_units: mut result,
+        mono_item_placements: _,
+        internalization_candidates: _,
+    } = post_inlining;
+
+    result.sort_by_cached_key(|cgu| cgu.name().as_str());
+
+    result
+}
+
+pub struct PreInliningPartitioning<'tcx> {
+    codegen_units: Vec<CodegenUnit<'tcx>>,
+    roots: FxHashSet<MonoItem<'tcx>>,
+    internalization_candidates: FxHashSet<MonoItem<'tcx>>,
+}
+
+/// For symbol internalization, we need to know whether a symbol/mono-item is
+/// accessed from outside the codegen unit it is defined in. This type is used
+/// to keep track of that.
+#[derive(Clone, PartialEq, Eq, Debug)]
+enum MonoItemPlacement {
+    SingleCgu { cgu_name: Symbol },
+    MultipleCgus,
+}
+
+struct PostInliningPartitioning<'tcx> {
+    codegen_units: Vec<CodegenUnit<'tcx>>,
+    mono_item_placements: FxHashMap<MonoItem<'tcx>, MonoItemPlacement>,
+    internalization_candidates: FxHashSet<MonoItem<'tcx>>,
+}
+
+fn debug_dump<'a, 'tcx, I>(tcx: TyCtxt<'tcx>, label: &str, cgus: I)
+where
+    I: Iterator<Item = &'a CodegenUnit<'tcx>>,
+    'tcx: 'a,
+{
+    if cfg!(debug_assertions) {
+        debug!("{}", label);
+        for cgu in cgus {
+            debug!("CodegenUnit {} estimated size {} :", cgu.name(), cgu.size_estimate());
+
+            for (mono_item, linkage) in cgu.items() {
+                let symbol_name = mono_item.symbol_name(tcx).name;
+                let symbol_hash_start = symbol_name.rfind('h');
+                let symbol_hash =
+                    symbol_hash_start.map(|i| &symbol_name[i..]).unwrap_or("<no hash>");
+
+                debug!(
+                    " - {} [{:?}] [{}] estimated size {}",
+                    mono_item.to_string(tcx, true),
+                    linkage,
+                    symbol_hash,
+                    mono_item.size_estimate(tcx)
+                );
+            }
+
+            debug!("");
+        }
+    }
+}
+
+#[inline(never)] // give this a place in the profiler
+fn assert_symbols_are_distinct<'a, 'tcx, I>(tcx: TyCtxt<'tcx>, mono_items: I)
+where
+    I: Iterator<Item = &'a MonoItem<'tcx>>,
+    'tcx: 'a,
+{
+    let _prof_timer = tcx.prof.generic_activity("assert_symbols_are_distinct");
+
+    let mut symbols: Vec<_> =
+        mono_items.map(|mono_item| (mono_item, mono_item.symbol_name(tcx))).collect();
+
+    symbols.sort_by_key(|sym| sym.1);
+
+    for pair in symbols.windows(2) {
+        let sym1 = &pair[0].1;
+        let sym2 = &pair[1].1;
+
+        if sym1 == sym2 {
+            let mono_item1 = pair[0].0;
+            let mono_item2 = pair[1].0;
+
+            let span1 = mono_item1.local_span(tcx);
+            let span2 = mono_item2.local_span(tcx);
+
+            // Deterministically select one of the spans for error reporting
+            let span = match (span1, span2) {
+                (Some(span1), Some(span2)) => {
+                    Some(if span1.lo().0 > span2.lo().0 { span1 } else { span2 })
+                }
+                (span1, span2) => span1.or(span2),
+            };
+
+            let error_message = format!("symbol `{}` is already defined", sym1);
+
+            if let Some(span) = span {
+                tcx.sess.span_fatal(span, &error_message)
+            } else {
+                tcx.sess.fatal(&error_message)
+            }
+        }
+    }
+}
+
+fn collect_and_partition_mono_items<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    cnum: CrateNum,
+) -> (&'tcx DefIdSet, &'tcx [CodegenUnit<'tcx>]) {
+    assert_eq!(cnum, LOCAL_CRATE);
+
+    let collection_mode = match tcx.sess.opts.debugging_opts.print_mono_items {
+        Some(ref s) => {
+            let mode_string = s.to_lowercase();
+            let mode_string = mode_string.trim();
+            if mode_string == "eager" {
+                MonoItemCollectionMode::Eager
+            } else {
+                if mode_string != "lazy" {
+                    let message = format!(
+                        "Unknown codegen-item collection mode '{}'. \
+                                           Falling back to 'lazy' mode.",
+                        mode_string
+                    );
+                    tcx.sess.warn(&message);
+                }
+
+                MonoItemCollectionMode::Lazy
+            }
+        }
+        None => {
+            if tcx.sess.opts.cg.link_dead_code == Some(true) {
+                MonoItemCollectionMode::Eager
+            } else {
+                MonoItemCollectionMode::Lazy
+            }
+        }
+    };
+
+    let (items, inlining_map) = collector::collect_crate_mono_items(tcx, collection_mode);
+
+    tcx.sess.abort_if_errors();
+
+    let (codegen_units, _) = tcx.sess.time("partition_and_assert_distinct_symbols", || {
+        sync::join(
+            || {
+                &*tcx.arena.alloc_from_iter(partition(
+                    tcx,
+                    &mut items.iter().cloned(),
+                    tcx.sess.codegen_units(),
+                    &inlining_map,
+                ))
+            },
+            || assert_symbols_are_distinct(tcx, items.iter()),
+        )
+    });
+
+    let mono_items: DefIdSet = items
+        .iter()
+        .filter_map(|mono_item| match *mono_item {
+            MonoItem::Fn(ref instance) => Some(instance.def_id()),
+            MonoItem::Static(def_id) => Some(def_id),
+            _ => None,
+        })
+        .collect();
+
+    if tcx.sess.opts.debugging_opts.print_mono_items.is_some() {
+        let mut item_to_cgus: FxHashMap<_, Vec<_>> = Default::default();
+
+        for cgu in codegen_units {
+            for (&mono_item, &linkage) in cgu.items() {
+                item_to_cgus.entry(mono_item).or_default().push((cgu.name(), linkage));
+            }
+        }
+
+        let mut item_keys: Vec<_> = items
+            .iter()
+            .map(|i| {
+                let mut output = i.to_string(tcx, false);
+                output.push_str(" @@");
+                let mut empty = Vec::new();
+                let cgus = item_to_cgus.get_mut(i).unwrap_or(&mut empty);
+                cgus.sort_by_key(|(name, _)| *name);
+                cgus.dedup();
+                for &(ref cgu_name, (linkage, _)) in cgus.iter() {
+                    output.push_str(" ");
+                    output.push_str(&cgu_name.as_str());
+
+                    let linkage_abbrev = match linkage {
+                        Linkage::External => "External",
+                        Linkage::AvailableExternally => "Available",
+                        Linkage::LinkOnceAny => "OnceAny",
+                        Linkage::LinkOnceODR => "OnceODR",
+                        Linkage::WeakAny => "WeakAny",
+                        Linkage::WeakODR => "WeakODR",
+                        Linkage::Appending => "Appending",
+                        Linkage::Internal => "Internal",
+                        Linkage::Private => "Private",
+                        Linkage::ExternalWeak => "ExternalWeak",
+                        Linkage::Common => "Common",
+                    };
+
+                    output.push_str("[");
+                    output.push_str(linkage_abbrev);
+                    output.push_str("]");
+                }
+                output
+            })
+            .collect();
+
+        item_keys.sort();
+
+        for item in item_keys {
+            println!("MONO_ITEM {}", item);
+        }
+    }
+
+    (tcx.arena.alloc(mono_items), codegen_units)
+}
+
+pub fn provide(providers: &mut Providers) {
+    providers.collect_and_partition_mono_items = collect_and_partition_mono_items;
+
+    providers.is_codegened_item = |tcx, def_id| {
+        let (all_mono_items, _) = tcx.collect_and_partition_mono_items(LOCAL_CRATE);
+        all_mono_items.contains(&def_id)
+    };
+
+    providers.codegen_unit = |tcx, name| {
+        let (_, all) = tcx.collect_and_partition_mono_items(LOCAL_CRATE);
+        all.iter()
+            .find(|cgu| cgu.name() == name)
+            .unwrap_or_else(|| panic!("failed to find cgu with name {:?}", name))
+    };
+}
index 6a7653b60752db1164fa40bd6f78ee33c692e501..479b6c2a6ca9fb33e0b2088d42322ea5fbace51c 100644 (file)
@@ -1,6 +1,6 @@
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
-use rustc_hir::lang_items::FnMutTraitLangItem;
+use rustc_hir::lang_items::LangItem;
 use rustc_middle::mir::*;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::subst::{InternalSubsts, Subst};
@@ -62,7 +62,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<'
             build_call_shim(tcx, instance, None, CallKind::Direct(def_id), None)
         }
         ty::InstanceDef::ClosureOnceShim { call_once: _ } => {
-            let fn_mut = tcx.require_lang_item(FnMutTraitLangItem, None);
+            let fn_mut = tcx.require_lang_item(LangItem::FnMut, None);
             let call_mut = tcx
                 .associated_items(fn_mut)
                 .in_definition_order()
@@ -295,7 +295,7 @@ fn deref_subpath(&self, _path: Self::Path) -> Option<Self::Path> {
     fn downcast_subpath(&self, _path: Self::Path, _variant: VariantIdx) -> Option<Self::Path> {
         Some(())
     }
-    fn array_subpath(&self, _path: Self::Path, _index: u32, _size: u32) -> Option<Self::Path> {
+    fn array_subpath(&self, _path: Self::Path, _index: u64, _size: u64) -> Option<Self::Path> {
         None
     }
 }
index 4812ef5a89455a19496c233f932daa0b1134ca7f..e21f314ca150b03b2a49ffdd6d8889e648c54568 100644 (file)
@@ -1,7 +1,7 @@
 //! The `Visitor` responsible for actually checking a `mir::Body` for invalid operations.
 
 use rustc_errors::struct_span_err;
-use rustc_hir::{self as hir, lang_items};
+use rustc_hir::{self as hir, LangItem};
 use rustc_hir::{def_id::DefId, HirId};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
@@ -618,7 +618,7 @@ fn check_return_ty_is_sync(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, hir_id: HirId)
     tcx.infer_ctxt().enter(|infcx| {
         let cause = traits::ObligationCause::new(body.span, hir_id, traits::SharedStatic);
         let mut fulfillment_cx = traits::FulfillmentContext::new();
-        let sync_def_id = tcx.require_lang_item(lang_items::SyncTraitLangItem, Some(body.span));
+        let sync_def_id = tcx.require_lang_item(LangItem::Sync, Some(body.span));
         fulfillment_cx.register_bound(&infcx, ty::ParamEnv::empty(), ty, sync_def_id, cause);
         if let Err(err) = fulfillment_cx.select_all_or_error(&infcx) {
             infcx.report_fulfillment_errors(&err, None, false);
index ad49090bfc50c1dbc3b5f6e0d67294adad7d988e..5f1930693568cc83a8d8a9c8c9adb313738d3f65 100644 (file)
@@ -219,7 +219,7 @@ fn field_subpath(&self, path: Self::Path, field: Field) -> Option<Self::Path> {
         })
     }
 
-    fn array_subpath(&self, path: Self::Path, index: u32, size: u32) -> Option<Self::Path> {
+    fn array_subpath(&self, path: Self::Path, index: u64, size: u64) -> Option<Self::Path> {
         dataflow::move_path_children_matching(self.ctxt.move_data(), path, |e| match e {
             ProjectionElem::ConstantIndex { offset, min_length, from_end } => {
                 debug_assert!(size == min_length, "min_length should be exact for arrays");
index e2f22c115d0792dccf791a74fec4da14e22b5eab..a22075e760a90885dcf2a45b932e8a38e7c4728b 100644 (file)
@@ -62,7 +62,7 @@
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
-use rustc_hir::lang_items::{GeneratorStateLangItem, PinTypeLangItem};
+use rustc_hir::lang_items::LangItem;
 use rustc_index::bit_set::{BitMatrix, BitSet};
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor};
@@ -395,7 +395,7 @@ fn make_generator_state_argument_indirect<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Bo
 fn make_generator_state_argument_pinned<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
     let ref_gen_ty = body.local_decls.raw[1].ty;
 
-    let pin_did = tcx.require_lang_item(PinTypeLangItem, Some(body.span));
+    let pin_did = tcx.require_lang_item(LangItem::Pin, Some(body.span));
     let pin_adt_ref = tcx.adt_def(pin_did);
     let substs = tcx.intern_substs(&[ref_gen_ty.into()]);
     let pin_ref_gen_ty = tcx.mk_adt(pin_adt_ref, substs);
@@ -1270,7 +1270,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'
         };
 
         // Compute GeneratorState<yield_ty, return_ty>
-        let state_did = tcx.require_lang_item(GeneratorStateLangItem, None);
+        let state_did = tcx.require_lang_item(LangItem::GeneratorState, None);
         let state_adt_ref = tcx.adt_def(state_did);
         let state_substs = tcx.intern_substs(&[yield_ty.into(), body.return_ty().into()]);
         let ret_ty = tcx.mk_adt(state_adt_ref, state_substs);
index 1a22eee3a0371379823c70db890160590a973d5b..130409b9df5c00c2c14a39be32ba975b6f3cf8dd 100644 (file)
@@ -3,6 +3,7 @@
 use rustc_middle::ty::{Ty, TyCtxt};
 use rustc_target::abi::VariantIdx;
 
+use std::convert::TryFrom;
 use std::iter::TrustedLen;
 
 /// Expand `lhs = Rvalue::Aggregate(kind, operands)` into assignments to the fields.
@@ -52,14 +53,11 @@ pub fn expand_aggregate<'tcx>(
         .enumerate()
         .map(move |(i, (op, ty))| {
             let lhs_field = if let AggregateKind::Array(_) = kind {
-                // FIXME(eddyb) `offset` should be u64.
-                let offset = i as u32;
-                assert_eq!(offset as usize, i);
+                let offset = u64::try_from(i).unwrap();
                 tcx.mk_place_elem(
                     lhs,
                     ProjectionElem::ConstantIndex {
                         offset,
-                        // FIXME(eddyb) `min_length` doesn't appear to be used.
                         min_length: offset + 1,
                         from_end: false,
                     },
index 20c2f5688eb591ef64e840550b53d792a1be8047..642935d243d0d927dffd9575f84fb0a4b6e404b9 100644 (file)
@@ -1,6 +1,6 @@
 use crate::util::patch::MirPatch;
 use rustc_hir as hir;
-use rustc_hir::lang_items::{BoxFreeFnLangItem, DropTraitLangItem};
+use rustc_hir::lang_items::LangItem;
 use rustc_index::vec::Idx;
 use rustc_middle::mir::*;
 use rustc_middle::traits::Reveal;
@@ -10,8 +10,6 @@
 use rustc_target::abi::VariantIdx;
 use std::fmt;
 
-use std::convert::TryInto;
-
 /// The value of an inserted drop flag.
 #[derive(Debug, PartialEq, Eq, Copy, Clone)]
 pub enum DropFlagState {
@@ -150,7 +148,7 @@ pub trait DropElaborator<'a, 'tcx>: fmt::Debug {
     /// If this returns `None`, elements of `path` will not get a dedicated drop flag.
     ///
     /// This is only relevant for array patterns, which can move out of individual array elements.
-    fn array_subpath(&self, path: Self::Path, index: u32, size: u32) -> Option<Self::Path>;
+    fn array_subpath(&self, path: Self::Path, index: u64, size: u64) -> Option<Self::Path>;
 }
 
 #[derive(Debug)]
@@ -613,7 +611,7 @@ fn adt_switch_block(
     fn destructor_call_block(&mut self, (succ, unwind): (BasicBlock, Unwind)) -> BasicBlock {
         debug!("destructor_call_block({:?}, {:?})", self, succ);
         let tcx = self.tcx();
-        let drop_trait = tcx.require_lang_item(DropTraitLangItem, None);
+        let drop_trait = tcx.require_lang_item(LangItem::Drop, None);
         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, &[]);
@@ -744,9 +742,6 @@ fn open_drop_for_array(&mut self, ety: Ty<'tcx>, opt_size: Option<u64>) -> Basic
         let tcx = self.tcx();
 
         if let Some(size) = opt_size {
-            let size: u32 = size.try_into().unwrap_or_else(|_| {
-                bug!("move out check isn't implemented for array sizes bigger than u32::MAX");
-            });
             let fields: Vec<(Place<'tcx>, Option<D::Path>)> = (0..size)
                 .map(|i| {
                     (
@@ -971,7 +966,7 @@ fn unelaborated_free_block(
     ) -> BasicBlock {
         let tcx = self.tcx();
         let unit_temp = Place::from(self.new_temp(tcx.mk_unit()));
-        let free_func = tcx.require_lang_item(BoxFreeFnLangItem, Some(self.source_info.span));
+        let free_func = tcx.require_lang_item(LangItem::BoxFree, Some(self.source_info.span));
         let args = adt.variants[VariantIdx::new(0)]
             .fields
             .iter()
index 5f87cb364b891de29159e869aed9739529ee79d7..3a525d10b08175cda5f8976e181f073ba7b64e78 100644 (file)
@@ -609,8 +609,8 @@ pub(super) fn visit_primary_bindings(
 
             PatKind::Array { ref prefix, ref slice, ref suffix }
             | PatKind::Slice { ref prefix, ref slice, ref suffix } => {
-                let from = u32::try_from(prefix.len()).unwrap();
-                let to = u32::try_from(suffix.len()).unwrap();
+                let from = u64::try_from(prefix.len()).unwrap();
+                let to = u64::try_from(suffix.len()).unwrap();
                 for subpattern in prefix {
                     self.visit_primary_bindings(subpattern, pattern_user_ty.clone().index(), f);
                 }
index 87977d6fe8904e84a7996150c9ec992c82960e92..c4a87a554a3d0a41b357f1c06f360576b036b3e5 100644 (file)
@@ -10,7 +10,7 @@
 use crate::thir::pattern::compare_const_vals;
 use crate::thir::*;
 use rustc_data_structures::fx::FxIndexMap;
-use rustc_hir::RangeEnd;
+use rustc_hir::{LangItem, RangeEnd};
 use rustc_index::bit_set::BitSet;
 use rustc_middle::mir::*;
 use rustc_middle::ty::util::IntTypeExt;
@@ -359,8 +359,6 @@ fn non_scalar_compare(
         place: Place<'tcx>,
         mut ty: Ty<'tcx>,
     ) {
-        use rustc_hir::lang_items::EqTraitLangItem;
-
         let mut expect = self.literal_operand(source_info.span, value);
         let mut val = Operand::Copy(place);
 
@@ -414,7 +412,7 @@ fn non_scalar_compare(
             _ => bug!("non_scalar_compare called on non-reference type: {}", ty),
         };
 
-        let eq_def_id = self.hir.tcx().require_lang_item(EqTraitLangItem, None);
+        let eq_def_id = self.hir.tcx().require_lang_item(LangItem::PartialEq, None);
         let method = self.hir.trait_method(eq_def_id, sym::eq, deref_ty, &[deref_ty.into()]);
 
         let bool_ty = self.hir.bool_ty();
@@ -537,10 +535,7 @@ pub(super) fn sort_candidate<'pat>(
                 Some(index)
             }
 
-            (
-                &TestKind::SwitchInt { switch_ty: _, ref options },
-                &PatKind::Range(range),
-            ) => {
+            (&TestKind::SwitchInt { switch_ty: _, ref options }, &PatKind::Range(range)) => {
                 let not_contained =
                     self.values_not_contained_in_range(range, options).unwrap_or(false);
 
index 605396c5eb639f722003f4e5b12528e7bde7bd16..c6d39947f7d153842790ca06a9786665c51e1363 100644 (file)
@@ -40,17 +40,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
         match_pairs.extend(prefix.iter().enumerate().map(|(idx, subpattern)| {
             let elem =
-                ProjectionElem::ConstantIndex { offset: idx as u32, min_length, from_end: false };
+                ProjectionElem::ConstantIndex { offset: idx as u64, min_length, from_end: false };
             let place = tcx.mk_place_elem(*place, elem);
             MatchPair::new(place, subpattern)
         }));
 
         if let Some(subslice_pat) = opt_slice {
-            let suffix_len = suffix.len() as u32;
+            let suffix_len = suffix.len() as u64;
             let subslice = tcx.mk_place_elem(
                 *place,
                 ProjectionElem::Subslice {
-                    from: prefix.len() as u32,
+                    from: prefix.len() as u64,
                     to: if exact_size { min_length - suffix_len } else { suffix_len },
                     from_end: !exact_size,
                 },
@@ -59,7 +59,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         }
 
         match_pairs.extend(suffix.iter().rev().enumerate().map(|(idx, subpattern)| {
-            let end_offset = (idx + 1) as u32;
+            let end_offset = (idx + 1) as u64;
             let elem = ProjectionElem::ConstantIndex {
                 offset: if exact_size { min_length - end_offset } else { end_offset },
                 min_length,
index 0c3f6fee665e85bc4afa1736e2ee7ffdef71fb30..71026f5096df6e8f3a2a675af563bd75f247fe14 100644 (file)
@@ -6,7 +6,7 @@
 use rustc_errors::ErrorReported;
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_hir::lang_items;
+use rustc_hir::lang_items::LangItem;
 use rustc_hir::{GeneratorKind, HirIdMap, Node};
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_infer::infer::TyCtxtInferExt;
@@ -37,22 +37,29 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_
     let id = tcx.hir().local_def_id_to_hir_id(def.did);
 
     // Figure out what primary body this item has.
-    let (body_id, return_ty_span) = match tcx.hir().get(id) {
+    let (body_id, return_ty_span, span_with_body) = match tcx.hir().get(id) {
         Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(_, decl, body_id, _, _), .. }) => {
-            (*body_id, decl.output.span())
+            (*body_id, decl.output.span(), None)
         }
         Node::Item(hir::Item {
             kind: hir::ItemKind::Fn(hir::FnSig { decl, .. }, _, body_id),
+            span,
             ..
         })
         | Node::ImplItem(hir::ImplItem {
             kind: hir::ImplItemKind::Fn(hir::FnSig { decl, .. }, body_id),
+            span,
             ..
         })
         | Node::TraitItem(hir::TraitItem {
             kind: hir::TraitItemKind::Fn(hir::FnSig { decl, .. }, hir::TraitFn::Provided(body_id)),
+            span,
             ..
-        }) => (*body_id, decl.output.span()),
+        }) => {
+            // Use the `Span` of the `Item/ImplItem/TraitItem` as the body span,
+            // since the def span of a function does not include the body
+            (*body_id, decl.output.span(), Some(*span))
+        }
         Node::Item(hir::Item {
             kind: hir::ItemKind::Static(ty, _, body_id) | hir::ItemKind::Const(ty, body_id),
             ..
@@ -61,12 +68,16 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_
         | Node::TraitItem(hir::TraitItem {
             kind: hir::TraitItemKind::Const(ty, Some(body_id)),
             ..
-        }) => (*body_id, ty.span),
-        Node::AnonConst(hir::AnonConst { body, hir_id, .. }) => (*body, tcx.hir().span(*hir_id)),
+        }) => (*body_id, ty.span, None),
+        Node::AnonConst(hir::AnonConst { body, hir_id, .. }) => (*body, tcx.hir().span(*hir_id), None),
 
         _ => span_bug!(tcx.hir().span(id), "can't build MIR for {:?}", def.did),
     };
 
+    // If we don't have a specialized span for the body, just use the
+    // normal def span.
+    let span_with_body = span_with_body.unwrap_or_else(|| tcx.hir().span(id));
+
     tcx.infer_ctxt().enter(|infcx| {
         let cx = Cx::new(&infcx, def, id);
         let body = if let Some(ErrorReported) = cx.typeck_results().tainted_by_errors {
@@ -134,8 +145,7 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_
                 // C-variadic fns also have a `VaList` input that's not listed in `fn_sig`
                 // (as it's created inside the body itself, not passed in from outside).
                 let ty = if fn_sig.c_variadic && index == fn_sig.inputs().len() {
-                    let va_list_did =
-                        tcx.require_lang_item(lang_items::VaListTypeLangItem, Some(arg.span));
+                    let va_list_did = tcx.require_lang_item(LangItem::VaList, Some(arg.span));
 
                     tcx.type_of(va_list_did).subst(tcx, &[tcx.lifetimes.re_erased.into()])
                 } else {
@@ -167,6 +177,7 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_
                 return_ty,
                 return_ty_span,
                 body,
+                span_with_body
             );
             mir.yield_ty = yield_ty;
             mir
@@ -571,6 +582,7 @@ fn construct_fn<'a, 'tcx, A>(
     return_ty: Ty<'tcx>,
     return_ty_span: Span,
     body: &'tcx hir::Body<'tcx>,
+    span_with_body: Span
 ) -> Body<'tcx>
 where
     A: Iterator<Item = ArgInfo<'tcx>>,
@@ -585,7 +597,7 @@ fn construct_fn<'a, 'tcx, A>(
 
     let mut builder = Builder::new(
         hir,
-        span,
+        span_with_body,
         arguments.len(),
         safety,
         return_ty,
@@ -628,7 +640,7 @@ fn construct_fn<'a, 'tcx, A>(
                 )
             );
             // Attribute epilogue to function's closing brace
-            let fn_end = span.shrink_to_hi();
+            let fn_end = span_with_body.shrink_to_hi();
             let source_info = builder.source_info(fn_end);
             let return_block = builder.return_block();
             builder.cfg.goto(block, source_info, return_block);
index 662b6c7735747c04f29ba53f0c753b50c27f286c..fd2d5a4abd424196071f70e2c65fcaadcdcbc65f 100644 (file)
@@ -38,7 +38,7 @@
         vis.reachable_recursive_calls.sort();
 
         let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
-        let sp = tcx.sess.source_map().guess_head_span(tcx.hir().span(hir_id));
+        let sp = tcx.sess.source_map().guess_head_span(tcx.hir().span_with_body(hir_id));
         tcx.struct_span_lint_hir(UNCONDITIONAL_RECURSION, hir_id, sp, |lint| {
             let mut db = lint.build("function cannot return without recursing");
             db.span_label(sp, "cannot return without recursing");
index 6dd7e0871b45ef8bb9b319dd805fa873d3fdb951..f6d3ccc1ae0a68fe98c86f803eecc1278e39a242 100644 (file)
@@ -1,5 +1,4 @@
 use rustc_hir as hir;
-use rustc_hir::lang_items::EqTraitLangItem;
 use rustc_index::vec::Idx;
 use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
 use rustc_middle::mir::Field;
@@ -164,7 +163,7 @@ fn to_pat(
                 // not *yet* implement `PartialEq`. So for now we leave this here.
                 let ty_is_partial_eq: bool = {
                     let partial_eq_trait_id =
-                        self.tcx().require_lang_item(EqTraitLangItem, Some(self.span));
+                        self.tcx().require_lang_item(hir::LangItem::PartialEq, Some(self.span));
                     let obligation: PredicateObligation<'_> = predicate_for_trait_def(
                         self.tcx(),
                         self.param_env,
index 7b7235eed36349a1a337541b56b0019dc78e8e52..bc857c9774218b75faad2800942d26a97718d31a 100644 (file)
@@ -7,8 +7,8 @@
 #![feature(or_patterns)]
 
 use rustc_ast as ast;
-use rustc_ast::token::{self, DelimToken, Nonterminal, Token};
-use rustc_ast::tokenstream::{self, TokenStream, TokenTree};
+use rustc_ast::token::{self, DelimToken, Nonterminal, Token, TokenKind};
+use rustc_ast::tokenstream::{self, IsJoint, TokenStream, TokenTree};
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::{Diagnostic, FatalError, Level, PResult};
@@ -309,7 +309,7 @@ pub fn nt_to_tokenstream(nt: &Nonterminal, sess: &ParseSess, span: Span) -> Toke
     // modifications, including adding/removing typically non-semantic
     // tokens such as extra braces and commas, don't happen.
     if let Some(tokens) = tokens {
-        if tokenstream_probably_equal_for_proc_macro(&tokens, &tokens_for_real) {
+        if tokenstream_probably_equal_for_proc_macro(&tokens, &tokens_for_real, sess) {
             return tokens;
         }
         info!(
@@ -327,7 +327,11 @@ pub fn nt_to_tokenstream(nt: &Nonterminal, sess: &ParseSess, span: Span) -> Toke
 //
 // This is otherwise the same as `eq_unspanned`, only recursing with a
 // different method.
-pub fn tokenstream_probably_equal_for_proc_macro(first: &TokenStream, other: &TokenStream) -> bool {
+pub fn tokenstream_probably_equal_for_proc_macro(
+    first: &TokenStream,
+    other: &TokenStream,
+    sess: &ParseSess,
+) -> bool {
     // When checking for `probably_eq`, we ignore certain tokens that aren't
     // preserved in the AST. Because they are not preserved, the pretty
     // printer arbitrarily adds or removes them when printing as token
@@ -408,9 +412,6 @@ fn break_tokens(tree: TokenTree) -> impl Iterator<Item = TokenTree> {
                 }
             }
             token_trees = out.into_iter().map(TokenTree::Token).collect();
-            if token_trees.len() != 1 {
-                debug!("break_tokens: broke {:?} to {:?}", tree, token_trees);
-            }
         } else {
             token_trees = SmallVec::new();
             token_trees.push(tree);
@@ -418,10 +419,32 @@ fn break_tokens(tree: TokenTree) -> impl Iterator<Item = TokenTree> {
         token_trees.into_iter()
     }
 
-    let mut t1 = first.trees().filter(semantic_tree).flat_map(break_tokens);
-    let mut t2 = other.trees().filter(semantic_tree).flat_map(break_tokens);
+    let expand_nt = |tree: TokenTree| {
+        if let TokenTree::Token(Token { kind: TokenKind::Interpolated(nt), span }) = &tree {
+            // When checking tokenstreams for 'probable equality', we are comparing
+            // a captured (from parsing) `TokenStream` to a reparsed tokenstream.
+            // The reparsed Tokenstream will never have `None`-delimited groups,
+            // since they are only ever inserted as a result of macro expansion.
+            // Therefore, inserting a `None`-delimtied group here (when we
+            // convert a nested `Nonterminal` to a tokenstream) would cause
+            // a mismatch with the reparsed tokenstream.
+            //
+            // Note that we currently do not handle the case where the
+            // reparsed stream has a `Parenthesis`-delimited group
+            // inserted. This will cause a spurious mismatch:
+            // issue #75734 tracks resolving this.
+            nt_to_tokenstream(nt, sess, *span).into_trees()
+        } else {
+            TokenStream::new(vec![(tree, IsJoint::NonJoint)]).into_trees()
+        }
+    };
+
+    // Break tokens after we expand any nonterminals, so that we break tokens
+    // that are produced as a result of nonterminal expansion.
+    let mut t1 = first.trees().filter(semantic_tree).flat_map(expand_nt).flat_map(break_tokens);
+    let mut t2 = other.trees().filter(semantic_tree).flat_map(expand_nt).flat_map(break_tokens);
     for (t1, t2) in t1.by_ref().zip(t2.by_ref()) {
-        if !tokentree_probably_equal_for_proc_macro(&t1, &t2) {
+        if !tokentree_probably_equal_for_proc_macro(&t1, &t2, sess) {
             return false;
         }
     }
@@ -433,13 +456,17 @@ fn break_tokens(tree: TokenTree) -> impl Iterator<Item = TokenTree> {
 //
 // This is otherwise the same as `eq_unspanned`, only recursing with a
 // different method.
-fn tokentree_probably_equal_for_proc_macro(first: &TokenTree, other: &TokenTree) -> bool {
+pub fn tokentree_probably_equal_for_proc_macro(
+    first: &TokenTree,
+    other: &TokenTree,
+    sess: &ParseSess,
+) -> bool {
     match (first, other) {
         (TokenTree::Token(token), TokenTree::Token(token2)) => {
             token_probably_equal_for_proc_macro(token, token2)
         }
         (TokenTree::Delimited(_, delim, tts), TokenTree::Delimited(_, delim2, tts2)) => {
-            delim == delim2 && tokenstream_probably_equal_for_proc_macro(&tts, &tts2)
+            delim == delim2 && tokenstream_probably_equal_for_proc_macro(&tts, &tts2, sess)
         }
         _ => false,
     }
@@ -498,7 +525,7 @@ fn token_probably_equal_for_proc_macro(first: &Token, other: &Token) -> bool {
             b == d && (a == c || a == kw::DollarCrate || c == kw::DollarCrate)
         }
 
-        (&Interpolated(..), &Interpolated(..)) => false,
+        (&Interpolated(..), &Interpolated(..)) => panic!("Unexpanded Interpolated!"),
 
         _ => panic!("forgot to add a token?"),
     }
index 62aec66a255d5f2d5973983e6b5b7de6370b99f7..f022c628fe27f7fc906b4232bff31971ceeda0e6 100644 (file)
@@ -1858,7 +1858,19 @@ pub(super) fn parse_arm(&mut self) -> PResult<'a, Arm> {
         let attrs = self.parse_outer_attributes()?;
         let lo = self.token.span;
         let pat = self.parse_top_pat(GateOr::No)?;
-        let guard = if self.eat_keyword(kw::If) { Some(self.parse_expr()?) } else { None };
+        let guard = if self.eat_keyword(kw::If) {
+            let if_span = self.prev_token.span;
+            let cond = self.parse_expr()?;
+            if let ExprKind::Let(..) = cond.kind {
+                // Remove the last feature gating of a `let` expression since it's stable.
+                self.sess.gated_spans.ungate_last(sym::let_chains, cond.span);
+                let span = if_span.to(cond.span);
+                self.sess.gated_spans.gate(sym::if_let_guard, span);
+            }
+            Some(cond)
+        } else {
+            None
+        };
         let arrow_span = self.token.span;
         self.expect(&token::FatArrow)?;
         let arm_start_span = self.token.span;
index 64479bc36e0155f56fd12df29935ae9c0376ca95..9143af651df2d35d4614701eb2b18b3db5bc8b5d 100644 (file)
@@ -227,7 +227,7 @@ fn parse_item_kind(
             (Ident::invalid(), ItemKind::Use(P(tree)))
         } else if self.check_fn_front_matter() {
             // FUNCTION ITEM
-            let (ident, sig, generics, body) = self.parse_fn(attrs, req_name)?;
+            let (ident, sig, generics, body) = self.parse_fn(attrs, req_name, lo)?;
             (ident, ItemKind::Fn(def(), sig, generics, body))
         } else if self.eat_keyword(kw::Extern) {
             if self.eat_keyword(kw::Crate) {
@@ -1492,21 +1492,31 @@ fn parse_fn(
         &mut self,
         attrs: &mut Vec<Attribute>,
         req_name: ReqName,
+        sig_lo: Span,
     ) -> PResult<'a, (Ident, FnSig, Generics, Option<P<Block>>)> {
         let header = self.parse_fn_front_matter()?; // `const ... fn`
         let ident = self.parse_ident()?; // `foo`
         let mut generics = self.parse_generics()?; // `<'a, T, ...>`
         let decl = self.parse_fn_decl(req_name, AllowPlus::Yes)?; // `(p: u8, ...)`
         generics.where_clause = self.parse_where_clause()?; // `where T: Ord`
-        let body = self.parse_fn_body(attrs)?; // `;` or `{ ... }`.
-        Ok((ident, FnSig { header, decl }, generics, body))
+
+        let mut sig_hi = self.prev_token.span;
+        let body = self.parse_fn_body(attrs, &mut sig_hi)?; // `;` or `{ ... }`.
+        let fn_sig_span = sig_lo.to(sig_hi);
+        Ok((ident, FnSig { header, decl, span: fn_sig_span }, generics, body))
     }
 
     /// Parse the "body" of a function.
     /// 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>>> {
+    fn parse_fn_body(
+        &mut self,
+        attrs: &mut Vec<Attribute>,
+        sig_hi: &mut Span,
+    ) -> PResult<'a, Option<P<Block>>> {
         let (inner_attrs, body) = if self.check(&token::Semi) {
+            // Include the trailing semicolon in the span of the signature
+            *sig_hi = self.token.span;
             self.bump(); // `;`
             (Vec::new(), None)
         } else if self.check(&token::OpenDelim(token::Brace)) || self.token.is_whole_block() {
index d5ce82ae28f28d6a71179f40b2e556f9fed71369..f559d66587b24082a5e5a45bbd181f4d72ee9509 100644 (file)
@@ -4,7 +4,7 @@
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
-use rustc_hir::lang_items;
+use rustc_hir::lang_items::{self, LangItem};
 use rustc_hir::weak_lang_items::WEAK_ITEMS_REFS;
 use rustc_middle::middle::lang_items::required;
 use rustc_middle::ty::TyCtxt;
@@ -24,7 +24,7 @@ pub fn check_crate<'tcx>(tcx: TyCtxt<'tcx>, items: &mut lang_items::LanguageItem
     // They will never implicitly be added to the `missing` array unless we do
     // so here.
     if items.eh_personality().is_none() {
-        items.missing.push(lang_items::EhPersonalityLangItem);
+        items.missing.push(LangItem::EhPersonality);
     }
 
     {
@@ -58,9 +58,9 @@ fn verify<'tcx>(tcx: TyCtxt<'tcx>, items: &lang_items::LanguageItems) {
 
     for (name, &item) in WEAK_ITEMS_REFS.iter() {
         if missing.contains(&item) && required(tcx, item) && items.require(item).is_err() {
-            if item == lang_items::PanicImplLangItem {
+            if item == LangItem::PanicImpl {
                 tcx.sess.err("`#[panic_handler]` function required, but not found");
-            } else if item == lang_items::OomLangItem {
+            } else if item == LangItem::Oom {
                 tcx.sess.err("`#[alloc_error_handler]` function required, but not found");
             } else {
                 tcx.sess.err(&format!("language item required, but not found: `{}`", name));
@@ -91,7 +91,7 @@ fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
 
     fn visit_foreign_item(&mut self, i: &hir::ForeignItem<'_>) {
         let check_name = |attr, sym| self.tcx.sess.check_name(attr, sym);
-        if let Some((lang_item, _)) = hir::lang_items::extract(check_name, &i.attrs) {
+        if let Some((lang_item, _)) = lang_items::extract(check_name, &i.attrs) {
             self.register(lang_item, i.span);
         }
         intravisit::walk_foreign_item(self, i)
index 0dbb6269d2eb3f3f3efbdbf6e6643868d018ca73..d113eb22abadcefb864cb295aa4c7bec4cc6d2d1 100644 (file)
@@ -8,7 +8,7 @@
 use RibKind::*;
 
 use crate::{path_names_to_string, BindingError, CrateLint, LexicalScopeBinding};
-use crate::{Module, ModuleOrUniformRoot, NameBindingKind, ParentScope, PathResult};
+use crate::{Module, ModuleOrUniformRoot, ParentScope, PathResult};
 use crate::{ResolutionError, Resolver, Segment, UseError};
 
 use rustc_ast::ptr::P;
@@ -24,7 +24,6 @@
 use rustc_hir::TraitCandidate;
 use rustc_middle::{bug, span_bug};
 use rustc_session::lint;
-use rustc_span::def_id::LocalDefId;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::Span;
 use smallvec::{smallvec, SmallVec};
@@ -2342,95 +2341,31 @@ fn get_traits_containing_item(
         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);
+            self.r.get_traits_in_module_containing_item(
+                ident,
+                ns,
+                search_module,
+                &mut found_traits,
+                &self.parent_scope,
+            );
             search_module =
                 unwrap_or!(self.r.hygienic_lexical_parent(search_module, &mut ident.span), break);
         }
 
         if let Some(prelude) = self.r.prelude {
             if !search_module.no_implicit_prelude {
-                self.get_traits_in_module_containing_item(ident, ns, prelude, &mut found_traits);
+                self.r.get_traits_in_module_containing_item(
+                    ident,
+                    ns,
+                    prelude,
+                    &mut found_traits,
+                    &self.parent_scope,
+                );
             }
         }
 
         found_traits
     }
-
-    fn get_traits_in_module_containing_item(
-        &mut self,
-        ident: Ident,
-        ns: Namespace,
-        module: Module<'a>,
-        found_traits: &mut Vec<TraitCandidate>,
-    ) {
-        assert!(ns == TypeNS || ns == ValueNS);
-        let mut traits = module.traits.borrow_mut();
-        if traits.is_none() {
-            let mut collected_traits = Vec::new();
-            module.for_each_child(self.r, |_, name, ns, binding| {
-                if ns != TypeNS {
-                    return;
-                }
-                match binding.res() {
-                    Res::Def(DefKind::Trait | DefKind::TraitAlias, _) => {
-                        collected_traits.push((name, binding))
-                    }
-                    _ => (),
-                }
-            });
-            *traits = Some(collected_traits.into_boxed_slice());
-        }
-
-        for &(trait_name, binding) in traits.as_ref().unwrap().iter() {
-            // Traits have pseudo-modules that can be used to search for the given ident.
-            if let Some(module) = binding.module() {
-                let mut ident = ident;
-                if ident.span.glob_adjust(module.expansion, binding.span).is_none() {
-                    continue;
-                }
-                if self
-                    .r
-                    .resolve_ident_in_module_unadjusted(
-                        ModuleOrUniformRoot::Module(module),
-                        ident,
-                        ns,
-                        &self.parent_scope,
-                        false,
-                        module.span,
-                    )
-                    .is_ok()
-                {
-                    let import_ids = self.find_transitive_imports(&binding.kind, trait_name);
-                    let trait_def_id = module.def_id().unwrap();
-                    found_traits.push(TraitCandidate { def_id: trait_def_id, import_ids });
-                }
-            } else if let Res::Def(DefKind::TraitAlias, _) = binding.res() {
-                // For now, just treat all trait aliases as possible candidates, since we don't
-                // know if the ident is somewhere in the transitive bounds.
-                let import_ids = self.find_transitive_imports(&binding.kind, trait_name);
-                let trait_def_id = binding.res().def_id();
-                found_traits.push(TraitCandidate { def_id: trait_def_id, import_ids });
-            } else {
-                bug!("candidate is not trait or trait alias?")
-            }
-        }
-    }
-
-    fn find_transitive_imports(
-        &mut self,
-        mut kind: &NameBindingKind<'_>,
-        trait_name: Ident,
-    ) -> SmallVec<[LocalDefId; 1]> {
-        let mut import_ids = smallvec![];
-        while let NameBindingKind::Import { import, binding, .. } = kind {
-            let id = self.r.local_def_id(import.id);
-            self.r.maybe_unused_trait_imports.insert(id);
-            self.r.add_to_glob_map(&import, trait_name);
-            import_ids.push(id);
-            kind = &binding.kind;
-        }
-        import_ids
-    }
 }
 
 impl<'a> Resolver<'a> {
index 36b7a430f78d1d8c4bd6a0aa475a741ece79114c..f2319bfe64de8c02257f3fb0498ee77c3db1e01c 100644 (file)
@@ -43,9 +43,9 @@
 use rustc_metadata::creader::{CStore, CrateLoader};
 use rustc_middle::hir::exports::ExportMap;
 use rustc_middle::middle::cstore::{CrateStore, MetadataLoaderDyn};
-use rustc_middle::span_bug;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, DefIdTree, ResolverOutputs};
+use rustc_middle::{bug, span_bug};
 use rustc_session::lint;
 use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer};
 use rustc_session::Session;
@@ -54,6 +54,7 @@
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{Span, DUMMY_SP};
 
+use smallvec::{smallvec, SmallVec};
 use std::cell::{Cell, RefCell};
 use std::collections::BTreeSet;
 use std::{cmp, fmt, iter, ptr};
@@ -521,6 +522,29 @@ fn for_each_child<R, F>(&'a self, resolver: &mut R, mut f: F)
         }
     }
 
+    /// This modifies `self` in place. The traits will be stored in `self.traits`.
+    fn ensure_traits<R>(&'a self, resolver: &mut R)
+    where
+        R: AsMut<Resolver<'a>>,
+    {
+        let mut traits = self.traits.borrow_mut();
+        if traits.is_none() {
+            let mut collected_traits = Vec::new();
+            self.for_each_child(resolver, |_, name, ns, binding| {
+                if ns != TypeNS {
+                    return;
+                }
+                match binding.res() {
+                    Res::Def(DefKind::Trait | DefKind::TraitAlias, _) => {
+                        collected_traits.push((name, binding))
+                    }
+                    _ => (),
+                }
+            });
+            *traits = Some(collected_traits.into_boxed_slice());
+        }
+    }
+
     fn res(&self) -> Option<Res> {
         match self.kind {
             ModuleKind::Def(kind, def_id, _) => Some(Res::Def(kind, def_id)),
@@ -1430,6 +1454,68 @@ pub fn resolve_crate(&mut self, krate: &Crate) {
         self.crate_loader.postprocess(krate);
     }
 
+    fn get_traits_in_module_containing_item(
+        &mut self,
+        ident: Ident,
+        ns: Namespace,
+        module: Module<'a>,
+        found_traits: &mut Vec<TraitCandidate>,
+        parent_scope: &ParentScope<'a>,
+    ) {
+        assert!(ns == TypeNS || ns == ValueNS);
+        module.ensure_traits(self);
+        let traits = module.traits.borrow();
+
+        for &(trait_name, binding) in traits.as_ref().unwrap().iter() {
+            // Traits have pseudo-modules that can be used to search for the given ident.
+            if let Some(module) = binding.module() {
+                let mut ident = ident;
+                if ident.span.glob_adjust(module.expansion, binding.span).is_none() {
+                    continue;
+                }
+                if self
+                    .resolve_ident_in_module_unadjusted(
+                        ModuleOrUniformRoot::Module(module),
+                        ident,
+                        ns,
+                        parent_scope,
+                        false,
+                        module.span,
+                    )
+                    .is_ok()
+                {
+                    let import_ids = self.find_transitive_imports(&binding.kind, trait_name);
+                    let trait_def_id = module.def_id().unwrap();
+                    found_traits.push(TraitCandidate { def_id: trait_def_id, import_ids });
+                }
+            } else if let Res::Def(DefKind::TraitAlias, _) = binding.res() {
+                // For now, just treat all trait aliases as possible candidates, since we don't
+                // know if the ident is somewhere in the transitive bounds.
+                let import_ids = self.find_transitive_imports(&binding.kind, trait_name);
+                let trait_def_id = binding.res().def_id();
+                found_traits.push(TraitCandidate { def_id: trait_def_id, import_ids });
+            } else {
+                bug!("candidate is not trait or trait alias?")
+            }
+        }
+    }
+
+    fn find_transitive_imports(
+        &mut self,
+        mut kind: &NameBindingKind<'_>,
+        trait_name: Ident,
+    ) -> SmallVec<[LocalDefId; 1]> {
+        let mut import_ids = smallvec![];
+        while let NameBindingKind::Import { import, binding, .. } = kind {
+            let id = self.local_def_id(import.id);
+            self.maybe_unused_trait_imports.insert(id);
+            self.add_to_glob_map(&import, trait_name);
+            import_ids.push(id);
+            kind = &binding.kind;
+        }
+        import_ids
+    }
+
     fn new_module(
         &self,
         parent: Module<'a>,
@@ -3039,6 +3125,34 @@ fn extern_prelude_get(
         })
     }
 
+    /// This is equivalent to `get_traits_in_module_containing_item`, but without filtering by the associated item.
+    ///
+    /// This is used by rustdoc for intra-doc links.
+    pub fn traits_in_scope(&mut self, module_id: DefId) -> Vec<TraitCandidate> {
+        let module = self.get_module(module_id);
+        module.ensure_traits(self);
+        let traits = module.traits.borrow();
+        let to_candidate =
+            |this: &mut Self, &(trait_name, binding): &(Ident, &NameBinding<'_>)| TraitCandidate {
+                def_id: binding.res().def_id(),
+                import_ids: this.find_transitive_imports(&binding.kind, trait_name),
+            };
+
+        let mut candidates: Vec<_> =
+            traits.as_ref().unwrap().iter().map(|x| to_candidate(self, x)).collect();
+
+        if let Some(prelude) = self.prelude {
+            if !module.no_implicit_prelude {
+                prelude.ensure_traits(self);
+                candidates.extend(
+                    prelude.traits.borrow().as_ref().unwrap().iter().map(|x| to_candidate(self, x)),
+                );
+            }
+        }
+
+        candidates
+    }
+
     /// Rustdoc uses this to resolve things in a recoverable way. `ResolutionError<'a>`
     /// isn't something that can be returned because it can't be made to live that long,
     /// and also it's a private type. Fortunately rustdoc doesn't need to know the error,
index b3003cc63d3110260c63bc9e1e0443b722d10cd0..6dd7f89d594869d97a2849bada2ad0c14524cd8a 100644 (file)
@@ -377,7 +377,7 @@ fn make(&self, offset: usize, _parent_id: Option<hir::HirId>, scx: &SaveContext<
 
                 Ok(extend_sig(ty, text, defs, vec![]))
             }
-            hir::ItemKind::Fn(hir::FnSig { ref decl, header }, ref generics, _) => {
+            hir::ItemKind::Fn(hir::FnSig { ref decl, header, span: _ }, ref generics, _) => {
                 let mut text = String::new();
                 if let hir::Constness::Const = header.constness {
                     text.push_str("const ");
index 80164840334a23ba3de4724190d8439ccd0b922e..d05f1a3f34b78337d924ba78ca9e22880331517e 100644 (file)
@@ -807,6 +807,8 @@ fn parse_target_feature(slot: &mut String, v: Option<&str>) -> bool {
         "select which borrowck is used (`mir` or `migrate`) (default: `migrate`)"),
     borrowck_stats: bool = (false, parse_bool, [UNTRACKED],
         "gather borrowck statistics (default: no)"),
+    cgu_partitioning_strategy: Option<String> = (None, parse_opt_string, [TRACKED],
+        "the codegen unit partitioning strategy to use"),
     chalk: bool = (false, parse_bool, [TRACKED],
         "enable the experimental Chalk-based trait solving engine"),
     codegen_backend: Option<String> = (None, parse_opt_string, [TRACKED],
index d7da2038b549fda6d2422767919718eb2ccdb723..c006e593e47558152882a22668c1fba602c78def 100644 (file)
@@ -218,8 +218,6 @@ pub struct Session {
 pub struct PerfStats {
     /// The accumulated time spent on computing symbol hashes.
     pub symbol_hash_time: Lock<Duration>,
-    /// The accumulated time spent decoding def path tables from metadata.
-    pub decode_def_path_tables_time: Lock<Duration>,
     /// Total number of values canonicalized queries constructed.
     pub queries_canonicalized: AtomicUsize,
     /// Number of times this query is invoked.
@@ -862,10 +860,6 @@ pub fn print_perf_stats(&self) {
             "Total time spent computing symbol hashes:      {}",
             duration_to_secs_str(*self.perf_stats.symbol_hash_time.lock())
         );
-        println!(
-            "Total time spent decoding DefPath tables:      {}",
-            duration_to_secs_str(*self.perf_stats.decode_def_path_tables_time.lock())
-        );
         println!(
             "Total queries canonicalized:                   {}",
             self.perf_stats.queries_canonicalized.load(Ordering::Relaxed)
@@ -1339,7 +1333,6 @@ pub fn build_session(
         prof,
         perf_stats: PerfStats {
             symbol_hash_time: Lock::new(Duration::from_secs(0)),
-            decode_def_path_tables_time: Lock::new(Duration::from_secs(0)),
             queries_canonicalized: AtomicUsize::new(0),
             normalize_generic_arg_after_erasing_regions: AtomicUsize::new(0),
             normalize_projection_ty: AtomicUsize::new(0),
index 3883d86520fee7334b17a63cc7e732ea30198d34..46612145bf02cb2b77702dfcc4eb58bcece6c497 100644 (file)
         arith_offset,
         arm_target_feature,
         array,
+        arrays,
         as_str,
         asm,
         assert,
         i8,
         ident,
         if_let,
+        if_let_guard,
         if_while_or_patterns,
         ignore,
         impl_header_lifetime_elision,
         impl_lint_pass,
+        impl_macros,
         impl_trait_in_bindings,
         import_shadowing,
         in_band_lifetimes,
index 2ae13b501e9412d532d9f095917c7e4d805521d9..24356844bafc952f494bf86622532209652a3147 100644 (file)
@@ -136,7 +136,7 @@ fn get_symbol_hash<'tcx>(
 }
 
 // Follow C++ namespace-mangling style, see
-// http://en.wikipedia.org/wiki/Name_mangling for more info.
+// https://en.wikipedia.org/wiki/Name_mangling for more info.
 //
 // It turns out that on macOS you can actually have arbitrary symbols in
 // function names (at least when given to LLVM), but this is not possible
index 5f978c03248b2ab85337255e0d0ad95a2f451621..e07b8f7a75655a8493f5bd995a8bc20647341a7a 100644 (file)
@@ -1,10 +1,8 @@
-use crate::spec::{LinkerFlavor, Target, TargetResult};
+use crate::spec::{LinkerFlavor, LldFlavor, Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::hermit_base::opts();
     base.max_atomic_width = Some(128);
-    base.unsupported_abis = super::arm_base::unsupported_abis();
-    base.linker = Some("aarch64-hermit-gcc".to_string());
 
     Ok(Target {
         llvm_target: "aarch64-unknown-hermit".to_string(),
@@ -16,7 +14,7 @@ pub fn target() -> TargetResult {
         target_os: "hermit".to_string(),
         target_env: String::new(),
         target_vendor: "unknown".to_string(),
-        linker_flavor: LinkerFlavor::Gcc,
+        linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
         options: base,
     })
 }
index 18fb2aa3d5693f00ab0afbde139a8fb1ec5d8d84..e063c94cf2ca6b16281bdb96504b4184ec5ec11b 100644 (file)
@@ -16,7 +16,8 @@ pub fn opts() -> TargetOptions {
         pre_link_args,
         panic_strategy: PanicStrategy::Abort,
         position_independent_executables: true,
-        relocation_model: RelocModel::Static,
+        static_position_independent_executables: true,
+        relocation_model: RelocModel::Pic,
         target_family: None,
         tls_model: TlsModel::InitialExec,
         ..Default::default()
index 7f2dada714d8f721145d3968dc3ce4924a0befa5..01b9f75637fc4020a78bf797388d3f3a2137a140 100644 (file)
@@ -17,7 +17,8 @@ pub fn opts() -> TargetOptions {
         pre_link_args,
         panic_strategy: PanicStrategy::Abort,
         position_independent_executables: true,
-        relocation_model: RelocModel::Static,
+        static_position_independent_executables: true,
+        relocation_model: RelocModel::Pic,
         target_family: None,
         tls_model: TlsModel::InitialExec,
         ..Default::default()
index dc895ad34a93205017fdd623c22e083b606e9dfa..4ec1b29bca4f1286fa01a53accd905e61a616f3c 100644 (file)
@@ -2,7 +2,7 @@
 use crate::traits::{self, TraitEngine, TraitEngineExt};
 
 use rustc_hir as hir;
-use rustc_hir::lang_items;
+use rustc_hir::lang_items::LangItem;
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
 use rustc_infer::traits::ObligationCause;
 use rustc_middle::arena::ArenaAllocatable;
@@ -47,7 +47,7 @@ fn type_is_copy_modulo_regions(
             return ty.is_copy_modulo_regions(self.tcx.at(span), param_env);
         }
 
-        let copy_def_id = self.tcx.require_lang_item(lang_items::CopyTraitLangItem, None);
+        let copy_def_id = self.tcx.require_lang_item(LangItem::Copy, None);
 
         // This can get called from typeck (by euv), and `moves_by_default`
         // rightly refuses to work with inference variables, but
index e597843e6ce91105077e73c122b8be13c14b768a..28542d4b12ed914cdff52d98e609eff6746a165e 100644 (file)
@@ -399,16 +399,17 @@ fn report_selection_error(
                             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,
-                                        })
+                            let body = 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,
                                     })
-                                    .to_def_id(),
-                            );
+                                });
+
+                            let enclosing_scope_span =
+                                tcx.hir().span_with_body(tcx.hir().local_def_id_to_hir_id(body));
 
                             err.span_label(enclosing_scope_span, s.as_str());
                         }
index 7513ff6b37ef82087eceef0c02c42075f0182cfa..138293c95331f911adcac7712c4467059d038a36 100644 (file)
@@ -13,7 +13,7 @@
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::Visitor;
-use rustc_hir::lang_items;
+use rustc_hir::lang_items::LangItem;
 use rustc_hir::{AsyncGeneratorKind, GeneratorKind, Node};
 use rustc_middle::ty::{
     self, suggest_constraining_type_param, AdtKind, DefIdTree, Infer, InferTy, ToPredicate, Ty,
@@ -2015,8 +2015,7 @@ fn suggest_await_before_try(
         if let Some(body_id) = self.tcx.hir().maybe_body_owned_by(item_id) {
             let body = self.tcx.hir().body(body_id);
             if let Some(hir::GeneratorKind::Async(_)) = body.generator_kind {
-                let future_trait =
-                    self.tcx.require_lang_item(lang_items::FutureTraitLangItem, None);
+                let future_trait = self.tcx.require_lang_item(LangItem::Future, None);
 
                 let self_ty = self.resolve_vars_if_possible(&trait_ref.self_ty());
 
index a505d1b594c6310a633d1a032c3171f64fc6fd2f..c788e4f5c90b38ff88dddeb24ff731d3e7113999 100644 (file)
@@ -23,9 +23,7 @@
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_errors::ErrorReported;
 use rustc_hir::def_id::DefId;
-use rustc_hir::lang_items::{
-    DiscriminantTypeLangItem, FnOnceOutputLangItem, FnOnceTraitLangItem, GeneratorTraitLangItem,
-};
+use rustc_hir::lang_items::LangItem;
 use rustc_infer::infer::resolve::OpportunisticRegionResolver;
 use rustc_middle::ty::fold::{TypeFoldable, TypeFolder};
 use rustc_middle::ty::subst::Subst;
@@ -1300,7 +1298,7 @@ fn confirm_generator_candidate<'cx, 'tcx>(
 
     let tcx = selcx.tcx();
 
-    let gen_def_id = tcx.require_lang_item(GeneratorTraitLangItem, None);
+    let gen_def_id = tcx.require_lang_item(LangItem::Generator, None);
 
     let predicate = super::util::generator_trait_ref_and_outputs(
         tcx,
@@ -1342,7 +1340,7 @@ fn confirm_discriminant_kind_candidate<'cx, 'tcx>(
     let self_ty = selcx.infcx().shallow_resolve(obligation.predicate.self_ty());
     let substs = tcx.mk_substs([self_ty.into()].iter());
 
-    let discriminant_def_id = tcx.require_lang_item(DiscriminantTypeLangItem, None);
+    let discriminant_def_id = tcx.require_lang_item(LangItem::Discriminant, None);
 
     let predicate = ty::ProjectionPredicate {
         projection_ty: ty::ProjectionTy { substs, item_def_id: discriminant_def_id },
@@ -1406,8 +1404,8 @@ fn confirm_callable_candidate<'cx, 'tcx>(
 
     debug!("confirm_callable_candidate({:?},{:?})", obligation, fn_sig);
 
-    let fn_once_def_id = tcx.require_lang_item(FnOnceTraitLangItem, None);
-    let fn_once_output_def_id = tcx.require_lang_item(FnOnceOutputLangItem, None);
+    let fn_once_def_id = tcx.require_lang_item(LangItem::FnOnce, None);
+    let fn_once_output_def_id = tcx.require_lang_item(LangItem::FnOnceOutput, None);
 
     let predicate = super::util::closure_trait_ref_and_return_type(
         tcx,
index a04636af5796a0d96b5ce4b036119344c344d6bd..3d6eb845136361427f6eda4a902c638ea5750fb2 100644 (file)
@@ -7,7 +7,7 @@
 //! [rustc dev guide]:
 //! https://rustc-dev-guide.rust-lang.org/traits/resolution.html#confirmation
 use rustc_data_structures::stack::ensure_sufficient_stack;
-use rustc_hir::lang_items;
+use rustc_hir::lang_items::LangItem;
 use rustc_index::bit_set::GrowableBitSet;
 use rustc_infer::infer::InferOk;
 use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst, SubstsRef};
@@ -669,7 +669,7 @@ fn confirm_builtin_unsize_candidate(
 
                 // We can only make objects from sized types.
                 let tr = ty::TraitRef::new(
-                    tcx.require_lang_item(lang_items::SizedTraitLangItem, None),
+                    tcx.require_lang_item(LangItem::Sized, None),
                     tcx.mk_substs_trait(source, &[]),
                 );
                 nested.push(predicate_to_obligation(tr.without_const().to_predicate(tcx)));
index 377d163d1043913cc4e92035bc8a2901563db11c..78186a5e8a5813003c21a2c775e03ffdb4d5a730 100644 (file)
@@ -4,7 +4,7 @@
 
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
-use rustc_hir::lang_items::{StructuralPeqTraitLangItem, StructuralTeqTraitLangItem};
+use rustc_hir::lang_items::LangItem;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt, TypeFoldable, TypeVisitor};
 use rustc_span::Span;
@@ -75,7 +75,7 @@ fn type_marked_structural(
     let mut fulfillment_cx = traits::FulfillmentContext::new();
     // require `#[derive(PartialEq)]`
     let structural_peq_def_id =
-        infcx.tcx.require_lang_item(StructuralPeqTraitLangItem, Some(cause.span));
+        infcx.tcx.require_lang_item(LangItem::StructuralPeq, Some(cause.span));
     fulfillment_cx.register_bound(
         infcx,
         ty::ParamEnv::empty(),
@@ -86,7 +86,7 @@ fn type_marked_structural(
     // 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 structural_teq_def_id =
-        infcx.tcx.require_lang_item(StructuralTeqTraitLangItem, Some(cause.span));
+        infcx.tcx.require_lang_item(LangItem::StructuralTeq, Some(cause.span));
     fulfillment_cx.register_bound(
         infcx,
         ty::ParamEnv::empty(),
index d225b10834a6b33e3744690733743c5cc385c78f..0ac3c6ffe62c89e010a52a45671b348ab496e24d 100644 (file)
@@ -3,7 +3,7 @@
 use crate::traits;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
-use rustc_hir::lang_items;
+use rustc_hir::lang_items::LangItem;
 use rustc_middle::ty::subst::{GenericArg, GenericArgKind, SubstsRef};
 use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
 use rustc_span::Span;
@@ -340,7 +340,7 @@ fn require_sized(&mut self, subty: Ty<'tcx>, cause: traits::ObligationCauseCode<
         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),
+                def_id: self.infcx.tcx.require_lang_item(LangItem::Sized, None),
                 substs: self.infcx.tcx.mk_substs_trait(subty, &[]),
             };
             self.out.push(traits::Obligation::new(
index 8d153e77f0b7d402e6791aeb48822bdd5703ae33..24ba071786607fc4daa5aa03e0661e8be2ab22c7 100644 (file)
@@ -1,27 +1,27 @@
 //! Queries for checking whether a type implements one of a few common traits.
 
-use rustc_hir::lang_items;
+use rustc_hir::lang_items::LangItem;
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 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)
+    is_item_raw(tcx, query, LangItem::Copy)
 }
 
 fn is_sized_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
-    is_item_raw(tcx, query, lang_items::SizedTraitLangItem)
+    is_item_raw(tcx, query, LangItem::Sized)
 }
 
 fn is_freeze_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
-    is_item_raw(tcx, query, lang_items::FreezeTraitLangItem)
+    is_item_raw(tcx, query, LangItem::Freeze)
 }
 
 fn is_item_raw<'tcx>(
     tcx: TyCtxt<'tcx>,
     query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
-    item: lang_items::LangItem,
+    item: LangItem,
 ) -> bool {
     let (param_env, ty) = query.into_parts();
     let trait_def_id = tcx.require_lang_item(item, None);
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
deleted file mode 100644 (file)
index 86081b1..0000000
+++ /dev/null
@@ -1,3339 +0,0 @@
-// ignore-tidy-filelength FIXME(#67418) Split up this file.
-//! Conversion from AST representation of types to the `ty.rs` representation.
-//! The main routine here is `ast_ty_to_ty()`; each use is parameterized by an
-//! instance of `AstConv`.
-
-// ignore-tidy-filelength
-
-use crate::collect::PlaceholderHirTyCollector;
-use crate::middle::resolve_lifetime as rl;
-use crate::require_c_abi_if_c_variadic;
-use rustc_ast::{util::lev_distance::find_best_match_for_name, ParamKindOrd};
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_errors::ErrorReported;
-use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId, FatalError};
-use rustc_hir as hir;
-use rustc_hir::def::{CtorOf, DefKind, Namespace, Res};
-use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_hir::intravisit::{walk_generics, Visitor as _};
-use rustc_hir::lang_items::SizedTraitLangItem;
-use rustc_hir::{Constness, GenericArg, GenericArgs};
-use rustc_middle::ty::subst::{self, InternalSubsts, Subst, SubstsRef};
-use rustc_middle::ty::{
-    self, Const, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness,
-};
-use rustc_middle::ty::{GenericParamDef, GenericParamDefKind};
-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::{kw, sym, Ident, Symbol};
-use rustc_span::{MultiSpan, Span, DUMMY_SP};
-use rustc_target::spec::abi;
-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;
-
-#[derive(Debug)]
-pub struct PathSeg(pub DefId, pub usize);
-
-pub trait AstConv<'tcx> {
-    fn tcx<'a>(&'a self) -> TyCtxt<'tcx>;
-
-    fn item_def_id(&self) -> Option<DefId>;
-
-    fn default_constness_for_trait_bounds(&self) -> Constness;
-
-    /// Returns predicates in scope of the form `X: Foo`, where `X` is
-    /// a type parameter `X` with the given id `def_id`. This is a
-    /// subset of the full set of predicates.
-    ///
-    /// This is used for one specific purpose: resolving "short-hand"
-    /// associated type references like `T::Item`. In principle, we
-    /// would do that by first getting the full set of predicates in
-    /// scope and then filtering down to find those that apply to `T`,
-    /// but this can lead to cycle errors. The problem is that we have
-    /// to do this resolution *in order to create the predicates in
-    /// the first place*. Hence, we have this "special pass".
-    fn get_type_parameter_bounds(&self, span: Span, def_id: DefId) -> ty::GenericPredicates<'tcx>;
-
-    /// Returns the lifetime to use when a lifetime is omitted (and not elided).
-    fn re_infer(&self, param: Option<&ty::GenericParamDef>, span: Span)
-    -> Option<ty::Region<'tcx>>;
-
-    /// Returns the type to use when a type is omitted.
-    fn ty_infer(&self, param: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx>;
-
-    /// Returns `true` if `_` is allowed in type signatures in the current context.
-    fn allow_ty_infer(&self) -> bool;
-
-    /// Returns the const to use when a const is omitted.
-    fn ct_infer(
-        &self,
-        ty: Ty<'tcx>,
-        param: Option<&ty::GenericParamDef>,
-        span: Span,
-    ) -> &'tcx Const<'tcx>;
-
-    /// Projecting an associated type from a (potentially)
-    /// higher-ranked trait reference is more complicated, because of
-    /// the possibility of late-bound regions appearing in the
-    /// associated type binding. This is not legal in function
-    /// signatures for that reason. In a function body, we can always
-    /// handle it because we can use inference variables to remove the
-    /// late-bound regions.
-    fn projected_ty_from_poly_trait_ref(
-        &self,
-        span: Span,
-        item_def_id: DefId,
-        item_segment: &hir::PathSegment<'_>,
-        poly_trait_ref: ty::PolyTraitRef<'tcx>,
-    ) -> Ty<'tcx>;
-
-    /// Normalize an associated type coming from the user.
-    fn normalize_ty(&self, span: Span, ty: Ty<'tcx>) -> Ty<'tcx>;
-
-    /// Invoked when we encounter an error from some prior pass
-    /// (e.g., resolve) that is translated into a ty-error. This is
-    /// used to help suppress derived errors typeck might otherwise
-    /// report.
-    fn set_tainted_by_errors(&self);
-
-    fn record_ty(&self, hir_id: hir::HirId, ty: Ty<'tcx>, span: Span);
-}
-
-pub enum SizedByDefault {
-    Yes,
-    No,
-}
-
-struct ConvertedBinding<'a, 'tcx> {
-    item_name: Ident,
-    kind: ConvertedBindingKind<'a, 'tcx>,
-    span: Span,
-}
-
-enum ConvertedBindingKind<'a, 'tcx> {
-    Equality(Ty<'tcx>),
-    Constraint(&'a [hir::GenericBound<'a>]),
-}
-
-/// New-typed boolean indicating whether explicit late-bound lifetimes
-/// are present in a set of generic arguments.
-///
-/// For example if we have some method `fn f<'a>(&'a self)` implemented
-/// for some type `T`, although `f` is generic in the lifetime `'a`, `'a`
-/// is late-bound so should not be provided explicitly. Thus, if `f` is
-/// instantiated with some generic arguments providing `'a` explicitly,
-/// we taint those arguments with `ExplicitLateBound::Yes` so that we
-/// can provide an appropriate diagnostic later.
-#[derive(Copy, Clone, PartialEq)]
-pub enum ExplicitLateBound {
-    Yes,
-    No,
-}
-
-#[derive(Copy, Clone, PartialEq)]
-enum GenericArgPosition {
-    Type,
-    Value, // e.g., functions
-    MethodCall,
-}
-
-/// A marker denoting that the generic arguments that were
-/// provided did not match the respective generic parameters.
-#[derive(Clone, Default)]
-pub struct GenericArgCountMismatch {
-    /// Indicates whether a fatal error was reported (`Some`), or just a lint (`None`).
-    pub reported: Option<ErrorReported>,
-    /// A list of spans of arguments provided that were not valid.
-    pub invalid_args: Vec<Span>,
-}
-
-/// Decorates the result of a generic argument count mismatch
-/// check with whether explicit late bounds were provided.
-#[derive(Clone)]
-pub struct GenericArgCountResult {
-    pub explicit_late_bound: ExplicitLateBound,
-    pub correct: Result<(), GenericArgCountMismatch>,
-}
-
-impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
-    pub fn ast_region_to_region(
-        &self,
-        lifetime: &hir::Lifetime,
-        def: Option<&ty::GenericParamDef>,
-    ) -> ty::Region<'tcx> {
-        let tcx = self.tcx();
-        let lifetime_name = |def_id| tcx.hir().name(tcx.hir().local_def_id_to_hir_id(def_id));
-
-        let r = match tcx.named_region(lifetime.hir_id) {
-            Some(rl::Region::Static) => tcx.lifetimes.re_static,
-
-            Some(rl::Region::LateBound(debruijn, id, _)) => {
-                let name = lifetime_name(id.expect_local());
-                tcx.mk_region(ty::ReLateBound(debruijn, ty::BrNamed(id, name)))
-            }
-
-            Some(rl::Region::LateBoundAnon(debruijn, index)) => {
-                tcx.mk_region(ty::ReLateBound(debruijn, ty::BrAnon(index)))
-            }
-
-            Some(rl::Region::EarlyBound(index, id, _)) => {
-                let name = lifetime_name(id.expect_local());
-                tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion { def_id: id, index, name }))
-            }
-
-            Some(rl::Region::Free(scope, id)) => {
-                let name = lifetime_name(id.expect_local());
-                tcx.mk_region(ty::ReFree(ty::FreeRegion {
-                    scope,
-                    bound_region: ty::BrNamed(id, name),
-                }))
-
-                // (*) -- not late-bound, won't change
-            }
-
-            None => {
-                self.re_infer(def, lifetime.span).unwrap_or_else(|| {
-                    // This indicates an illegal lifetime
-                    // elision. `resolve_lifetime` should have
-                    // reported an error in this case -- but if
-                    // not, let's error out.
-                    tcx.sess.delay_span_bug(lifetime.span, "unelided lifetime in signature");
-
-                    // Supply some dummy value. We don't have an
-                    // `re_error`, annoyingly, so use `'static`.
-                    tcx.lifetimes.re_static
-                })
-            }
-        };
-
-        debug!("ast_region_to_region(lifetime={:?}) yields {:?}", lifetime, r);
-
-        r
-    }
-
-    /// Given a path `path` that refers to an item `I` with the declared generics `decl_generics`,
-    /// returns an appropriate set of substitutions for this particular reference to `I`.
-    pub fn ast_path_substs_for_ty(
-        &self,
-        span: Span,
-        def_id: DefId,
-        item_segment: &hir::PathSegment<'_>,
-    ) -> SubstsRef<'tcx> {
-        let (substs, assoc_bindings, _) = self.create_substs_for_ast_path(
-            span,
-            def_id,
-            &[],
-            item_segment.generic_args(),
-            item_segment.infer_args,
-            None,
-        );
-
-        if let Some(b) = assoc_bindings.first() {
-            Self::prohibit_assoc_ty_binding(self.tcx(), b.span);
-        }
-
-        substs
-    }
-
-    /// Report error if there is an explicit type parameter when using `impl Trait`.
-    fn check_impl_trait(
-        tcx: TyCtxt<'_>,
-        seg: &hir::PathSegment<'_>,
-        generics: &ty::Generics,
-    ) -> bool {
-        let explicit = !seg.infer_args;
-        let impl_trait = generics.params.iter().any(|param| match param.kind {
-            ty::GenericParamDefKind::Type {
-                synthetic: Some(hir::SyntheticTyParamKind::ImplTrait),
-                ..
-            } => true,
-            _ => false,
-        });
-
-        if explicit && impl_trait {
-            let spans = seg
-                .generic_args()
-                .args
-                .iter()
-                .filter_map(|arg| match arg {
-                    GenericArg::Type(_) => Some(arg.span()),
-                    _ => None,
-                })
-                .collect::<Vec<_>>();
-
-            let mut err = struct_span_err! {
-                tcx.sess,
-                spans.clone(),
-                E0632,
-                "cannot provide explicit generic arguments when `impl Trait` is \
-                used in argument position"
-            };
-
-            for span in spans {
-                err.span_label(span, "explicit generic argument not allowed");
-            }
-
-            err.emit();
-        }
-
-        impl_trait
-    }
-
-    /// Checks that the correct number of generic arguments have been provided.
-    /// Used specifically for function calls.
-    pub fn check_generic_arg_count_for_call(
-        tcx: TyCtxt<'_>,
-        span: Span,
-        def: &ty::Generics,
-        seg: &hir::PathSegment<'_>,
-        is_method_call: bool,
-    ) -> GenericArgCountResult {
-        let empty_args = hir::GenericArgs::none();
-        let suppress_mismatch = Self::check_impl_trait(tcx, seg, &def);
-        Self::check_generic_arg_count(
-            tcx,
-            span,
-            def,
-            if let Some(ref args) = seg.args { args } else { &empty_args },
-            if is_method_call { GenericArgPosition::MethodCall } else { GenericArgPosition::Value },
-            def.parent.is_none() && def.has_self, // `has_self`
-            seg.infer_args || suppress_mismatch,  // `infer_args`
-        )
-    }
-
-    /// Checks that the correct number of generic arguments have been provided.
-    /// This is used both for datatypes and function calls.
-    fn check_generic_arg_count(
-        tcx: TyCtxt<'_>,
-        span: Span,
-        def: &ty::Generics,
-        args: &hir::GenericArgs<'_>,
-        position: GenericArgPosition,
-        has_self: bool,
-        infer_args: bool,
-    ) -> GenericArgCountResult {
-        // At this stage we are guaranteed that the generic arguments are in the correct order, e.g.
-        // that lifetimes will proceed types. So it suffices to check the number of each generic
-        // arguments in order to validate them with respect to the generic parameters.
-        let param_counts = def.own_counts();
-        let arg_counts = args.own_counts();
-        let infer_lifetimes = position != GenericArgPosition::Type && arg_counts.lifetimes == 0;
-
-        let mut defaults: ty::GenericParamCount = Default::default();
-        for param in &def.params {
-            match param.kind {
-                GenericParamDefKind::Lifetime => {}
-                GenericParamDefKind::Type { has_default, .. } => {
-                    defaults.types += has_default as usize
-                }
-                GenericParamDefKind::Const => {
-                    // FIXME(const_generics:defaults)
-                }
-            };
-        }
-
-        if position != GenericArgPosition::Type && !args.bindings.is_empty() {
-            AstConv::prohibit_assoc_ty_binding(tcx, args.bindings[0].span);
-        }
-
-        let explicit_late_bound =
-            Self::prohibit_explicit_late_bound_lifetimes(tcx, def, args, position);
-
-        let check_kind_count = |kind,
-                                required,
-                                permitted,
-                                provided,
-                                offset,
-                                unexpected_spans: &mut Vec<Span>,
-                                silent| {
-            debug!(
-                "check_kind_count: kind: {} required: {} permitted: {} provided: {} offset: {}",
-                kind, required, permitted, provided, offset
-            );
-            // We enforce the following: `required` <= `provided` <= `permitted`.
-            // For kinds without defaults (e.g.., lifetimes), `required == permitted`.
-            // For other kinds (i.e., types), `permitted` may be greater than `required`.
-            if required <= provided && provided <= permitted {
-                return Ok(());
-            }
-
-            if silent {
-                return Err(true);
-            }
-
-            // Unfortunately lifetime and type parameter mismatches are typically styled
-            // differently in diagnostics, which means we have a few cases to consider here.
-            let (bound, quantifier) = if required != permitted {
-                if provided < required {
-                    (required, "at least ")
-                } else {
-                    // provided > permitted
-                    (permitted, "at most ")
-                }
-            } else {
-                (required, "")
-            };
-
-            let (spans, label) = if required == permitted && provided > permitted {
-                // In the case when the user has provided too many arguments,
-                // we want to point to the unexpected arguments.
-                let spans: Vec<Span> = args.args[offset + permitted..offset + provided]
-                    .iter()
-                    .map(|arg| arg.span())
-                    .collect();
-                unexpected_spans.extend(spans.clone());
-                (spans, format!("unexpected {} argument", kind))
-            } else {
-                (
-                    vec![span],
-                    format!(
-                        "expected {}{} {} argument{}",
-                        quantifier,
-                        bound,
-                        kind,
-                        pluralize!(bound),
-                    ),
-                )
-            };
-
-            let mut err = tcx.sess.struct_span_err_with_code(
-                spans.clone(),
-                &format!(
-                    "wrong number of {} arguments: expected {}{}, found {}",
-                    kind, quantifier, bound, provided,
-                ),
-                DiagnosticId::Error("E0107".into()),
-            );
-            for span in spans {
-                err.span_label(span, label.as_str());
-            }
-            err.emit();
-
-            Err(true)
-        };
-
-        let mut arg_count_correct = Ok(());
-        let mut unexpected_spans = vec![];
-
-        if !infer_lifetimes || arg_counts.lifetimes > param_counts.lifetimes {
-            arg_count_correct = check_kind_count(
-                "lifetime",
-                param_counts.lifetimes,
-                param_counts.lifetimes,
-                arg_counts.lifetimes,
-                0,
-                &mut unexpected_spans,
-                explicit_late_bound == ExplicitLateBound::Yes,
-            )
-            .and(arg_count_correct);
-        }
-        // FIXME(const_generics:defaults)
-        if !infer_args || arg_counts.consts > param_counts.consts {
-            arg_count_correct = check_kind_count(
-                "const",
-                param_counts.consts,
-                param_counts.consts,
-                arg_counts.consts,
-                arg_counts.lifetimes + arg_counts.types,
-                &mut unexpected_spans,
-                false,
-            )
-            .and(arg_count_correct);
-        }
-        // Note that type errors are currently be emitted *after* const errors.
-        if !infer_args || arg_counts.types > param_counts.types - defaults.types - has_self as usize
-        {
-            arg_count_correct = check_kind_count(
-                "type",
-                param_counts.types - defaults.types - has_self as usize,
-                param_counts.types - has_self as usize,
-                arg_counts.types,
-                arg_counts.lifetimes,
-                &mut unexpected_spans,
-                false,
-            )
-            .and(arg_count_correct);
-        }
-
-        GenericArgCountResult {
-            explicit_late_bound,
-            correct: arg_count_correct.map_err(|reported_err| GenericArgCountMismatch {
-                reported: if reported_err { Some(ErrorReported) } else { None },
-                invalid_args: unexpected_spans,
-            }),
-        }
-    }
-
-    /// Report an error that a generic argument did not match the generic parameter that was
-    /// expected.
-    fn generic_arg_mismatch_err(
-        sess: &Session,
-        arg: &GenericArg<'_>,
-        kind: &'static str,
-        help: Option<&str>,
-    ) {
-        let mut err = struct_span_err!(
-            sess,
-            arg.span(),
-            E0747,
-            "{} provided when a {} was expected",
-            arg.descr(),
-            kind,
-        );
-
-        let unordered = sess.features_untracked().const_generics;
-        let kind_ord = match kind {
-            "lifetime" => ParamKindOrd::Lifetime,
-            "type" => ParamKindOrd::Type,
-            "constant" => ParamKindOrd::Const { unordered },
-            // It's more concise to match on the string representation, though it means
-            // the match is non-exhaustive.
-            _ => bug!("invalid generic parameter kind {}", kind),
-        };
-        let arg_ord = match arg {
-            GenericArg::Lifetime(_) => ParamKindOrd::Lifetime,
-            GenericArg::Type(_) => ParamKindOrd::Type,
-            GenericArg::Const(_) => ParamKindOrd::Const { unordered },
-        };
-
-        // This note is only true when generic parameters are strictly ordered by their kind.
-        if kind_ord.cmp(&arg_ord) != core::cmp::Ordering::Equal {
-            let (first, last) =
-                if kind_ord < arg_ord { (kind, arg.descr()) } else { (arg.descr(), kind) };
-            err.note(&format!("{} arguments must be provided before {} arguments", first, last));
-            if let Some(help) = help {
-                err.help(help);
-            }
-        }
-
-        err.emit();
-    }
-
-    /// Creates the relevant generic argument substitutions
-    /// corresponding to a set of generic parameters. This is a
-    /// rather complex function. Let us try to explain the role
-    /// of each of its parameters:
-    ///
-    /// To start, we are given the `def_id` of the thing we are
-    /// creating the substitutions for, and a partial set of
-    /// substitutions `parent_substs`. In general, the substitutions
-    /// for an item begin with substitutions for all the "parents" of
-    /// that item -- e.g., for a method it might include the
-    /// parameters from the impl.
-    ///
-    /// Therefore, the method begins by walking down these parents,
-    /// starting with the outermost parent and proceed inwards until
-    /// it reaches `def_id`. For each parent `P`, it will check `parent_substs`
-    /// first to see if the parent's substitutions are listed in there. If so,
-    /// we can append those and move on. Otherwise, it invokes the
-    /// three callback functions:
-    ///
-    /// - `args_for_def_id`: given the `DefId` `P`, supplies back the
-    ///   generic arguments that were given to that parent from within
-    ///   the path; so e.g., if you have `<T as Foo>::Bar`, the `DefId`
-    ///   might refer to the trait `Foo`, and the arguments might be
-    ///   `[T]`. The boolean value indicates whether to infer values
-    ///   for arguments whose values were not explicitly provided.
-    /// - `provided_kind`: given the generic parameter and the value from `args_for_def_id`,
-    ///   instantiate a `GenericArg`.
-    /// - `inferred_kind`: if no parameter was provided, and inference is enabled, then
-    ///   creates a suitable inference variable.
-    pub fn create_substs_for_generic_args<'b>(
-        tcx: TyCtxt<'tcx>,
-        def_id: DefId,
-        parent_substs: &[subst::GenericArg<'tcx>],
-        has_self: bool,
-        self_ty: Option<Ty<'tcx>>,
-        arg_count: GenericArgCountResult,
-        args_for_def_id: impl Fn(DefId) -> (Option<&'b GenericArgs<'b>>, bool),
-        mut provided_kind: impl FnMut(&GenericParamDef, &GenericArg<'_>) -> subst::GenericArg<'tcx>,
-        mut inferred_kind: impl FnMut(
-            Option<&[subst::GenericArg<'tcx>]>,
-            &GenericParamDef,
-            bool,
-        ) -> subst::GenericArg<'tcx>,
-    ) -> SubstsRef<'tcx> {
-        // Collect the segments of the path; we need to substitute arguments
-        // for parameters throughout the entire path (wherever there are
-        // generic parameters).
-        let mut parent_defs = tcx.generics_of(def_id);
-        let count = parent_defs.count();
-        let mut stack = vec![(def_id, parent_defs)];
-        while let Some(def_id) = parent_defs.parent {
-            parent_defs = tcx.generics_of(def_id);
-            stack.push((def_id, parent_defs));
-        }
-
-        // We manually build up the substitution, rather than using convenience
-        // methods in `subst.rs`, so that we can iterate over the arguments and
-        // parameters in lock-step linearly, instead of trying to match each pair.
-        let mut substs: SmallVec<[subst::GenericArg<'tcx>; 8]> = SmallVec::with_capacity(count);
-        // Iterate over each segment of the path.
-        while let Some((def_id, defs)) = stack.pop() {
-            let mut params = defs.params.iter().peekable();
-
-            // If we have already computed substitutions for parents, we can use those directly.
-            while let Some(&param) = params.peek() {
-                if let Some(&kind) = parent_substs.get(param.index as usize) {
-                    substs.push(kind);
-                    params.next();
-                } else {
-                    break;
-                }
-            }
-
-            // `Self` is handled first, unless it's been handled in `parent_substs`.
-            if has_self {
-                if let Some(&param) = params.peek() {
-                    if param.index == 0 {
-                        if let GenericParamDefKind::Type { .. } = param.kind {
-                            substs.push(
-                                self_ty
-                                    .map(|ty| ty.into())
-                                    .unwrap_or_else(|| inferred_kind(None, param, true)),
-                            );
-                            params.next();
-                        }
-                    }
-                }
-            }
-
-            // Check whether this segment takes generic arguments and the user has provided any.
-            let (generic_args, infer_args) = args_for_def_id(def_id);
-
-            let mut args =
-                generic_args.iter().flat_map(|generic_args| generic_args.args.iter()).peekable();
-
-            // If we encounter a type or const when we expect a lifetime, we infer the lifetimes.
-            // If we later encounter a lifetime, we know that the arguments were provided in the
-            // wrong order. `force_infer_lt` records the type or const that forced lifetimes to be
-            // inferred, so we can use it for diagnostics later.
-            let mut force_infer_lt = None;
-
-            loop {
-                // We're going to iterate through the generic arguments that the user
-                // provided, matching them with the generic parameters we expect.
-                // Mismatches can occur as a result of elided lifetimes, or for malformed
-                // input. We try to handle both sensibly.
-                match (args.peek(), params.peek()) {
-                    (Some(&arg), Some(&param)) => {
-                        match (arg, &param.kind, arg_count.explicit_late_bound) {
-                            (GenericArg::Lifetime(_), GenericParamDefKind::Lifetime, _)
-                            | (GenericArg::Type(_), GenericParamDefKind::Type { .. }, _)
-                            | (GenericArg::Const(_), GenericParamDefKind::Const, _) => {
-                                substs.push(provided_kind(param, arg));
-                                args.next();
-                                params.next();
-                            }
-                            (
-                                GenericArg::Type(_) | GenericArg::Const(_),
-                                GenericParamDefKind::Lifetime,
-                                _,
-                            ) => {
-                                // We expected a lifetime argument, but got a type or const
-                                // argument. That means we're inferring the lifetimes.
-                                substs.push(inferred_kind(None, param, infer_args));
-                                force_infer_lt = Some(arg);
-                                params.next();
-                            }
-                            (GenericArg::Lifetime(_), _, ExplicitLateBound::Yes) => {
-                                // We've come across a lifetime when we expected something else in
-                                // the presence of explicit late bounds. This is most likely
-                                // due to the presence of the explicit bound so we're just going to
-                                // ignore it.
-                                args.next();
-                            }
-                            (_, kind, _) => {
-                                // We expected one kind of parameter, but the user provided
-                                // another. This is an error. However, if we already know that
-                                // the arguments don't match up with the parameters, we won't issue
-                                // an additional error, as the user already knows what's wrong.
-                                if arg_count.correct.is_ok()
-                                    && arg_count.explicit_late_bound == ExplicitLateBound::No
-                                {
-                                    // We're going to iterate over the parameters to sort them out, and
-                                    // show that order to the user as a possible order for the parameters
-                                    let mut param_types_present = defs
-                                        .params
-                                        .clone()
-                                        .into_iter()
-                                        .map(|param| {
-                                            (
-                                                match param.kind {
-                                                    GenericParamDefKind::Lifetime => {
-                                                        ParamKindOrd::Lifetime
-                                                    }
-                                                    GenericParamDefKind::Type { .. } => {
-                                                        ParamKindOrd::Type
-                                                    }
-                                                    GenericParamDefKind::Const => {
-                                                        ParamKindOrd::Const {
-                                                            unordered: tcx
-                                                                .sess
-                                                                .features_untracked()
-                                                                .const_generics,
-                                                        }
-                                                    }
-                                                },
-                                                param,
-                                            )
-                                        })
-                                        .collect::<Vec<(ParamKindOrd, GenericParamDef)>>();
-                                    param_types_present.sort_by_key(|(ord, _)| *ord);
-                                    let (mut param_types_present, ordered_params): (
-                                        Vec<ParamKindOrd>,
-                                        Vec<GenericParamDef>,
-                                    ) = param_types_present.into_iter().unzip();
-                                    param_types_present.dedup();
-
-                                    Self::generic_arg_mismatch_err(
-                                        tcx.sess,
-                                        arg,
-                                        kind.descr(),
-                                        Some(&format!(
-                                            "reorder the arguments: {}: `<{}>`",
-                                            param_types_present
-                                                .into_iter()
-                                                .map(|ord| format!("{}s", ord.to_string()))
-                                                .collect::<Vec<String>>()
-                                                .join(", then "),
-                                            ordered_params
-                                                .into_iter()
-                                                .filter_map(|param| {
-                                                    if param.name == kw::SelfUpper {
-                                                        None
-                                                    } else {
-                                                        Some(param.name.to_string())
-                                                    }
-                                                })
-                                                .collect::<Vec<String>>()
-                                                .join(", ")
-                                        )),
-                                    );
-                                }
-
-                                // We've reported the error, but we want to make sure that this
-                                // problem doesn't bubble down and create additional, irrelevant
-                                // errors. In this case, we're simply going to ignore the argument
-                                // and any following arguments. The rest of the parameters will be
-                                // inferred.
-                                while args.next().is_some() {}
-                            }
-                        }
-                    }
-
-                    (Some(&arg), None) => {
-                        // We should never be able to reach this point with well-formed input.
-                        // There are three situations in which we can encounter this issue.
-                        //
-                        //  1.  The number of arguments is incorrect. In this case, an error
-                        //      will already have been emitted, and we can ignore it.
-                        //  2.  There are late-bound lifetime parameters present, yet the
-                        //      lifetime arguments have also been explicitly specified by the
-                        //      user.
-                        //  3.  We've inferred some lifetimes, which have been provided later (i.e.
-                        //      after a type or const). We want to throw an error in this case.
-
-                        if arg_count.correct.is_ok()
-                            && arg_count.explicit_late_bound == ExplicitLateBound::No
-                        {
-                            let kind = arg.descr();
-                            assert_eq!(kind, "lifetime");
-                            let provided =
-                                force_infer_lt.expect("lifetimes ought to have been inferred");
-                            Self::generic_arg_mismatch_err(tcx.sess, provided, kind, None);
-                        }
-
-                        break;
-                    }
-
-                    (None, Some(&param)) => {
-                        // If there are fewer arguments than parameters, it means
-                        // we're inferring the remaining arguments.
-                        substs.push(inferred_kind(Some(&substs), param, infer_args));
-                        params.next();
-                    }
-
-                    (None, None) => break,
-                }
-            }
-        }
-
-        tcx.intern_substs(&substs)
-    }
-
-    /// 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 constraints on associated types.
-    ///
-    /// Example:
-    ///
-    /// ```
-    /// T: std::ops::Index<usize, Output = u32>
-    /// ^1 ^^^^^^^^^^^^^^2 ^^^^3  ^^^^^^^^^^^4
-    /// ```
-    ///
-    /// 1. The `self_ty` here would refer to the type `T`.
-    /// 2. The path in question is the path to the trait `std::ops::Index`,
-    ///    which will have been resolved to a `def_id`
-    /// 3. The `generic_args` contains info on the `<...>` contents. The `usize` type
-    ///    parameters are returned in the `SubstsRef`, the associated type bindings like
-    ///    `Output = u32` are returned in the `Vec<ConvertedBinding...>` result.
-    ///
-    /// Note that the type listing given here is *exactly* what the user provided.
-    ///
-    /// For (generic) associated types
-    ///
-    /// ```
-    /// <Vec<u8> as Iterable<u8>>::Iter::<'a>
-    /// ```
-    ///
-    /// We have the parent substs are the substs for the parent trait:
-    /// `[Vec<u8>, u8]` and `generic_args` are the arguments for the associated
-    /// type itself: `['a]`. The returned `SubstsRef` concatenates these two
-    /// lists: `[Vec<u8>, u8, 'a]`.
-    fn create_substs_for_ast_path<'a>(
-        &self,
-        span: Span,
-        def_id: DefId,
-        parent_substs: &[subst::GenericArg<'tcx>],
-        generic_args: &'a hir::GenericArgs<'_>,
-        infer_args: bool,
-        self_ty: Option<Ty<'tcx>>,
-    ) -> (SubstsRef<'tcx>, Vec<ConvertedBinding<'a, 'tcx>>, GenericArgCountResult) {
-        // If the type is parameterized by this region, then replace this
-        // region with the current anon region binding (in other words,
-        // whatever & would get replaced with).
-        debug!(
-            "create_substs_for_ast_path(def_id={:?}, self_ty={:?}, \
-                generic_args={:?})",
-            def_id, self_ty, generic_args
-        );
-
-        let tcx = self.tcx();
-        let generic_params = tcx.generics_of(def_id);
-
-        if generic_params.has_self {
-            if generic_params.parent.is_some() {
-                // The parent is a trait so it should have at least one subst
-                // for the `Self` type.
-                assert!(!parent_substs.is_empty())
-            } else {
-                // This item (presumably a trait) needs a self-type.
-                assert!(self_ty.is_some());
-            }
-        } else {
-            assert!(self_ty.is_none() && parent_substs.is_empty());
-        }
-
-        let arg_count = Self::check_generic_arg_count(
-            tcx,
-            span,
-            &generic_params,
-            &generic_args,
-            GenericArgPosition::Type,
-            self_ty.is_some(),
-            infer_args,
-        );
-
-        let is_object = self_ty.map_or(false, |ty| ty == self.tcx().types.trait_object_dummy_self);
-        let default_needs_object_self = |param: &ty::GenericParamDef| {
-            if let GenericParamDefKind::Type { has_default, .. } = param.kind {
-                if is_object && has_default {
-                    let default_ty = tcx.at(span).type_of(param.def_id);
-                    let self_param = tcx.types.self_param;
-                    if default_ty.walk().any(|arg| arg == self_param.into()) {
-                        // There is no suitable inference default for a type parameter
-                        // that references self, in an object type.
-                        return true;
-                    }
-                }
-            }
-
-            false
-        };
-
-        let mut missing_type_params = vec![];
-        let mut inferred_params = vec![];
-        let substs = Self::create_substs_for_generic_args(
-            tcx,
-            def_id,
-            parent_substs,
-            self_ty.is_some(),
-            self_ty,
-            arg_count.clone(),
-            // Provide the generic args, and whether types should be inferred.
-            |did| {
-                if did == def_id {
-                    (Some(generic_args), infer_args)
-                } else {
-                    // The last component of this tuple is unimportant.
-                    (None, false)
-                }
-            },
-            // Provide substitutions for parameters for which (valid) arguments have been provided.
-            |param, arg| match (&param.kind, arg) {
-                (GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => {
-                    self.ast_region_to_region(&lt, Some(param)).into()
-                }
-                (GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => {
-                    if let (hir::TyKind::Infer, false) = (&ty.kind, self.allow_ty_infer()) {
-                        inferred_params.push(ty.span);
-                        tcx.ty_error().into()
-                    } else {
-                        self.ast_ty_to_ty(&ty).into()
-                    }
-                }
-                (GenericParamDefKind::Const, GenericArg::Const(ct)) => {
-                    ty::Const::from_opt_const_arg_anon_const(
-                        tcx,
-                        ty::WithOptConstParam {
-                            did: tcx.hir().local_def_id(ct.value.hir_id),
-                            const_param_did: Some(param.def_id),
-                        },
-                    )
-                    .into()
-                }
-                _ => unreachable!(),
-            },
-            // Provide substitutions for parameters for which arguments are inferred.
-            |substs, param, infer_args| {
-                match param.kind {
-                    GenericParamDefKind::Lifetime => tcx.lifetimes.re_static.into(),
-                    GenericParamDefKind::Type { has_default, .. } => {
-                        if !infer_args && has_default {
-                            // No type parameter provided, but a default exists.
-
-                            // If we are converting an object type, then the
-                            // `Self` parameter is unknown. However, some of the
-                            // other type parameters may reference `Self` in their
-                            // defaults. This will lead to an ICE if we are not
-                            // careful!
-                            if default_needs_object_self(param) {
-                                missing_type_params.push(param.name.to_string());
-                                tcx.ty_error().into()
-                            } else {
-                                // This is a default type parameter.
-                                self.normalize_ty(
-                                    span,
-                                    tcx.at(span).type_of(param.def_id).subst_spanned(
-                                        tcx,
-                                        substs.unwrap(),
-                                        Some(span),
-                                    ),
-                                )
-                                .into()
-                            }
-                        } else if infer_args {
-                            // No type parameters were provided, we can infer all.
-                            let param =
-                                if !default_needs_object_self(param) { Some(param) } else { None };
-                            self.ty_infer(param, span).into()
-                        } else {
-                            // We've already errored above about the mismatch.
-                            tcx.ty_error().into()
-                        }
-                    }
-                    GenericParamDefKind::Const => {
-                        let ty = tcx.at(span).type_of(param.def_id);
-                        // FIXME(const_generics:defaults)
-                        if infer_args {
-                            // No const parameters were provided, we can infer all.
-                            self.ct_infer(ty, Some(param), span).into()
-                        } else {
-                            // We've already errored above about the mismatch.
-                            tcx.const_error(ty).into()
-                        }
-                    }
-                }
-            },
-        );
-
-        self.complain_about_missing_type_params(
-            missing_type_params,
-            def_id,
-            span,
-            generic_args.args.is_empty(),
-        );
-
-        // Convert associated-type bindings or constraints into a separate vector.
-        // Example: Given this:
-        //
-        //     T: Iterator<Item = u32>
-        //
-        // The `T` is passed in as a self-type; the `Item = u32` is
-        // not a "type parameter" of the `Iterator` trait, but rather
-        // a restriction on `<T as Iterator>::Item`, so it is passed
-        // back separately.
-        let assoc_bindings = generic_args
-            .bindings
-            .iter()
-            .map(|binding| {
-                let kind = match binding.kind {
-                    hir::TypeBindingKind::Equality { ref ty } => {
-                        ConvertedBindingKind::Equality(self.ast_ty_to_ty(ty))
-                    }
-                    hir::TypeBindingKind::Constraint { ref bounds } => {
-                        ConvertedBindingKind::Constraint(bounds)
-                    }
-                };
-                ConvertedBinding { item_name: binding.ident, kind, span: binding.span }
-            })
-            .collect();
-
-        debug!(
-            "create_substs_for_ast_path(generic_params={:?}, self_ty={:?}) -> {:?}",
-            generic_params, self_ty, substs
-        );
-
-        (substs, assoc_bindings, arg_count)
-    }
-
-    crate fn create_substs_for_associated_item(
-        &self,
-        tcx: TyCtxt<'tcx>,
-        span: Span,
-        item_def_id: DefId,
-        item_segment: &hir::PathSegment<'_>,
-        parent_substs: SubstsRef<'tcx>,
-    ) -> SubstsRef<'tcx> {
-        if tcx.generics_of(item_def_id).params.is_empty() {
-            self.prohibit_generics(slice::from_ref(item_segment));
-
-            parent_substs
-        } else {
-            self.create_substs_for_ast_path(
-                span,
-                item_def_id,
-                parent_substs,
-                item_segment.generic_args(),
-                item_segment.infer_args,
-                None,
-            )
-            .0
-        }
-    }
-
-    /// On missing type parameters, emit an E0393 error and provide a structured suggestion using
-    /// the type parameter's name as a placeholder.
-    fn complain_about_missing_type_params(
-        &self,
-        missing_type_params: Vec<String>,
-        def_id: DefId,
-        span: Span,
-        empty_generic_args: bool,
-    ) {
-        if missing_type_params.is_empty() {
-            return;
-        }
-        let display =
-            missing_type_params.iter().map(|n| format!("`{}`", n)).collect::<Vec<_>>().join(", ");
-        let mut err = struct_span_err!(
-            self.tcx().sess,
-            span,
-            E0393,
-            "the type parameter{} {} must be explicitly specified",
-            pluralize!(missing_type_params.len()),
-            display,
-        );
-        err.span_label(
-            self.tcx().def_span(def_id),
-            &format!(
-                "type parameter{} {} must be specified for this",
-                pluralize!(missing_type_params.len()),
-                display,
-            ),
-        );
-        let mut suggested = false;
-        if let (Ok(snippet), true) = (
-            self.tcx().sess.source_map().span_to_snippet(span),
-            // Don't suggest setting the type params if there are some already: the order is
-            // tricky to get right and the user will already know what the syntax is.
-            empty_generic_args,
-        ) {
-            if snippet.ends_with('>') {
-                // The user wrote `Trait<'a, T>` or similar. To provide an accurate suggestion
-                // we would have to preserve the right order. For now, as clearly the user is
-                // aware of the syntax, we do nothing.
-            } else {
-                // The user wrote `Iterator`, so we don't have a type we can suggest, but at
-                // least we can clue them to the correct syntax `Iterator<Type>`.
-                err.span_suggestion(
-                    span,
-                    &format!(
-                        "set the type parameter{plural} to the desired type{plural}",
-                        plural = pluralize!(missing_type_params.len()),
-                    ),
-                    format!("{}<{}>", snippet, missing_type_params.join(", ")),
-                    Applicability::HasPlaceholders,
-                );
-                suggested = true;
-            }
-        }
-        if !suggested {
-            err.span_label(
-                span,
-                format!(
-                    "missing reference{} to {}",
-                    pluralize!(missing_type_params.len()),
-                    display,
-                ),
-            );
-        }
-        err.note(
-            "because of the default `Self` reference, type parameters must be \
-                  specified on object types",
-        );
-        err.emit();
-    }
-
-    /// Instantiates the path for the given trait reference, assuming that it's
-    /// bound to a valid trait type. Returns the `DefId` of the defining trait.
-    /// The type _cannot_ be a type other than a trait type.
-    ///
-    /// If the `projections` argument is `None`, then assoc type bindings like `Foo<T = X>`
-    /// are disallowed. Otherwise, they are pushed onto the vector given.
-    pub fn instantiate_mono_trait_ref(
-        &self,
-        trait_ref: &hir::TraitRef<'_>,
-        self_ty: Ty<'tcx>,
-    ) -> ty::TraitRef<'tcx> {
-        self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1);
-
-        self.ast_path_to_mono_trait_ref(
-            trait_ref.path.span,
-            trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise()),
-            self_ty,
-            trait_ref.path.segments.last().unwrap(),
-        )
-    }
-
-    /// The given trait-ref must actually be a trait.
-    pub(super) fn instantiate_poly_trait_ref_inner(
-        &self,
-        trait_ref: &hir::TraitRef<'_>,
-        span: Span,
-        constness: Constness,
-        self_ty: Ty<'tcx>,
-        bounds: &mut Bounds<'tcx>,
-        speculative: bool,
-    ) -> GenericArgCountResult {
-        let trait_def_id = trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise());
-
-        debug!("instantiate_poly_trait_ref({:?}, def_id={:?})", trait_ref, trait_def_id);
-
-        self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1);
-
-        let (substs, assoc_bindings, arg_count) = self.create_substs_for_ast_trait_ref(
-            trait_ref.path.span,
-            trait_def_id,
-            self_ty,
-            trait_ref.path.segments.last().unwrap(),
-        );
-        let poly_trait_ref = ty::Binder::bind(ty::TraitRef::new(trait_def_id, substs));
-
-        bounds.trait_bounds.push((poly_trait_ref, span, constness));
-
-        let mut dup_bindings = FxHashMap::default();
-        for binding in &assoc_bindings {
-            // Specify type to assert that error was already reported in `Err` case.
-            let _: Result<_, ErrorReported> = self.add_predicates_for_ast_type_binding(
-                trait_ref.hir_ref_id,
-                poly_trait_ref,
-                binding,
-                bounds,
-                speculative,
-                &mut dup_bindings,
-                binding.span,
-            );
-            // Okay to ignore `Err` because of `ErrorReported` (see above).
-        }
-
-        debug!(
-            "instantiate_poly_trait_ref({:?}, bounds={:?}) -> {:?}",
-            trait_ref, bounds, poly_trait_ref
-        );
-
-        arg_count
-    }
-
-    /// Given a trait bound like `Debug`, applies that trait bound the given self-type to construct
-    /// a full trait reference. The resulting trait reference is returned. This may also generate
-    /// auxiliary bounds, which are added to `bounds`.
-    ///
-    /// Example:
-    ///
-    /// ```
-    /// poly_trait_ref = Iterator<Item = u32>
-    /// self_ty = Foo
-    /// ```
-    ///
-    /// this would return `Foo: Iterator` and add `<Foo as Iterator>::Item = u32` into `bounds`.
-    ///
-    /// **A note on binders:** against our usual convention, there is an implied bounder around
-    /// the `self_ty` and `poly_trait_ref` parameters here. So they may reference bound regions.
-    /// If for example you had `for<'a> Foo<'a>: Bar<'a>`, then the `self_ty` would be `Foo<'a>`
-    /// where `'a` is a bound region at depth 0. Similarly, the `poly_trait_ref` would be
-    /// `Bar<'a>`. The returned poly-trait-ref will have this binder instantiated explicitly,
-    /// however.
-    pub fn instantiate_poly_trait_ref(
-        &self,
-        poly_trait_ref: &hir::PolyTraitRef<'_>,
-        constness: Constness,
-        self_ty: Ty<'tcx>,
-        bounds: &mut Bounds<'tcx>,
-    ) -> GenericArgCountResult {
-        self.instantiate_poly_trait_ref_inner(
-            &poly_trait_ref.trait_ref,
-            poly_trait_ref.span,
-            constness,
-            self_ty,
-            bounds,
-            false,
-        )
-    }
-
-    pub fn instantiate_lang_item_trait_ref(
-        &self,
-        lang_item: hir::LangItem,
-        span: Span,
-        hir_id: hir::HirId,
-        args: &GenericArgs<'_>,
-        self_ty: Ty<'tcx>,
-        bounds: &mut Bounds<'tcx>,
-    ) {
-        let trait_def_id = self.tcx().require_lang_item(lang_item, Some(span));
-
-        let (substs, assoc_bindings, _) =
-            self.create_substs_for_ast_path(span, trait_def_id, &[], args, false, Some(self_ty));
-        let poly_trait_ref = ty::Binder::bind(ty::TraitRef::new(trait_def_id, substs));
-        bounds.trait_bounds.push((poly_trait_ref, span, Constness::NotConst));
-
-        let mut dup_bindings = FxHashMap::default();
-        for binding in assoc_bindings {
-            let _: Result<_, ErrorReported> = self.add_predicates_for_ast_type_binding(
-                hir_id,
-                poly_trait_ref,
-                &binding,
-                bounds,
-                false,
-                &mut dup_bindings,
-                span,
-            );
-        }
-    }
-
-    fn ast_path_to_mono_trait_ref(
-        &self,
-        span: Span,
-        trait_def_id: DefId,
-        self_ty: Ty<'tcx>,
-        trait_segment: &hir::PathSegment<'_>,
-    ) -> ty::TraitRef<'tcx> {
-        let (substs, assoc_bindings, _) =
-            self.create_substs_for_ast_trait_ref(span, trait_def_id, self_ty, trait_segment);
-        if let Some(b) = assoc_bindings.first() {
-            AstConv::prohibit_assoc_ty_binding(self.tcx(), b.span);
-        }
-        ty::TraitRef::new(trait_def_id, substs)
-    }
-
-    /// When the code is using the `Fn` traits directly, instead of the `Fn(A) -> B` syntax, emit
-    /// an error and attempt to build a reasonable structured suggestion.
-    fn complain_about_internal_fn_trait(
-        &self,
-        span: Span,
-        trait_def_id: DefId,
-        trait_segment: &'a hir::PathSegment<'a>,
-    ) {
-        let trait_def = self.tcx().trait_def(trait_def_id);
-
-        if !self.tcx().features().unboxed_closures
-            && trait_segment.generic_args().parenthesized != trait_def.paren_sugar
-        {
-            let sess = &self.tcx().sess.parse_sess;
-            // For now, require that parenthetical notation be used only with `Fn()` etc.
-            let (msg, sugg) = if trait_def.paren_sugar {
-                (
-                    "the precise format of `Fn`-family traits' type parameters is subject to \
-                     change",
-                    Some(format!(
-                        "{}{} -> {}",
-                        trait_segment.ident,
-                        trait_segment
-                            .args
-                            .as_ref()
-                            .and_then(|args| args.args.get(0))
-                            .and_then(|arg| match arg {
-                                hir::GenericArg::Type(ty) => match ty.kind {
-                                    hir::TyKind::Tup(t) => t
-                                        .iter()
-                                        .map(|e| sess.source_map().span_to_snippet(e.span))
-                                        .collect::<Result<Vec<_>, _>>()
-                                        .map(|a| a.join(", ")),
-                                    _ => sess.source_map().span_to_snippet(ty.span),
-                                }
-                                .map(|s| format!("({})", s))
-                                .ok(),
-                                _ => None,
-                            })
-                            .unwrap_or_else(|| "()".to_string()),
-                        trait_segment
-                            .generic_args()
-                            .bindings
-                            .iter()
-                            .find_map(|b| match (b.ident.name == sym::Output, &b.kind) {
-                                (true, hir::TypeBindingKind::Equality { ty }) => {
-                                    sess.source_map().span_to_snippet(ty.span).ok()
-                                }
-                                _ => None,
-                            })
-                            .unwrap_or_else(|| "()".to_string()),
-                    )),
-                )
-            } else {
-                ("parenthetical notation is only stable when used with `Fn`-family traits", None)
-            };
-            let mut err = feature_err(sess, sym::unboxed_closures, span, msg);
-            if let Some(sugg) = sugg {
-                let msg = "use parenthetical notation instead";
-                err.span_suggestion(span, msg, sugg, Applicability::MaybeIncorrect);
-            }
-            err.emit();
-        }
-    }
-
-    fn create_substs_for_ast_trait_ref<'a>(
-        &self,
-        span: Span,
-        trait_def_id: DefId,
-        self_ty: Ty<'tcx>,
-        trait_segment: &'a hir::PathSegment<'a>,
-    ) -> (SubstsRef<'tcx>, Vec<ConvertedBinding<'a, 'tcx>>, GenericArgCountResult) {
-        debug!("create_substs_for_ast_trait_ref(trait_segment={:?})", trait_segment);
-
-        self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment);
-
-        self.create_substs_for_ast_path(
-            span,
-            trait_def_id,
-            &[],
-            trait_segment.generic_args(),
-            trait_segment.infer_args,
-            Some(self_ty),
-        )
-    }
-
-    fn trait_defines_associated_type_named(&self, trait_def_id: DefId, assoc_name: Ident) -> bool {
-        self.tcx()
-            .associated_items(trait_def_id)
-            .find_by_name_and_kind(self.tcx(), assoc_name, ty::AssocKind::Type, trait_def_id)
-            .is_some()
-    }
-
-    // Returns `true` if a bounds list includes `?Sized`.
-    pub fn is_unsized(&self, ast_bounds: &[hir::GenericBound<'_>], span: Span) -> bool {
-        let tcx = self.tcx();
-
-        // Try to find an unbound in bounds.
-        let mut unbound = None;
-        for ab in ast_bounds {
-            if let &hir::GenericBound::Trait(ref ptr, hir::TraitBoundModifier::Maybe) = ab {
-                if unbound.is_none() {
-                    unbound = Some(&ptr.trait_ref);
-                } else {
-                    struct_span_err!(
-                        tcx.sess,
-                        span,
-                        E0203,
-                        "type parameter has more than one relaxed default \
-                        bound, only one is supported"
-                    )
-                    .emit();
-                }
-            }
-        }
-
-        let kind_id = tcx.lang_items().require(SizedTraitLangItem);
-        match unbound {
-            Some(tpb) => {
-                // FIXME(#8559) currently requires the unbound to be built-in.
-                if let Ok(kind_id) = kind_id {
-                    if tpb.path.res != Res::Def(DefKind::Trait, kind_id) {
-                        tcx.sess.span_warn(
-                            span,
-                            "default bound relaxed for a type parameter, but \
-                             this does nothing because the given bound is not \
-                             a default; only `?Sized` is supported",
-                        );
-                    }
-                }
-            }
-            _ if kind_id.is_ok() => {
-                return false;
-            }
-            // No lang item for `Sized`, so we can't add it as a bound.
-            None => {}
-        }
-
-        true
-    }
-
-    /// This helper takes a *converted* parameter type (`param_ty`)
-    /// and an *unconverted* list of bounds:
-    ///
-    /// ```text
-    /// fn foo<T: Debug>
-    ///        ^  ^^^^^ `ast_bounds` parameter, in HIR form
-    ///        |
-    ///        `param_ty`, in ty form
-    /// ```
-    ///
-    /// It adds these `ast_bounds` into the `bounds` structure.
-    ///
-    /// **A note on binders:** there is an implied binder around
-    /// `param_ty` and `ast_bounds`. See `instantiate_poly_trait_ref`
-    /// for more details.
-    fn add_bounds(
-        &self,
-        param_ty: Ty<'tcx>,
-        ast_bounds: &[hir::GenericBound<'_>],
-        bounds: &mut Bounds<'tcx>,
-    ) {
-        let mut trait_bounds = Vec::new();
-        let mut region_bounds = Vec::new();
-
-        let constness = self.default_constness_for_trait_bounds();
-        for ast_bound in ast_bounds {
-            match *ast_bound {
-                hir::GenericBound::Trait(ref b, hir::TraitBoundModifier::None) => {
-                    trait_bounds.push((b, constness))
-                }
-                hir::GenericBound::Trait(ref b, hir::TraitBoundModifier::MaybeConst) => {
-                    trait_bounds.push((b, Constness::NotConst))
-                }
-                hir::GenericBound::Trait(_, hir::TraitBoundModifier::Maybe) => {}
-                hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => self
-                    .instantiate_lang_item_trait_ref(
-                        lang_item, span, hir_id, args, param_ty, bounds,
-                    ),
-                hir::GenericBound::Outlives(ref l) => region_bounds.push(l),
-            }
-        }
-
-        for (bound, constness) in trait_bounds {
-            let _ = self.instantiate_poly_trait_ref(bound, constness, param_ty, bounds);
-        }
-
-        bounds.region_bounds.extend(
-            region_bounds.into_iter().map(|r| (self.ast_region_to_region(r, None), r.span)),
-        );
-    }
-
-    /// Translates a list of bounds from the HIR into the `Bounds` data structure.
-    /// The self-type for the bounds is given by `param_ty`.
-    ///
-    /// Example:
-    ///
-    /// ```
-    /// fn foo<T: Bar + Baz>() { }
-    ///        ^  ^^^^^^^^^ ast_bounds
-    ///        param_ty
-    /// ```
-    ///
-    /// The `sized_by_default` parameter indicates if, in this context, the `param_ty` should be
-    /// considered `Sized` unless there is an explicit `?Sized` bound.  This would be true in the
-    /// example above, but is not true in supertrait listings like `trait Foo: Bar + Baz`.
-    ///
-    /// `span` should be the declaration size of the parameter.
-    pub fn compute_bounds(
-        &self,
-        param_ty: Ty<'tcx>,
-        ast_bounds: &[hir::GenericBound<'_>],
-        sized_by_default: SizedByDefault,
-        span: Span,
-    ) -> Bounds<'tcx> {
-        let mut bounds = Bounds::default();
-
-        self.add_bounds(param_ty, ast_bounds, &mut bounds);
-        bounds.trait_bounds.sort_by_key(|(t, _, _)| t.def_id());
-
-        bounds.implicitly_sized = if let SizedByDefault::Yes = sized_by_default {
-            if !self.is_unsized(ast_bounds, span) { Some(span) } else { None }
-        } else {
-            None
-        };
-
-        bounds
-    }
-
-    /// Given an HIR binding like `Item = Foo` or `Item: Foo`, pushes the corresponding predicates
-    /// onto `bounds`.
-    ///
-    /// **A note on binders:** given something like `T: for<'a> Iterator<Item = &'a u32>`, the
-    /// `trait_ref` here will be `for<'a> T: Iterator`. The `binding` data however is from *inside*
-    /// the binder (e.g., `&'a u32`) and hence may reference bound regions.
-    fn add_predicates_for_ast_type_binding(
-        &self,
-        hir_ref_id: hir::HirId,
-        trait_ref: ty::PolyTraitRef<'tcx>,
-        binding: &ConvertedBinding<'_, 'tcx>,
-        bounds: &mut Bounds<'tcx>,
-        speculative: bool,
-        dup_bindings: &mut FxHashMap<DefId, Span>,
-        path_span: Span,
-    ) -> Result<(), ErrorReported> {
-        let tcx = self.tcx();
-
-        if !speculative {
-            // Given something like `U: SomeTrait<T = X>`, we want to produce a
-            // predicate like `<U as SomeTrait>::T = X`. This is somewhat
-            // subtle in the event that `T` is defined in a supertrait of
-            // `SomeTrait`, because in that case we need to upcast.
-            //
-            // That is, consider this case:
-            //
-            // ```
-            // trait SubTrait: SuperTrait<i32> { }
-            // trait SuperTrait<A> { type T; }
-            //
-            // ... B: SubTrait<T = foo> ...
-            // ```
-            //
-            // We want to produce `<B as SuperTrait<i32>>::T == foo`.
-
-            // Find any late-bound regions declared in `ty` that are not
-            // declared in the trait-ref. These are not well-formed.
-            //
-            // Example:
-            //
-            //     for<'a> <T as Iterator>::Item = &'a str // <-- 'a is bad
-            //     for<'a> <T as FnMut<(&'a u32,)>>::Output = &'a str // <-- 'a is ok
-            if let ConvertedBindingKind::Equality(ty) = binding.kind {
-                let late_bound_in_trait_ref =
-                    tcx.collect_constrained_late_bound_regions(&trait_ref);
-                let late_bound_in_ty =
-                    tcx.collect_referenced_late_bound_regions(&ty::Binder::bind(ty));
-                debug!("late_bound_in_trait_ref = {:?}", late_bound_in_trait_ref);
-                debug!("late_bound_in_ty = {:?}", late_bound_in_ty);
-
-                // FIXME: point at the type params that don't have appropriate lifetimes:
-                // struct S1<F: for<'a> Fn(&i32, &i32) -> &'a i32>(F);
-                //                         ----  ----     ^^^^^^^
-                self.validate_late_bound_regions(
-                    late_bound_in_trait_ref,
-                    late_bound_in_ty,
-                    |br_name| {
-                        struct_span_err!(
-                            tcx.sess,
-                            binding.span,
-                            E0582,
-                            "binding for associated type `{}` references {}, \
-                             which does not appear in the trait input types",
-                            binding.item_name,
-                            br_name
-                        )
-                    },
-                );
-            }
-        }
-
-        let candidate =
-            if self.trait_defines_associated_type_named(trait_ref.def_id(), binding.item_name) {
-                // Simple case: X is defined in the current trait.
-                trait_ref
-            } else {
-                // Otherwise, we have to walk through the supertraits to find
-                // those that do.
-                self.one_bound_for_assoc_type(
-                    || traits::supertraits(tcx, trait_ref),
-                    || trait_ref.print_only_trait_path().to_string(),
-                    binding.item_name,
-                    path_span,
-                    || match binding.kind {
-                        ConvertedBindingKind::Equality(ty) => Some(ty.to_string()),
-                        _ => None,
-                    },
-                )?
-            };
-
-        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.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.normalize_to_macros_2_0() == assoc_ident
-            })
-            .expect("missing associated type");
-
-        if !assoc_ty.vis.is_accessible_from(def_scope, tcx) {
-            tcx.sess
-                .struct_span_err(
-                    binding.span,
-                    &format!("associated type `{}` is private", binding.item_name),
-                )
-                .span_label(binding.span, "private associated type")
-                .emit();
-        }
-        tcx.check_stability(assoc_ty.def_id, Some(hir_ref_id), binding.span);
-
-        if !speculative {
-            dup_bindings
-                .entry(assoc_ty.def_id)
-                .and_modify(|prev_span| {
-                    struct_span_err!(
-                        self.tcx().sess,
-                        binding.span,
-                        E0719,
-                        "the value of the associated type `{}` (from trait `{}`) \
-                         is already specified",
-                        binding.item_name,
-                        tcx.def_path_str(assoc_ty.container.id())
-                    )
-                    .span_label(binding.span, "re-bound here")
-                    .span_label(*prev_span, format!("`{}` bound here first", binding.item_name))
-                    .emit();
-                })
-                .or_insert(binding.span);
-        }
-
-        match binding.kind {
-            ConvertedBindingKind::Equality(ref ty) => {
-                // "Desugar" a constraint like `T: Iterator<Item = u32>` this to
-                // the "projection predicate" for:
-                //
-                // `<T as Iterator>::Item = u32`
-                bounds.projection_bounds.push((
-                    candidate.map_bound(|trait_ref| ty::ProjectionPredicate {
-                        projection_ty: ty::ProjectionTy::from_ref_and_name(
-                            tcx,
-                            trait_ref,
-                            binding.item_name,
-                        ),
-                        ty,
-                    }),
-                    binding.span,
-                ));
-            }
-            ConvertedBindingKind::Constraint(ast_bounds) => {
-                // "Desugar" a constraint like `T: Iterator<Item: Debug>` to
-                //
-                // `<T as Iterator>::Item: Debug`
-                //
-                // Calling `skip_binder` is okay, because `add_bounds` expects the `param_ty`
-                // parameter to have a skipped binder.
-                let param_ty = tcx.mk_projection(assoc_ty.def_id, candidate.skip_binder().substs);
-                self.add_bounds(param_ty, ast_bounds, bounds);
-            }
-        }
-        Ok(())
-    }
-
-    fn ast_path_to_ty(
-        &self,
-        span: Span,
-        did: DefId,
-        item_segment: &hir::PathSegment<'_>,
-    ) -> Ty<'tcx> {
-        let substs = self.ast_path_substs_for_ty(span, did, item_segment);
-        self.normalize_ty(span, self.tcx().at(span).type_of(did).subst(self.tcx(), substs))
-    }
-
-    fn conv_object_ty_poly_trait_ref(
-        &self,
-        span: Span,
-        trait_bounds: &[hir::PolyTraitRef<'_>],
-        lifetime: &hir::Lifetime,
-        borrowed: bool,
-    ) -> Ty<'tcx> {
-        let tcx = self.tcx();
-
-        let mut bounds = Bounds::default();
-        let mut potential_assoc_types = Vec::new();
-        let dummy_self = self.tcx().types.trait_object_dummy_self;
-        for trait_bound in trait_bounds.iter().rev() {
-            if let GenericArgCountResult {
-                correct:
-                    Err(GenericArgCountMismatch { invalid_args: cur_potential_assoc_types, .. }),
-                ..
-            } = self.instantiate_poly_trait_ref(
-                trait_bound,
-                Constness::NotConst,
-                dummy_self,
-                &mut bounds,
-            ) {
-                potential_assoc_types.extend(cur_potential_assoc_types.into_iter());
-            }
-        }
-
-        // Expand trait aliases recursively and check that only one regular (non-auto) trait
-        // is used and no 'maybe' bounds are used.
-        let expanded_traits =
-            traits::expand_trait_aliases(tcx, bounds.trait_bounds.iter().map(|&(a, b, _)| (a, b)));
-        let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) =
-            expanded_traits.partition(|i| tcx.trait_is_auto(i.trait_ref().def_id()));
-        if regular_traits.len() > 1 {
-            let first_trait = &regular_traits[0];
-            let additional_trait = &regular_traits[1];
-            let mut err = struct_span_err!(
-                tcx.sess,
-                additional_trait.bottom().1,
-                E0225,
-                "only auto traits can be used as additional traits in a trait object"
-            );
-            additional_trait.label_with_exp_info(
-                &mut err,
-                "additional non-auto trait",
-                "additional use",
-            );
-            first_trait.label_with_exp_info(&mut err, "first non-auto trait", "first use");
-            err.help(&format!(
-                "consider creating a new trait with all of these as super-traits and using that \
-                 trait here instead: `trait NewTrait: {} {{}}`",
-                regular_traits
-                    .iter()
-                    .map(|t| t.trait_ref().print_only_trait_path().to_string())
-                    .collect::<Vec<_>>()
-                    .join(" + "),
-            ));
-            err.note(
-                "auto-traits like `Send` and `Sync` are traits that have special properties; \
-                 for more information on them, visit \
-                 <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>",
-            );
-            err.emit();
-        }
-
-        if regular_traits.is_empty() && auto_traits.is_empty() {
-            struct_span_err!(
-                tcx.sess,
-                span,
-                E0224,
-                "at least one trait is required for an object type"
-            )
-            .emit();
-            return tcx.ty_error();
-        }
-
-        // Check that there are no gross object safety violations;
-        // most importantly, that the supertraits don't contain `Self`,
-        // to avoid ICEs.
-        for item in &regular_traits {
-            let object_safety_violations =
-                astconv_object_safety_violations(tcx, item.trait_ref().def_id());
-            if !object_safety_violations.is_empty() {
-                report_object_safety_error(
-                    tcx,
-                    span,
-                    item.trait_ref().def_id(),
-                    &object_safety_violations[..],
-                )
-                .emit();
-                return tcx.ty_error();
-            }
-        }
-
-        // Use a `BTreeSet` to keep output in a more consistent order.
-        let mut associated_types: FxHashMap<Span, BTreeSet<DefId>> = FxHashMap::default();
-
-        let regular_traits_refs_spans = bounds
-            .trait_bounds
-            .into_iter()
-            .filter(|(trait_ref, _, _)| !tcx.trait_is_auto(trait_ref.def_id()));
-
-        for (base_trait_ref, span, constness) in regular_traits_refs_spans {
-            assert_eq!(constness, Constness::NotConst);
-
-            for obligation in traits::elaborate_trait_ref(tcx, base_trait_ref) {
-                debug!(
-                    "conv_object_ty_poly_trait_ref: observing object predicate `{:?}`",
-                    obligation.predicate
-                );
-
-                match obligation.predicate.skip_binders() {
-                    ty::PredicateAtom::Trait(pred, _) => {
-                        let pred = ty::Binder::bind(pred);
-                        associated_types.entry(span).or_default().extend(
-                            tcx.associated_items(pred.def_id())
-                                .in_definition_order()
-                                .filter(|item| item.kind == ty::AssocKind::Type)
-                                .map(|item| item.def_id),
-                        );
-                    }
-                    ty::PredicateAtom::Projection(pred) => {
-                        let pred = ty::Binder::bind(pred);
-                        // A `Self` within the original bound will be substituted with a
-                        // `trait_object_dummy_self`, so check for that.
-                        let references_self =
-                            pred.skip_binder().ty.walk().any(|arg| arg == dummy_self.into());
-
-                        // If the projection output contains `Self`, force the user to
-                        // elaborate it explicitly to avoid a lot of complexity.
-                        //
-                        // The "classicaly useful" case is the following:
-                        // ```
-                        //     trait MyTrait: FnMut() -> <Self as MyTrait>::MyOutput {
-                        //         type MyOutput;
-                        //     }
-                        // ```
-                        //
-                        // Here, the user could theoretically write `dyn MyTrait<Output = X>`,
-                        // but actually supporting that would "expand" to an infinitely-long type
-                        // `fix $ Ï„ â†’ dyn MyTrait<MyOutput = X, Output = <Ï„ as MyTrait>::MyOutput`.
-                        //
-                        // Instead, we force the user to write
-                        // `dyn MyTrait<MyOutput = X, Output = X>`, which is uglier but works. See
-                        // the discussion in #56288 for alternatives.
-                        if !references_self {
-                            // Include projections defined on supertraits.
-                            bounds.projection_bounds.push((pred, span));
-                        }
-                    }
-                    _ => (),
-                }
-            }
-        }
-
-        for (projection_bound, _) in &bounds.projection_bounds {
-            for def_ids in associated_types.values_mut() {
-                def_ids.remove(&projection_bound.projection_def_id());
-            }
-        }
-
-        self.complain_about_missing_associated_types(
-            associated_types,
-            potential_assoc_types,
-            trait_bounds,
-        );
-
-        // De-duplicate auto traits so that, e.g., `dyn Trait + Send + Send` is the same as
-        // `dyn Trait + Send`.
-        auto_traits.sort_by_key(|i| i.trait_ref().def_id());
-        auto_traits.dedup_by_key(|i| i.trait_ref().def_id());
-        debug!("regular_traits: {:?}", regular_traits);
-        debug!("auto_traits: {:?}", auto_traits);
-
-        // Transform a `PolyTraitRef` into a `PolyExistentialTraitRef` by
-        // removing the dummy `Self` type (`trait_object_dummy_self`).
-        let trait_ref_to_existential = |trait_ref: ty::TraitRef<'tcx>| {
-            if trait_ref.self_ty() != dummy_self {
-                // FIXME: There appears to be a missing filter on top of `expand_trait_aliases`,
-                // which picks up non-supertraits where clauses - but also, the object safety
-                // completely ignores trait aliases, which could be object safety hazards. We
-                // `delay_span_bug` here to avoid an ICE in stable even when the feature is
-                // disabled. (#66420)
-                tcx.sess.delay_span_bug(
-                    DUMMY_SP,
-                    &format!(
-                        "trait_ref_to_existential called on {:?} with non-dummy Self",
-                        trait_ref,
-                    ),
-                );
-            }
-            ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref)
-        };
-
-        // Erase the `dummy_self` (`trait_object_dummy_self`) used above.
-        let existential_trait_refs =
-            regular_traits.iter().map(|i| i.trait_ref().map_bound(trait_ref_to_existential));
-        let existential_projections = bounds.projection_bounds.iter().map(|(bound, _)| {
-            bound.map_bound(|b| {
-                let trait_ref = trait_ref_to_existential(b.projection_ty.trait_ref(tcx));
-                ty::ExistentialProjection {
-                    ty: b.ty,
-                    item_def_id: b.projection_ty.item_def_id,
-                    substs: trait_ref.substs,
-                }
-            })
-        });
-
-        // Calling `skip_binder` is okay because the predicates are re-bound.
-        let regular_trait_predicates = existential_trait_refs
-            .map(|trait_ref| ty::ExistentialPredicate::Trait(trait_ref.skip_binder()));
-        let auto_trait_predicates = auto_traits
-            .into_iter()
-            .map(|trait_ref| ty::ExistentialPredicate::AutoTrait(trait_ref.trait_ref().def_id()));
-        let mut v = regular_trait_predicates
-            .chain(auto_trait_predicates)
-            .chain(
-                existential_projections
-                    .map(|x| ty::ExistentialPredicate::Projection(x.skip_binder())),
-            )
-            .collect::<SmallVec<[_; 8]>>();
-        v.sort_by(|a, b| a.stable_cmp(tcx, b));
-        v.dedup();
-        let existential_predicates = ty::Binder::bind(tcx.mk_existential_predicates(v.into_iter()));
-
-        // Use explicitly-specified region bound.
-        let region_bound = if !lifetime.is_elided() {
-            self.ast_region_to_region(lifetime, None)
-        } else {
-            self.compute_object_lifetime_bound(span, existential_predicates).unwrap_or_else(|| {
-                if tcx.named_region(lifetime.hir_id).is_some() {
-                    self.ast_region_to_region(lifetime, None)
-                } else {
-                    self.re_infer(None, span).unwrap_or_else(|| {
-                        let mut err = struct_span_err!(
-                            tcx.sess,
-                            span,
-                            E0228,
-                            "the lifetime bound for this object type cannot be deduced \
-                             from context; please supply an explicit bound"
-                        );
-                        if borrowed {
-                            // We will have already emitted an error E0106 complaining about a
-                            // missing named lifetime in `&dyn Trait`, so we elide this one.
-                            err.delay_as_bug();
-                        } else {
-                            err.emit();
-                        }
-                        tcx.lifetimes.re_static
-                    })
-                }
-            })
-        };
-        debug!("region_bound: {:?}", region_bound);
-
-        let ty = tcx.mk_dynamic(existential_predicates, region_bound);
-        debug!("trait_object_type: {:?}", ty);
-        ty
-    }
-
-    /// When there are any missing associated types, emit an E0191 error and attempt to supply a
-    /// reasonable suggestion on how to write it. For the case of multiple associated types in the
-    /// same trait bound have the same name (as they come from different super-traits), we instead
-    /// emit a generic note suggesting using a `where` clause to constraint instead.
-    fn complain_about_missing_associated_types(
-        &self,
-        associated_types: FxHashMap<Span, BTreeSet<DefId>>,
-        potential_assoc_types: Vec<Span>,
-        trait_bounds: &[hir::PolyTraitRef<'_>],
-    ) {
-        if associated_types.values().all(|v| v.is_empty()) {
-            return;
-        }
-        let tcx = self.tcx();
-        // FIXME: Marked `mut` so that we can replace the spans further below with a more
-        // appropriate one, but this should be handled earlier in the span assignment.
-        let mut associated_types: FxHashMap<Span, Vec<_>> = associated_types
-            .into_iter()
-            .map(|(span, def_ids)| {
-                (span, def_ids.into_iter().map(|did| tcx.associated_item(did)).collect())
-            })
-            .collect();
-        let mut names = vec![];
-
-        // Account for things like `dyn Foo + 'a`, like in tests `issue-22434.rs` and
-        // `issue-22560.rs`.
-        let mut trait_bound_spans: Vec<Span> = vec![];
-        for (span, items) in &associated_types {
-            if !items.is_empty() {
-                trait_bound_spans.push(*span);
-            }
-            for assoc_item in items {
-                let trait_def_id = assoc_item.container.id();
-                names.push(format!(
-                    "`{}` (from trait `{}`)",
-                    assoc_item.ident,
-                    tcx.def_path_str(trait_def_id),
-                ));
-            }
-        }
-        if let ([], [bound]) = (&potential_assoc_types[..], &trait_bounds) {
-            match &bound.trait_ref.path.segments[..] {
-                // FIXME: `trait_ref.path.span` can point to a full path with multiple
-                // segments, even though `trait_ref.path.segments` is of length `1`. Work
-                // around that bug here, even though it should be fixed elsewhere.
-                // This would otherwise cause an invalid suggestion. For an example, look at
-                // `src/test/ui/issues/issue-28344.rs` where instead of the following:
-                //
-                //   error[E0191]: the value of the associated type `Output`
-                //                 (from trait `std::ops::BitXor`) must be specified
-                //   --> $DIR/issue-28344.rs:4:17
-                //    |
-                // LL |     let x: u8 = BitXor::bitor(0 as u8, 0 as u8);
-                //    |                 ^^^^^^ help: specify the associated type:
-                //    |                              `BitXor<Output = Type>`
-                //
-                // we would output:
-                //
-                //   error[E0191]: the value of the associated type `Output`
-                //                 (from trait `std::ops::BitXor`) must be specified
-                //   --> $DIR/issue-28344.rs:4:17
-                //    |
-                // LL |     let x: u8 = BitXor::bitor(0 as u8, 0 as u8);
-                //    |                 ^^^^^^^^^^^^^ help: specify the associated type:
-                //    |                                     `BitXor::bitor<Output = Type>`
-                [segment] if segment.args.is_none() => {
-                    trait_bound_spans = vec![segment.ident.span];
-                    associated_types = associated_types
-                        .into_iter()
-                        .map(|(_, items)| (segment.ident.span, items))
-                        .collect();
-                }
-                _ => {}
-            }
-        }
-        names.sort();
-        trait_bound_spans.sort();
-        let mut err = struct_span_err!(
-            tcx.sess,
-            trait_bound_spans,
-            E0191,
-            "the value of the associated type{} {} must be specified",
-            pluralize!(names.len()),
-            names.join(", "),
-        );
-        let mut suggestions = vec![];
-        let mut types_count = 0;
-        let mut where_constraints = vec![];
-        for (span, assoc_items) in &associated_types {
-            let mut names: FxHashMap<_, usize> = FxHashMap::default();
-            for item in assoc_items {
-                types_count += 1;
-                *names.entry(item.ident.name).or_insert(0) += 1;
-            }
-            let mut dupes = false;
-            for item in assoc_items {
-                let prefix = if names[&item.ident.name] > 1 {
-                    let trait_def_id = item.container.id();
-                    dupes = true;
-                    format!("{}::", tcx.def_path_str(trait_def_id))
-                } else {
-                    String::new()
-                };
-                if let Some(sp) = tcx.hir().span_if_local(item.def_id) {
-                    err.span_label(sp, format!("`{}{}` defined here", prefix, item.ident));
-                }
-            }
-            if potential_assoc_types.len() == assoc_items.len() {
-                // Only suggest when the amount of missing associated types equals the number of
-                // extra type arguments present, as that gives us a relatively high confidence
-                // that the user forgot to give the associtated type's name. The canonical
-                // example would be trying to use `Iterator<isize>` instead of
-                // `Iterator<Item = isize>`.
-                for (potential, item) in potential_assoc_types.iter().zip(assoc_items.iter()) {
-                    if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(*potential) {
-                        suggestions.push((*potential, format!("{} = {}", item.ident, snippet)));
-                    }
-                }
-            } else if let (Ok(snippet), false) =
-                (tcx.sess.source_map().span_to_snippet(*span), dupes)
-            {
-                let types: Vec<_> =
-                    assoc_items.iter().map(|item| format!("{} = Type", item.ident)).collect();
-                let code = if snippet.ends_with('>') {
-                    // The user wrote `Trait<'a>` or similar and we don't have a type we can
-                    // suggest, but at least we can clue them to the correct syntax
-                    // `Trait<'a, Item = Type>` while accounting for the `<'a>` in the
-                    // suggestion.
-                    format!("{}, {}>", &snippet[..snippet.len() - 1], types.join(", "))
-                } else {
-                    // The user wrote `Iterator`, so we don't have a type we can suggest, but at
-                    // least we can clue them to the correct syntax `Iterator<Item = Type>`.
-                    format!("{}<{}>", snippet, types.join(", "))
-                };
-                suggestions.push((*span, code));
-            } else if dupes {
-                where_constraints.push(*span);
-            }
-        }
-        let where_msg = "consider introducing a new type parameter, adding `where` constraints \
-                         using the fully-qualified path to the associated types";
-        if !where_constraints.is_empty() && suggestions.is_empty() {
-            // If there are duplicates associated type names and a single trait bound do not
-            // use structured suggestion, it means that there are multiple super-traits with
-            // the same associated type name.
-            err.help(where_msg);
-        }
-        if suggestions.len() != 1 {
-            // We don't need this label if there's an inline suggestion, show otherwise.
-            for (span, assoc_items) in &associated_types {
-                let mut names: FxHashMap<_, usize> = FxHashMap::default();
-                for item in assoc_items {
-                    types_count += 1;
-                    *names.entry(item.ident.name).or_insert(0) += 1;
-                }
-                let mut label = vec![];
-                for item in assoc_items {
-                    let postfix = if names[&item.ident.name] > 1 {
-                        let trait_def_id = item.container.id();
-                        format!(" (from trait `{}`)", tcx.def_path_str(trait_def_id))
-                    } else {
-                        String::new()
-                    };
-                    label.push(format!("`{}`{}", item.ident, postfix));
-                }
-                if !label.is_empty() {
-                    err.span_label(
-                        *span,
-                        format!(
-                            "associated type{} {} must be specified",
-                            pluralize!(label.len()),
-                            label.join(", "),
-                        ),
-                    );
-                }
-            }
-        }
-        if !suggestions.is_empty() {
-            err.multipart_suggestion(
-                &format!("specify the associated type{}", pluralize!(types_count)),
-                suggestions,
-                Applicability::HasPlaceholders,
-            );
-            if !where_constraints.is_empty() {
-                err.span_help(where_constraints, where_msg);
-            }
-        }
-        err.emit();
-    }
-
-    fn report_ambiguous_associated_type(
-        &self,
-        span: Span,
-        type_str: &str,
-        trait_str: &str,
-        name: Symbol,
-    ) {
-        let mut err = struct_span_err!(self.tcx().sess, span, E0223, "ambiguous associated type");
-        if let (Some(_), Ok(snippet)) = (
-            self.tcx().sess.confused_type_with_std_module.borrow().get(&span),
-            self.tcx().sess.source_map().span_to_snippet(span),
-        ) {
-            err.span_suggestion(
-                span,
-                "you are looking for the module in `std`, not the primitive type",
-                format!("std::{}", snippet),
-                Applicability::MachineApplicable,
-            );
-        } else {
-            err.span_suggestion(
-                span,
-                "use fully-qualified syntax",
-                format!("<{} as {}>::{}", type_str, trait_str, name),
-                Applicability::HasPlaceholders,
-            );
-        }
-        err.emit();
-    }
-
-    // Search for a bound on a type parameter which includes the associated item
-    // given by `assoc_name`. `ty_param_def_id` is the `DefId` of the type parameter
-    // This function will fail if there are no suitable bounds or there is
-    // any ambiguity.
-    fn find_bound_for_assoc_item(
-        &self,
-        ty_param_def_id: LocalDefId,
-        assoc_name: Ident,
-        span: Span,
-    ) -> Result<ty::PolyTraitRef<'tcx>, ErrorReported> {
-        let tcx = self.tcx();
-
-        debug!(
-            "find_bound_for_assoc_item(ty_param_def_id={:?}, assoc_name={:?}, span={:?})",
-            ty_param_def_id, assoc_name, span,
-        );
-
-        let predicates =
-            &self.get_type_parameter_bounds(span, ty_param_def_id.to_def_id()).predicates;
-
-        debug!("find_bound_for_assoc_item: predicates={:#?}", predicates);
-
-        let param_hir_id = tcx.hir().local_def_id_to_hir_id(ty_param_def_id);
-        let param_name = tcx.hir().ty_param_name(param_hir_id);
-        self.one_bound_for_assoc_type(
-            || {
-                traits::transitive_bounds(
-                    tcx,
-                    predicates.iter().filter_map(|(p, _)| p.to_opt_poly_trait_ref()),
-                )
-            },
-            || param_name.to_string(),
-            assoc_name,
-            span,
-            || None,
-        )
-    }
-
-    // Checks that `bounds` contains exactly one element and reports appropriate
-    // errors otherwise.
-    fn one_bound_for_assoc_type<I>(
-        &self,
-        all_candidates: impl Fn() -> I,
-        ty_param_name: impl Fn() -> String,
-        assoc_name: Ident,
-        span: Span,
-        is_equality: impl Fn() -> Option<String>,
-    ) -> Result<ty::PolyTraitRef<'tcx>, ErrorReported>
-    where
-        I: Iterator<Item = ty::PolyTraitRef<'tcx>>,
-    {
-        let mut matching_candidates = all_candidates()
-            .filter(|r| self.trait_defines_associated_type_named(r.def_id(), assoc_name));
-
-        let bound = match matching_candidates.next() {
-            Some(bound) => bound,
-            None => {
-                self.complain_about_assoc_type_not_found(
-                    all_candidates,
-                    &ty_param_name(),
-                    assoc_name,
-                    span,
-                );
-                return Err(ErrorReported);
-            }
-        };
-
-        debug!("one_bound_for_assoc_type: bound = {:?}", bound);
-
-        if let Some(bound2) = matching_candidates.next() {
-            debug!("one_bound_for_assoc_type: bound2 = {:?}", bound2);
-
-            let is_equality = is_equality();
-            let bounds = iter::once(bound).chain(iter::once(bound2)).chain(matching_candidates);
-            let mut err = if is_equality.is_some() {
-                // More specific Error Index entry.
-                struct_span_err!(
-                    self.tcx().sess,
-                    span,
-                    E0222,
-                    "ambiguous associated type `{}` in bounds of `{}`",
-                    assoc_name,
-                    ty_param_name()
-                )
-            } else {
-                struct_span_err!(
-                    self.tcx().sess,
-                    span,
-                    E0221,
-                    "ambiguous associated type `{}` in bounds of `{}`",
-                    assoc_name,
-                    ty_param_name()
-                )
-            };
-            err.span_label(span, format!("ambiguous associated type `{}`", assoc_name));
-
-            let mut where_bounds = vec![];
-            for bound in bounds {
-                let bound_id = bound.def_id();
-                let bound_span = self
-                    .tcx()
-                    .associated_items(bound_id)
-                    .find_by_name_and_kind(self.tcx(), assoc_name, ty::AssocKind::Type, bound_id)
-                    .and_then(|item| self.tcx().hir().span_if_local(item.def_id));
-
-                if let Some(bound_span) = bound_span {
-                    err.span_label(
-                        bound_span,
-                        format!(
-                            "ambiguous `{}` from `{}`",
-                            assoc_name,
-                            bound.print_only_trait_path(),
-                        ),
-                    );
-                    if let Some(constraint) = &is_equality {
-                        where_bounds.push(format!(
-                            "        T: {trait}::{assoc} = {constraint}",
-                            trait=bound.print_only_trait_path(),
-                            assoc=assoc_name,
-                            constraint=constraint,
-                        ));
-                    } else {
-                        err.span_suggestion(
-                            span,
-                            "use fully qualified syntax to disambiguate",
-                            format!(
-                                "<{} as {}>::{}",
-                                ty_param_name(),
-                                bound.print_only_trait_path(),
-                                assoc_name,
-                            ),
-                            Applicability::MaybeIncorrect,
-                        );
-                    }
-                } else {
-                    err.note(&format!(
-                        "associated type `{}` could derive from `{}`",
-                        ty_param_name(),
-                        bound.print_only_trait_path(),
-                    ));
-                }
-            }
-            if !where_bounds.is_empty() {
-                err.help(&format!(
-                    "consider introducing a new type parameter `T` and adding `where` constraints:\
-                     \n    where\n        T: {},\n{}",
-                    ty_param_name(),
-                    where_bounds.join(",\n"),
-                ));
-            }
-            err.emit();
-            if !where_bounds.is_empty() {
-                return Err(ErrorReported);
-            }
-        }
-        Ok(bound)
-    }
-
-    fn complain_about_assoc_type_not_found<I>(
-        &self,
-        all_candidates: impl Fn() -> I,
-        ty_param_name: &str,
-        assoc_name: Ident,
-        span: Span,
-    ) where
-        I: Iterator<Item = ty::PolyTraitRef<'tcx>>,
-    {
-        // The fallback span is needed because `assoc_name` might be an `Fn()`'s `Output` without a
-        // valid span, so we point at the whole path segment instead.
-        let span = if assoc_name.span != DUMMY_SP { assoc_name.span } else { span };
-        let mut err = struct_span_err!(
-            self.tcx().sess,
-            span,
-            E0220,
-            "associated type `{}` not found for `{}`",
-            assoc_name,
-            ty_param_name
-        );
-
-        let all_candidate_names: Vec<_> = all_candidates()
-            .map(|r| self.tcx().associated_items(r.def_id()).in_definition_order())
-            .flatten()
-            .filter_map(
-                |item| if item.kind == ty::AssocKind::Type { Some(item.ident.name) } else { None },
-            )
-            .collect();
-
-        if let (Some(suggested_name), true) = (
-            find_best_match_for_name(all_candidate_names.iter(), assoc_name.name, None),
-            assoc_name.span != DUMMY_SP,
-        ) {
-            err.span_suggestion(
-                assoc_name.span,
-                "there is an associated type with a similar name",
-                suggested_name.to_string(),
-                Applicability::MaybeIncorrect,
-            );
-        } else {
-            err.span_label(span, format!("associated type `{}` not found", assoc_name));
-        }
-
-        err.emit();
-    }
-
-    // Create a type from a path to an associated type.
-    // For a path `A::B::C::D`, `qself_ty` and `qself_def` are the type and def for `A::B::C`
-    // and item_segment is the path segment for `D`. We return a type and a def for
-    // the whole path.
-    // Will fail except for `T::A` and `Self::A`; i.e., if `qself_ty`/`qself_def` are not a type
-    // parameter or `Self`.
-    pub fn associated_path_to_ty(
-        &self,
-        hir_ref_id: hir::HirId,
-        span: Span,
-        qself_ty: Ty<'tcx>,
-        qself_res: Res,
-        assoc_segment: &hir::PathSegment<'_>,
-        permit_variants: bool,
-    ) -> Result<(Ty<'tcx>, DefKind, DefId), ErrorReported> {
-        let tcx = self.tcx();
-        let assoc_ident = assoc_segment.ident;
-
-        debug!("associated_path_to_ty: {:?}::{}", qself_ty, assoc_ident);
-
-        // Check if we have an enum variant.
-        let mut variant_resolution = None;
-        if let ty::Adt(adt_def, _) = qself_ty.kind {
-            if adt_def.is_enum() {
-                let variant_def = adt_def
-                    .variants
-                    .iter()
-                    .find(|vd| tcx.hygienic_eq(assoc_ident, vd.ident, adt_def.did));
-                if let Some(variant_def) = variant_def {
-                    if permit_variants {
-                        tcx.check_stability(variant_def.def_id, Some(hir_ref_id), span);
-                        self.prohibit_generics(slice::from_ref(assoc_segment));
-                        return Ok((qself_ty, DefKind::Variant, variant_def.def_id));
-                    } else {
-                        variant_resolution = Some(variant_def.def_id);
-                    }
-                }
-            }
-        }
-
-        // Find the type of the associated item, and the trait where the associated
-        // item is declared.
-        let bound = match (&qself_ty.kind, qself_res) {
-            (_, Res::SelfTy(Some(_), Some(impl_def_id))) => {
-                // `Self` in an impl of a trait -- we have a concrete self type and a
-                // trait reference.
-                let trait_ref = match tcx.impl_trait_ref(impl_def_id) {
-                    Some(trait_ref) => trait_ref,
-                    None => {
-                        // A cycle error occurred, most likely.
-                        return Err(ErrorReported);
-                    }
-                };
-
-                self.one_bound_for_assoc_type(
-                    || traits::supertraits(tcx, ty::Binder::bind(trait_ref)),
-                    || "Self".to_string(),
-                    assoc_ident,
-                    span,
-                    || None,
-                )?
-            }
-            (
-                &ty::Param(_),
-                Res::SelfTy(Some(param_did), None) | Res::Def(DefKind::TyParam, param_did),
-            ) => self.find_bound_for_assoc_item(param_did.expect_local(), assoc_ident, span)?,
-            _ => {
-                if variant_resolution.is_some() {
-                    // Variant in type position
-                    let msg = format!("expected type, found variant `{}`", assoc_ident);
-                    tcx.sess.span_err(span, &msg);
-                } else if qself_ty.is_enum() {
-                    let mut err = struct_span_err!(
-                        tcx.sess,
-                        assoc_ident.span,
-                        E0599,
-                        "no variant named `{}` found for enum `{}`",
-                        assoc_ident,
-                        qself_ty,
-                    );
-
-                    let adt_def = qself_ty.ty_adt_def().expect("enum is not an ADT");
-                    if let Some(suggested_name) = find_best_match_for_name(
-                        adt_def.variants.iter().map(|variant| &variant.ident.name),
-                        assoc_ident.name,
-                        None,
-                    ) {
-                        err.span_suggestion(
-                            assoc_ident.span,
-                            "there is a variant with a similar name",
-                            suggested_name.to_string(),
-                            Applicability::MaybeIncorrect,
-                        );
-                    } else {
-                        err.span_label(
-                            assoc_ident.span,
-                            format!("variant not found in `{}`", qself_ty),
-                        );
-                    }
-
-                    if let Some(sp) = tcx.hir().span_if_local(adt_def.did) {
-                        let sp = tcx.sess.source_map().guess_head_span(sp);
-                        err.span_label(sp, format!("variant `{}` not found here", assoc_ident));
-                    }
-
-                    err.emit();
-                } else if !qself_ty.references_error() {
-                    // Don't print `TyErr` to the user.
-                    self.report_ambiguous_associated_type(
-                        span,
-                        &qself_ty.to_string(),
-                        "Trait",
-                        assoc_ident.name,
-                    );
-                }
-                return Err(ErrorReported);
-            }
-        };
-
-        let trait_did = bound.def_id();
-        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.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.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);
-        let ty = self.normalize_ty(span, ty);
-
-        let kind = DefKind::AssocTy;
-        if !item.vis.is_accessible_from(def_scope, tcx) {
-            let kind = kind.descr(item.def_id);
-            let msg = format!("{} `{}` is private", kind, assoc_ident);
-            tcx.sess
-                .struct_span_err(span, &msg)
-                .span_label(span, &format!("private {}", kind))
-                .emit();
-        }
-        tcx.check_stability(item.def_id, Some(hir_ref_id), span);
-
-        if let Some(variant_def_id) = variant_resolution {
-            tcx.struct_span_lint_hir(AMBIGUOUS_ASSOCIATED_ITEMS, hir_ref_id, span, |lint| {
-                let mut err = lint.build("ambiguous associated item");
-                let mut could_refer_to = |kind: DefKind, def_id, also| {
-                    let note_msg = format!(
-                        "`{}` could{} refer to the {} defined here",
-                        assoc_ident,
-                        also,
-                        kind.descr(def_id)
-                    );
-                    err.span_note(tcx.def_span(def_id), &note_msg);
-                };
-
-                could_refer_to(DefKind::Variant, variant_def_id, "");
-                could_refer_to(kind, item.def_id, " also");
-
-                err.span_suggestion(
-                    span,
-                    "use fully-qualified syntax",
-                    format!("<{} as {}>::{}", qself_ty, tcx.item_name(trait_did), assoc_ident),
-                    Applicability::MachineApplicable,
-                );
-
-                err.emit();
-            });
-        }
-        Ok((ty, kind, item.def_id))
-    }
-
-    fn qpath_to_ty(
-        &self,
-        span: Span,
-        opt_self_ty: Option<Ty<'tcx>>,
-        item_def_id: DefId,
-        trait_segment: &hir::PathSegment<'_>,
-        item_segment: &hir::PathSegment<'_>,
-    ) -> Ty<'tcx> {
-        let tcx = self.tcx();
-
-        let trait_def_id = tcx.parent(item_def_id).unwrap();
-
-        debug!("qpath_to_ty: trait_def_id={:?}", trait_def_id);
-
-        let self_ty = if let Some(ty) = opt_self_ty {
-            ty
-        } else {
-            let path_str = tcx.def_path_str(trait_def_id);
-
-            let def_id = self.item_def_id();
-
-            debug!("qpath_to_ty: self.item_def_id()={:?}", def_id);
-
-            let parent_def_id = def_id
-                .and_then(|def_id| {
-                    def_id.as_local().map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id))
-                })
-                .map(|hir_id| tcx.hir().get_parent_did(hir_id).to_def_id());
-
-            debug!("qpath_to_ty: parent_def_id={:?}", parent_def_id);
-
-            // If the trait in segment is the same as the trait defining the item,
-            // use the `<Self as ..>` syntax in the error.
-            let is_part_of_self_trait_constraints = def_id == Some(trait_def_id);
-            let is_part_of_fn_in_self_trait = parent_def_id == Some(trait_def_id);
-
-            let type_name = if is_part_of_self_trait_constraints || is_part_of_fn_in_self_trait {
-                "Self"
-            } else {
-                "Type"
-            };
-
-            self.report_ambiguous_associated_type(
-                span,
-                type_name,
-                &path_str,
-                item_segment.ident.name,
-            );
-            return tcx.ty_error();
-        };
-
-        debug!("qpath_to_ty: self_type={:?}", self_ty);
-
-        let trait_ref = self.ast_path_to_mono_trait_ref(span, trait_def_id, self_ty, trait_segment);
-
-        let item_substs = self.create_substs_for_associated_item(
-            tcx,
-            span,
-            item_def_id,
-            item_segment,
-            trait_ref.substs,
-        );
-
-        debug!("qpath_to_ty: trait_ref={:?}", trait_ref);
-
-        self.normalize_ty(span, tcx.mk_projection(item_def_id, item_substs))
-    }
-
-    pub fn prohibit_generics<'a, T: IntoIterator<Item = &'a hir::PathSegment<'a>>>(
-        &self,
-        segments: T,
-    ) -> bool {
-        let mut has_err = false;
-        for segment in segments {
-            let (mut err_for_lt, mut err_for_ty, mut err_for_ct) = (false, false, false);
-            for arg in segment.generic_args().args {
-                let (span, kind) = match arg {
-                    hir::GenericArg::Lifetime(lt) => {
-                        if err_for_lt {
-                            continue;
-                        }
-                        err_for_lt = true;
-                        has_err = true;
-                        (lt.span, "lifetime")
-                    }
-                    hir::GenericArg::Type(ty) => {
-                        if err_for_ty {
-                            continue;
-                        }
-                        err_for_ty = true;
-                        has_err = true;
-                        (ty.span, "type")
-                    }
-                    hir::GenericArg::Const(ct) => {
-                        if err_for_ct {
-                            continue;
-                        }
-                        err_for_ct = true;
-                        has_err = true;
-                        (ct.span, "const")
-                    }
-                };
-                let mut err = struct_span_err!(
-                    self.tcx().sess,
-                    span,
-                    E0109,
-                    "{} arguments are not allowed for this type",
-                    kind,
-                );
-                err.span_label(span, format!("{} argument not allowed", kind));
-                err.emit();
-                if err_for_lt && err_for_ty && err_for_ct {
-                    break;
-                }
-            }
-
-            // Only emit the first error to avoid overloading the user with error messages.
-            if let [binding, ..] = segment.generic_args().bindings {
-                has_err = true;
-                Self::prohibit_assoc_ty_binding(self.tcx(), binding.span);
-            }
-        }
-        has_err
-    }
-
-    pub fn prohibit_assoc_ty_binding(tcx: TyCtxt<'_>, span: Span) {
-        let mut err = struct_span_err!(
-            tcx.sess,
-            span,
-            E0229,
-            "associated type bindings are not allowed here"
-        );
-        err.span_label(span, "associated type not allowed here").emit();
-    }
-
-    /// Prohibits explicit lifetime arguments if late-bound lifetime parameters
-    /// are present. This is used both for datatypes and function calls.
-    fn prohibit_explicit_late_bound_lifetimes(
-        tcx: TyCtxt<'_>,
-        def: &ty::Generics,
-        args: &hir::GenericArgs<'_>,
-        position: GenericArgPosition,
-    ) -> ExplicitLateBound {
-        let param_counts = def.own_counts();
-        let arg_counts = args.own_counts();
-        let infer_lifetimes = position != GenericArgPosition::Type && arg_counts.lifetimes == 0;
-
-        if infer_lifetimes {
-            ExplicitLateBound::No
-        } else if let Some(span_late) = def.has_late_bound_regions {
-            let msg = "cannot specify lifetime arguments explicitly \
-                       if late bound lifetime parameters are present";
-            let note = "the late bound lifetime parameter is introduced here";
-            let span = args.args[0].span();
-            if position == GenericArgPosition::Value
-                && arg_counts.lifetimes != param_counts.lifetimes
-            {
-                let mut err = tcx.sess.struct_span_err(span, msg);
-                err.span_note(span_late, note);
-                err.emit();
-            } else {
-                let mut multispan = MultiSpan::from_span(span);
-                multispan.push_span_label(span_late, note.to_string());
-                tcx.struct_span_lint_hir(
-                    LATE_BOUND_LIFETIME_ARGUMENTS,
-                    args.args[0].id(),
-                    multispan,
-                    |lint| lint.build(msg).emit(),
-                );
-            }
-            ExplicitLateBound::Yes
-        } else {
-            ExplicitLateBound::No
-        }
-    }
-
-    // FIXME(eddyb, varkor) handle type paths here too, not just value ones.
-    pub fn def_ids_for_value_path_segments(
-        &self,
-        segments: &[hir::PathSegment<'_>],
-        self_ty: Option<Ty<'tcx>>,
-        kind: DefKind,
-        def_id: DefId,
-    ) -> Vec<PathSeg> {
-        // We need to extract the type parameters supplied by the user in
-        // the path `path`. Due to the current setup, this is a bit of a
-        // tricky-process; the problem is that resolve only tells us the
-        // end-point of the path resolution, and not the intermediate steps.
-        // Luckily, we can (at least for now) deduce the intermediate steps
-        // just from the end-point.
-        //
-        // There are basically five cases to consider:
-        //
-        // 1. Reference to a constructor of a struct:
-        //
-        //        struct Foo<T>(...)
-        //
-        //    In this case, the parameters are declared in the type space.
-        //
-        // 2. Reference to a constructor of an enum variant:
-        //
-        //        enum E<T> { Foo(...) }
-        //
-        //    In this case, the parameters are defined in the type space,
-        //    but may be specified either on the type or the variant.
-        //
-        // 3. Reference to a fn item or a free constant:
-        //
-        //        fn foo<T>() { }
-        //
-        //    In this case, the path will again always have the form
-        //    `a::b::foo::<T>` where only the final segment should have
-        //    type parameters. However, in this case, those parameters are
-        //    declared on a value, and hence are in the `FnSpace`.
-        //
-        // 4. Reference to a method or an associated constant:
-        //
-        //        impl<A> SomeStruct<A> {
-        //            fn foo<B>(...)
-        //        }
-        //
-        //    Here we can have a path like
-        //    `a::b::SomeStruct::<A>::foo::<B>`, in which case parameters
-        //    may appear in two places. The penultimate segment,
-        //    `SomeStruct::<A>`, contains parameters in TypeSpace, and the
-        //    final segment, `foo::<B>` contains parameters in fn space.
-        //
-        // The first step then is to categorize the segments appropriately.
-
-        let tcx = self.tcx();
-
-        assert!(!segments.is_empty());
-        let last = segments.len() - 1;
-
-        let mut path_segs = vec![];
-
-        match kind {
-            // Case 1. Reference to a struct constructor.
-            DefKind::Ctor(CtorOf::Struct, ..) => {
-                // Everything but the final segment should have no
-                // parameters at all.
-                let generics = tcx.generics_of(def_id);
-                // Variant and struct constructors use the
-                // generics of their parent type definition.
-                let generics_def_id = generics.parent.unwrap_or(def_id);
-                path_segs.push(PathSeg(generics_def_id, last));
-            }
-
-            // Case 2. Reference to a variant constructor.
-            DefKind::Ctor(CtorOf::Variant, ..) | DefKind::Variant => {
-                let adt_def = self_ty.map(|t| t.ty_adt_def().unwrap());
-                let (generics_def_id, index) = if let Some(adt_def) = adt_def {
-                    debug_assert!(adt_def.is_enum());
-                    (adt_def.did, last)
-                } else if last >= 1 && segments[last - 1].args.is_some() {
-                    // Everything but the penultimate segment should have no
-                    // parameters at all.
-                    let mut def_id = def_id;
-
-                    // `DefKind::Ctor` -> `DefKind::Variant`
-                    if let DefKind::Ctor(..) = kind {
-                        def_id = tcx.parent(def_id).unwrap()
-                    }
-
-                    // `DefKind::Variant` -> `DefKind::Enum`
-                    let enum_def_id = tcx.parent(def_id).unwrap();
-                    (enum_def_id, last - 1)
-                } else {
-                    // FIXME: lint here recommending `Enum::<...>::Variant` form
-                    // instead of `Enum::Variant::<...>` form.
-
-                    // Everything but the final segment should have no
-                    // parameters at all.
-                    let generics = tcx.generics_of(def_id);
-                    // Variant and struct constructors use the
-                    // generics of their parent type definition.
-                    (generics.parent.unwrap_or(def_id), last)
-                };
-                path_segs.push(PathSeg(generics_def_id, index));
-            }
-
-            // Case 3. Reference to a top-level value.
-            DefKind::Fn | DefKind::Const | DefKind::ConstParam | DefKind::Static => {
-                path_segs.push(PathSeg(def_id, last));
-            }
-
-            // Case 4. Reference to a method or associated const.
-            DefKind::AssocFn | DefKind::AssocConst => {
-                if segments.len() >= 2 {
-                    let generics = tcx.generics_of(def_id);
-                    path_segs.push(PathSeg(generics.parent.unwrap(), last - 1));
-                }
-                path_segs.push(PathSeg(def_id, last));
-            }
-
-            kind => bug!("unexpected definition kind {:?} for {:?}", kind, def_id),
-        }
-
-        debug!("path_segs = {:?}", path_segs);
-
-        path_segs
-    }
-
-    // Check a type `Path` and convert it to a `Ty`.
-    pub fn res_to_ty(
-        &self,
-        opt_self_ty: Option<Ty<'tcx>>,
-        path: &hir::Path<'_>,
-        permit_variants: bool,
-    ) -> Ty<'tcx> {
-        let tcx = self.tcx();
-
-        debug!(
-            "res_to_ty(res={:?}, opt_self_ty={:?}, path_segments={:?})",
-            path.res, opt_self_ty, path.segments
-        );
-
-        let span = path.span;
-        match path.res {
-            Res::Def(DefKind::OpaqueTy, did) => {
-                // Check for desugared `impl Trait`.
-                assert!(ty::is_impl_trait_defn(tcx, did).is_none());
-                let item_segment = path.segments.split_last().unwrap();
-                self.prohibit_generics(item_segment.1);
-                let substs = self.ast_path_substs_for_ty(span, did, item_segment.0);
-                self.normalize_ty(span, tcx.mk_opaque(did, substs))
-            }
-            Res::Def(
-                DefKind::Enum
-                | DefKind::TyAlias
-                | DefKind::Struct
-                | DefKind::Union
-                | DefKind::ForeignTy,
-                did,
-            ) => {
-                assert_eq!(opt_self_ty, None);
-                self.prohibit_generics(path.segments.split_last().unwrap().1);
-                self.ast_path_to_ty(span, did, path.segments.last().unwrap())
-            }
-            Res::Def(kind @ DefKind::Variant, def_id) if permit_variants => {
-                // Convert "variant type" as if it were a real type.
-                // The resulting `Ty` is type of the variant's enum for now.
-                assert_eq!(opt_self_ty, None);
-
-                let path_segs =
-                    self.def_ids_for_value_path_segments(&path.segments, None, kind, def_id);
-                let generic_segs: FxHashSet<_> =
-                    path_segs.iter().map(|PathSeg(_, index)| index).collect();
-                self.prohibit_generics(path.segments.iter().enumerate().filter_map(
-                    |(index, seg)| {
-                        if !generic_segs.contains(&index) { Some(seg) } else { None }
-                    },
-                ));
-
-                let PathSeg(def_id, index) = path_segs.last().unwrap();
-                self.ast_path_to_ty(span, *def_id, &path.segments[*index])
-            }
-            Res::Def(DefKind::TyParam, def_id) => {
-                assert_eq!(opt_self_ty, None);
-                self.prohibit_generics(path.segments);
-
-                let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
-                let item_id = tcx.hir().get_parent_node(hir_id);
-                let item_def_id = tcx.hir().local_def_id(item_id);
-                let generics = tcx.generics_of(item_def_id);
-                let index = generics.param_def_id_to_index[&def_id];
-                tcx.mk_ty_param(index, tcx.hir().name(hir_id))
-            }
-            Res::SelfTy(Some(_), None) => {
-                // `Self` in trait or type alias.
-                assert_eq!(opt_self_ty, None);
-                self.prohibit_generics(path.segments);
-                tcx.types.self_param
-            }
-            Res::SelfTy(_, Some(def_id)) => {
-                // `Self` in impl (we know the concrete type).
-                assert_eq!(opt_self_ty, None);
-                self.prohibit_generics(path.segments);
-                // Try to evaluate any array length constants.
-                self.normalize_ty(span, tcx.at(span).type_of(def_id))
-            }
-            Res::Def(DefKind::AssocTy, def_id) => {
-                debug_assert!(path.segments.len() >= 2);
-                self.prohibit_generics(&path.segments[..path.segments.len() - 2]);
-                self.qpath_to_ty(
-                    span,
-                    opt_self_ty,
-                    def_id,
-                    &path.segments[path.segments.len() - 2],
-                    path.segments.last().unwrap(),
-                )
-            }
-            Res::PrimTy(prim_ty) => {
-                assert_eq!(opt_self_ty, None);
-                self.prohibit_generics(path.segments);
-                match prim_ty {
-                    hir::PrimTy::Bool => tcx.types.bool,
-                    hir::PrimTy::Char => tcx.types.char,
-                    hir::PrimTy::Int(it) => tcx.mk_mach_int(it),
-                    hir::PrimTy::Uint(uit) => tcx.mk_mach_uint(uit),
-                    hir::PrimTy::Float(ft) => tcx.mk_mach_float(ft),
-                    hir::PrimTy::Str => tcx.types.str_,
-                }
-            }
-            Res::Err => {
-                self.set_tainted_by_errors();
-                self.tcx().ty_error()
-            }
-            _ => span_bug!(span, "unexpected resolution: {:?}", path.res),
-        }
-    }
-
-    /// Parses the programmer's textual representation of a type into our
-    /// internal notion of a type.
-    pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> {
-        self.ast_ty_to_ty_inner(ast_ty, false)
-    }
-
-    /// Turns a `hir::Ty` into a `Ty`. For diagnostics' purposes we keep track of whether trait
-    /// objects are borrowed like `&dyn Trait` to avoid emitting redundant errors.
-    fn ast_ty_to_ty_inner(&self, ast_ty: &hir::Ty<'_>, borrowed: bool) -> Ty<'tcx> {
-        debug!("ast_ty_to_ty(id={:?}, ast_ty={:?} ty_ty={:?})", ast_ty.hir_id, ast_ty, ast_ty.kind);
-
-        let tcx = self.tcx();
-
-        let result_ty = match ast_ty.kind {
-            hir::TyKind::Slice(ref ty) => tcx.mk_slice(self.ast_ty_to_ty(&ty)),
-            hir::TyKind::Ptr(ref mt) => {
-                tcx.mk_ptr(ty::TypeAndMut { ty: self.ast_ty_to_ty(&mt.ty), mutbl: mt.mutbl })
-            }
-            hir::TyKind::Rptr(ref region, ref mt) => {
-                let r = self.ast_region_to_region(region, None);
-                debug!("ast_ty_to_ty: r={:?}", r);
-                let t = self.ast_ty_to_ty_inner(&mt.ty, true);
-                tcx.mk_ref(r, ty::TypeAndMut { ty: t, mutbl: mt.mutbl })
-            }
-            hir::TyKind::Never => tcx.types.never,
-            hir::TyKind::Tup(ref fields) => {
-                tcx.mk_tup(fields.iter().map(|t| self.ast_ty_to_ty(&t)))
-            }
-            hir::TyKind::BareFn(ref bf) => {
-                require_c_abi_if_c_variadic(tcx, &bf.decl, bf.abi, ast_ty.span);
-                tcx.mk_fn_ptr(self.ty_of_fn(
-                    bf.unsafety,
-                    bf.abi,
-                    &bf.decl,
-                    &hir::Generics::empty(),
-                    None,
-                ))
-            }
-            hir::TyKind::TraitObject(ref bounds, ref lifetime) => {
-                self.conv_object_ty_poly_trait_ref(ast_ty.span, bounds, lifetime, borrowed)
-            }
-            hir::TyKind::Path(hir::QPath::Resolved(ref maybe_qself, ref path)) => {
-                debug!("ast_ty_to_ty: maybe_qself={:?} path={:?}", maybe_qself, path);
-                let opt_self_ty = maybe_qself.as_ref().map(|qself| self.ast_ty_to_ty(qself));
-                self.res_to_ty(opt_self_ty, path, false)
-            }
-            hir::TyKind::OpaqueDef(item_id, ref lifetimes) => {
-                let opaque_ty = tcx.hir().expect_item(item_id.id);
-                let def_id = tcx.hir().local_def_id(item_id.id).to_def_id();
-
-                match opaque_ty.kind {
-                    hir::ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn, .. }) => {
-                        self.impl_trait_ty_to_ty(def_id, lifetimes, impl_trait_fn.is_some())
-                    }
-                    ref i => bug!("`impl Trait` pointed to non-opaque type?? {:#?}", i),
-                }
-            }
-            hir::TyKind::Path(hir::QPath::TypeRelative(ref qself, ref segment)) => {
-                debug!("ast_ty_to_ty: qself={:?} segment={:?}", qself, segment);
-                let ty = self.ast_ty_to_ty(qself);
-
-                let res = if let hir::TyKind::Path(hir::QPath::Resolved(_, ref path)) = qself.kind {
-                    path.res
-                } else {
-                    Res::Err
-                };
-                self.associated_path_to_ty(ast_ty.hir_id, ast_ty.span, ty, res, segment, false)
-                    .map(|(ty, _, _)| ty)
-                    .unwrap_or_else(|_| tcx.ty_error())
-            }
-            hir::TyKind::Path(hir::QPath::LangItem(lang_item, span)) => {
-                let def_id = tcx.require_lang_item(lang_item, Some(span));
-                let (substs, _, _) = self.create_substs_for_ast_path(
-                    span,
-                    def_id,
-                    &[],
-                    &GenericArgs::none(),
-                    true,
-                    None,
-                );
-                self.normalize_ty(span, tcx.at(span).type_of(def_id).subst(tcx, substs))
-            }
-            hir::TyKind::Array(ref ty, ref length) => {
-                let length_def_id = tcx.hir().local_def_id(length.hir_id);
-                let length = ty::Const::from_anon_const(tcx, length_def_id);
-                let array_ty = tcx.mk_ty(ty::Array(self.ast_ty_to_ty(&ty), length));
-                self.normalize_ty(ast_ty.span, array_ty)
-            }
-            hir::TyKind::Typeof(ref _e) => {
-                struct_span_err!(
-                    tcx.sess,
-                    ast_ty.span,
-                    E0516,
-                    "`typeof` is a reserved keyword but unimplemented"
-                )
-                .span_label(ast_ty.span, "reserved keyword")
-                .emit();
-
-                tcx.ty_error()
-            }
-            hir::TyKind::Infer => {
-                // Infer also appears as the type of arguments or return
-                // values in a ExprKind::Closure, or as
-                // the type of local variables. Both of these cases are
-                // handled specially and will not descend into this routine.
-                self.ty_infer(None, ast_ty.span)
-            }
-            hir::TyKind::Err => tcx.ty_error(),
-        };
-
-        debug!("ast_ty_to_ty: result_ty={:?}", result_ty);
-
-        self.record_ty(ast_ty.hir_id, result_ty, ast_ty.span);
-        result_ty
-    }
-
-    pub fn impl_trait_ty_to_ty(
-        &self,
-        def_id: DefId,
-        lifetimes: &[hir::GenericArg<'_>],
-        replace_parent_lifetimes: bool,
-    ) -> Ty<'tcx> {
-        debug!("impl_trait_ty_to_ty(def_id={:?}, lifetimes={:?})", def_id, lifetimes);
-        let tcx = self.tcx();
-
-        let generics = tcx.generics_of(def_id);
-
-        debug!("impl_trait_ty_to_ty: generics={:?}", generics);
-        let substs = InternalSubsts::for_item(tcx, def_id, |param, _| {
-            if let Some(i) = (param.index as usize).checked_sub(generics.parent_count) {
-                // Our own parameters are the resolved lifetimes.
-                match param.kind {
-                    GenericParamDefKind::Lifetime => {
-                        if let hir::GenericArg::Lifetime(lifetime) = &lifetimes[i] {
-                            self.ast_region_to_region(lifetime, None).into()
-                        } else {
-                            bug!()
-                        }
-                    }
-                    _ => bug!(),
-                }
-            } else {
-                match param.kind {
-                    // For RPIT (return position impl trait), only lifetimes
-                    // mentioned in the impl Trait predicate are captured by
-                    // the opaque type, so the lifetime parameters from the
-                    // parent item need to be replaced with `'static`.
-                    //
-                    // For `impl Trait` in the types of statics, constants,
-                    // locals and type aliases. These capture all parent
-                    // lifetimes, so they can use their identity subst.
-                    GenericParamDefKind::Lifetime if replace_parent_lifetimes => {
-                        tcx.lifetimes.re_static.into()
-                    }
-                    _ => tcx.mk_param_from_def(param),
-                }
-            }
-        });
-        debug!("impl_trait_ty_to_ty: substs={:?}", substs);
-
-        let ty = tcx.mk_opaque(def_id, substs);
-        debug!("impl_trait_ty_to_ty: {}", ty);
-        ty
-    }
-
-    pub fn ty_of_arg(&self, ty: &hir::Ty<'_>, expected_ty: Option<Ty<'tcx>>) -> Ty<'tcx> {
-        match ty.kind {
-            hir::TyKind::Infer if expected_ty.is_some() => {
-                self.record_ty(ty.hir_id, expected_ty.unwrap(), ty.span);
-                expected_ty.unwrap()
-            }
-            _ => self.ast_ty_to_ty(ty),
-        }
-    }
-
-    pub fn ty_of_fn(
-        &self,
-        unsafety: hir::Unsafety,
-        abi: abi::Abi,
-        decl: &hir::FnDecl<'_>,
-        generics: &hir::Generics<'_>,
-        ident_span: Option<Span>,
-    ) -> ty::PolyFnSig<'tcx> {
-        debug!("ty_of_fn");
-
-        let tcx = self.tcx();
-
-        // 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);
-        }
-        walk_generics(&mut visitor, generics);
-
-        let input_tys = decl.inputs.iter().map(|a| self.ty_of_arg(a, None));
-        let output_ty = match decl.output {
-            hir::FnRetTy::Return(ref output) => {
-                visitor.visit_ty(output);
-                self.ast_ty_to_ty(output)
-            }
-            hir::FnRetTy::DefaultReturn(..) => tcx.mk_unit(),
-        };
-
-        debug!("ty_of_fn: output_ty={:?}", output_ty);
-
-        let bare_fn_ty =
-            ty::Binder::bind(tcx.mk_fn_sig(input_tys, output_ty, decl.c_variadic, unsafety, abi));
-
-        if !self.allow_ty_infer() {
-            // We always collect the spans for placeholder types when evaluating `fn`s, but we
-            // only want to emit an error complaining about them if infer types (`_`) are not
-            // allowed. `allow_ty_infer` gates this behavior. We check for the presence of
-            // `ident_span` to not emit an error twice when we have `fn foo(_: fn() -> _)`.
-            crate::collect::placeholder_type_error(
-                tcx,
-                ident_span.map(|sp| sp.shrink_to_hi()),
-                &generics.params[..],
-                visitor.0,
-                true,
-            );
-        }
-
-        // Find any late-bound regions declared in return type that do
-        // not appear in the arguments. These are not well-formed.
-        //
-        // Example:
-        //     for<'a> fn() -> &'a str <-- 'a is bad
-        //     for<'a> fn(&'a String) -> &'a str <-- 'a is ok
-        let inputs = bare_fn_ty.inputs();
-        let late_bound_in_args =
-            tcx.collect_constrained_late_bound_regions(&inputs.map_bound(|i| i.to_owned()));
-        let output = bare_fn_ty.output();
-        let late_bound_in_ret = tcx.collect_referenced_late_bound_regions(&output);
-
-        self.validate_late_bound_regions(late_bound_in_args, late_bound_in_ret, |br_name| {
-            struct_span_err!(
-                tcx.sess,
-                decl.output.span(),
-                E0581,
-                "return type references {}, which is not constrained by the fn input types",
-                br_name
-            )
-        });
-
-        bare_fn_ty
-    }
-
-    fn validate_late_bound_regions(
-        &self,
-        constrained_regions: FxHashSet<ty::BoundRegion>,
-        referenced_regions: FxHashSet<ty::BoundRegion>,
-        generate_err: impl Fn(&str) -> rustc_errors::DiagnosticBuilder<'tcx>,
-    ) {
-        for br in referenced_regions.difference(&constrained_regions) {
-            let br_name = match *br {
-                ty::BrNamed(_, name) => format!("lifetime `{}`", name),
-                ty::BrAnon(_) | ty::BrEnv => "an anonymous lifetime".to_string(),
-            };
-
-            let mut err = generate_err(&br_name);
-
-            if let ty::BrAnon(_) = *br {
-                // The only way for an anonymous lifetime to wind up
-                // in the return type but **also** be unconstrained is
-                // if it only appears in "associated types" in the
-                // input. See #47511 and #62200 for examples. In this case,
-                // though we can easily give a hint that ought to be
-                // relevant.
-                err.note(
-                    "lifetimes appearing in an associated type are not considered constrained",
-                );
-            }
-
-            err.emit();
-        }
-    }
-
-    /// Given the bounds on an object, determines what single region bound (if any) we can
-    /// use to summarize this type. The basic idea is that we will use the bound the user
-    /// provided, if they provided one, and otherwise search the supertypes of trait bounds
-    /// for region bounds. It may be that we can derive no bound at all, in which case
-    /// we return `None`.
-    fn compute_object_lifetime_bound(
-        &self,
-        span: Span,
-        existential_predicates: ty::Binder<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>,
-    ) -> Option<ty::Region<'tcx>> // if None, use the default
-    {
-        let tcx = self.tcx();
-
-        debug!("compute_opt_region_bound(existential_predicates={:?})", existential_predicates);
-
-        // No explicit region bound specified. Therefore, examine trait
-        // bounds and see if we can derive region bounds from those.
-        let derived_region_bounds = object_region_bounds(tcx, existential_predicates);
-
-        // If there are no derived region bounds, then report back that we
-        // can find no region bound. The caller will use the default.
-        if derived_region_bounds.is_empty() {
-            return None;
-        }
-
-        // If any of the derived region bounds are 'static, that is always
-        // the best choice.
-        if derived_region_bounds.iter().any(|&r| ty::ReStatic == *r) {
-            return Some(tcx.lifetimes.re_static);
-        }
-
-        // Determine whether there is exactly one unique region in the set
-        // of derived region bounds. If so, use that. Otherwise, report an
-        // error.
-        let r = derived_region_bounds[0];
-        if derived_region_bounds[1..].iter().any(|r1| r != *r1) {
-            struct_span_err!(
-                tcx.sess,
-                span,
-                E0227,
-                "ambiguous lifetime bound, explicit lifetime bound required"
-            )
-            .emit();
-        }
-        Some(r)
-    }
-}
-
-/// Collects together a list of bounds that are applied to some type,
-/// after they've been converted into `ty` form (from the HIR
-/// representations). These lists of bounds occur in many places in
-/// Rust's syntax:
-///
-/// ```text
-/// trait Foo: Bar + Baz { }
-///            ^^^^^^^^^ supertrait list bounding the `Self` type parameter
-///
-/// fn foo<T: Bar + Baz>() { }
-///           ^^^^^^^^^ bounding the type parameter `T`
-///
-/// impl dyn Bar + Baz
-///          ^^^^^^^^^ bounding the forgotten dynamic type
-/// ```
-///
-/// Our representation is a bit mixed here -- in some cases, we
-/// include the self type (e.g., `trait_bounds`) but in others we do
-#[derive(Default, PartialEq, Eq, Clone, Debug)]
-pub struct Bounds<'tcx> {
-    /// A list of region bounds on the (implicit) self type. So if you
-    /// had `T: 'a + 'b` this might would be a list `['a, 'b]` (but
-    /// the `T` is not explicitly included).
-    pub region_bounds: Vec<(ty::Region<'tcx>, Span)>,
-
-    /// A list of trait bounds. So if you had `T: Debug` this would be
-    /// `T: Debug`. Note that the self-type is explicit here.
-    pub trait_bounds: Vec<(ty::PolyTraitRef<'tcx>, Span, Constness)>,
-
-    /// A list of projection equality bounds. So if you had `T:
-    /// Iterator<Item = u32>` this would include `<T as
-    /// Iterator>::Item => u32`. Note that the self-type is explicit
-    /// here.
-    pub projection_bounds: Vec<(ty::PolyProjectionPredicate<'tcx>, Span)>,
-
-    /// `Some` if there is *no* `?Sized` predicate. The `span`
-    /// is the location in the source of the `T` declaration which can
-    /// be cited as the source of the `T: Sized` requirement.
-    pub implicitly_sized: Option<Span>,
-}
-
-impl<'tcx> Bounds<'tcx> {
-    /// Converts a bounds list into a flat set of predicates (like
-    /// where-clauses). Because some of our bounds listings (e.g.,
-    /// regions) don't include the self-type, you must supply the
-    /// self-type here (the `param_ty` parameter).
-    pub fn predicates(
-        &self,
-        tcx: TyCtxt<'tcx>,
-        param_ty: Ty<'tcx>,
-    ) -> Vec<(ty::Predicate<'tcx>, Span)> {
-        // If it could be sized, and is, add the `Sized` predicate.
-        let sized_predicate = self.implicitly_sized.and_then(|span| {
-            tcx.lang_items().sized_trait().map(|sized| {
-                let trait_ref = ty::Binder::bind(ty::TraitRef {
-                    def_id: sized,
-                    substs: tcx.mk_substs_trait(param_ty, &[]),
-                });
-                (trait_ref.without_const().to_predicate(tcx), span)
-            })
-        });
-
-        sized_predicate
-            .into_iter()
-            .chain(
-                self.region_bounds
-                    .iter()
-                    .map(|&(region_bound, span)| {
-                        // Account for the binder being introduced below; no need to shift `param_ty`
-                        // because, at present at least, it either only refers to early-bound regions,
-                        // or it's a generic associated type that deliberately has escaping bound vars.
-                        let region_bound = ty::fold::shift_region(tcx, region_bound, 1);
-                        let outlives = ty::OutlivesPredicate(param_ty, region_bound);
-                        (ty::Binder::bind(outlives).to_predicate(tcx), span)
-                    })
-                    .chain(self.trait_bounds.iter().map(|&(bound_trait_ref, span, constness)| {
-                        let predicate = bound_trait_ref.with_constness(constness).to_predicate(tcx);
-                        (predicate, span)
-                    }))
-                    .chain(
-                        self.projection_bounds
-                            .iter()
-                            .map(|&(projection, span)| (projection.to_predicate(tcx), span)),
-                    ),
-            )
-            .collect()
-    }
-}
diff --git a/src/librustc_typeck/astconv/errors.rs b/src/librustc_typeck/astconv/errors.rs
new file mode 100644 (file)
index 0000000..685243f
--- /dev/null
@@ -0,0 +1,388 @@
+use crate::astconv::AstConv;
+use rustc_ast::util::lev_distance::find_best_match_for_name;
+use rustc_data_structures::fx::FxHashMap;
+use rustc_errors::{pluralize, struct_span_err, Applicability};
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
+use rustc_middle::ty;
+use rustc_session::parse::feature_err;
+use rustc_span::symbol::{sym, Ident};
+use rustc_span::{Span, DUMMY_SP};
+
+use std::collections::BTreeSet;
+
+impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
+    /// On missing type parameters, emit an E0393 error and provide a structured suggestion using
+    /// the type parameter's name as a placeholder.
+    pub(crate) fn complain_about_missing_type_params(
+        &self,
+        missing_type_params: Vec<String>,
+        def_id: DefId,
+        span: Span,
+        empty_generic_args: bool,
+    ) {
+        if missing_type_params.is_empty() {
+            return;
+        }
+        let display =
+            missing_type_params.iter().map(|n| format!("`{}`", n)).collect::<Vec<_>>().join(", ");
+        let mut err = struct_span_err!(
+            self.tcx().sess,
+            span,
+            E0393,
+            "the type parameter{} {} must be explicitly specified",
+            pluralize!(missing_type_params.len()),
+            display,
+        );
+        err.span_label(
+            self.tcx().def_span(def_id),
+            &format!(
+                "type parameter{} {} must be specified for this",
+                pluralize!(missing_type_params.len()),
+                display,
+            ),
+        );
+        let mut suggested = false;
+        if let (Ok(snippet), true) = (
+            self.tcx().sess.source_map().span_to_snippet(span),
+            // Don't suggest setting the type params if there are some already: the order is
+            // tricky to get right and the user will already know what the syntax is.
+            empty_generic_args,
+        ) {
+            if snippet.ends_with('>') {
+                // The user wrote `Trait<'a, T>` or similar. To provide an accurate suggestion
+                // we would have to preserve the right order. For now, as clearly the user is
+                // aware of the syntax, we do nothing.
+            } else {
+                // The user wrote `Iterator`, so we don't have a type we can suggest, but at
+                // least we can clue them to the correct syntax `Iterator<Type>`.
+                err.span_suggestion(
+                    span,
+                    &format!(
+                        "set the type parameter{plural} to the desired type{plural}",
+                        plural = pluralize!(missing_type_params.len()),
+                    ),
+                    format!("{}<{}>", snippet, missing_type_params.join(", ")),
+                    Applicability::HasPlaceholders,
+                );
+                suggested = true;
+            }
+        }
+        if !suggested {
+            err.span_label(
+                span,
+                format!(
+                    "missing reference{} to {}",
+                    pluralize!(missing_type_params.len()),
+                    display,
+                ),
+            );
+        }
+        err.note(
+            "because of the default `Self` reference, type parameters must be \
+                  specified on object types",
+        );
+        err.emit();
+    }
+
+    /// When the code is using the `Fn` traits directly, instead of the `Fn(A) -> B` syntax, emit
+    /// an error and attempt to build a reasonable structured suggestion.
+    pub(crate) fn complain_about_internal_fn_trait(
+        &self,
+        span: Span,
+        trait_def_id: DefId,
+        trait_segment: &'a hir::PathSegment<'a>,
+    ) {
+        let trait_def = self.tcx().trait_def(trait_def_id);
+
+        if !self.tcx().features().unboxed_closures
+            && trait_segment.generic_args().parenthesized != trait_def.paren_sugar
+        {
+            let sess = &self.tcx().sess.parse_sess;
+            // For now, require that parenthetical notation be used only with `Fn()` etc.
+            let (msg, sugg) = if trait_def.paren_sugar {
+                (
+                    "the precise format of `Fn`-family traits' type parameters is subject to \
+                     change",
+                    Some(format!(
+                        "{}{} -> {}",
+                        trait_segment.ident,
+                        trait_segment
+                            .args
+                            .as_ref()
+                            .and_then(|args| args.args.get(0))
+                            .and_then(|arg| match arg {
+                                hir::GenericArg::Type(ty) => match ty.kind {
+                                    hir::TyKind::Tup(t) => t
+                                        .iter()
+                                        .map(|e| sess.source_map().span_to_snippet(e.span))
+                                        .collect::<Result<Vec<_>, _>>()
+                                        .map(|a| a.join(", ")),
+                                    _ => sess.source_map().span_to_snippet(ty.span),
+                                }
+                                .map(|s| format!("({})", s))
+                                .ok(),
+                                _ => None,
+                            })
+                            .unwrap_or_else(|| "()".to_string()),
+                        trait_segment
+                            .generic_args()
+                            .bindings
+                            .iter()
+                            .find_map(|b| match (b.ident.name == sym::Output, &b.kind) {
+                                (true, hir::TypeBindingKind::Equality { ty }) => {
+                                    sess.source_map().span_to_snippet(ty.span).ok()
+                                }
+                                _ => None,
+                            })
+                            .unwrap_or_else(|| "()".to_string()),
+                    )),
+                )
+            } else {
+                ("parenthetical notation is only stable when used with `Fn`-family traits", None)
+            };
+            let mut err = feature_err(sess, sym::unboxed_closures, span, msg);
+            if let Some(sugg) = sugg {
+                let msg = "use parenthetical notation instead";
+                err.span_suggestion(span, msg, sugg, Applicability::MaybeIncorrect);
+            }
+            err.emit();
+        }
+    }
+
+    pub(crate) fn complain_about_assoc_type_not_found<I>(
+        &self,
+        all_candidates: impl Fn() -> I,
+        ty_param_name: &str,
+        assoc_name: Ident,
+        span: Span,
+    ) where
+        I: Iterator<Item = ty::PolyTraitRef<'tcx>>,
+    {
+        // The fallback span is needed because `assoc_name` might be an `Fn()`'s `Output` without a
+        // valid span, so we point at the whole path segment instead.
+        let span = if assoc_name.span != DUMMY_SP { assoc_name.span } else { span };
+        let mut err = struct_span_err!(
+            self.tcx().sess,
+            span,
+            E0220,
+            "associated type `{}` not found for `{}`",
+            assoc_name,
+            ty_param_name
+        );
+
+        let all_candidate_names: Vec<_> = all_candidates()
+            .map(|r| self.tcx().associated_items(r.def_id()).in_definition_order())
+            .flatten()
+            .filter_map(
+                |item| if item.kind == ty::AssocKind::Type { Some(item.ident.name) } else { None },
+            )
+            .collect();
+
+        if let (Some(suggested_name), true) = (
+            find_best_match_for_name(all_candidate_names.iter(), assoc_name.name, None),
+            assoc_name.span != DUMMY_SP,
+        ) {
+            err.span_suggestion(
+                assoc_name.span,
+                "there is an associated type with a similar name",
+                suggested_name.to_string(),
+                Applicability::MaybeIncorrect,
+            );
+        } else {
+            err.span_label(span, format!("associated type `{}` not found", assoc_name));
+        }
+
+        err.emit();
+    }
+
+    /// When there are any missing associated types, emit an E0191 error and attempt to supply a
+    /// reasonable suggestion on how to write it. For the case of multiple associated types in the
+    /// same trait bound have the same name (as they come from different super-traits), we instead
+    /// emit a generic note suggesting using a `where` clause to constraint instead.
+    pub(crate) fn complain_about_missing_associated_types(
+        &self,
+        associated_types: FxHashMap<Span, BTreeSet<DefId>>,
+        potential_assoc_types: Vec<Span>,
+        trait_bounds: &[hir::PolyTraitRef<'_>],
+    ) {
+        if associated_types.values().all(|v| v.is_empty()) {
+            return;
+        }
+        let tcx = self.tcx();
+        // FIXME: Marked `mut` so that we can replace the spans further below with a more
+        // appropriate one, but this should be handled earlier in the span assignment.
+        let mut associated_types: FxHashMap<Span, Vec<_>> = associated_types
+            .into_iter()
+            .map(|(span, def_ids)| {
+                (span, def_ids.into_iter().map(|did| tcx.associated_item(did)).collect())
+            })
+            .collect();
+        let mut names = vec![];
+
+        // Account for things like `dyn Foo + 'a`, like in tests `issue-22434.rs` and
+        // `issue-22560.rs`.
+        let mut trait_bound_spans: Vec<Span> = vec![];
+        for (span, items) in &associated_types {
+            if !items.is_empty() {
+                trait_bound_spans.push(*span);
+            }
+            for assoc_item in items {
+                let trait_def_id = assoc_item.container.id();
+                names.push(format!(
+                    "`{}` (from trait `{}`)",
+                    assoc_item.ident,
+                    tcx.def_path_str(trait_def_id),
+                ));
+            }
+        }
+        if let ([], [bound]) = (&potential_assoc_types[..], &trait_bounds) {
+            match &bound.trait_ref.path.segments[..] {
+                // FIXME: `trait_ref.path.span` can point to a full path with multiple
+                // segments, even though `trait_ref.path.segments` is of length `1`. Work
+                // around that bug here, even though it should be fixed elsewhere.
+                // This would otherwise cause an invalid suggestion. For an example, look at
+                // `src/test/ui/issues/issue-28344.rs` where instead of the following:
+                //
+                //   error[E0191]: the value of the associated type `Output`
+                //                 (from trait `std::ops::BitXor`) must be specified
+                //   --> $DIR/issue-28344.rs:4:17
+                //    |
+                // LL |     let x: u8 = BitXor::bitor(0 as u8, 0 as u8);
+                //    |                 ^^^^^^ help: specify the associated type:
+                //    |                              `BitXor<Output = Type>`
+                //
+                // we would output:
+                //
+                //   error[E0191]: the value of the associated type `Output`
+                //                 (from trait `std::ops::BitXor`) must be specified
+                //   --> $DIR/issue-28344.rs:4:17
+                //    |
+                // LL |     let x: u8 = BitXor::bitor(0 as u8, 0 as u8);
+                //    |                 ^^^^^^^^^^^^^ help: specify the associated type:
+                //    |                                     `BitXor::bitor<Output = Type>`
+                [segment] if segment.args.is_none() => {
+                    trait_bound_spans = vec![segment.ident.span];
+                    associated_types = associated_types
+                        .into_iter()
+                        .map(|(_, items)| (segment.ident.span, items))
+                        .collect();
+                }
+                _ => {}
+            }
+        }
+        names.sort();
+        trait_bound_spans.sort();
+        let mut err = struct_span_err!(
+            tcx.sess,
+            trait_bound_spans,
+            E0191,
+            "the value of the associated type{} {} must be specified",
+            pluralize!(names.len()),
+            names.join(", "),
+        );
+        let mut suggestions = vec![];
+        let mut types_count = 0;
+        let mut where_constraints = vec![];
+        for (span, assoc_items) in &associated_types {
+            let mut names: FxHashMap<_, usize> = FxHashMap::default();
+            for item in assoc_items {
+                types_count += 1;
+                *names.entry(item.ident.name).or_insert(0) += 1;
+            }
+            let mut dupes = false;
+            for item in assoc_items {
+                let prefix = if names[&item.ident.name] > 1 {
+                    let trait_def_id = item.container.id();
+                    dupes = true;
+                    format!("{}::", tcx.def_path_str(trait_def_id))
+                } else {
+                    String::new()
+                };
+                if let Some(sp) = tcx.hir().span_if_local(item.def_id) {
+                    err.span_label(sp, format!("`{}{}` defined here", prefix, item.ident));
+                }
+            }
+            if potential_assoc_types.len() == assoc_items.len() {
+                // Only suggest when the amount of missing associated types equals the number of
+                // extra type arguments present, as that gives us a relatively high confidence
+                // that the user forgot to give the associtated type's name. The canonical
+                // example would be trying to use `Iterator<isize>` instead of
+                // `Iterator<Item = isize>`.
+                for (potential, item) in potential_assoc_types.iter().zip(assoc_items.iter()) {
+                    if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(*potential) {
+                        suggestions.push((*potential, format!("{} = {}", item.ident, snippet)));
+                    }
+                }
+            } else if let (Ok(snippet), false) =
+                (tcx.sess.source_map().span_to_snippet(*span), dupes)
+            {
+                let types: Vec<_> =
+                    assoc_items.iter().map(|item| format!("{} = Type", item.ident)).collect();
+                let code = if snippet.ends_with('>') {
+                    // The user wrote `Trait<'a>` or similar and we don't have a type we can
+                    // suggest, but at least we can clue them to the correct syntax
+                    // `Trait<'a, Item = Type>` while accounting for the `<'a>` in the
+                    // suggestion.
+                    format!("{}, {}>", &snippet[..snippet.len() - 1], types.join(", "))
+                } else {
+                    // The user wrote `Iterator`, so we don't have a type we can suggest, but at
+                    // least we can clue them to the correct syntax `Iterator<Item = Type>`.
+                    format!("{}<{}>", snippet, types.join(", "))
+                };
+                suggestions.push((*span, code));
+            } else if dupes {
+                where_constraints.push(*span);
+            }
+        }
+        let where_msg = "consider introducing a new type parameter, adding `where` constraints \
+                         using the fully-qualified path to the associated types";
+        if !where_constraints.is_empty() && suggestions.is_empty() {
+            // If there are duplicates associated type names and a single trait bound do not
+            // use structured suggestion, it means that there are multiple super-traits with
+            // the same associated type name.
+            err.help(where_msg);
+        }
+        if suggestions.len() != 1 {
+            // We don't need this label if there's an inline suggestion, show otherwise.
+            for (span, assoc_items) in &associated_types {
+                let mut names: FxHashMap<_, usize> = FxHashMap::default();
+                for item in assoc_items {
+                    types_count += 1;
+                    *names.entry(item.ident.name).or_insert(0) += 1;
+                }
+                let mut label = vec![];
+                for item in assoc_items {
+                    let postfix = if names[&item.ident.name] > 1 {
+                        let trait_def_id = item.container.id();
+                        format!(" (from trait `{}`)", tcx.def_path_str(trait_def_id))
+                    } else {
+                        String::new()
+                    };
+                    label.push(format!("`{}`{}", item.ident, postfix));
+                }
+                if !label.is_empty() {
+                    err.span_label(
+                        *span,
+                        format!(
+                            "associated type{} {} must be specified",
+                            pluralize!(label.len()),
+                            label.join(", "),
+                        ),
+                    );
+                }
+            }
+        }
+        if !suggestions.is_empty() {
+            err.multipart_suggestion(
+                &format!("specify the associated type{}", pluralize!(types_count)),
+                suggestions,
+                Applicability::HasPlaceholders,
+            );
+            if !where_constraints.is_empty() {
+                err.span_help(where_constraints, where_msg);
+            }
+        }
+        err.emit();
+    }
+}
diff --git a/src/librustc_typeck/astconv/generics.rs b/src/librustc_typeck/astconv/generics.rs
new file mode 100644 (file)
index 0000000..84dab6d
--- /dev/null
@@ -0,0 +1,596 @@
+use crate::astconv::{
+    AstConv, ExplicitLateBound, GenericArgCountMismatch, GenericArgCountResult, GenericArgPosition,
+};
+use rustc_ast::ast::ParamKindOrd;
+use rustc_errors::{pluralize, struct_span_err, DiagnosticId, ErrorReported};
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
+use rustc_hir::{GenericArg, GenericArgs};
+use rustc_middle::ty::{
+    self, subst, subst::SubstsRef, GenericParamDef, GenericParamDefKind, Ty, TyCtxt,
+};
+use rustc_session::{lint::builtin::LATE_BOUND_LIFETIME_ARGUMENTS, Session};
+use rustc_span::{symbol::kw, MultiSpan, Span};
+
+use smallvec::SmallVec;
+
+impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
+    /// Report an error that a generic argument did not match the generic parameter that was
+    /// expected.
+    fn generic_arg_mismatch_err(
+        sess: &Session,
+        arg: &GenericArg<'_>,
+        kind: &'static str,
+        help: Option<&str>,
+    ) {
+        let mut err = struct_span_err!(
+            sess,
+            arg.span(),
+            E0747,
+            "{} provided when a {} was expected",
+            arg.descr(),
+            kind,
+        );
+
+        let unordered = sess.features_untracked().const_generics;
+        let kind_ord = match kind {
+            "lifetime" => ParamKindOrd::Lifetime,
+            "type" => ParamKindOrd::Type,
+            "constant" => ParamKindOrd::Const { unordered },
+            // It's more concise to match on the string representation, though it means
+            // the match is non-exhaustive.
+            _ => bug!("invalid generic parameter kind {}", kind),
+        };
+        let arg_ord = match arg {
+            GenericArg::Lifetime(_) => ParamKindOrd::Lifetime,
+            GenericArg::Type(_) => ParamKindOrd::Type,
+            GenericArg::Const(_) => ParamKindOrd::Const { unordered },
+        };
+
+        // This note is only true when generic parameters are strictly ordered by their kind.
+        if kind_ord.cmp(&arg_ord) != core::cmp::Ordering::Equal {
+            let (first, last) =
+                if kind_ord < arg_ord { (kind, arg.descr()) } else { (arg.descr(), kind) };
+            err.note(&format!("{} arguments must be provided before {} arguments", first, last));
+            if let Some(help) = help {
+                err.help(help);
+            }
+        }
+
+        err.emit();
+    }
+
+    /// Creates the relevant generic argument substitutions
+    /// corresponding to a set of generic parameters. This is a
+    /// rather complex function. Let us try to explain the role
+    /// of each of its parameters:
+    ///
+    /// To start, we are given the `def_id` of the thing we are
+    /// creating the substitutions for, and a partial set of
+    /// substitutions `parent_substs`. In general, the substitutions
+    /// for an item begin with substitutions for all the "parents" of
+    /// that item -- e.g., for a method it might include the
+    /// parameters from the impl.
+    ///
+    /// Therefore, the method begins by walking down these parents,
+    /// starting with the outermost parent and proceed inwards until
+    /// it reaches `def_id`. For each parent `P`, it will check `parent_substs`
+    /// first to see if the parent's substitutions are listed in there. If so,
+    /// we can append those and move on. Otherwise, it invokes the
+    /// three callback functions:
+    ///
+    /// - `args_for_def_id`: given the `DefId` `P`, supplies back the
+    ///   generic arguments that were given to that parent from within
+    ///   the path; so e.g., if you have `<T as Foo>::Bar`, the `DefId`
+    ///   might refer to the trait `Foo`, and the arguments might be
+    ///   `[T]`. The boolean value indicates whether to infer values
+    ///   for arguments whose values were not explicitly provided.
+    /// - `provided_kind`: given the generic parameter and the value from `args_for_def_id`,
+    ///   instantiate a `GenericArg`.
+    /// - `inferred_kind`: if no parameter was provided, and inference is enabled, then
+    ///   creates a suitable inference variable.
+    pub fn create_substs_for_generic_args<'b>(
+        tcx: TyCtxt<'tcx>,
+        def_id: DefId,
+        parent_substs: &[subst::GenericArg<'tcx>],
+        has_self: bool,
+        self_ty: Option<Ty<'tcx>>,
+        arg_count: GenericArgCountResult,
+        args_for_def_id: impl Fn(DefId) -> (Option<&'b GenericArgs<'b>>, bool),
+        mut provided_kind: impl FnMut(&GenericParamDef, &GenericArg<'_>) -> subst::GenericArg<'tcx>,
+        mut inferred_kind: impl FnMut(
+            Option<&[subst::GenericArg<'tcx>]>,
+            &GenericParamDef,
+            bool,
+        ) -> subst::GenericArg<'tcx>,
+    ) -> SubstsRef<'tcx> {
+        // Collect the segments of the path; we need to substitute arguments
+        // for parameters throughout the entire path (wherever there are
+        // generic parameters).
+        let mut parent_defs = tcx.generics_of(def_id);
+        let count = parent_defs.count();
+        let mut stack = vec![(def_id, parent_defs)];
+        while let Some(def_id) = parent_defs.parent {
+            parent_defs = tcx.generics_of(def_id);
+            stack.push((def_id, parent_defs));
+        }
+
+        // We manually build up the substitution, rather than using convenience
+        // methods in `subst.rs`, so that we can iterate over the arguments and
+        // parameters in lock-step linearly, instead of trying to match each pair.
+        let mut substs: SmallVec<[subst::GenericArg<'tcx>; 8]> = SmallVec::with_capacity(count);
+        // Iterate over each segment of the path.
+        while let Some((def_id, defs)) = stack.pop() {
+            let mut params = defs.params.iter().peekable();
+
+            // If we have already computed substitutions for parents, we can use those directly.
+            while let Some(&param) = params.peek() {
+                if let Some(&kind) = parent_substs.get(param.index as usize) {
+                    substs.push(kind);
+                    params.next();
+                } else {
+                    break;
+                }
+            }
+
+            // `Self` is handled first, unless it's been handled in `parent_substs`.
+            if has_self {
+                if let Some(&param) = params.peek() {
+                    if param.index == 0 {
+                        if let GenericParamDefKind::Type { .. } = param.kind {
+                            substs.push(
+                                self_ty
+                                    .map(|ty| ty.into())
+                                    .unwrap_or_else(|| inferred_kind(None, param, true)),
+                            );
+                            params.next();
+                        }
+                    }
+                }
+            }
+
+            // Check whether this segment takes generic arguments and the user has provided any.
+            let (generic_args, infer_args) = args_for_def_id(def_id);
+
+            let mut args =
+                generic_args.iter().flat_map(|generic_args| generic_args.args.iter()).peekable();
+
+            // If we encounter a type or const when we expect a lifetime, we infer the lifetimes.
+            // If we later encounter a lifetime, we know that the arguments were provided in the
+            // wrong order. `force_infer_lt` records the type or const that forced lifetimes to be
+            // inferred, so we can use it for diagnostics later.
+            let mut force_infer_lt = None;
+
+            loop {
+                // We're going to iterate through the generic arguments that the user
+                // provided, matching them with the generic parameters we expect.
+                // Mismatches can occur as a result of elided lifetimes, or for malformed
+                // input. We try to handle both sensibly.
+                match (args.peek(), params.peek()) {
+                    (Some(&arg), Some(&param)) => {
+                        match (arg, &param.kind, arg_count.explicit_late_bound) {
+                            (GenericArg::Lifetime(_), GenericParamDefKind::Lifetime, _)
+                            | (GenericArg::Type(_), GenericParamDefKind::Type { .. }, _)
+                            | (GenericArg::Const(_), GenericParamDefKind::Const, _) => {
+                                substs.push(provided_kind(param, arg));
+                                args.next();
+                                params.next();
+                            }
+                            (
+                                GenericArg::Type(_) | GenericArg::Const(_),
+                                GenericParamDefKind::Lifetime,
+                                _,
+                            ) => {
+                                // We expected a lifetime argument, but got a type or const
+                                // argument. That means we're inferring the lifetimes.
+                                substs.push(inferred_kind(None, param, infer_args));
+                                force_infer_lt = Some(arg);
+                                params.next();
+                            }
+                            (GenericArg::Lifetime(_), _, ExplicitLateBound::Yes) => {
+                                // We've come across a lifetime when we expected something else in
+                                // the presence of explicit late bounds. This is most likely
+                                // due to the presence of the explicit bound so we're just going to
+                                // ignore it.
+                                args.next();
+                            }
+                            (_, kind, _) => {
+                                // We expected one kind of parameter, but the user provided
+                                // another. This is an error. However, if we already know that
+                                // the arguments don't match up with the parameters, we won't issue
+                                // an additional error, as the user already knows what's wrong.
+                                if arg_count.correct.is_ok()
+                                    && arg_count.explicit_late_bound == ExplicitLateBound::No
+                                {
+                                    // We're going to iterate over the parameters to sort them out, and
+                                    // show that order to the user as a possible order for the parameters
+                                    let mut param_types_present = defs
+                                        .params
+                                        .clone()
+                                        .into_iter()
+                                        .map(|param| {
+                                            (
+                                                match param.kind {
+                                                    GenericParamDefKind::Lifetime => {
+                                                        ParamKindOrd::Lifetime
+                                                    }
+                                                    GenericParamDefKind::Type { .. } => {
+                                                        ParamKindOrd::Type
+                                                    }
+                                                    GenericParamDefKind::Const => {
+                                                        ParamKindOrd::Const {
+                                                            unordered: tcx
+                                                                .sess
+                                                                .features_untracked()
+                                                                .const_generics,
+                                                        }
+                                                    }
+                                                },
+                                                param,
+                                            )
+                                        })
+                                        .collect::<Vec<(ParamKindOrd, GenericParamDef)>>();
+                                    param_types_present.sort_by_key(|(ord, _)| *ord);
+                                    let (mut param_types_present, ordered_params): (
+                                        Vec<ParamKindOrd>,
+                                        Vec<GenericParamDef>,
+                                    ) = param_types_present.into_iter().unzip();
+                                    param_types_present.dedup();
+
+                                    Self::generic_arg_mismatch_err(
+                                        tcx.sess,
+                                        arg,
+                                        kind.descr(),
+                                        Some(&format!(
+                                            "reorder the arguments: {}: `<{}>`",
+                                            param_types_present
+                                                .into_iter()
+                                                .map(|ord| format!("{}s", ord.to_string()))
+                                                .collect::<Vec<String>>()
+                                                .join(", then "),
+                                            ordered_params
+                                                .into_iter()
+                                                .filter_map(|param| {
+                                                    if param.name == kw::SelfUpper {
+                                                        None
+                                                    } else {
+                                                        Some(param.name.to_string())
+                                                    }
+                                                })
+                                                .collect::<Vec<String>>()
+                                                .join(", ")
+                                        )),
+                                    );
+                                }
+
+                                // We've reported the error, but we want to make sure that this
+                                // problem doesn't bubble down and create additional, irrelevant
+                                // errors. In this case, we're simply going to ignore the argument
+                                // and any following arguments. The rest of the parameters will be
+                                // inferred.
+                                while args.next().is_some() {}
+                            }
+                        }
+                    }
+
+                    (Some(&arg), None) => {
+                        // We should never be able to reach this point with well-formed input.
+                        // There are three situations in which we can encounter this issue.
+                        //
+                        //  1.  The number of arguments is incorrect. In this case, an error
+                        //      will already have been emitted, and we can ignore it.
+                        //  2.  There are late-bound lifetime parameters present, yet the
+                        //      lifetime arguments have also been explicitly specified by the
+                        //      user.
+                        //  3.  We've inferred some lifetimes, which have been provided later (i.e.
+                        //      after a type or const). We want to throw an error in this case.
+
+                        if arg_count.correct.is_ok()
+                            && arg_count.explicit_late_bound == ExplicitLateBound::No
+                        {
+                            let kind = arg.descr();
+                            assert_eq!(kind, "lifetime");
+                            let provided =
+                                force_infer_lt.expect("lifetimes ought to have been inferred");
+                            Self::generic_arg_mismatch_err(tcx.sess, provided, kind, None);
+                        }
+
+                        break;
+                    }
+
+                    (None, Some(&param)) => {
+                        // If there are fewer arguments than parameters, it means
+                        // we're inferring the remaining arguments.
+                        substs.push(inferred_kind(Some(&substs), param, infer_args));
+                        params.next();
+                    }
+
+                    (None, None) => break,
+                }
+            }
+        }
+
+        tcx.intern_substs(&substs)
+    }
+
+    /// Checks that the correct number of generic arguments have been provided.
+    /// Used specifically for function calls.
+    pub fn check_generic_arg_count_for_call(
+        tcx: TyCtxt<'_>,
+        span: Span,
+        def: &ty::Generics,
+        seg: &hir::PathSegment<'_>,
+        is_method_call: bool,
+    ) -> GenericArgCountResult {
+        let empty_args = hir::GenericArgs::none();
+        let suppress_mismatch = Self::check_impl_trait(tcx, seg, &def);
+        Self::check_generic_arg_count(
+            tcx,
+            span,
+            def,
+            if let Some(ref args) = seg.args { args } else { &empty_args },
+            if is_method_call { GenericArgPosition::MethodCall } else { GenericArgPosition::Value },
+            def.parent.is_none() && def.has_self, // `has_self`
+            seg.infer_args || suppress_mismatch,  // `infer_args`
+        )
+    }
+
+    /// Checks that the correct number of generic arguments have been provided.
+    /// This is used both for datatypes and function calls.
+    pub(crate) fn check_generic_arg_count(
+        tcx: TyCtxt<'_>,
+        span: Span,
+        def: &ty::Generics,
+        args: &hir::GenericArgs<'_>,
+        position: GenericArgPosition,
+        has_self: bool,
+        infer_args: bool,
+    ) -> GenericArgCountResult {
+        // At this stage we are guaranteed that the generic arguments are in the correct order, e.g.
+        // that lifetimes will proceed types. So it suffices to check the number of each generic
+        // arguments in order to validate them with respect to the generic parameters.
+        let param_counts = def.own_counts();
+        let arg_counts = args.own_counts();
+        let infer_lifetimes = position != GenericArgPosition::Type && arg_counts.lifetimes == 0;
+
+        let mut defaults: ty::GenericParamCount = Default::default();
+        for param in &def.params {
+            match param.kind {
+                GenericParamDefKind::Lifetime => {}
+                GenericParamDefKind::Type { has_default, .. } => {
+                    defaults.types += has_default as usize
+                }
+                GenericParamDefKind::Const => {
+                    // FIXME(const_generics:defaults)
+                }
+            };
+        }
+
+        if position != GenericArgPosition::Type && !args.bindings.is_empty() {
+            Self::prohibit_assoc_ty_binding(tcx, args.bindings[0].span);
+        }
+
+        let explicit_late_bound =
+            Self::prohibit_explicit_late_bound_lifetimes(tcx, def, args, position);
+
+        let check_kind_count = |kind,
+                                required,
+                                permitted,
+                                provided,
+                                offset,
+                                unexpected_spans: &mut Vec<Span>,
+                                silent| {
+            debug!(
+                "check_kind_count: kind: {} required: {} permitted: {} provided: {} offset: {}",
+                kind, required, permitted, provided, offset
+            );
+            // We enforce the following: `required` <= `provided` <= `permitted`.
+            // For kinds without defaults (e.g.., lifetimes), `required == permitted`.
+            // For other kinds (i.e., types), `permitted` may be greater than `required`.
+            if required <= provided && provided <= permitted {
+                return Ok(());
+            }
+
+            if silent {
+                return Err(true);
+            }
+
+            // Unfortunately lifetime and type parameter mismatches are typically styled
+            // differently in diagnostics, which means we have a few cases to consider here.
+            let (bound, quantifier) = if required != permitted {
+                if provided < required {
+                    (required, "at least ")
+                } else {
+                    // provided > permitted
+                    (permitted, "at most ")
+                }
+            } else {
+                (required, "")
+            };
+
+            let (spans, label) = if required == permitted && provided > permitted {
+                // In the case when the user has provided too many arguments,
+                // we want to point to the unexpected arguments.
+                let spans: Vec<Span> = args.args[offset + permitted..offset + provided]
+                    .iter()
+                    .map(|arg| arg.span())
+                    .collect();
+                unexpected_spans.extend(spans.clone());
+                (spans, format!("unexpected {} argument", kind))
+            } else {
+                (
+                    vec![span],
+                    format!(
+                        "expected {}{} {} argument{}",
+                        quantifier,
+                        bound,
+                        kind,
+                        pluralize!(bound),
+                    ),
+                )
+            };
+
+            let mut err = tcx.sess.struct_span_err_with_code(
+                spans.clone(),
+                &format!(
+                    "wrong number of {} arguments: expected {}{}, found {}",
+                    kind, quantifier, bound, provided,
+                ),
+                DiagnosticId::Error("E0107".into()),
+            );
+            for span in spans {
+                err.span_label(span, label.as_str());
+            }
+            err.emit();
+
+            Err(true)
+        };
+
+        let mut arg_count_correct = Ok(());
+        let mut unexpected_spans = vec![];
+
+        if !infer_lifetimes || arg_counts.lifetimes > param_counts.lifetimes {
+            arg_count_correct = check_kind_count(
+                "lifetime",
+                param_counts.lifetimes,
+                param_counts.lifetimes,
+                arg_counts.lifetimes,
+                0,
+                &mut unexpected_spans,
+                explicit_late_bound == ExplicitLateBound::Yes,
+            )
+            .and(arg_count_correct);
+        }
+        // FIXME(const_generics:defaults)
+        if !infer_args || arg_counts.consts > param_counts.consts {
+            arg_count_correct = check_kind_count(
+                "const",
+                param_counts.consts,
+                param_counts.consts,
+                arg_counts.consts,
+                arg_counts.lifetimes + arg_counts.types,
+                &mut unexpected_spans,
+                false,
+            )
+            .and(arg_count_correct);
+        }
+        // Note that type errors are currently be emitted *after* const errors.
+        if !infer_args || arg_counts.types > param_counts.types - defaults.types - has_self as usize
+        {
+            arg_count_correct = check_kind_count(
+                "type",
+                param_counts.types - defaults.types - has_self as usize,
+                param_counts.types - has_self as usize,
+                arg_counts.types,
+                arg_counts.lifetimes,
+                &mut unexpected_spans,
+                false,
+            )
+            .and(arg_count_correct);
+        }
+
+        GenericArgCountResult {
+            explicit_late_bound,
+            correct: arg_count_correct.map_err(|reported_err| GenericArgCountMismatch {
+                reported: if reported_err { Some(ErrorReported) } else { None },
+                invalid_args: unexpected_spans,
+            }),
+        }
+    }
+
+    /// Report error if there is an explicit type parameter when using `impl Trait`.
+    pub(crate) fn check_impl_trait(
+        tcx: TyCtxt<'_>,
+        seg: &hir::PathSegment<'_>,
+        generics: &ty::Generics,
+    ) -> bool {
+        let explicit = !seg.infer_args;
+        let impl_trait = generics.params.iter().any(|param| match param.kind {
+            ty::GenericParamDefKind::Type {
+                synthetic: Some(hir::SyntheticTyParamKind::ImplTrait),
+                ..
+            } => true,
+            _ => false,
+        });
+
+        if explicit && impl_trait {
+            let spans = seg
+                .generic_args()
+                .args
+                .iter()
+                .filter_map(|arg| match arg {
+                    GenericArg::Type(_) => Some(arg.span()),
+                    _ => None,
+                })
+                .collect::<Vec<_>>();
+
+            let mut err = struct_span_err! {
+                tcx.sess,
+                spans.clone(),
+                E0632,
+                "cannot provide explicit generic arguments when `impl Trait` is \
+                used in argument position"
+            };
+
+            for span in spans {
+                err.span_label(span, "explicit generic argument not allowed");
+            }
+
+            err.emit();
+        }
+
+        impl_trait
+    }
+
+    /// Emits an error regarding forbidden type binding associations
+    pub fn prohibit_assoc_ty_binding(tcx: TyCtxt<'_>, span: Span) {
+        let mut err = struct_span_err!(
+            tcx.sess,
+            span,
+            E0229,
+            "associated type bindings are not allowed here"
+        );
+        err.span_label(span, "associated type not allowed here").emit();
+    }
+
+    /// Prohibits explicit lifetime arguments if late-bound lifetime parameters
+    /// are present. This is used both for datatypes and function calls.
+    pub(crate) fn prohibit_explicit_late_bound_lifetimes(
+        tcx: TyCtxt<'_>,
+        def: &ty::Generics,
+        args: &hir::GenericArgs<'_>,
+        position: GenericArgPosition,
+    ) -> ExplicitLateBound {
+        let param_counts = def.own_counts();
+        let arg_counts = args.own_counts();
+        let infer_lifetimes = position != GenericArgPosition::Type && arg_counts.lifetimes == 0;
+
+        if infer_lifetimes {
+            ExplicitLateBound::No
+        } else if let Some(span_late) = def.has_late_bound_regions {
+            let msg = "cannot specify lifetime arguments explicitly \
+                       if late bound lifetime parameters are present";
+            let note = "the late bound lifetime parameter is introduced here";
+            let span = args.args[0].span();
+            if position == GenericArgPosition::Value
+                && arg_counts.lifetimes != param_counts.lifetimes
+            {
+                let mut err = tcx.sess.struct_span_err(span, msg);
+                err.span_note(span_late, note);
+                err.emit();
+            } else {
+                let mut multispan = MultiSpan::from_span(span);
+                multispan.push_span_label(span_late, note.to_string());
+                tcx.struct_span_lint_hir(
+                    LATE_BOUND_LIFETIME_ARGUMENTS,
+                    args.args[0].id(),
+                    multispan,
+                    |lint| lint.build(msg).emit(),
+                );
+            }
+            ExplicitLateBound::Yes
+        } else {
+            ExplicitLateBound::No
+        }
+    }
+}
diff --git a/src/librustc_typeck/astconv/mod.rs b/src/librustc_typeck/astconv/mod.rs
new file mode 100644 (file)
index 0000000..80dd26e
--- /dev/null
@@ -0,0 +1,2296 @@
+//! Conversion from AST representation of types to the `ty.rs` representation.
+//! The main routine here is `ast_ty_to_ty()`; each use is parameterized by an
+//! instance of `AstConv`.
+
+mod errors;
+mod generics;
+
+use crate::bounds::Bounds;
+use crate::collect::PlaceholderHirTyCollector;
+use crate::middle::resolve_lifetime as rl;
+use crate::require_c_abi_if_c_variadic;
+use rustc_ast::util::lev_distance::find_best_match_for_name;
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_errors::{struct_span_err, Applicability, ErrorReported, FatalError};
+use rustc_hir as hir;
+use rustc_hir::def::{CtorOf, DefKind, Namespace, Res};
+use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::intravisit::{walk_generics, Visitor as _};
+use rustc_hir::lang_items::LangItem;
+use rustc_hir::{Constness, GenericArg, GenericArgs};
+use rustc_middle::ty::subst::{self, InternalSubsts, Subst, SubstsRef};
+use rustc_middle::ty::GenericParamDefKind;
+use rustc_middle::ty::{self, Const, DefIdTree, Ty, TyCtxt, TypeFoldable};
+use rustc_session::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS;
+use rustc_span::symbol::{Ident, Symbol};
+use rustc_span::{Span, DUMMY_SP};
+use rustc_target::spec::abi;
+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;
+
+#[derive(Debug)]
+pub struct PathSeg(pub DefId, pub usize);
+
+pub trait AstConv<'tcx> {
+    fn tcx<'a>(&'a self) -> TyCtxt<'tcx>;
+
+    fn item_def_id(&self) -> Option<DefId>;
+
+    fn default_constness_for_trait_bounds(&self) -> Constness;
+
+    /// Returns predicates in scope of the form `X: Foo`, where `X` is
+    /// a type parameter `X` with the given id `def_id`. This is a
+    /// subset of the full set of predicates.
+    ///
+    /// This is used for one specific purpose: resolving "short-hand"
+    /// associated type references like `T::Item`. In principle, we
+    /// would do that by first getting the full set of predicates in
+    /// scope and then filtering down to find those that apply to `T`,
+    /// but this can lead to cycle errors. The problem is that we have
+    /// to do this resolution *in order to create the predicates in
+    /// the first place*. Hence, we have this "special pass".
+    fn get_type_parameter_bounds(&self, span: Span, def_id: DefId) -> ty::GenericPredicates<'tcx>;
+
+    /// Returns the lifetime to use when a lifetime is omitted (and not elided).
+    fn re_infer(&self, param: Option<&ty::GenericParamDef>, span: Span)
+    -> Option<ty::Region<'tcx>>;
+
+    /// Returns the type to use when a type is omitted.
+    fn ty_infer(&self, param: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx>;
+
+    /// Returns `true` if `_` is allowed in type signatures in the current context.
+    fn allow_ty_infer(&self) -> bool;
+
+    /// Returns the const to use when a const is omitted.
+    fn ct_infer(
+        &self,
+        ty: Ty<'tcx>,
+        param: Option<&ty::GenericParamDef>,
+        span: Span,
+    ) -> &'tcx Const<'tcx>;
+
+    /// Projecting an associated type from a (potentially)
+    /// higher-ranked trait reference is more complicated, because of
+    /// the possibility of late-bound regions appearing in the
+    /// associated type binding. This is not legal in function
+    /// signatures for that reason. In a function body, we can always
+    /// handle it because we can use inference variables to remove the
+    /// late-bound regions.
+    fn projected_ty_from_poly_trait_ref(
+        &self,
+        span: Span,
+        item_def_id: DefId,
+        item_segment: &hir::PathSegment<'_>,
+        poly_trait_ref: ty::PolyTraitRef<'tcx>,
+    ) -> Ty<'tcx>;
+
+    /// Normalize an associated type coming from the user.
+    fn normalize_ty(&self, span: Span, ty: Ty<'tcx>) -> Ty<'tcx>;
+
+    /// Invoked when we encounter an error from some prior pass
+    /// (e.g., resolve) that is translated into a ty-error. This is
+    /// used to help suppress derived errors typeck might otherwise
+    /// report.
+    fn set_tainted_by_errors(&self);
+
+    fn record_ty(&self, hir_id: hir::HirId, ty: Ty<'tcx>, span: Span);
+}
+
+pub enum SizedByDefault {
+    Yes,
+    No,
+}
+
+struct ConvertedBinding<'a, 'tcx> {
+    item_name: Ident,
+    kind: ConvertedBindingKind<'a, 'tcx>,
+    span: Span,
+}
+
+enum ConvertedBindingKind<'a, 'tcx> {
+    Equality(Ty<'tcx>),
+    Constraint(&'a [hir::GenericBound<'a>]),
+}
+
+/// New-typed boolean indicating whether explicit late-bound lifetimes
+/// are present in a set of generic arguments.
+///
+/// For example if we have some method `fn f<'a>(&'a self)` implemented
+/// for some type `T`, although `f` is generic in the lifetime `'a`, `'a`
+/// is late-bound so should not be provided explicitly. Thus, if `f` is
+/// instantiated with some generic arguments providing `'a` explicitly,
+/// we taint those arguments with `ExplicitLateBound::Yes` so that we
+/// can provide an appropriate diagnostic later.
+#[derive(Copy, Clone, PartialEq)]
+pub enum ExplicitLateBound {
+    Yes,
+    No,
+}
+
+/// Denotes the "position" of a generic argument, indicating if it is a generic type,
+/// generic function or generic method call.
+#[derive(Copy, Clone, PartialEq)]
+pub(crate) enum GenericArgPosition {
+    Type,
+    Value, // e.g., functions
+    MethodCall,
+}
+
+/// A marker denoting that the generic arguments that were
+/// provided did not match the respective generic parameters.
+#[derive(Clone, Default)]
+pub struct GenericArgCountMismatch {
+    /// Indicates whether a fatal error was reported (`Some`), or just a lint (`None`).
+    pub reported: Option<ErrorReported>,
+    /// A list of spans of arguments provided that were not valid.
+    pub invalid_args: Vec<Span>,
+}
+
+/// Decorates the result of a generic argument count mismatch
+/// check with whether explicit late bounds were provided.
+#[derive(Clone)]
+pub struct GenericArgCountResult {
+    pub explicit_late_bound: ExplicitLateBound,
+    pub correct: Result<(), GenericArgCountMismatch>,
+}
+
+impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
+    pub fn ast_region_to_region(
+        &self,
+        lifetime: &hir::Lifetime,
+        def: Option<&ty::GenericParamDef>,
+    ) -> ty::Region<'tcx> {
+        let tcx = self.tcx();
+        let lifetime_name = |def_id| tcx.hir().name(tcx.hir().local_def_id_to_hir_id(def_id));
+
+        let r = match tcx.named_region(lifetime.hir_id) {
+            Some(rl::Region::Static) => tcx.lifetimes.re_static,
+
+            Some(rl::Region::LateBound(debruijn, id, _)) => {
+                let name = lifetime_name(id.expect_local());
+                tcx.mk_region(ty::ReLateBound(debruijn, ty::BrNamed(id, name)))
+            }
+
+            Some(rl::Region::LateBoundAnon(debruijn, index)) => {
+                tcx.mk_region(ty::ReLateBound(debruijn, ty::BrAnon(index)))
+            }
+
+            Some(rl::Region::EarlyBound(index, id, _)) => {
+                let name = lifetime_name(id.expect_local());
+                tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion { def_id: id, index, name }))
+            }
+
+            Some(rl::Region::Free(scope, id)) => {
+                let name = lifetime_name(id.expect_local());
+                tcx.mk_region(ty::ReFree(ty::FreeRegion {
+                    scope,
+                    bound_region: ty::BrNamed(id, name),
+                }))
+
+                // (*) -- not late-bound, won't change
+            }
+
+            None => {
+                self.re_infer(def, lifetime.span).unwrap_or_else(|| {
+                    // This indicates an illegal lifetime
+                    // elision. `resolve_lifetime` should have
+                    // reported an error in this case -- but if
+                    // not, let's error out.
+                    tcx.sess.delay_span_bug(lifetime.span, "unelided lifetime in signature");
+
+                    // Supply some dummy value. We don't have an
+                    // `re_error`, annoyingly, so use `'static`.
+                    tcx.lifetimes.re_static
+                })
+            }
+        };
+
+        debug!("ast_region_to_region(lifetime={:?}) yields {:?}", lifetime, r);
+
+        r
+    }
+
+    /// Given a path `path` that refers to an item `I` with the declared generics `decl_generics`,
+    /// returns an appropriate set of substitutions for this particular reference to `I`.
+    pub fn ast_path_substs_for_ty(
+        &self,
+        span: Span,
+        def_id: DefId,
+        item_segment: &hir::PathSegment<'_>,
+    ) -> SubstsRef<'tcx> {
+        let (substs, assoc_bindings, _) = self.create_substs_for_ast_path(
+            span,
+            def_id,
+            &[],
+            item_segment.generic_args(),
+            item_segment.infer_args,
+            None,
+        );
+
+        if let Some(b) = assoc_bindings.first() {
+            Self::prohibit_assoc_ty_binding(self.tcx(), b.span);
+        }
+
+        substs
+    }
+
+    /// 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 constraints on associated types.
+    ///
+    /// Example:
+    ///
+    /// ```
+    /// T: std::ops::Index<usize, Output = u32>
+    /// ^1 ^^^^^^^^^^^^^^2 ^^^^3  ^^^^^^^^^^^4
+    /// ```
+    ///
+    /// 1. The `self_ty` here would refer to the type `T`.
+    /// 2. The path in question is the path to the trait `std::ops::Index`,
+    ///    which will have been resolved to a `def_id`
+    /// 3. The `generic_args` contains info on the `<...>` contents. The `usize` type
+    ///    parameters are returned in the `SubstsRef`, the associated type bindings like
+    ///    `Output = u32` are returned in the `Vec<ConvertedBinding...>` result.
+    ///
+    /// Note that the type listing given here is *exactly* what the user provided.
+    ///
+    /// For (generic) associated types
+    ///
+    /// ```
+    /// <Vec<u8> as Iterable<u8>>::Iter::<'a>
+    /// ```
+    ///
+    /// We have the parent substs are the substs for the parent trait:
+    /// `[Vec<u8>, u8]` and `generic_args` are the arguments for the associated
+    /// type itself: `['a]`. The returned `SubstsRef` concatenates these two
+    /// lists: `[Vec<u8>, u8, 'a]`.
+    fn create_substs_for_ast_path<'a>(
+        &self,
+        span: Span,
+        def_id: DefId,
+        parent_substs: &[subst::GenericArg<'tcx>],
+        generic_args: &'a hir::GenericArgs<'_>,
+        infer_args: bool,
+        self_ty: Option<Ty<'tcx>>,
+    ) -> (SubstsRef<'tcx>, Vec<ConvertedBinding<'a, 'tcx>>, GenericArgCountResult) {
+        // If the type is parameterized by this region, then replace this
+        // region with the current anon region binding (in other words,
+        // whatever & would get replaced with).
+        debug!(
+            "create_substs_for_ast_path(def_id={:?}, self_ty={:?}, \
+                generic_args={:?})",
+            def_id, self_ty, generic_args
+        );
+
+        let tcx = self.tcx();
+        let generic_params = tcx.generics_of(def_id);
+
+        if generic_params.has_self {
+            if generic_params.parent.is_some() {
+                // The parent is a trait so it should have at least one subst
+                // for the `Self` type.
+                assert!(!parent_substs.is_empty())
+            } else {
+                // This item (presumably a trait) needs a self-type.
+                assert!(self_ty.is_some());
+            }
+        } else {
+            assert!(self_ty.is_none() && parent_substs.is_empty());
+        }
+
+        let arg_count = Self::check_generic_arg_count(
+            tcx,
+            span,
+            &generic_params,
+            &generic_args,
+            GenericArgPosition::Type,
+            self_ty.is_some(),
+            infer_args,
+        );
+
+        let is_object = self_ty.map_or(false, |ty| ty == self.tcx().types.trait_object_dummy_self);
+        let default_needs_object_self = |param: &ty::GenericParamDef| {
+            if let GenericParamDefKind::Type { has_default, .. } = param.kind {
+                if is_object && has_default {
+                    let default_ty = tcx.at(span).type_of(param.def_id);
+                    let self_param = tcx.types.self_param;
+                    if default_ty.walk().any(|arg| arg == self_param.into()) {
+                        // There is no suitable inference default for a type parameter
+                        // that references self, in an object type.
+                        return true;
+                    }
+                }
+            }
+
+            false
+        };
+
+        let mut missing_type_params = vec![];
+        let mut inferred_params = vec![];
+        let substs = Self::create_substs_for_generic_args(
+            tcx,
+            def_id,
+            parent_substs,
+            self_ty.is_some(),
+            self_ty,
+            arg_count.clone(),
+            // Provide the generic args, and whether types should be inferred.
+            |did| {
+                if did == def_id {
+                    (Some(generic_args), infer_args)
+                } else {
+                    // The last component of this tuple is unimportant.
+                    (None, false)
+                }
+            },
+            // Provide substitutions for parameters for which (valid) arguments have been provided.
+            |param, arg| match (&param.kind, arg) {
+                (GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => {
+                    self.ast_region_to_region(&lt, Some(param)).into()
+                }
+                (GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => {
+                    if let (hir::TyKind::Infer, false) = (&ty.kind, self.allow_ty_infer()) {
+                        inferred_params.push(ty.span);
+                        tcx.ty_error().into()
+                    } else {
+                        self.ast_ty_to_ty(&ty).into()
+                    }
+                }
+                (GenericParamDefKind::Const, GenericArg::Const(ct)) => {
+                    ty::Const::from_opt_const_arg_anon_const(
+                        tcx,
+                        ty::WithOptConstParam {
+                            did: tcx.hir().local_def_id(ct.value.hir_id),
+                            const_param_did: Some(param.def_id),
+                        },
+                    )
+                    .into()
+                }
+                _ => unreachable!(),
+            },
+            // Provide substitutions for parameters for which arguments are inferred.
+            |substs, param, infer_args| {
+                match param.kind {
+                    GenericParamDefKind::Lifetime => tcx.lifetimes.re_static.into(),
+                    GenericParamDefKind::Type { has_default, .. } => {
+                        if !infer_args && has_default {
+                            // No type parameter provided, but a default exists.
+
+                            // If we are converting an object type, then the
+                            // `Self` parameter is unknown. However, some of the
+                            // other type parameters may reference `Self` in their
+                            // defaults. This will lead to an ICE if we are not
+                            // careful!
+                            if default_needs_object_self(param) {
+                                missing_type_params.push(param.name.to_string());
+                                tcx.ty_error().into()
+                            } else {
+                                // This is a default type parameter.
+                                self.normalize_ty(
+                                    span,
+                                    tcx.at(span).type_of(param.def_id).subst_spanned(
+                                        tcx,
+                                        substs.unwrap(),
+                                        Some(span),
+                                    ),
+                                )
+                                .into()
+                            }
+                        } else if infer_args {
+                            // No type parameters were provided, we can infer all.
+                            let param =
+                                if !default_needs_object_self(param) { Some(param) } else { None };
+                            self.ty_infer(param, span).into()
+                        } else {
+                            // We've already errored above about the mismatch.
+                            tcx.ty_error().into()
+                        }
+                    }
+                    GenericParamDefKind::Const => {
+                        let ty = tcx.at(span).type_of(param.def_id);
+                        // FIXME(const_generics:defaults)
+                        if infer_args {
+                            // No const parameters were provided, we can infer all.
+                            self.ct_infer(ty, Some(param), span).into()
+                        } else {
+                            // We've already errored above about the mismatch.
+                            tcx.const_error(ty).into()
+                        }
+                    }
+                }
+            },
+        );
+
+        self.complain_about_missing_type_params(
+            missing_type_params,
+            def_id,
+            span,
+            generic_args.args.is_empty(),
+        );
+
+        // Convert associated-type bindings or constraints into a separate vector.
+        // Example: Given this:
+        //
+        //     T: Iterator<Item = u32>
+        //
+        // The `T` is passed in as a self-type; the `Item = u32` is
+        // not a "type parameter" of the `Iterator` trait, but rather
+        // a restriction on `<T as Iterator>::Item`, so it is passed
+        // back separately.
+        let assoc_bindings = generic_args
+            .bindings
+            .iter()
+            .map(|binding| {
+                let kind = match binding.kind {
+                    hir::TypeBindingKind::Equality { ref ty } => {
+                        ConvertedBindingKind::Equality(self.ast_ty_to_ty(ty))
+                    }
+                    hir::TypeBindingKind::Constraint { ref bounds } => {
+                        ConvertedBindingKind::Constraint(bounds)
+                    }
+                };
+                ConvertedBinding { item_name: binding.ident, kind, span: binding.span }
+            })
+            .collect();
+
+        debug!(
+            "create_substs_for_ast_path(generic_params={:?}, self_ty={:?}) -> {:?}",
+            generic_params, self_ty, substs
+        );
+
+        (substs, assoc_bindings, arg_count)
+    }
+
+    crate fn create_substs_for_associated_item(
+        &self,
+        tcx: TyCtxt<'tcx>,
+        span: Span,
+        item_def_id: DefId,
+        item_segment: &hir::PathSegment<'_>,
+        parent_substs: SubstsRef<'tcx>,
+    ) -> SubstsRef<'tcx> {
+        if tcx.generics_of(item_def_id).params.is_empty() {
+            self.prohibit_generics(slice::from_ref(item_segment));
+
+            parent_substs
+        } else {
+            self.create_substs_for_ast_path(
+                span,
+                item_def_id,
+                parent_substs,
+                item_segment.generic_args(),
+                item_segment.infer_args,
+                None,
+            )
+            .0
+        }
+    }
+
+    /// Instantiates the path for the given trait reference, assuming that it's
+    /// bound to a valid trait type. Returns the `DefId` of the defining trait.
+    /// The type _cannot_ be a type other than a trait type.
+    ///
+    /// If the `projections` argument is `None`, then assoc type bindings like `Foo<T = X>`
+    /// are disallowed. Otherwise, they are pushed onto the vector given.
+    pub fn instantiate_mono_trait_ref(
+        &self,
+        trait_ref: &hir::TraitRef<'_>,
+        self_ty: Ty<'tcx>,
+    ) -> ty::TraitRef<'tcx> {
+        self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1);
+
+        self.ast_path_to_mono_trait_ref(
+            trait_ref.path.span,
+            trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise()),
+            self_ty,
+            trait_ref.path.segments.last().unwrap(),
+        )
+    }
+
+    /// The given trait-ref must actually be a trait.
+    pub(super) fn instantiate_poly_trait_ref_inner(
+        &self,
+        trait_ref: &hir::TraitRef<'_>,
+        span: Span,
+        constness: Constness,
+        self_ty: Ty<'tcx>,
+        bounds: &mut Bounds<'tcx>,
+        speculative: bool,
+    ) -> GenericArgCountResult {
+        let trait_def_id = trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise());
+
+        debug!("instantiate_poly_trait_ref({:?}, def_id={:?})", trait_ref, trait_def_id);
+
+        self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1);
+
+        let (substs, assoc_bindings, arg_count) = self.create_substs_for_ast_trait_ref(
+            trait_ref.path.span,
+            trait_def_id,
+            self_ty,
+            trait_ref.path.segments.last().unwrap(),
+        );
+        let poly_trait_ref = ty::Binder::bind(ty::TraitRef::new(trait_def_id, substs));
+
+        bounds.trait_bounds.push((poly_trait_ref, span, constness));
+
+        let mut dup_bindings = FxHashMap::default();
+        for binding in &assoc_bindings {
+            // Specify type to assert that error was already reported in `Err` case.
+            let _: Result<_, ErrorReported> = self.add_predicates_for_ast_type_binding(
+                trait_ref.hir_ref_id,
+                poly_trait_ref,
+                binding,
+                bounds,
+                speculative,
+                &mut dup_bindings,
+                binding.span,
+            );
+            // Okay to ignore `Err` because of `ErrorReported` (see above).
+        }
+
+        debug!(
+            "instantiate_poly_trait_ref({:?}, bounds={:?}) -> {:?}",
+            trait_ref, bounds, poly_trait_ref
+        );
+
+        arg_count
+    }
+
+    /// Given a trait bound like `Debug`, applies that trait bound the given self-type to construct
+    /// a full trait reference. The resulting trait reference is returned. This may also generate
+    /// auxiliary bounds, which are added to `bounds`.
+    ///
+    /// Example:
+    ///
+    /// ```
+    /// poly_trait_ref = Iterator<Item = u32>
+    /// self_ty = Foo
+    /// ```
+    ///
+    /// this would return `Foo: Iterator` and add `<Foo as Iterator>::Item = u32` into `bounds`.
+    ///
+    /// **A note on binders:** against our usual convention, there is an implied bounder around
+    /// the `self_ty` and `poly_trait_ref` parameters here. So they may reference bound regions.
+    /// If for example you had `for<'a> Foo<'a>: Bar<'a>`, then the `self_ty` would be `Foo<'a>`
+    /// where `'a` is a bound region at depth 0. Similarly, the `poly_trait_ref` would be
+    /// `Bar<'a>`. The returned poly-trait-ref will have this binder instantiated explicitly,
+    /// however.
+    pub fn instantiate_poly_trait_ref(
+        &self,
+        poly_trait_ref: &hir::PolyTraitRef<'_>,
+        constness: Constness,
+        self_ty: Ty<'tcx>,
+        bounds: &mut Bounds<'tcx>,
+    ) -> GenericArgCountResult {
+        self.instantiate_poly_trait_ref_inner(
+            &poly_trait_ref.trait_ref,
+            poly_trait_ref.span,
+            constness,
+            self_ty,
+            bounds,
+            false,
+        )
+    }
+
+    pub fn instantiate_lang_item_trait_ref(
+        &self,
+        lang_item: hir::LangItem,
+        span: Span,
+        hir_id: hir::HirId,
+        args: &GenericArgs<'_>,
+        self_ty: Ty<'tcx>,
+        bounds: &mut Bounds<'tcx>,
+    ) {
+        let trait_def_id = self.tcx().require_lang_item(lang_item, Some(span));
+
+        let (substs, assoc_bindings, _) =
+            self.create_substs_for_ast_path(span, trait_def_id, &[], args, false, Some(self_ty));
+        let poly_trait_ref = ty::Binder::bind(ty::TraitRef::new(trait_def_id, substs));
+        bounds.trait_bounds.push((poly_trait_ref, span, Constness::NotConst));
+
+        let mut dup_bindings = FxHashMap::default();
+        for binding in assoc_bindings {
+            let _: Result<_, ErrorReported> = self.add_predicates_for_ast_type_binding(
+                hir_id,
+                poly_trait_ref,
+                &binding,
+                bounds,
+                false,
+                &mut dup_bindings,
+                span,
+            );
+        }
+    }
+
+    fn ast_path_to_mono_trait_ref(
+        &self,
+        span: Span,
+        trait_def_id: DefId,
+        self_ty: Ty<'tcx>,
+        trait_segment: &hir::PathSegment<'_>,
+    ) -> ty::TraitRef<'tcx> {
+        let (substs, assoc_bindings, _) =
+            self.create_substs_for_ast_trait_ref(span, trait_def_id, self_ty, trait_segment);
+        if let Some(b) = assoc_bindings.first() {
+            Self::prohibit_assoc_ty_binding(self.tcx(), b.span);
+        }
+        ty::TraitRef::new(trait_def_id, substs)
+    }
+
+    fn create_substs_for_ast_trait_ref<'a>(
+        &self,
+        span: Span,
+        trait_def_id: DefId,
+        self_ty: Ty<'tcx>,
+        trait_segment: &'a hir::PathSegment<'a>,
+    ) -> (SubstsRef<'tcx>, Vec<ConvertedBinding<'a, 'tcx>>, GenericArgCountResult) {
+        debug!("create_substs_for_ast_trait_ref(trait_segment={:?})", trait_segment);
+
+        self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment);
+
+        self.create_substs_for_ast_path(
+            span,
+            trait_def_id,
+            &[],
+            trait_segment.generic_args(),
+            trait_segment.infer_args,
+            Some(self_ty),
+        )
+    }
+
+    fn trait_defines_associated_type_named(&self, trait_def_id: DefId, assoc_name: Ident) -> bool {
+        self.tcx()
+            .associated_items(trait_def_id)
+            .find_by_name_and_kind(self.tcx(), assoc_name, ty::AssocKind::Type, trait_def_id)
+            .is_some()
+    }
+
+    // Returns `true` if a bounds list includes `?Sized`.
+    pub fn is_unsized(&self, ast_bounds: &[hir::GenericBound<'_>], span: Span) -> bool {
+        let tcx = self.tcx();
+
+        // Try to find an unbound in bounds.
+        let mut unbound = None;
+        for ab in ast_bounds {
+            if let &hir::GenericBound::Trait(ref ptr, hir::TraitBoundModifier::Maybe) = ab {
+                if unbound.is_none() {
+                    unbound = Some(&ptr.trait_ref);
+                } else {
+                    struct_span_err!(
+                        tcx.sess,
+                        span,
+                        E0203,
+                        "type parameter has more than one relaxed default \
+                        bound, only one is supported"
+                    )
+                    .emit();
+                }
+            }
+        }
+
+        let kind_id = tcx.lang_items().require(LangItem::Sized);
+        match unbound {
+            Some(tpb) => {
+                // FIXME(#8559) currently requires the unbound to be built-in.
+                if let Ok(kind_id) = kind_id {
+                    if tpb.path.res != Res::Def(DefKind::Trait, kind_id) {
+                        tcx.sess.span_warn(
+                            span,
+                            "default bound relaxed for a type parameter, but \
+                             this does nothing because the given bound is not \
+                             a default; only `?Sized` is supported",
+                        );
+                    }
+                }
+            }
+            _ if kind_id.is_ok() => {
+                return false;
+            }
+            // No lang item for `Sized`, so we can't add it as a bound.
+            None => {}
+        }
+
+        true
+    }
+
+    /// This helper takes a *converted* parameter type (`param_ty`)
+    /// and an *unconverted* list of bounds:
+    ///
+    /// ```text
+    /// fn foo<T: Debug>
+    ///        ^  ^^^^^ `ast_bounds` parameter, in HIR form
+    ///        |
+    ///        `param_ty`, in ty form
+    /// ```
+    ///
+    /// It adds these `ast_bounds` into the `bounds` structure.
+    ///
+    /// **A note on binders:** there is an implied binder around
+    /// `param_ty` and `ast_bounds`. See `instantiate_poly_trait_ref`
+    /// for more details.
+    fn add_bounds(
+        &self,
+        param_ty: Ty<'tcx>,
+        ast_bounds: &[hir::GenericBound<'_>],
+        bounds: &mut Bounds<'tcx>,
+    ) {
+        let mut trait_bounds = Vec::new();
+        let mut region_bounds = Vec::new();
+
+        let constness = self.default_constness_for_trait_bounds();
+        for ast_bound in ast_bounds {
+            match *ast_bound {
+                hir::GenericBound::Trait(ref b, hir::TraitBoundModifier::None) => {
+                    trait_bounds.push((b, constness))
+                }
+                hir::GenericBound::Trait(ref b, hir::TraitBoundModifier::MaybeConst) => {
+                    trait_bounds.push((b, Constness::NotConst))
+                }
+                hir::GenericBound::Trait(_, hir::TraitBoundModifier::Maybe) => {}
+                hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => self
+                    .instantiate_lang_item_trait_ref(
+                        lang_item, span, hir_id, args, param_ty, bounds,
+                    ),
+                hir::GenericBound::Outlives(ref l) => region_bounds.push(l),
+            }
+        }
+
+        for (bound, constness) in trait_bounds {
+            let _ = self.instantiate_poly_trait_ref(bound, constness, param_ty, bounds);
+        }
+
+        bounds.region_bounds.extend(
+            region_bounds.into_iter().map(|r| (self.ast_region_to_region(r, None), r.span)),
+        );
+    }
+
+    /// Translates a list of bounds from the HIR into the `Bounds` data structure.
+    /// The self-type for the bounds is given by `param_ty`.
+    ///
+    /// Example:
+    ///
+    /// ```
+    /// fn foo<T: Bar + Baz>() { }
+    ///        ^  ^^^^^^^^^ ast_bounds
+    ///        param_ty
+    /// ```
+    ///
+    /// The `sized_by_default` parameter indicates if, in this context, the `param_ty` should be
+    /// considered `Sized` unless there is an explicit `?Sized` bound.  This would be true in the
+    /// example above, but is not true in supertrait listings like `trait Foo: Bar + Baz`.
+    ///
+    /// `span` should be the declaration size of the parameter.
+    pub fn compute_bounds(
+        &self,
+        param_ty: Ty<'tcx>,
+        ast_bounds: &[hir::GenericBound<'_>],
+        sized_by_default: SizedByDefault,
+        span: Span,
+    ) -> Bounds<'tcx> {
+        let mut bounds = Bounds::default();
+
+        self.add_bounds(param_ty, ast_bounds, &mut bounds);
+        bounds.trait_bounds.sort_by_key(|(t, _, _)| t.def_id());
+
+        bounds.implicitly_sized = if let SizedByDefault::Yes = sized_by_default {
+            if !self.is_unsized(ast_bounds, span) { Some(span) } else { None }
+        } else {
+            None
+        };
+
+        bounds
+    }
+
+    /// Given an HIR binding like `Item = Foo` or `Item: Foo`, pushes the corresponding predicates
+    /// onto `bounds`.
+    ///
+    /// **A note on binders:** given something like `T: for<'a> Iterator<Item = &'a u32>`, the
+    /// `trait_ref` here will be `for<'a> T: Iterator`. The `binding` data however is from *inside*
+    /// the binder (e.g., `&'a u32`) and hence may reference bound regions.
+    fn add_predicates_for_ast_type_binding(
+        &self,
+        hir_ref_id: hir::HirId,
+        trait_ref: ty::PolyTraitRef<'tcx>,
+        binding: &ConvertedBinding<'_, 'tcx>,
+        bounds: &mut Bounds<'tcx>,
+        speculative: bool,
+        dup_bindings: &mut FxHashMap<DefId, Span>,
+        path_span: Span,
+    ) -> Result<(), ErrorReported> {
+        let tcx = self.tcx();
+
+        if !speculative {
+            // Given something like `U: SomeTrait<T = X>`, we want to produce a
+            // predicate like `<U as SomeTrait>::T = X`. This is somewhat
+            // subtle in the event that `T` is defined in a supertrait of
+            // `SomeTrait`, because in that case we need to upcast.
+            //
+            // That is, consider this case:
+            //
+            // ```
+            // trait SubTrait: SuperTrait<i32> { }
+            // trait SuperTrait<A> { type T; }
+            //
+            // ... B: SubTrait<T = foo> ...
+            // ```
+            //
+            // We want to produce `<B as SuperTrait<i32>>::T == foo`.
+
+            // Find any late-bound regions declared in `ty` that are not
+            // declared in the trait-ref. These are not well-formed.
+            //
+            // Example:
+            //
+            //     for<'a> <T as Iterator>::Item = &'a str // <-- 'a is bad
+            //     for<'a> <T as FnMut<(&'a u32,)>>::Output = &'a str // <-- 'a is ok
+            if let ConvertedBindingKind::Equality(ty) = binding.kind {
+                let late_bound_in_trait_ref =
+                    tcx.collect_constrained_late_bound_regions(&trait_ref);
+                let late_bound_in_ty =
+                    tcx.collect_referenced_late_bound_regions(&ty::Binder::bind(ty));
+                debug!("late_bound_in_trait_ref = {:?}", late_bound_in_trait_ref);
+                debug!("late_bound_in_ty = {:?}", late_bound_in_ty);
+
+                // FIXME: point at the type params that don't have appropriate lifetimes:
+                // struct S1<F: for<'a> Fn(&i32, &i32) -> &'a i32>(F);
+                //                         ----  ----     ^^^^^^^
+                self.validate_late_bound_regions(
+                    late_bound_in_trait_ref,
+                    late_bound_in_ty,
+                    |br_name| {
+                        struct_span_err!(
+                            tcx.sess,
+                            binding.span,
+                            E0582,
+                            "binding for associated type `{}` references {}, \
+                             which does not appear in the trait input types",
+                            binding.item_name,
+                            br_name
+                        )
+                    },
+                );
+            }
+        }
+
+        let candidate =
+            if self.trait_defines_associated_type_named(trait_ref.def_id(), binding.item_name) {
+                // Simple case: X is defined in the current trait.
+                trait_ref
+            } else {
+                // Otherwise, we have to walk through the supertraits to find
+                // those that do.
+                self.one_bound_for_assoc_type(
+                    || traits::supertraits(tcx, trait_ref),
+                    || trait_ref.print_only_trait_path().to_string(),
+                    binding.item_name,
+                    path_span,
+                    || match binding.kind {
+                        ConvertedBindingKind::Equality(ty) => Some(ty.to_string()),
+                        _ => None,
+                    },
+                )?
+            };
+
+        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.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.normalize_to_macros_2_0() == assoc_ident
+            })
+            .expect("missing associated type");
+
+        if !assoc_ty.vis.is_accessible_from(def_scope, tcx) {
+            tcx.sess
+                .struct_span_err(
+                    binding.span,
+                    &format!("associated type `{}` is private", binding.item_name),
+                )
+                .span_label(binding.span, "private associated type")
+                .emit();
+        }
+        tcx.check_stability(assoc_ty.def_id, Some(hir_ref_id), binding.span);
+
+        if !speculative {
+            dup_bindings
+                .entry(assoc_ty.def_id)
+                .and_modify(|prev_span| {
+                    struct_span_err!(
+                        self.tcx().sess,
+                        binding.span,
+                        E0719,
+                        "the value of the associated type `{}` (from trait `{}`) \
+                         is already specified",
+                        binding.item_name,
+                        tcx.def_path_str(assoc_ty.container.id())
+                    )
+                    .span_label(binding.span, "re-bound here")
+                    .span_label(*prev_span, format!("`{}` bound here first", binding.item_name))
+                    .emit();
+                })
+                .or_insert(binding.span);
+        }
+
+        match binding.kind {
+            ConvertedBindingKind::Equality(ref ty) => {
+                // "Desugar" a constraint like `T: Iterator<Item = u32>` this to
+                // the "projection predicate" for:
+                //
+                // `<T as Iterator>::Item = u32`
+                bounds.projection_bounds.push((
+                    candidate.map_bound(|trait_ref| ty::ProjectionPredicate {
+                        projection_ty: ty::ProjectionTy::from_ref_and_name(
+                            tcx,
+                            trait_ref,
+                            binding.item_name,
+                        ),
+                        ty,
+                    }),
+                    binding.span,
+                ));
+            }
+            ConvertedBindingKind::Constraint(ast_bounds) => {
+                // "Desugar" a constraint like `T: Iterator<Item: Debug>` to
+                //
+                // `<T as Iterator>::Item: Debug`
+                //
+                // Calling `skip_binder` is okay, because `add_bounds` expects the `param_ty`
+                // parameter to have a skipped binder.
+                let param_ty = tcx.mk_projection(assoc_ty.def_id, candidate.skip_binder().substs);
+                self.add_bounds(param_ty, ast_bounds, bounds);
+            }
+        }
+        Ok(())
+    }
+
+    fn ast_path_to_ty(
+        &self,
+        span: Span,
+        did: DefId,
+        item_segment: &hir::PathSegment<'_>,
+    ) -> Ty<'tcx> {
+        let substs = self.ast_path_substs_for_ty(span, did, item_segment);
+        self.normalize_ty(span, self.tcx().at(span).type_of(did).subst(self.tcx(), substs))
+    }
+
+    fn conv_object_ty_poly_trait_ref(
+        &self,
+        span: Span,
+        trait_bounds: &[hir::PolyTraitRef<'_>],
+        lifetime: &hir::Lifetime,
+        borrowed: bool,
+    ) -> Ty<'tcx> {
+        let tcx = self.tcx();
+
+        let mut bounds = Bounds::default();
+        let mut potential_assoc_types = Vec::new();
+        let dummy_self = self.tcx().types.trait_object_dummy_self;
+        for trait_bound in trait_bounds.iter().rev() {
+            if let GenericArgCountResult {
+                correct:
+                    Err(GenericArgCountMismatch { invalid_args: cur_potential_assoc_types, .. }),
+                ..
+            } = self.instantiate_poly_trait_ref(
+                trait_bound,
+                Constness::NotConst,
+                dummy_self,
+                &mut bounds,
+            ) {
+                potential_assoc_types.extend(cur_potential_assoc_types.into_iter());
+            }
+        }
+
+        // Expand trait aliases recursively and check that only one regular (non-auto) trait
+        // is used and no 'maybe' bounds are used.
+        let expanded_traits =
+            traits::expand_trait_aliases(tcx, bounds.trait_bounds.iter().map(|&(a, b, _)| (a, b)));
+        let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) =
+            expanded_traits.partition(|i| tcx.trait_is_auto(i.trait_ref().def_id()));
+        if regular_traits.len() > 1 {
+            let first_trait = &regular_traits[0];
+            let additional_trait = &regular_traits[1];
+            let mut err = struct_span_err!(
+                tcx.sess,
+                additional_trait.bottom().1,
+                E0225,
+                "only auto traits can be used as additional traits in a trait object"
+            );
+            additional_trait.label_with_exp_info(
+                &mut err,
+                "additional non-auto trait",
+                "additional use",
+            );
+            first_trait.label_with_exp_info(&mut err, "first non-auto trait", "first use");
+            err.help(&format!(
+                "consider creating a new trait with all of these as super-traits and using that \
+                 trait here instead: `trait NewTrait: {} {{}}`",
+                regular_traits
+                    .iter()
+                    .map(|t| t.trait_ref().print_only_trait_path().to_string())
+                    .collect::<Vec<_>>()
+                    .join(" + "),
+            ));
+            err.note(
+                "auto-traits like `Send` and `Sync` are traits that have special properties; \
+                 for more information on them, visit \
+                 <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>",
+            );
+            err.emit();
+        }
+
+        if regular_traits.is_empty() && auto_traits.is_empty() {
+            struct_span_err!(
+                tcx.sess,
+                span,
+                E0224,
+                "at least one trait is required for an object type"
+            )
+            .emit();
+            return tcx.ty_error();
+        }
+
+        // Check that there are no gross object safety violations;
+        // most importantly, that the supertraits don't contain `Self`,
+        // to avoid ICEs.
+        for item in &regular_traits {
+            let object_safety_violations =
+                astconv_object_safety_violations(tcx, item.trait_ref().def_id());
+            if !object_safety_violations.is_empty() {
+                report_object_safety_error(
+                    tcx,
+                    span,
+                    item.trait_ref().def_id(),
+                    &object_safety_violations[..],
+                )
+                .emit();
+                return tcx.ty_error();
+            }
+        }
+
+        // Use a `BTreeSet` to keep output in a more consistent order.
+        let mut associated_types: FxHashMap<Span, BTreeSet<DefId>> = FxHashMap::default();
+
+        let regular_traits_refs_spans = bounds
+            .trait_bounds
+            .into_iter()
+            .filter(|(trait_ref, _, _)| !tcx.trait_is_auto(trait_ref.def_id()));
+
+        for (base_trait_ref, span, constness) in regular_traits_refs_spans {
+            assert_eq!(constness, Constness::NotConst);
+
+            for obligation in traits::elaborate_trait_ref(tcx, base_trait_ref) {
+                debug!(
+                    "conv_object_ty_poly_trait_ref: observing object predicate `{:?}`",
+                    obligation.predicate
+                );
+
+                match obligation.predicate.skip_binders() {
+                    ty::PredicateAtom::Trait(pred, _) => {
+                        let pred = ty::Binder::bind(pred);
+                        associated_types.entry(span).or_default().extend(
+                            tcx.associated_items(pred.def_id())
+                                .in_definition_order()
+                                .filter(|item| item.kind == ty::AssocKind::Type)
+                                .map(|item| item.def_id),
+                        );
+                    }
+                    ty::PredicateAtom::Projection(pred) => {
+                        let pred = ty::Binder::bind(pred);
+                        // A `Self` within the original bound will be substituted with a
+                        // `trait_object_dummy_self`, so check for that.
+                        let references_self =
+                            pred.skip_binder().ty.walk().any(|arg| arg == dummy_self.into());
+
+                        // If the projection output contains `Self`, force the user to
+                        // elaborate it explicitly to avoid a lot of complexity.
+                        //
+                        // The "classicaly useful" case is the following:
+                        // ```
+                        //     trait MyTrait: FnMut() -> <Self as MyTrait>::MyOutput {
+                        //         type MyOutput;
+                        //     }
+                        // ```
+                        //
+                        // Here, the user could theoretically write `dyn MyTrait<Output = X>`,
+                        // but actually supporting that would "expand" to an infinitely-long type
+                        // `fix $ Ï„ â†’ dyn MyTrait<MyOutput = X, Output = <Ï„ as MyTrait>::MyOutput`.
+                        //
+                        // Instead, we force the user to write
+                        // `dyn MyTrait<MyOutput = X, Output = X>`, which is uglier but works. See
+                        // the discussion in #56288 for alternatives.
+                        if !references_self {
+                            // Include projections defined on supertraits.
+                            bounds.projection_bounds.push((pred, span));
+                        }
+                    }
+                    _ => (),
+                }
+            }
+        }
+
+        for (projection_bound, _) in &bounds.projection_bounds {
+            for def_ids in associated_types.values_mut() {
+                def_ids.remove(&projection_bound.projection_def_id());
+            }
+        }
+
+        self.complain_about_missing_associated_types(
+            associated_types,
+            potential_assoc_types,
+            trait_bounds,
+        );
+
+        // De-duplicate auto traits so that, e.g., `dyn Trait + Send + Send` is the same as
+        // `dyn Trait + Send`.
+        auto_traits.sort_by_key(|i| i.trait_ref().def_id());
+        auto_traits.dedup_by_key(|i| i.trait_ref().def_id());
+        debug!("regular_traits: {:?}", regular_traits);
+        debug!("auto_traits: {:?}", auto_traits);
+
+        // Transform a `PolyTraitRef` into a `PolyExistentialTraitRef` by
+        // removing the dummy `Self` type (`trait_object_dummy_self`).
+        let trait_ref_to_existential = |trait_ref: ty::TraitRef<'tcx>| {
+            if trait_ref.self_ty() != dummy_self {
+                // FIXME: There appears to be a missing filter on top of `expand_trait_aliases`,
+                // which picks up non-supertraits where clauses - but also, the object safety
+                // completely ignores trait aliases, which could be object safety hazards. We
+                // `delay_span_bug` here to avoid an ICE in stable even when the feature is
+                // disabled. (#66420)
+                tcx.sess.delay_span_bug(
+                    DUMMY_SP,
+                    &format!(
+                        "trait_ref_to_existential called on {:?} with non-dummy Self",
+                        trait_ref,
+                    ),
+                );
+            }
+            ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref)
+        };
+
+        // Erase the `dummy_self` (`trait_object_dummy_self`) used above.
+        let existential_trait_refs =
+            regular_traits.iter().map(|i| i.trait_ref().map_bound(trait_ref_to_existential));
+        let existential_projections = bounds.projection_bounds.iter().map(|(bound, _)| {
+            bound.map_bound(|b| {
+                let trait_ref = trait_ref_to_existential(b.projection_ty.trait_ref(tcx));
+                ty::ExistentialProjection {
+                    ty: b.ty,
+                    item_def_id: b.projection_ty.item_def_id,
+                    substs: trait_ref.substs,
+                }
+            })
+        });
+
+        // Calling `skip_binder` is okay because the predicates are re-bound.
+        let regular_trait_predicates = existential_trait_refs
+            .map(|trait_ref| ty::ExistentialPredicate::Trait(trait_ref.skip_binder()));
+        let auto_trait_predicates = auto_traits
+            .into_iter()
+            .map(|trait_ref| ty::ExistentialPredicate::AutoTrait(trait_ref.trait_ref().def_id()));
+        let mut v = regular_trait_predicates
+            .chain(auto_trait_predicates)
+            .chain(
+                existential_projections
+                    .map(|x| ty::ExistentialPredicate::Projection(x.skip_binder())),
+            )
+            .collect::<SmallVec<[_; 8]>>();
+        v.sort_by(|a, b| a.stable_cmp(tcx, b));
+        v.dedup();
+        let existential_predicates = ty::Binder::bind(tcx.mk_existential_predicates(v.into_iter()));
+
+        // Use explicitly-specified region bound.
+        let region_bound = if !lifetime.is_elided() {
+            self.ast_region_to_region(lifetime, None)
+        } else {
+            self.compute_object_lifetime_bound(span, existential_predicates).unwrap_or_else(|| {
+                if tcx.named_region(lifetime.hir_id).is_some() {
+                    self.ast_region_to_region(lifetime, None)
+                } else {
+                    self.re_infer(None, span).unwrap_or_else(|| {
+                        let mut err = struct_span_err!(
+                            tcx.sess,
+                            span,
+                            E0228,
+                            "the lifetime bound for this object type cannot be deduced \
+                             from context; please supply an explicit bound"
+                        );
+                        if borrowed {
+                            // We will have already emitted an error E0106 complaining about a
+                            // missing named lifetime in `&dyn Trait`, so we elide this one.
+                            err.delay_as_bug();
+                        } else {
+                            err.emit();
+                        }
+                        tcx.lifetimes.re_static
+                    })
+                }
+            })
+        };
+        debug!("region_bound: {:?}", region_bound);
+
+        let ty = tcx.mk_dynamic(existential_predicates, region_bound);
+        debug!("trait_object_type: {:?}", ty);
+        ty
+    }
+
+    fn report_ambiguous_associated_type(
+        &self,
+        span: Span,
+        type_str: &str,
+        trait_str: &str,
+        name: Symbol,
+    ) {
+        let mut err = struct_span_err!(self.tcx().sess, span, E0223, "ambiguous associated type");
+        if let (Some(_), Ok(snippet)) = (
+            self.tcx().sess.confused_type_with_std_module.borrow().get(&span),
+            self.tcx().sess.source_map().span_to_snippet(span),
+        ) {
+            err.span_suggestion(
+                span,
+                "you are looking for the module in `std`, not the primitive type",
+                format!("std::{}", snippet),
+                Applicability::MachineApplicable,
+            );
+        } else {
+            err.span_suggestion(
+                span,
+                "use fully-qualified syntax",
+                format!("<{} as {}>::{}", type_str, trait_str, name),
+                Applicability::HasPlaceholders,
+            );
+        }
+        err.emit();
+    }
+
+    // Search for a bound on a type parameter which includes the associated item
+    // given by `assoc_name`. `ty_param_def_id` is the `DefId` of the type parameter
+    // This function will fail if there are no suitable bounds or there is
+    // any ambiguity.
+    fn find_bound_for_assoc_item(
+        &self,
+        ty_param_def_id: LocalDefId,
+        assoc_name: Ident,
+        span: Span,
+    ) -> Result<ty::PolyTraitRef<'tcx>, ErrorReported> {
+        let tcx = self.tcx();
+
+        debug!(
+            "find_bound_for_assoc_item(ty_param_def_id={:?}, assoc_name={:?}, span={:?})",
+            ty_param_def_id, assoc_name, span,
+        );
+
+        let predicates =
+            &self.get_type_parameter_bounds(span, ty_param_def_id.to_def_id()).predicates;
+
+        debug!("find_bound_for_assoc_item: predicates={:#?}", predicates);
+
+        let param_hir_id = tcx.hir().local_def_id_to_hir_id(ty_param_def_id);
+        let param_name = tcx.hir().ty_param_name(param_hir_id);
+        self.one_bound_for_assoc_type(
+            || {
+                traits::transitive_bounds(
+                    tcx,
+                    predicates.iter().filter_map(|(p, _)| p.to_opt_poly_trait_ref()),
+                )
+            },
+            || param_name.to_string(),
+            assoc_name,
+            span,
+            || None,
+        )
+    }
+
+    // Checks that `bounds` contains exactly one element and reports appropriate
+    // errors otherwise.
+    fn one_bound_for_assoc_type<I>(
+        &self,
+        all_candidates: impl Fn() -> I,
+        ty_param_name: impl Fn() -> String,
+        assoc_name: Ident,
+        span: Span,
+        is_equality: impl Fn() -> Option<String>,
+    ) -> Result<ty::PolyTraitRef<'tcx>, ErrorReported>
+    where
+        I: Iterator<Item = ty::PolyTraitRef<'tcx>>,
+    {
+        let mut matching_candidates = all_candidates()
+            .filter(|r| self.trait_defines_associated_type_named(r.def_id(), assoc_name));
+
+        let bound = match matching_candidates.next() {
+            Some(bound) => bound,
+            None => {
+                self.complain_about_assoc_type_not_found(
+                    all_candidates,
+                    &ty_param_name(),
+                    assoc_name,
+                    span,
+                );
+                return Err(ErrorReported);
+            }
+        };
+
+        debug!("one_bound_for_assoc_type: bound = {:?}", bound);
+
+        if let Some(bound2) = matching_candidates.next() {
+            debug!("one_bound_for_assoc_type: bound2 = {:?}", bound2);
+
+            let is_equality = is_equality();
+            let bounds = iter::once(bound).chain(iter::once(bound2)).chain(matching_candidates);
+            let mut err = if is_equality.is_some() {
+                // More specific Error Index entry.
+                struct_span_err!(
+                    self.tcx().sess,
+                    span,
+                    E0222,
+                    "ambiguous associated type `{}` in bounds of `{}`",
+                    assoc_name,
+                    ty_param_name()
+                )
+            } else {
+                struct_span_err!(
+                    self.tcx().sess,
+                    span,
+                    E0221,
+                    "ambiguous associated type `{}` in bounds of `{}`",
+                    assoc_name,
+                    ty_param_name()
+                )
+            };
+            err.span_label(span, format!("ambiguous associated type `{}`", assoc_name));
+
+            let mut where_bounds = vec![];
+            for bound in bounds {
+                let bound_id = bound.def_id();
+                let bound_span = self
+                    .tcx()
+                    .associated_items(bound_id)
+                    .find_by_name_and_kind(self.tcx(), assoc_name, ty::AssocKind::Type, bound_id)
+                    .and_then(|item| self.tcx().hir().span_if_local(item.def_id));
+
+                if let Some(bound_span) = bound_span {
+                    err.span_label(
+                        bound_span,
+                        format!(
+                            "ambiguous `{}` from `{}`",
+                            assoc_name,
+                            bound.print_only_trait_path(),
+                        ),
+                    );
+                    if let Some(constraint) = &is_equality {
+                        where_bounds.push(format!(
+                            "        T: {trait}::{assoc} = {constraint}",
+                            trait=bound.print_only_trait_path(),
+                            assoc=assoc_name,
+                            constraint=constraint,
+                        ));
+                    } else {
+                        err.span_suggestion(
+                            span,
+                            "use fully qualified syntax to disambiguate",
+                            format!(
+                                "<{} as {}>::{}",
+                                ty_param_name(),
+                                bound.print_only_trait_path(),
+                                assoc_name,
+                            ),
+                            Applicability::MaybeIncorrect,
+                        );
+                    }
+                } else {
+                    err.note(&format!(
+                        "associated type `{}` could derive from `{}`",
+                        ty_param_name(),
+                        bound.print_only_trait_path(),
+                    ));
+                }
+            }
+            if !where_bounds.is_empty() {
+                err.help(&format!(
+                    "consider introducing a new type parameter `T` and adding `where` constraints:\
+                     \n    where\n        T: {},\n{}",
+                    ty_param_name(),
+                    where_bounds.join(",\n"),
+                ));
+            }
+            err.emit();
+            if !where_bounds.is_empty() {
+                return Err(ErrorReported);
+            }
+        }
+        Ok(bound)
+    }
+
+    // Create a type from a path to an associated type.
+    // For a path `A::B::C::D`, `qself_ty` and `qself_def` are the type and def for `A::B::C`
+    // and item_segment is the path segment for `D`. We return a type and a def for
+    // the whole path.
+    // Will fail except for `T::A` and `Self::A`; i.e., if `qself_ty`/`qself_def` are not a type
+    // parameter or `Self`.
+    pub fn associated_path_to_ty(
+        &self,
+        hir_ref_id: hir::HirId,
+        span: Span,
+        qself_ty: Ty<'tcx>,
+        qself_res: Res,
+        assoc_segment: &hir::PathSegment<'_>,
+        permit_variants: bool,
+    ) -> Result<(Ty<'tcx>, DefKind, DefId), ErrorReported> {
+        let tcx = self.tcx();
+        let assoc_ident = assoc_segment.ident;
+
+        debug!("associated_path_to_ty: {:?}::{}", qself_ty, assoc_ident);
+
+        // Check if we have an enum variant.
+        let mut variant_resolution = None;
+        if let ty::Adt(adt_def, _) = qself_ty.kind {
+            if adt_def.is_enum() {
+                let variant_def = adt_def
+                    .variants
+                    .iter()
+                    .find(|vd| tcx.hygienic_eq(assoc_ident, vd.ident, adt_def.did));
+                if let Some(variant_def) = variant_def {
+                    if permit_variants {
+                        tcx.check_stability(variant_def.def_id, Some(hir_ref_id), span);
+                        self.prohibit_generics(slice::from_ref(assoc_segment));
+                        return Ok((qself_ty, DefKind::Variant, variant_def.def_id));
+                    } else {
+                        variant_resolution = Some(variant_def.def_id);
+                    }
+                }
+            }
+        }
+
+        // Find the type of the associated item, and the trait where the associated
+        // item is declared.
+        let bound = match (&qself_ty.kind, qself_res) {
+            (_, Res::SelfTy(Some(_), Some(impl_def_id))) => {
+                // `Self` in an impl of a trait -- we have a concrete self type and a
+                // trait reference.
+                let trait_ref = match tcx.impl_trait_ref(impl_def_id) {
+                    Some(trait_ref) => trait_ref,
+                    None => {
+                        // A cycle error occurred, most likely.
+                        return Err(ErrorReported);
+                    }
+                };
+
+                self.one_bound_for_assoc_type(
+                    || traits::supertraits(tcx, ty::Binder::bind(trait_ref)),
+                    || "Self".to_string(),
+                    assoc_ident,
+                    span,
+                    || None,
+                )?
+            }
+            (
+                &ty::Param(_),
+                Res::SelfTy(Some(param_did), None) | Res::Def(DefKind::TyParam, param_did),
+            ) => self.find_bound_for_assoc_item(param_did.expect_local(), assoc_ident, span)?,
+            _ => {
+                if variant_resolution.is_some() {
+                    // Variant in type position
+                    let msg = format!("expected type, found variant `{}`", assoc_ident);
+                    tcx.sess.span_err(span, &msg);
+                } else if qself_ty.is_enum() {
+                    let mut err = struct_span_err!(
+                        tcx.sess,
+                        assoc_ident.span,
+                        E0599,
+                        "no variant named `{}` found for enum `{}`",
+                        assoc_ident,
+                        qself_ty,
+                    );
+
+                    let adt_def = qself_ty.ty_adt_def().expect("enum is not an ADT");
+                    if let Some(suggested_name) = find_best_match_for_name(
+                        adt_def.variants.iter().map(|variant| &variant.ident.name),
+                        assoc_ident.name,
+                        None,
+                    ) {
+                        err.span_suggestion(
+                            assoc_ident.span,
+                            "there is a variant with a similar name",
+                            suggested_name.to_string(),
+                            Applicability::MaybeIncorrect,
+                        );
+                    } else {
+                        err.span_label(
+                            assoc_ident.span,
+                            format!("variant not found in `{}`", qself_ty),
+                        );
+                    }
+
+                    if let Some(sp) = tcx.hir().span_if_local(adt_def.did) {
+                        let sp = tcx.sess.source_map().guess_head_span(sp);
+                        err.span_label(sp, format!("variant `{}` not found here", assoc_ident));
+                    }
+
+                    err.emit();
+                } else if !qself_ty.references_error() {
+                    // Don't print `TyErr` to the user.
+                    self.report_ambiguous_associated_type(
+                        span,
+                        &qself_ty.to_string(),
+                        "Trait",
+                        assoc_ident.name,
+                    );
+                }
+                return Err(ErrorReported);
+            }
+        };
+
+        let trait_did = bound.def_id();
+        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.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.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);
+        let ty = self.normalize_ty(span, ty);
+
+        let kind = DefKind::AssocTy;
+        if !item.vis.is_accessible_from(def_scope, tcx) {
+            let kind = kind.descr(item.def_id);
+            let msg = format!("{} `{}` is private", kind, assoc_ident);
+            tcx.sess
+                .struct_span_err(span, &msg)
+                .span_label(span, &format!("private {}", kind))
+                .emit();
+        }
+        tcx.check_stability(item.def_id, Some(hir_ref_id), span);
+
+        if let Some(variant_def_id) = variant_resolution {
+            tcx.struct_span_lint_hir(AMBIGUOUS_ASSOCIATED_ITEMS, hir_ref_id, span, |lint| {
+                let mut err = lint.build("ambiguous associated item");
+                let mut could_refer_to = |kind: DefKind, def_id, also| {
+                    let note_msg = format!(
+                        "`{}` could{} refer to the {} defined here",
+                        assoc_ident,
+                        also,
+                        kind.descr(def_id)
+                    );
+                    err.span_note(tcx.def_span(def_id), &note_msg);
+                };
+
+                could_refer_to(DefKind::Variant, variant_def_id, "");
+                could_refer_to(kind, item.def_id, " also");
+
+                err.span_suggestion(
+                    span,
+                    "use fully-qualified syntax",
+                    format!("<{} as {}>::{}", qself_ty, tcx.item_name(trait_did), assoc_ident),
+                    Applicability::MachineApplicable,
+                );
+
+                err.emit();
+            });
+        }
+        Ok((ty, kind, item.def_id))
+    }
+
+    fn qpath_to_ty(
+        &self,
+        span: Span,
+        opt_self_ty: Option<Ty<'tcx>>,
+        item_def_id: DefId,
+        trait_segment: &hir::PathSegment<'_>,
+        item_segment: &hir::PathSegment<'_>,
+    ) -> Ty<'tcx> {
+        let tcx = self.tcx();
+
+        let trait_def_id = tcx.parent(item_def_id).unwrap();
+
+        debug!("qpath_to_ty: trait_def_id={:?}", trait_def_id);
+
+        let self_ty = if let Some(ty) = opt_self_ty {
+            ty
+        } else {
+            let path_str = tcx.def_path_str(trait_def_id);
+
+            let def_id = self.item_def_id();
+
+            debug!("qpath_to_ty: self.item_def_id()={:?}", def_id);
+
+            let parent_def_id = def_id
+                .and_then(|def_id| {
+                    def_id.as_local().map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id))
+                })
+                .map(|hir_id| tcx.hir().get_parent_did(hir_id).to_def_id());
+
+            debug!("qpath_to_ty: parent_def_id={:?}", parent_def_id);
+
+            // If the trait in segment is the same as the trait defining the item,
+            // use the `<Self as ..>` syntax in the error.
+            let is_part_of_self_trait_constraints = def_id == Some(trait_def_id);
+            let is_part_of_fn_in_self_trait = parent_def_id == Some(trait_def_id);
+
+            let type_name = if is_part_of_self_trait_constraints || is_part_of_fn_in_self_trait {
+                "Self"
+            } else {
+                "Type"
+            };
+
+            self.report_ambiguous_associated_type(
+                span,
+                type_name,
+                &path_str,
+                item_segment.ident.name,
+            );
+            return tcx.ty_error();
+        };
+
+        debug!("qpath_to_ty: self_type={:?}", self_ty);
+
+        let trait_ref = self.ast_path_to_mono_trait_ref(span, trait_def_id, self_ty, trait_segment);
+
+        let item_substs = self.create_substs_for_associated_item(
+            tcx,
+            span,
+            item_def_id,
+            item_segment,
+            trait_ref.substs,
+        );
+
+        debug!("qpath_to_ty: trait_ref={:?}", trait_ref);
+
+        self.normalize_ty(span, tcx.mk_projection(item_def_id, item_substs))
+    }
+
+    pub fn prohibit_generics<'a, T: IntoIterator<Item = &'a hir::PathSegment<'a>>>(
+        &self,
+        segments: T,
+    ) -> bool {
+        let mut has_err = false;
+        for segment in segments {
+            let (mut err_for_lt, mut err_for_ty, mut err_for_ct) = (false, false, false);
+            for arg in segment.generic_args().args {
+                let (span, kind) = match arg {
+                    hir::GenericArg::Lifetime(lt) => {
+                        if err_for_lt {
+                            continue;
+                        }
+                        err_for_lt = true;
+                        has_err = true;
+                        (lt.span, "lifetime")
+                    }
+                    hir::GenericArg::Type(ty) => {
+                        if err_for_ty {
+                            continue;
+                        }
+                        err_for_ty = true;
+                        has_err = true;
+                        (ty.span, "type")
+                    }
+                    hir::GenericArg::Const(ct) => {
+                        if err_for_ct {
+                            continue;
+                        }
+                        err_for_ct = true;
+                        has_err = true;
+                        (ct.span, "const")
+                    }
+                };
+                let mut err = struct_span_err!(
+                    self.tcx().sess,
+                    span,
+                    E0109,
+                    "{} arguments are not allowed for this type",
+                    kind,
+                );
+                err.span_label(span, format!("{} argument not allowed", kind));
+                err.emit();
+                if err_for_lt && err_for_ty && err_for_ct {
+                    break;
+                }
+            }
+
+            // Only emit the first error to avoid overloading the user with error messages.
+            if let [binding, ..] = segment.generic_args().bindings {
+                has_err = true;
+                Self::prohibit_assoc_ty_binding(self.tcx(), binding.span);
+            }
+        }
+        has_err
+    }
+
+    // FIXME(eddyb, varkor) handle type paths here too, not just value ones.
+    pub fn def_ids_for_value_path_segments(
+        &self,
+        segments: &[hir::PathSegment<'_>],
+        self_ty: Option<Ty<'tcx>>,
+        kind: DefKind,
+        def_id: DefId,
+    ) -> Vec<PathSeg> {
+        // We need to extract the type parameters supplied by the user in
+        // the path `path`. Due to the current setup, this is a bit of a
+        // tricky-process; the problem is that resolve only tells us the
+        // end-point of the path resolution, and not the intermediate steps.
+        // Luckily, we can (at least for now) deduce the intermediate steps
+        // just from the end-point.
+        //
+        // There are basically five cases to consider:
+        //
+        // 1. Reference to a constructor of a struct:
+        //
+        //        struct Foo<T>(...)
+        //
+        //    In this case, the parameters are declared in the type space.
+        //
+        // 2. Reference to a constructor of an enum variant:
+        //
+        //        enum E<T> { Foo(...) }
+        //
+        //    In this case, the parameters are defined in the type space,
+        //    but may be specified either on the type or the variant.
+        //
+        // 3. Reference to a fn item or a free constant:
+        //
+        //        fn foo<T>() { }
+        //
+        //    In this case, the path will again always have the form
+        //    `a::b::foo::<T>` where only the final segment should have
+        //    type parameters. However, in this case, those parameters are
+        //    declared on a value, and hence are in the `FnSpace`.
+        //
+        // 4. Reference to a method or an associated constant:
+        //
+        //        impl<A> SomeStruct<A> {
+        //            fn foo<B>(...)
+        //        }
+        //
+        //    Here we can have a path like
+        //    `a::b::SomeStruct::<A>::foo::<B>`, in which case parameters
+        //    may appear in two places. The penultimate segment,
+        //    `SomeStruct::<A>`, contains parameters in TypeSpace, and the
+        //    final segment, `foo::<B>` contains parameters in fn space.
+        //
+        // The first step then is to categorize the segments appropriately.
+
+        let tcx = self.tcx();
+
+        assert!(!segments.is_empty());
+        let last = segments.len() - 1;
+
+        let mut path_segs = vec![];
+
+        match kind {
+            // Case 1. Reference to a struct constructor.
+            DefKind::Ctor(CtorOf::Struct, ..) => {
+                // Everything but the final segment should have no
+                // parameters at all.
+                let generics = tcx.generics_of(def_id);
+                // Variant and struct constructors use the
+                // generics of their parent type definition.
+                let generics_def_id = generics.parent.unwrap_or(def_id);
+                path_segs.push(PathSeg(generics_def_id, last));
+            }
+
+            // Case 2. Reference to a variant constructor.
+            DefKind::Ctor(CtorOf::Variant, ..) | DefKind::Variant => {
+                let adt_def = self_ty.map(|t| t.ty_adt_def().unwrap());
+                let (generics_def_id, index) = if let Some(adt_def) = adt_def {
+                    debug_assert!(adt_def.is_enum());
+                    (adt_def.did, last)
+                } else if last >= 1 && segments[last - 1].args.is_some() {
+                    // Everything but the penultimate segment should have no
+                    // parameters at all.
+                    let mut def_id = def_id;
+
+                    // `DefKind::Ctor` -> `DefKind::Variant`
+                    if let DefKind::Ctor(..) = kind {
+                        def_id = tcx.parent(def_id).unwrap()
+                    }
+
+                    // `DefKind::Variant` -> `DefKind::Enum`
+                    let enum_def_id = tcx.parent(def_id).unwrap();
+                    (enum_def_id, last - 1)
+                } else {
+                    // FIXME: lint here recommending `Enum::<...>::Variant` form
+                    // instead of `Enum::Variant::<...>` form.
+
+                    // Everything but the final segment should have no
+                    // parameters at all.
+                    let generics = tcx.generics_of(def_id);
+                    // Variant and struct constructors use the
+                    // generics of their parent type definition.
+                    (generics.parent.unwrap_or(def_id), last)
+                };
+                path_segs.push(PathSeg(generics_def_id, index));
+            }
+
+            // Case 3. Reference to a top-level value.
+            DefKind::Fn | DefKind::Const | DefKind::ConstParam | DefKind::Static => {
+                path_segs.push(PathSeg(def_id, last));
+            }
+
+            // Case 4. Reference to a method or associated const.
+            DefKind::AssocFn | DefKind::AssocConst => {
+                if segments.len() >= 2 {
+                    let generics = tcx.generics_of(def_id);
+                    path_segs.push(PathSeg(generics.parent.unwrap(), last - 1));
+                }
+                path_segs.push(PathSeg(def_id, last));
+            }
+
+            kind => bug!("unexpected definition kind {:?} for {:?}", kind, def_id),
+        }
+
+        debug!("path_segs = {:?}", path_segs);
+
+        path_segs
+    }
+
+    // Check a type `Path` and convert it to a `Ty`.
+    pub fn res_to_ty(
+        &self,
+        opt_self_ty: Option<Ty<'tcx>>,
+        path: &hir::Path<'_>,
+        permit_variants: bool,
+    ) -> Ty<'tcx> {
+        let tcx = self.tcx();
+
+        debug!(
+            "res_to_ty(res={:?}, opt_self_ty={:?}, path_segments={:?})",
+            path.res, opt_self_ty, path.segments
+        );
+
+        let span = path.span;
+        match path.res {
+            Res::Def(DefKind::OpaqueTy, did) => {
+                // Check for desugared `impl Trait`.
+                assert!(ty::is_impl_trait_defn(tcx, did).is_none());
+                let item_segment = path.segments.split_last().unwrap();
+                self.prohibit_generics(item_segment.1);
+                let substs = self.ast_path_substs_for_ty(span, did, item_segment.0);
+                self.normalize_ty(span, tcx.mk_opaque(did, substs))
+            }
+            Res::Def(
+                DefKind::Enum
+                | DefKind::TyAlias
+                | DefKind::Struct
+                | DefKind::Union
+                | DefKind::ForeignTy,
+                did,
+            ) => {
+                assert_eq!(opt_self_ty, None);
+                self.prohibit_generics(path.segments.split_last().unwrap().1);
+                self.ast_path_to_ty(span, did, path.segments.last().unwrap())
+            }
+            Res::Def(kind @ DefKind::Variant, def_id) if permit_variants => {
+                // Convert "variant type" as if it were a real type.
+                // The resulting `Ty` is type of the variant's enum for now.
+                assert_eq!(opt_self_ty, None);
+
+                let path_segs =
+                    self.def_ids_for_value_path_segments(&path.segments, None, kind, def_id);
+                let generic_segs: FxHashSet<_> =
+                    path_segs.iter().map(|PathSeg(_, index)| index).collect();
+                self.prohibit_generics(path.segments.iter().enumerate().filter_map(
+                    |(index, seg)| {
+                        if !generic_segs.contains(&index) { Some(seg) } else { None }
+                    },
+                ));
+
+                let PathSeg(def_id, index) = path_segs.last().unwrap();
+                self.ast_path_to_ty(span, *def_id, &path.segments[*index])
+            }
+            Res::Def(DefKind::TyParam, def_id) => {
+                assert_eq!(opt_self_ty, None);
+                self.prohibit_generics(path.segments);
+
+                let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
+                let item_id = tcx.hir().get_parent_node(hir_id);
+                let item_def_id = tcx.hir().local_def_id(item_id);
+                let generics = tcx.generics_of(item_def_id);
+                let index = generics.param_def_id_to_index[&def_id];
+                tcx.mk_ty_param(index, tcx.hir().name(hir_id))
+            }
+            Res::SelfTy(Some(_), None) => {
+                // `Self` in trait or type alias.
+                assert_eq!(opt_self_ty, None);
+                self.prohibit_generics(path.segments);
+                tcx.types.self_param
+            }
+            Res::SelfTy(_, Some(def_id)) => {
+                // `Self` in impl (we know the concrete type).
+                assert_eq!(opt_self_ty, None);
+                self.prohibit_generics(path.segments);
+                // Try to evaluate any array length constants.
+                self.normalize_ty(span, tcx.at(span).type_of(def_id))
+            }
+            Res::Def(DefKind::AssocTy, def_id) => {
+                debug_assert!(path.segments.len() >= 2);
+                self.prohibit_generics(&path.segments[..path.segments.len() - 2]);
+                self.qpath_to_ty(
+                    span,
+                    opt_self_ty,
+                    def_id,
+                    &path.segments[path.segments.len() - 2],
+                    path.segments.last().unwrap(),
+                )
+            }
+            Res::PrimTy(prim_ty) => {
+                assert_eq!(opt_self_ty, None);
+                self.prohibit_generics(path.segments);
+                match prim_ty {
+                    hir::PrimTy::Bool => tcx.types.bool,
+                    hir::PrimTy::Char => tcx.types.char,
+                    hir::PrimTy::Int(it) => tcx.mk_mach_int(it),
+                    hir::PrimTy::Uint(uit) => tcx.mk_mach_uint(uit),
+                    hir::PrimTy::Float(ft) => tcx.mk_mach_float(ft),
+                    hir::PrimTy::Str => tcx.types.str_,
+                }
+            }
+            Res::Err => {
+                self.set_tainted_by_errors();
+                self.tcx().ty_error()
+            }
+            _ => span_bug!(span, "unexpected resolution: {:?}", path.res),
+        }
+    }
+
+    /// Parses the programmer's textual representation of a type into our
+    /// internal notion of a type.
+    pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> {
+        self.ast_ty_to_ty_inner(ast_ty, false)
+    }
+
+    /// Turns a `hir::Ty` into a `Ty`. For diagnostics' purposes we keep track of whether trait
+    /// objects are borrowed like `&dyn Trait` to avoid emitting redundant errors.
+    fn ast_ty_to_ty_inner(&self, ast_ty: &hir::Ty<'_>, borrowed: bool) -> Ty<'tcx> {
+        debug!("ast_ty_to_ty(id={:?}, ast_ty={:?} ty_ty={:?})", ast_ty.hir_id, ast_ty, ast_ty.kind);
+
+        let tcx = self.tcx();
+
+        let result_ty = match ast_ty.kind {
+            hir::TyKind::Slice(ref ty) => tcx.mk_slice(self.ast_ty_to_ty(&ty)),
+            hir::TyKind::Ptr(ref mt) => {
+                tcx.mk_ptr(ty::TypeAndMut { ty: self.ast_ty_to_ty(&mt.ty), mutbl: mt.mutbl })
+            }
+            hir::TyKind::Rptr(ref region, ref mt) => {
+                let r = self.ast_region_to_region(region, None);
+                debug!("ast_ty_to_ty: r={:?}", r);
+                let t = self.ast_ty_to_ty_inner(&mt.ty, true);
+                tcx.mk_ref(r, ty::TypeAndMut { ty: t, mutbl: mt.mutbl })
+            }
+            hir::TyKind::Never => tcx.types.never,
+            hir::TyKind::Tup(ref fields) => {
+                tcx.mk_tup(fields.iter().map(|t| self.ast_ty_to_ty(&t)))
+            }
+            hir::TyKind::BareFn(ref bf) => {
+                require_c_abi_if_c_variadic(tcx, &bf.decl, bf.abi, ast_ty.span);
+                tcx.mk_fn_ptr(self.ty_of_fn(
+                    bf.unsafety,
+                    bf.abi,
+                    &bf.decl,
+                    &hir::Generics::empty(),
+                    None,
+                ))
+            }
+            hir::TyKind::TraitObject(ref bounds, ref lifetime) => {
+                self.conv_object_ty_poly_trait_ref(ast_ty.span, bounds, lifetime, borrowed)
+            }
+            hir::TyKind::Path(hir::QPath::Resolved(ref maybe_qself, ref path)) => {
+                debug!("ast_ty_to_ty: maybe_qself={:?} path={:?}", maybe_qself, path);
+                let opt_self_ty = maybe_qself.as_ref().map(|qself| self.ast_ty_to_ty(qself));
+                self.res_to_ty(opt_self_ty, path, false)
+            }
+            hir::TyKind::OpaqueDef(item_id, ref lifetimes) => {
+                let opaque_ty = tcx.hir().expect_item(item_id.id);
+                let def_id = tcx.hir().local_def_id(item_id.id).to_def_id();
+
+                match opaque_ty.kind {
+                    hir::ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn, .. }) => {
+                        self.impl_trait_ty_to_ty(def_id, lifetimes, impl_trait_fn.is_some())
+                    }
+                    ref i => bug!("`impl Trait` pointed to non-opaque type?? {:#?}", i),
+                }
+            }
+            hir::TyKind::Path(hir::QPath::TypeRelative(ref qself, ref segment)) => {
+                debug!("ast_ty_to_ty: qself={:?} segment={:?}", qself, segment);
+                let ty = self.ast_ty_to_ty(qself);
+
+                let res = if let hir::TyKind::Path(hir::QPath::Resolved(_, ref path)) = qself.kind {
+                    path.res
+                } else {
+                    Res::Err
+                };
+                self.associated_path_to_ty(ast_ty.hir_id, ast_ty.span, ty, res, segment, false)
+                    .map(|(ty, _, _)| ty)
+                    .unwrap_or_else(|_| tcx.ty_error())
+            }
+            hir::TyKind::Path(hir::QPath::LangItem(lang_item, span)) => {
+                let def_id = tcx.require_lang_item(lang_item, Some(span));
+                let (substs, _, _) = self.create_substs_for_ast_path(
+                    span,
+                    def_id,
+                    &[],
+                    &GenericArgs::none(),
+                    true,
+                    None,
+                );
+                self.normalize_ty(span, tcx.at(span).type_of(def_id).subst(tcx, substs))
+            }
+            hir::TyKind::Array(ref ty, ref length) => {
+                let length_def_id = tcx.hir().local_def_id(length.hir_id);
+                let length = ty::Const::from_anon_const(tcx, length_def_id);
+                let array_ty = tcx.mk_ty(ty::Array(self.ast_ty_to_ty(&ty), length));
+                self.normalize_ty(ast_ty.span, array_ty)
+            }
+            hir::TyKind::Typeof(ref _e) => {
+                struct_span_err!(
+                    tcx.sess,
+                    ast_ty.span,
+                    E0516,
+                    "`typeof` is a reserved keyword but unimplemented"
+                )
+                .span_label(ast_ty.span, "reserved keyword")
+                .emit();
+
+                tcx.ty_error()
+            }
+            hir::TyKind::Infer => {
+                // Infer also appears as the type of arguments or return
+                // values in a ExprKind::Closure, or as
+                // the type of local variables. Both of these cases are
+                // handled specially and will not descend into this routine.
+                self.ty_infer(None, ast_ty.span)
+            }
+            hir::TyKind::Err => tcx.ty_error(),
+        };
+
+        debug!("ast_ty_to_ty: result_ty={:?}", result_ty);
+
+        self.record_ty(ast_ty.hir_id, result_ty, ast_ty.span);
+        result_ty
+    }
+
+    pub fn impl_trait_ty_to_ty(
+        &self,
+        def_id: DefId,
+        lifetimes: &[hir::GenericArg<'_>],
+        replace_parent_lifetimes: bool,
+    ) -> Ty<'tcx> {
+        debug!("impl_trait_ty_to_ty(def_id={:?}, lifetimes={:?})", def_id, lifetimes);
+        let tcx = self.tcx();
+
+        let generics = tcx.generics_of(def_id);
+
+        debug!("impl_trait_ty_to_ty: generics={:?}", generics);
+        let substs = InternalSubsts::for_item(tcx, def_id, |param, _| {
+            if let Some(i) = (param.index as usize).checked_sub(generics.parent_count) {
+                // Our own parameters are the resolved lifetimes.
+                match param.kind {
+                    GenericParamDefKind::Lifetime => {
+                        if let hir::GenericArg::Lifetime(lifetime) = &lifetimes[i] {
+                            self.ast_region_to_region(lifetime, None).into()
+                        } else {
+                            bug!()
+                        }
+                    }
+                    _ => bug!(),
+                }
+            } else {
+                match param.kind {
+                    // For RPIT (return position impl trait), only lifetimes
+                    // mentioned in the impl Trait predicate are captured by
+                    // the opaque type, so the lifetime parameters from the
+                    // parent item need to be replaced with `'static`.
+                    //
+                    // For `impl Trait` in the types of statics, constants,
+                    // locals and type aliases. These capture all parent
+                    // lifetimes, so they can use their identity subst.
+                    GenericParamDefKind::Lifetime if replace_parent_lifetimes => {
+                        tcx.lifetimes.re_static.into()
+                    }
+                    _ => tcx.mk_param_from_def(param),
+                }
+            }
+        });
+        debug!("impl_trait_ty_to_ty: substs={:?}", substs);
+
+        let ty = tcx.mk_opaque(def_id, substs);
+        debug!("impl_trait_ty_to_ty: {}", ty);
+        ty
+    }
+
+    pub fn ty_of_arg(&self, ty: &hir::Ty<'_>, expected_ty: Option<Ty<'tcx>>) -> Ty<'tcx> {
+        match ty.kind {
+            hir::TyKind::Infer if expected_ty.is_some() => {
+                self.record_ty(ty.hir_id, expected_ty.unwrap(), ty.span);
+                expected_ty.unwrap()
+            }
+            _ => self.ast_ty_to_ty(ty),
+        }
+    }
+
+    pub fn ty_of_fn(
+        &self,
+        unsafety: hir::Unsafety,
+        abi: abi::Abi,
+        decl: &hir::FnDecl<'_>,
+        generics: &hir::Generics<'_>,
+        ident_span: Option<Span>,
+    ) -> ty::PolyFnSig<'tcx> {
+        debug!("ty_of_fn");
+
+        let tcx = self.tcx();
+
+        // 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);
+        }
+        walk_generics(&mut visitor, generics);
+
+        let input_tys = decl.inputs.iter().map(|a| self.ty_of_arg(a, None));
+        let output_ty = match decl.output {
+            hir::FnRetTy::Return(ref output) => {
+                visitor.visit_ty(output);
+                self.ast_ty_to_ty(output)
+            }
+            hir::FnRetTy::DefaultReturn(..) => tcx.mk_unit(),
+        };
+
+        debug!("ty_of_fn: output_ty={:?}", output_ty);
+
+        let bare_fn_ty =
+            ty::Binder::bind(tcx.mk_fn_sig(input_tys, output_ty, decl.c_variadic, unsafety, abi));
+
+        if !self.allow_ty_infer() {
+            // We always collect the spans for placeholder types when evaluating `fn`s, but we
+            // only want to emit an error complaining about them if infer types (`_`) are not
+            // allowed. `allow_ty_infer` gates this behavior. We check for the presence of
+            // `ident_span` to not emit an error twice when we have `fn foo(_: fn() -> _)`.
+            crate::collect::placeholder_type_error(
+                tcx,
+                ident_span.map(|sp| sp.shrink_to_hi()),
+                &generics.params[..],
+                visitor.0,
+                true,
+            );
+        }
+
+        // Find any late-bound regions declared in return type that do
+        // not appear in the arguments. These are not well-formed.
+        //
+        // Example:
+        //     for<'a> fn() -> &'a str <-- 'a is bad
+        //     for<'a> fn(&'a String) -> &'a str <-- 'a is ok
+        let inputs = bare_fn_ty.inputs();
+        let late_bound_in_args =
+            tcx.collect_constrained_late_bound_regions(&inputs.map_bound(|i| i.to_owned()));
+        let output = bare_fn_ty.output();
+        let late_bound_in_ret = tcx.collect_referenced_late_bound_regions(&output);
+
+        self.validate_late_bound_regions(late_bound_in_args, late_bound_in_ret, |br_name| {
+            struct_span_err!(
+                tcx.sess,
+                decl.output.span(),
+                E0581,
+                "return type references {}, which is not constrained by the fn input types",
+                br_name
+            )
+        });
+
+        bare_fn_ty
+    }
+
+    fn validate_late_bound_regions(
+        &self,
+        constrained_regions: FxHashSet<ty::BoundRegion>,
+        referenced_regions: FxHashSet<ty::BoundRegion>,
+        generate_err: impl Fn(&str) -> rustc_errors::DiagnosticBuilder<'tcx>,
+    ) {
+        for br in referenced_regions.difference(&constrained_regions) {
+            let br_name = match *br {
+                ty::BrNamed(_, name) => format!("lifetime `{}`", name),
+                ty::BrAnon(_) | ty::BrEnv => "an anonymous lifetime".to_string(),
+            };
+
+            let mut err = generate_err(&br_name);
+
+            if let ty::BrAnon(_) = *br {
+                // The only way for an anonymous lifetime to wind up
+                // in the return type but **also** be unconstrained is
+                // if it only appears in "associated types" in the
+                // input. See #47511 and #62200 for examples. In this case,
+                // though we can easily give a hint that ought to be
+                // relevant.
+                err.note(
+                    "lifetimes appearing in an associated type are not considered constrained",
+                );
+            }
+
+            err.emit();
+        }
+    }
+
+    /// Given the bounds on an object, determines what single region bound (if any) we can
+    /// use to summarize this type. The basic idea is that we will use the bound the user
+    /// provided, if they provided one, and otherwise search the supertypes of trait bounds
+    /// for region bounds. It may be that we can derive no bound at all, in which case
+    /// we return `None`.
+    fn compute_object_lifetime_bound(
+        &self,
+        span: Span,
+        existential_predicates: ty::Binder<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>,
+    ) -> Option<ty::Region<'tcx>> // if None, use the default
+    {
+        let tcx = self.tcx();
+
+        debug!("compute_opt_region_bound(existential_predicates={:?})", existential_predicates);
+
+        // No explicit region bound specified. Therefore, examine trait
+        // bounds and see if we can derive region bounds from those.
+        let derived_region_bounds = object_region_bounds(tcx, existential_predicates);
+
+        // If there are no derived region bounds, then report back that we
+        // can find no region bound. The caller will use the default.
+        if derived_region_bounds.is_empty() {
+            return None;
+        }
+
+        // If any of the derived region bounds are 'static, that is always
+        // the best choice.
+        if derived_region_bounds.iter().any(|&r| ty::ReStatic == *r) {
+            return Some(tcx.lifetimes.re_static);
+        }
+
+        // Determine whether there is exactly one unique region in the set
+        // of derived region bounds. If so, use that. Otherwise, report an
+        // error.
+        let r = derived_region_bounds[0];
+        if derived_region_bounds[1..].iter().any(|r1| r != *r1) {
+            struct_span_err!(
+                tcx.sess,
+                span,
+                E0227,
+                "ambiguous lifetime bound, explicit lifetime bound required"
+            )
+            .emit();
+        }
+        Some(r)
+    }
+}
diff --git a/src/librustc_typeck/bounds.rs b/src/librustc_typeck/bounds.rs
new file mode 100644 (file)
index 0000000..63295f5
--- /dev/null
@@ -0,0 +1,93 @@
+//! Bounds are restrictions applied to some types after they've been converted into the
+//! `ty` form from the HIR.
+
+use rustc_hir::Constness;
+use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness};
+use rustc_span::Span;
+
+/// Collects together a list of type bounds. These lists of bounds occur in many places
+/// in Rust's syntax:
+///
+/// ```text
+/// trait Foo: Bar + Baz { }
+///            ^^^^^^^^^ supertrait list bounding the `Self` type parameter
+///
+/// fn foo<T: Bar + Baz>() { }
+///           ^^^^^^^^^ bounding the type parameter `T`
+///
+/// impl dyn Bar + Baz
+///          ^^^^^^^^^ bounding the forgotten dynamic type
+/// ```
+///
+/// Our representation is a bit mixed here -- in some cases, we
+/// include the self type (e.g., `trait_bounds`) but in others we do not
+#[derive(Default, PartialEq, Eq, Clone, Debug)]
+pub struct Bounds<'tcx> {
+    /// A list of region bounds on the (implicit) self type. So if you
+    /// had `T: 'a + 'b` this might would be a list `['a, 'b]` (but
+    /// the `T` is not explicitly included).
+    pub region_bounds: Vec<(ty::Region<'tcx>, Span)>,
+
+    /// A list of trait bounds. So if you had `T: Debug` this would be
+    /// `T: Debug`. Note that the self-type is explicit here.
+    pub trait_bounds: Vec<(ty::PolyTraitRef<'tcx>, Span, Constness)>,
+
+    /// A list of projection equality bounds. So if you had `T:
+    /// Iterator<Item = u32>` this would include `<T as
+    /// Iterator>::Item => u32`. Note that the self-type is explicit
+    /// here.
+    pub projection_bounds: Vec<(ty::PolyProjectionPredicate<'tcx>, Span)>,
+
+    /// `Some` if there is *no* `?Sized` predicate. The `span`
+    /// is the location in the source of the `T` declaration which can
+    /// be cited as the source of the `T: Sized` requirement.
+    pub implicitly_sized: Option<Span>,
+}
+
+impl<'tcx> Bounds<'tcx> {
+    /// Converts a bounds list into a flat set of predicates (like
+    /// where-clauses). Because some of our bounds listings (e.g.,
+    /// regions) don't include the self-type, you must supply the
+    /// self-type here (the `param_ty` parameter).
+    pub fn predicates(
+        &self,
+        tcx: TyCtxt<'tcx>,
+        param_ty: Ty<'tcx>,
+    ) -> Vec<(ty::Predicate<'tcx>, Span)> {
+        // If it could be sized, and is, add the `Sized` predicate.
+        let sized_predicate = self.implicitly_sized.and_then(|span| {
+            tcx.lang_items().sized_trait().map(|sized| {
+                let trait_ref = ty::Binder::bind(ty::TraitRef {
+                    def_id: sized,
+                    substs: tcx.mk_substs_trait(param_ty, &[]),
+                });
+                (trait_ref.without_const().to_predicate(tcx), span)
+            })
+        });
+
+        sized_predicate
+            .into_iter()
+            .chain(
+                self.region_bounds
+                    .iter()
+                    .map(|&(region_bound, span)| {
+                        // Account for the binder being introduced below; no need to shift `param_ty`
+                        // because, at present at least, it either only refers to early-bound regions,
+                        // or it's a generic associated type that deliberately has escaping bound vars.
+                        let region_bound = ty::fold::shift_region(tcx, region_bound, 1);
+                        let outlives = ty::OutlivesPredicate(param_ty, region_bound);
+                        (ty::Binder::bind(outlives).to_predicate(tcx), span)
+                    })
+                    .chain(self.trait_bounds.iter().map(|&(bound_trait_ref, span, constness)| {
+                        let predicate = bound_trait_ref.with_constness(constness).to_predicate(tcx);
+                        (predicate, span)
+                    }))
+                    .chain(
+                        self.projection_bounds
+                            .iter()
+                            .map(|&(projection, span)| (projection.to_predicate(tcx), span)),
+                    ),
+            )
+            .collect()
+    }
+}
index 9e23f5df3c6a8a367d9fc5821979f40ec464be49..40088bc06900543a885943d1ff4e1c197da07eac 100644 (file)
@@ -124,11 +124,10 @@ pub fn check_match(
                     }
                 }
             } else {
-                let arm_span = if let hir::ExprKind::Block(blk, _) = &arm.body.kind {
-                    // Point at the block expr instead of the entire block
-                    blk.expr.as_ref().map(|e| e.span).unwrap_or(arm.body.span)
+                let (arm_span, semi_span) = if let hir::ExprKind::Block(blk, _) = &arm.body.kind {
+                    self.find_block_span(blk, prior_arm_ty)
                 } else {
-                    arm.body.span
+                    (arm.body.span, None)
                 };
                 let (span, code) = match i {
                     // The reason for the first arm to fail is not that the match arms diverge,
@@ -138,6 +137,7 @@ pub fn check_match(
                         expr.span,
                         ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
                             arm_span,
+                            semi_span,
                             source: match_src,
                             prior_arms: other_arms.clone(),
                             last_ty: prior_arm_ty.unwrap(),
@@ -295,14 +295,9 @@ fn if_cause(
 
         let mut remove_semicolon = None;
         let error_sp = if let ExprKind::Block(block, _) = &else_expr.kind {
-            if let Some(expr) = &block.expr {
-                expr.span
-            } else if let Some(stmt) = block.stmts.last() {
-                // possibly incorrect trailing `;` in the else arm
-                remove_semicolon = self.could_remove_semicolon(block, then_ty);
-                stmt.span
-            } else {
-                // empty block; point at its entirety
+            let (error_sp, semi_sp) = self.find_block_span(block, Some(then_ty));
+            remove_semicolon = semi_sp;
+            if block.expr.is_none() && block.stmts.is_empty() {
                 // Avoid overlapping spans that aren't as readable:
                 // ```
                 // 2 |        let x = if true {
@@ -333,8 +328,8 @@ fn if_cause(
                 if outer_sp.is_some() {
                     outer_sp = Some(self.tcx.sess.source_map().guess_head_span(span));
                 }
-                else_expr.span
             }
+            error_sp
         } else {
             // shouldn't happen unless the parser has done something weird
             else_expr.span
@@ -342,17 +337,12 @@ fn if_cause(
 
         // Compute `Span` of `then` part of `if`-expression.
         let then_sp = if let ExprKind::Block(block, _) = &then_expr.kind {
-            if let Some(expr) = &block.expr {
-                expr.span
-            } else if let Some(stmt) = block.stmts.last() {
-                // possibly incorrect trailing `;` in the else arm
-                remove_semicolon = remove_semicolon.or(self.could_remove_semicolon(block, else_ty));
-                stmt.span
-            } else {
-                // empty block; point at its entirety
+            let (then_sp, semi_sp) = self.find_block_span(block, Some(else_ty));
+            remove_semicolon = remove_semicolon.or(semi_sp);
+            if block.expr.is_none() && block.stmts.is_empty() {
                 outer_sp = None; // same as in `error_sp`; cleanup output
-                then_expr.span
             }
+            then_sp
         } else {
             // shouldn't happen unless the parser has done something weird
             then_expr.span
@@ -450,4 +440,20 @@ fn demand_scrutinee_type(
             scrut_ty
         }
     }
+
+    fn find_block_span(
+        &self,
+        block: &'tcx hir::Block<'tcx>,
+        expected_ty: Option<Ty<'tcx>>,
+    ) -> (Span, Option<Span>) {
+        if let Some(expr) = &block.expr {
+            (expr.span, None)
+        } else if let Some(stmt) = block.stmts.last() {
+            // possibly incorrect trailing `;` in the else arm
+            (stmt.span, expected_ty.and_then(|ty| self.could_remove_semicolon(block, ty)))
+        } else {
+            // empty block; point at its entirety
+            (block.span, None)
+        }
+    }
 }
index 34693a73217884d9adf688fb4cdad80fa0509e8d..e41314e8ab03f438364ffe092411eb55eb41ff31 100644 (file)
@@ -35,7 +35,7 @@
 use rustc_ast as ast;
 use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorReported};
 use rustc_hir as hir;
-use rustc_hir::lang_items;
+use rustc_hir::lang_items::LangItem;
 use rustc_middle::ty::adjustment::AllowTwoPhase;
 use rustc_middle::ty::cast::{CastKind, CastTy};
 use rustc_middle::ty::error::TypeError;
@@ -838,7 +838,7 @@ fn cenum_impl_drop_lint(&self, fcx: &FnCtxt<'a, 'tcx>) {
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     fn type_is_known_to_be_sized_modulo_regions(&self, ty: Ty<'tcx>, span: Span) -> bool {
-        let lang_item = self.tcx.require_lang_item(lang_items::SizedTraitLangItem, None);
+        let lang_item = self.tcx.require_lang_item(LangItem::Sized, None);
         traits::type_known_to_meet_bound_modulo_regions(self, self.param_env, ty, lang_item, span)
     }
 }
index c7f9e9d63e03c576a21a595dd72144437b5d5040..97f7e4537ce9584fda1bfa87d40c9cdab1917bb5 100644 (file)
@@ -5,7 +5,7 @@
 use crate::astconv::AstConv;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
-use rustc_hir::lang_items::{FutureTraitLangItem, GeneratorTraitLangItem};
+use rustc_hir::lang_items::LangItem;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_infer::infer::LateBoundRegionConversionTime;
 use rustc_infer::infer::{InferOk, InferResult};
@@ -245,7 +245,7 @@ fn deduce_sig_from_projection(
         let trait_ref = projection.to_poly_trait_ref(tcx);
 
         let is_fn = tcx.fn_trait_kind_from_lang_item(trait_ref.def_id()).is_some();
-        let gen_trait = tcx.require_lang_item(GeneratorTraitLangItem, cause_span);
+        let gen_trait = tcx.require_lang_item(LangItem::Generator, cause_span);
         let is_gen = gen_trait == trait_ref.def_id();
         if !is_fn && !is_gen {
             debug!("deduce_sig_from_projection: not fn or generator");
@@ -668,7 +668,7 @@ fn deduce_future_output_from_projection(
 
         // Check that this is a projection from the `Future` trait.
         let trait_ref = predicate.projection_ty.trait_ref(self.tcx);
-        let future_trait = self.tcx.require_lang_item(FutureTraitLangItem, Some(cause_span));
+        let future_trait = self.tcx.require_lang_item(LangItem::Future, Some(cause_span));
         if trait_ref.def_id != future_trait {
             debug!("deduce_future_output_from_projection: not a future");
             return None;
index aa92d8b8b2b9b8d7e8f57bd57e70762c16bfbbee..5dc5480c3353c0140b3a6399d1cbfe58c8dd4e61 100644 (file)
@@ -6,7 +6,7 @@
 use rustc_ast::util::parser::PREC_POSTFIX;
 use rustc_errors::{Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
-use rustc_hir::lang_items::CloneTraitLangItem;
+use rustc_hir::lang_items::LangItem;
 use rustc_hir::{is_range_literal, Node};
 use rustc_middle::ty::adjustment::AllowTwoPhase;
 use rustc_middle::ty::{self, AssocItem, Ty, TypeAndMut};
@@ -465,7 +465,7 @@ pub fn check_ref(
                 if self.can_coerce(ref_ty, expected) {
                     let mut sugg_sp = sp;
                     if let hir::ExprKind::MethodCall(ref segment, sp, ref args, _) = expr.kind {
-                        let clone_trait = self.tcx.require_lang_item(CloneTraitLangItem, Some(sp));
+                        let clone_trait = self.tcx.require_lang_item(LangItem::Clone, Some(sp));
                         if let ([arg], Some(true), sym::clone) = (
                             &args[..],
                             self.typeck_results.borrow().type_dependent_def_id(expr.hir_id).map(
index ff0c788c18b51598cdce7442c08927ce2618ea65..0e9f64c359690c3ecfe32f051b665722394a385c 100644 (file)
@@ -25,7 +25,7 @@
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, DefKind, Res};
 use rustc_hir::def_id::DefId;
-use rustc_hir::lang_items;
+use rustc_hir::lang_items::LangItem;
 use rustc_hir::{ExprKind, QPath};
 use rustc_infer::infer;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
@@ -926,8 +926,8 @@ fn report_extended_method_error(
                 // Try alternative arbitrary self types that could fulfill this call.
                 // FIXME: probe for all types that *could* be arbitrary self-types, not
                 // just this list.
-                try_alt_rcvr(&mut err, self.tcx.mk_lang_item(rcvr_t, lang_items::OwnedBoxLangItem));
-                try_alt_rcvr(&mut err, self.tcx.mk_lang_item(rcvr_t, lang_items::PinTypeLangItem));
+                try_alt_rcvr(&mut err, self.tcx.mk_lang_item(rcvr_t, LangItem::OwnedBox));
+                try_alt_rcvr(&mut err, self.tcx.mk_lang_item(rcvr_t, LangItem::Pin));
                 try_alt_rcvr(&mut err, self.tcx.mk_diagnostic_item(rcvr_t, sym::Arc));
                 try_alt_rcvr(&mut err, self.tcx.mk_diagnostic_item(rcvr_t, sym::Rc));
             }
index e941c844a6d9058113a018e0d2fa6ab561275399..896bfc0795434e4ac021e04be9d1f473ff6a8ff3 100644 (file)
@@ -9,7 +9,7 @@
 use rustc_hir::def::{DefKind, Namespace, Res};
 use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_hir::intravisit;
-use rustc_hir::lang_items::FnOnceTraitLangItem;
+use rustc_hir::lang_items::LangItem;
 use rustc_hir::{ExprKind, Node, QPath};
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_middle::hir::map as hir_map;
@@ -36,7 +36,7 @@ fn is_fn_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
             ty::Closure(..) | ty::FnDef(..) | ty::FnPtr(_) => true,
             // If it's not a simple function, look for things which implement `FnOnce`.
             _ => {
-                let fn_once = match tcx.lang_items().require(FnOnceTraitLangItem) {
+                let fn_once = match tcx.lang_items().require(LangItem::FnOnce) {
                     Ok(fn_once) => fn_once,
                     Err(..) => return false,
                 };
index 824e81a974ca61f00b8dd7c6bf1d08a4fad52448..031d48f8a6086f97f10334a2ced7fd121469c056 100644 (file)
 use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LOCAL_CRATE};
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
-use rustc_hir::lang_items::{
-    FutureTraitLangItem, PinTypeLangItem, SizedTraitLangItem, VaListTypeLangItem,
-};
+use rustc_hir::lang_items::LangItem;
 use rustc_hir::{ExprKind, GenericArg, HirIdMap, ItemKind, Node, PatKind, QPath};
 use rustc_index::bit_set::BitSet;
 use rustc_index::vec::Idx;
@@ -1339,7 +1337,7 @@ fn check_fn<'a, 'tcx>(
     // (as it's created inside the body itself, not passed in from outside).
     let maybe_va_list = if fn_sig.c_variadic {
         let span = body.params.last().unwrap().span;
-        let va_list_did = tcx.require_lang_item(VaListTypeLangItem, Some(span));
+        let va_list_did = tcx.require_lang_item(LangItem::VaList, Some(span));
         let region = fcx.next_region_var(RegionVariableOrigin::MiscVariable(span));
 
         Some(tcx.type_of(va_list_did).subst(tcx, &[region.into()]))
@@ -3493,7 +3491,7 @@ pub fn require_type_is_sized(
         code: traits::ObligationCauseCode<'tcx>,
     ) {
         if !ty.references_error() {
-            let lang_item = self.tcx.require_lang_item(SizedTraitLangItem, None);
+            let lang_item = self.tcx.require_lang_item(LangItem::Sized, None);
             self.require_type_meets(ty, span, code, lang_item);
         }
     }
@@ -5265,7 +5263,7 @@ fn suggest_calling_boxed_future_when_appropriate(
             _ => {}
         }
         let boxed_found = self.tcx.mk_box(found);
-        let new_found = self.tcx.mk_lang_item(boxed_found, PinTypeLangItem).unwrap();
+        let new_found = self.tcx.mk_lang_item(boxed_found, LangItem::Pin).unwrap();
         if let (true, Ok(snippet)) = (
             self.can_coerce(new_found, expected),
             self.sess().source_map().span_to_snippet(expr.span),
@@ -5422,7 +5420,7 @@ fn suggest_missing_await(
                 let sp = expr.span;
                 // Check for `Future` implementations by constructing a predicate to
                 // prove: `<T as Future>::Output == U`
-                let future_trait = self.tcx.require_lang_item(FutureTraitLangItem, Some(sp));
+                let future_trait = self.tcx.require_lang_item(LangItem::Future, Some(sp));
                 let item_def_id = self
                     .tcx
                     .associated_items(future_trait)
index 810bf59ea6c35ad936da1cbcdd6266520379b658..9c692edaa7fa4412f63ab57870af474933ffca1f 100644 (file)
@@ -9,7 +9,7 @@
 use rustc_hir::intravisit as hir_visit;
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::itemlikevisit::ParItemLikeVisitor;
-use rustc_hir::lang_items;
+use rustc_hir::lang_items::LangItem;
 use rustc_hir::ItemKind;
 use rustc_middle::hir::map as hir_map;
 use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts, Subst};
@@ -495,7 +495,7 @@ fn check_type_defn<'tcx, F>(
                 let last = idx == variant.fields.len() - 1;
                 fcx.register_bound(
                     field.ty,
-                    fcx.tcx.require_lang_item(lang_items::SizedTraitLangItem, None),
+                    fcx.tcx.require_lang_item(LangItem::Sized, None),
                     traits::ObligationCause::new(
                         field.span,
                         fcx.body_id,
@@ -718,7 +718,7 @@ fn check_item_type(tcx: TyCtxt<'_>, item_id: hir::HirId, ty_span: Span, allow_fo
         if forbid_unsized {
             fcx.register_bound(
                 item_ty,
-                fcx.tcx.require_lang_item(lang_items::SizedTraitLangItem, None),
+                fcx.tcx.require_lang_item(LangItem::Sized, None),
                 traits::ObligationCause::new(ty_span, fcx.body_id, traits::MiscObligation),
             );
         }
@@ -1223,7 +1223,7 @@ fn receiver_is_valid<'fcx, 'tcx>(
     // The first type is `receiver_ty`, which we know its not equal to `self_ty`; skip it.
     autoderef.next();
 
-    let receiver_trait_def_id = fcx.tcx.require_lang_item(lang_items::ReceiverTraitLangItem, None);
+    let receiver_trait_def_id = fcx.tcx.require_lang_item(LangItem::Receiver, None);
 
     // Keep dereferencing `receiver_ty` until we get to `self_ty`.
     loop {
index 56a737964c0479809caa9ba85642d015bec8aefb..0d3cac7f7f38a2cd7d6a9dc423e4da5a682bc86a 100644 (file)
@@ -4,9 +4,7 @@
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_hir::lang_items::{
-    CoerceUnsizedTraitLangItem, DispatchFromDynTraitLangItem, UnsizeTraitLangItem,
-};
+use rustc_hir::lang_items::LangItem;
 use rustc_hir::ItemKind;
 use rustc_infer::infer;
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
@@ -149,7 +147,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
     let impl_hir_id = tcx.hir().local_def_id_to_hir_id(impl_did);
     let span = tcx.hir().span(impl_hir_id);
 
-    let dispatch_from_dyn_trait = tcx.require_lang_item(DispatchFromDynTraitLangItem, Some(span));
+    let dispatch_from_dyn_trait = tcx.require_lang_item(LangItem::DispatchFromDyn, Some(span));
 
     let source = tcx.type_of(impl_did);
     assert!(!source.has_escaping_bound_vars());
@@ -318,9 +316,9 @@ pub fn coerce_unsized_info(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUnsizedI
     let impl_hir_id = tcx.hir().local_def_id_to_hir_id(impl_did.expect_local());
     let span = tcx.hir().span(impl_hir_id);
 
-    let coerce_unsized_trait = tcx.require_lang_item(CoerceUnsizedTraitLangItem, Some(span));
+    let coerce_unsized_trait = tcx.require_lang_item(LangItem::CoerceUnsized, Some(span));
 
-    let unsize_trait = tcx.lang_items().require(UnsizeTraitLangItem).unwrap_or_else(|err| {
+    let unsize_trait = tcx.lang_items().require(LangItem::Unsize).unwrap_or_else(|err| {
         tcx.sess.fatal(&format!("`CoerceUnsized` implementation {}", err));
     });
 
index 7fb4026117be9d71b7aadcbce1ec80bb7c29ab99..1b472810ccf1d1950a8abb5072ca0ef93545a4cc 100644 (file)
@@ -14,7 +14,8 @@
 //! At present, however, we do run collection across all items in the
 //! crate as a kind of pass. This should eventually be factored away.
 
-use crate::astconv::{AstConv, Bounds, SizedByDefault};
+use crate::astconv::{AstConv, SizedByDefault};
+use crate::bounds::Bounds;
 use crate::check::intrinsic::intrinsic_operation_unsafety;
 use crate::constrained_generic_params as cgp;
 use crate::middle::resolve_lifetime as rl;
@@ -1542,7 +1543,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
         }
 
         TraitItem(hir::TraitItem {
-            kind: TraitItemKind::Fn(FnSig { header, decl }, _),
+            kind: TraitItemKind::Fn(FnSig { header, decl, span: _ }, _),
             ident,
             generics,
             ..
index 4248253172598c877d82b0554e95e9faa6d0d69c..62f92fe7ffa484859e2699610230ba8ae827740a 100644 (file)
@@ -79,6 +79,7 @@
 pub mod expr_use_visitor;
 
 mod astconv;
+mod bounds;
 mod check_unused;
 mod coherence;
 mod collect;
 
 use std::iter;
 
-use astconv::{AstConv, Bounds};
+use astconv::AstConv;
+use bounds::Bounds;
 
 fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: Abi, span: Span) {
     if decl.c_variadic && !(abi == Abi::C || abi == Abi::Cdecl) {
index 9c44d27447db8614445e2073acb3a640db25f426..1ea1a0910695762bec2c78daf7a0005c513aba1f 100644 (file)
@@ -1,6 +1,6 @@
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
-use rustc_hir::lang_items;
+use rustc_hir::lang_items::LangItem;
 use rustc_middle::ty::{self, Region, RegionVid, TypeFoldable};
 use rustc_trait_selection::traits::auto_trait::{self, AutoTraitResult};
 
@@ -454,7 +454,7 @@ fn param_env_to_generics(
 
         // The `Sized` trait must be handled specially, since we only display it when
         // it is *not* required (i.e., '?Sized')
-        let sized_trait = self.cx.tcx.require_lang_item(lang_items::SizedTraitLangItem, None);
+        let sized_trait = self.cx.tcx.require_lang_item(LangItem::Sized, None);
 
         let mut replacer = RegionReplacer { vid_to_region: &vid_to_region, tcx };
 
@@ -742,9 +742,9 @@ fn unstable_debug_sort<T: Debug>(&self, vec: &mut Vec<T>) {
     fn is_fn_ty(&self, tcx: TyCtxt<'_>, ty: &Type) -> bool {
         match &ty {
             &&Type::ResolvedPath { ref did, .. } => {
-                *did == tcx.require_lang_item(lang_items::FnTraitLangItem, None)
-                    || *did == tcx.require_lang_item(lang_items::FnMutTraitLangItem, None)
-                    || *did == tcx.require_lang_item(lang_items::FnOnceTraitLangItem, None)
+                *did == tcx.require_lang_item(LangItem::Fn, None)
+                    || *did == tcx.require_lang_item(LangItem::FnMut, None)
+                    || *did == tcx.require_lang_item(LangItem::FnOnce, None)
             }
             _ => false,
         }
index 3eac5bbda007898b9c5f31a3df2e2ba0037d2049..a458cdab3030320cca651fc6f9d1458436acbf81 100644 (file)
 use rustc_hir as hir;
 use rustc_hir::def::Res;
 use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
-use rustc_hir::lang_items;
+use rustc_hir::lang_items::LangItem;
 use rustc_hir::Mutability;
 use rustc_index::vec::IndexVec;
 use rustc_middle::middle::stability;
-use rustc_middle::ty::TyCtxt;
+use rustc_middle::ty::{AssocKind, TyCtxt};
 use rustc_span::hygiene::MacroKind;
 use rustc_span::source_map::DUMMY_SP;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
@@ -282,12 +282,21 @@ pub enum ItemEnum {
 }
 
 impl ItemEnum {
-    pub fn is_associated(&self) -> bool {
+    pub fn is_type_alias(&self) -> bool {
         match *self {
             ItemEnum::TypedefItem(_, _) | ItemEnum::AssocTypeItem(_, _) => true,
             _ => false,
         }
     }
+
+    pub fn as_assoc_kind(&self) -> Option<AssocKind> {
+        match *self {
+            ItemEnum::AssocConstItem(..) => Some(AssocKind::Const),
+            ItemEnum::AssocTypeItem(..) => Some(AssocKind::Type),
+            ItemEnum::TyMethodItem(..) | ItemEnum::MethodItem(..) => Some(AssocKind::Fn),
+            _ => None,
+        }
+    }
 }
 
 #[derive(Clone, Debug)]
@@ -701,7 +710,7 @@ pub enum GenericBound {
 
 impl GenericBound {
     pub fn maybe_sized(cx: &DocContext<'_>) -> GenericBound {
-        let did = cx.tcx.require_lang_item(lang_items::SizedTraitLangItem, None);
+        let did = cx.tcx.require_lang_item(LangItem::Sized, None);
         let empty = cx.tcx.intern_substs(&[]);
         let path = external_path(cx, cx.tcx.item_name(did), Some(did), false, vec![], empty);
         inline::record_extern_fqn(cx, did, TypeKind::Trait);
index 4f751decc8090a2bbeb16ca3f05a67b6112871dc..14df4e7aa8e59567d2594ae9a7069c51ee2dfb84 100644 (file)
@@ -83,9 +83,9 @@ pub struct Options {
     /// Codegen options strings to hand to the compiler.
     pub codegen_options_strs: Vec<String>,
     /// Debugging (`-Z`) options to pass to the compiler.
-    pub debugging_options: DebuggingOptions,
+    pub debugging_opts: DebuggingOptions,
     /// Debugging (`-Z`) options strings to pass to the compiler.
-    pub debugging_options_strs: Vec<String>,
+    pub debugging_opts_strs: Vec<String>,
     /// The target used to compile the crate against.
     pub target: TargetTriple,
     /// Edition used when reading the crate. Defaults to "2015". Also used by default when
@@ -318,9 +318,9 @@ fn println_condition(condition: Condition) {
         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);
+        let debugging_opts = build_debugging_options(matches, error_format);
 
-        let diag = new_handler(error_format, None, &debugging_options);
+        let diag = new_handler(error_format, None, &debugging_opts);
 
         // check for deprecated options
         check_deprecated_options(&matches, &diag);
@@ -365,7 +365,7 @@ fn println_condition(condition: Condition) {
             .iter()
             .map(|s| SearchPath::from_cli_opt(s, error_format))
             .collect();
-        let externs = parse_externs(&matches, &debugging_options, error_format);
+        let externs = parse_externs(&matches, &debugging_opts, error_format);
         let extern_html_root_urls = match parse_extern_html_roots(&matches) {
             Ok(ex) => ex,
             Err(err) => {
@@ -546,7 +546,7 @@ fn println_condition(condition: Condition) {
         let persist_doctests = matches.opt_str("persist-doctests").map(PathBuf::from);
         let test_builder = matches.opt_str("test-builder").map(PathBuf::from);
         let codegen_options_strs = matches.opt_strs("C");
-        let debugging_options_strs = matches.opt_strs("Z");
+        let debugging_opts_strs = matches.opt_strs("Z");
         let lib_strs = matches.opt_strs("L");
         let extern_strs = matches.opt_strs("extern");
         let runtool = matches.opt_str("runtool");
@@ -569,8 +569,8 @@ fn println_condition(condition: Condition) {
             cfgs,
             codegen_options,
             codegen_options_strs,
-            debugging_options,
-            debugging_options_strs,
+            debugging_opts,
+            debugging_opts_strs,
             target,
             edition,
             maybe_sysroot,
index 5049dbdb1ddc72d277457f72eb204ff5fe3999bb..89b217dc7d4f255d44a2794173f0ce10f2680656 100644 (file)
@@ -32,8 +32,8 @@
 
 use crate::clean;
 use crate::clean::{AttributesExt, MAX_DEF_ID};
-use crate::config::RenderInfo;
 use crate::config::{Options as RustdocOptions, RenderOptions};
+use crate::config::{OutputFormat, RenderInfo};
 use crate::passes::{self, Condition::*, ConditionalPass};
 
 pub use rustc_session::config::{CodegenOptions, DebuggingOptions, Input, Options};
@@ -69,6 +69,11 @@ pub struct DocContext<'tcx> {
     pub auto_traits: Vec<DefId>,
     /// The options given to rustdoc that could be relevant to a pass.
     pub render_options: RenderOptions,
+    /// The traits in scope for a given module.
+    ///
+    /// See `collect_intra_doc_links::traits_implemented_by` for more details.
+    /// `map<module, set<trait>>`
+    pub module_trait_cache: RefCell<FxHashMap<DefId, FxHashSet<DefId>>>,
 }
 
 impl<'tcx> DocContext<'tcx> {
@@ -117,13 +122,13 @@ pub fn enter_alias<F, R>(
     // def ids, as we'll end up with a panic if we use the DefId Debug impl for fake DefIds
     pub fn next_def_id(&self, crate_num: CrateNum) -> DefId {
         let start_def_id = {
-            let next_id = if crate_num == LOCAL_CRATE {
-                self.tcx.hir().definitions().def_path_table().next_id()
+            let num_def_ids = if crate_num == LOCAL_CRATE {
+                self.tcx.hir().definitions().def_path_table().num_def_ids()
             } else {
-                self.enter_resolver(|r| r.cstore().def_path_table(crate_num).next_id())
+                self.enter_resolver(|r| r.cstore().num_def_ids(crate_num))
             };
 
-            DefId { krate: crate_num, index: next_id }
+            DefId { krate: crate_num, index: DefIndex::from_usize(num_def_ids) }
         };
 
         let mut fake_ids = self.fake_def_ids.borrow_mut();
@@ -229,7 +234,7 @@ pub fn new_handler(
 /// It returns a tuple containing:
 ///  * Vector of tuples of lints' name and their associated "max" level
 ///  * HashMap of lint id with their associated "max" level
-pub fn init_lints<F>(
+pub(crate) fn init_lints<F>(
     mut allowed_lints: Vec<String>,
     lint_opts: Vec<(String, lint::Level)>,
     filter_call: F,
@@ -252,7 +257,7 @@ pub fn init_lints<F>(
         .filter_map(|lint| {
             // Permit feature-gated lints to avoid feature errors when trying to
             // allow all lints.
-            if lint.name == warnings_lint_name || lint.feature_gate.is_some() {
+            if lint.feature_gate.is_some() || allowed_lints.iter().any(|l| lint.name == l) {
                 None
             } else {
                 filter_call(lint)
@@ -275,7 +280,9 @@ pub fn init_lints<F>(
     (lint_opts, lint_caps)
 }
 
-pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOptions) {
+pub fn run_core(
+    options: RustdocOptions,
+) -> (clean::Crate, RenderInfo, RenderOptions, Lrc<Session>) {
     // Parse, resolve, and typecheck the given crate.
 
     let RustdocOptions {
@@ -287,15 +294,15 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
         externs,
         mut cfgs,
         codegen_options,
-        debugging_options,
+        debugging_opts,
         target,
         edition,
         maybe_sysroot,
         lint_opts,
         describe_lints,
         lint_cap,
-        mut default_passes,
-        mut manual_passes,
+        default_passes,
+        manual_passes,
         display_warnings,
         render_options,
         output_format,
@@ -321,19 +328,23 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
     let private_doc_tests = rustc_lint::builtin::PRIVATE_DOC_TESTS.name;
     let no_crate_level_docs = rustc_lint::builtin::MISSING_CRATE_LEVEL_DOCS.name;
     let invalid_codeblock_attributes_name = rustc_lint::builtin::INVALID_CODEBLOCK_ATTRIBUTES.name;
+    let renamed_and_removed_lints = rustc_lint::builtin::RENAMED_AND_REMOVED_LINTS.name;
+    let unknown_lints = rustc_lint::builtin::UNKNOWN_LINTS.name;
 
     // In addition to those specific lints, we also need to allow those given through
     // command line, otherwise they'll get ignored and we don't want that.
-    let allowed_lints = vec![
+    let lints_to_show = vec![
         intra_link_resolution_failure_name.to_owned(),
         missing_docs.to_owned(),
         missing_doc_example.to_owned(),
         private_doc_tests.to_owned(),
         no_crate_level_docs.to_owned(),
         invalid_codeblock_attributes_name.to_owned(),
+        renamed_and_removed_lints.to_owned(),
+        unknown_lints.to_owned(),
     ];
 
-    let (lint_opts, lint_caps) = init_lints(allowed_lints, lint_opts, |lint| {
+    let (lint_opts, lint_caps) = init_lints(lints_to_show, lint_opts, |lint| {
         if lint.name == intra_link_resolution_failure_name
             || lint.name == invalid_codeblock_attributes_name
         {
@@ -351,13 +362,13 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
         search_paths: libs,
         crate_types,
         lint_opts: if !display_warnings { lint_opts } else { vec![] },
-        lint_cap: Some(lint_cap.unwrap_or_else(|| lint::Forbid)),
+        lint_cap,
         cg: codegen_options,
         externs,
         target_triple: target,
         unstable_features: UnstableFeatures::from_environment(),
         actually_rustdoc: true,
-        debugging_opts: debugging_options,
+        debugging_opts,
         error_format,
         edition,
         describe_lints,
@@ -402,7 +413,9 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
                 let hir = tcx.hir();
                 let body = hir.body(hir.body_owned_by(hir.local_def_id_to_hir_id(def_id)));
                 debug!("visiting body for {:?}", def_id);
-                EmitIgnoredResolutionErrors::new(tcx).visit_body(body);
+                tcx.sess.time("emit_ignored_resolution_errors", || {
+                    EmitIgnoredResolutionErrors::new(tcx).visit_body(body);
+                });
                 (rustc_interface::DEFAULT_QUERY_PROVIDERS.typeck)(tcx, def_id)
             };
         }),
@@ -424,18 +437,20 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
                 // actually be loaded, just in case they're only referred to inside
                 // intra-doc-links
                 resolver.borrow_mut().access(|resolver| {
-                    for extern_name in &extern_names {
-                        resolver
-                            .resolve_str_path_error(
-                                DUMMY_SP,
-                                extern_name,
-                                TypeNS,
-                                LocalDefId { local_def_index: CRATE_DEF_INDEX }.to_def_id(),
-                            )
-                            .unwrap_or_else(|()| {
-                                panic!("Unable to resolve external crate {}", extern_name)
-                            });
-                    }
+                    sess.time("load_extern_crates", || {
+                        for extern_name in &extern_names {
+                            resolver
+                                .resolve_str_path_error(
+                                    DUMMY_SP,
+                                    extern_name,
+                                    TypeNS,
+                                    LocalDefId { local_def_index: CRATE_DEF_INDEX }.to_def_id(),
+                                )
+                                .unwrap_or_else(|()| {
+                                    panic!("Unable to resolve external crate {}", extern_name)
+                                });
+                        }
+                    });
                 });
 
                 // Now we're good to clone the resolver because everything should be loaded
@@ -448,180 +463,201 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
 
             let mut global_ctxt = abort_on_err(queries.global_ctxt(), sess).take();
 
-            global_ctxt.enter(|tcx| {
-                // Certain queries assume that some checks were run elsewhere
-                // (see https://github.com/rust-lang/rust/pull/73566#issuecomment-656954425),
-                // so type-check everything other than function bodies in this crate before running lints.
+            let (krate, render_info, opts) = sess.time("run_global_ctxt", || {
+                global_ctxt.enter(|tcx| {
+                    run_global_ctxt(
+                        tcx,
+                        resolver,
+                        default_passes,
+                        manual_passes,
+                        render_options,
+                        output_format,
+                    )
+                })
+            });
+            (krate, render_info, opts, Lrc::clone(sess))
+        })
+    })
+}
 
-                // NOTE: this does not call `tcx.analysis()` so that we won't
-                // typeck function bodies or run the default rustc lints.
-                // (see `override_queries` in the `config`)
+fn run_global_ctxt(
+    tcx: TyCtxt<'_>,
+    resolver: Rc<RefCell<interface::BoxedResolver>>,
+    mut default_passes: passes::DefaultPassOption,
+    mut manual_passes: Vec<String>,
+    render_options: RenderOptions,
+    output_format: Option<OutputFormat>,
+) -> (clean::Crate, RenderInfo, RenderOptions) {
+    // Certain queries assume that some checks were run elsewhere
+    // (see https://github.com/rust-lang/rust/pull/73566#issuecomment-656954425),
+    // so type-check everything other than function bodies in this crate before running lints.
+
+    // NOTE: this does not call `tcx.analysis()` so that we won't
+    // typeck function bodies or run the default rustc lints.
+    // (see `override_queries` in the `config`)
+
+    // HACK(jynelson) this calls an _extremely_ limited subset of `typeck`
+    // and might break if queries change their assumptions in the future.
+
+    // NOTE: This is copy/pasted from typeck/lib.rs and should be kept in sync with those changes.
+    tcx.sess.time("item_types_checking", || {
+        for &module in tcx.hir().krate().modules.keys() {
+            tcx.ensure().check_mod_item_types(tcx.hir().local_def_id(module));
+        }
+    });
+    tcx.sess.abort_if_errors();
+    tcx.sess.time("missing_docs", || {
+        rustc_lint::check_crate(tcx, rustc_lint::builtin::MissingDoc::new);
+    });
+    tcx.sess.time("check_mod_attrs", || {
+        for &module in tcx.hir().krate().modules.keys() {
+            let local_def_id = tcx.hir().local_def_id(module);
+            tcx.ensure().check_mod_attrs(local_def_id);
+        }
+    });
 
-                // HACK(jynelson) this calls an _extremely_ limited subset of `typeck`
-                // and might break if queries change their assumptions in the future.
+    let access_levels = tcx.privacy_access_levels(LOCAL_CRATE);
+    // Convert from a HirId set to a DefId set since we don't always have easy access
+    // to the map from defid -> hirid
+    let access_levels = AccessLevels {
+        map: access_levels
+            .map
+            .iter()
+            .map(|(&k, &v)| (tcx.hir().local_def_id(k).to_def_id(), v))
+            .collect(),
+    };
 
-                // NOTE: This is copy/pasted from typeck/lib.rs and should be kept in sync with those changes.
-                tcx.sess.time("item_types_checking", || {
-                    for &module in tcx.hir().krate().modules.keys() {
-                        tcx.ensure().check_mod_item_types(tcx.hir().local_def_id(module));
-                    }
-                });
-                tcx.sess.abort_if_errors();
-                sess.time("missing_docs", || {
-                    rustc_lint::check_crate(tcx, rustc_lint::builtin::MissingDoc::new);
-                });
-                for &module in tcx.hir().krate().modules.keys() {
-                    let local_def_id = tcx.hir().local_def_id(module);
-                    tcx.ensure().check_mod_attrs(local_def_id);
-                }
+    let mut renderinfo = RenderInfo::default();
+    renderinfo.access_levels = access_levels;
+    renderinfo.output_format = output_format;
+
+    let mut ctxt = DocContext {
+        tcx,
+        resolver,
+        external_traits: Default::default(),
+        active_extern_traits: Default::default(),
+        renderinfo: RefCell::new(renderinfo),
+        ty_substs: Default::default(),
+        lt_substs: Default::default(),
+        ct_substs: Default::default(),
+        impl_trait_bounds: Default::default(),
+        fake_def_ids: Default::default(),
+        all_fake_def_ids: Default::default(),
+        generated_synthetics: Default::default(),
+        auto_traits: tcx
+            .all_traits(LOCAL_CRATE)
+            .iter()
+            .cloned()
+            .filter(|trait_def_id| tcx.trait_is_auto(*trait_def_id))
+            .collect(),
+        render_options,
+        module_trait_cache: RefCell::new(FxHashMap::default()),
+    };
+    debug!("crate: {:?}", tcx.hir().krate());
+
+    let mut krate = tcx.sess.time("clean_crate", || clean::krate(&mut ctxt));
+
+    if let Some(ref m) = krate.module {
+        if let None | Some("") = m.doc_value() {
+            let help = "The following guide may be of use:\n\
+                    https://doc.rust-lang.org/nightly/rustdoc/how-to-write-documentation\
+                    .html";
+            tcx.struct_lint_node(
+                rustc_lint::builtin::MISSING_CRATE_LEVEL_DOCS,
+                ctxt.as_local_hir_id(m.def_id).unwrap(),
+                |lint| {
+                    let mut diag =
+                        lint.build("no documentation found for this crate's top-level module");
+                    diag.help(help);
+                    diag.emit();
+                },
+            );
+        }
+    }
 
-                let access_levels = tcx.privacy_access_levels(LOCAL_CRATE);
-                // Convert from a HirId set to a DefId set since we don't always have easy access
-                // to the map from defid -> hirid
-                let access_levels = AccessLevels {
-                    map: access_levels
-                        .map
-                        .iter()
-                        .map(|(&k, &v)| (tcx.hir().local_def_id(k).to_def_id(), v))
-                        .collect(),
-                };
-
-                let mut renderinfo = RenderInfo::default();
-                renderinfo.access_levels = access_levels;
-                renderinfo.output_format = output_format;
-
-                let mut ctxt = DocContext {
-                    tcx,
-                    resolver,
-                    external_traits: Default::default(),
-                    active_extern_traits: Default::default(),
-                    renderinfo: RefCell::new(renderinfo),
-                    ty_substs: Default::default(),
-                    lt_substs: Default::default(),
-                    ct_substs: Default::default(),
-                    impl_trait_bounds: Default::default(),
-                    fake_def_ids: Default::default(),
-                    all_fake_def_ids: Default::default(),
-                    generated_synthetics: Default::default(),
-                    auto_traits: tcx
-                        .all_traits(LOCAL_CRATE)
-                        .iter()
-                        .cloned()
-                        .filter(|trait_def_id| tcx.trait_is_auto(*trait_def_id))
-                        .collect(),
-                    render_options,
-                };
-                debug!("crate: {:?}", tcx.hir().krate());
-
-                let mut krate = clean::krate(&mut ctxt);
-
-                if let Some(ref m) = krate.module {
-                    if let None | Some("") = m.doc_value() {
-                        let help = "The following guide may be of use:\n\
-                             https://doc.rust-lang.org/nightly/rustdoc/how-to-write-documentation\
-                             .html";
-                        tcx.struct_lint_node(
-                            rustc_lint::builtin::MISSING_CRATE_LEVEL_DOCS,
-                            ctxt.as_local_hir_id(m.def_id).unwrap(),
-                            |lint| {
-                                let mut diag = lint.build(
-                                    "no documentation found for this crate's top-level module",
-                                );
-                                diag.help(help);
-                                diag.emit();
-                            },
-                        );
-                    }
-                }
+    fn report_deprecated_attr(name: &str, diag: &rustc_errors::Handler) {
+        let mut msg = diag
+            .struct_warn(&format!("the `#![doc({})]` attribute is considered deprecated", name));
+        msg.warn(
+            "see issue #44136 <https://github.com/rust-lang/rust/issues/44136> \
+                for more information",
+        );
 
-                fn report_deprecated_attr(name: &str, diag: &rustc_errors::Handler) {
-                    let mut msg = diag.struct_warn(&format!(
-                        "the `#![doc({})]` attribute is considered deprecated",
-                        name
-                    ));
-                    msg.warn(
-                        "see issue #44136 <https://github.com/rust-lang/rust/issues/44136> \
-                         for more information",
-                    );
+        if name == "no_default_passes" {
+            msg.help("you may want to use `#![doc(document_private_items)]`");
+        }
 
-                    if name == "no_default_passes" {
-                        msg.help("you may want to use `#![doc(document_private_items)]`");
-                    }
+        msg.emit();
+    }
 
-                    msg.emit();
+    // Process all of the crate attributes, extracting plugin metadata along
+    // with the passes which we are supposed to run.
+    for attr in krate.module.as_ref().unwrap().attrs.lists(sym::doc) {
+        let diag = ctxt.sess().diagnostic();
+
+        let name = attr.name_or_empty();
+        if attr.is_word() {
+            if name == sym::no_default_passes {
+                report_deprecated_attr("no_default_passes", diag);
+                if default_passes == passes::DefaultPassOption::Default {
+                    default_passes = passes::DefaultPassOption::None;
+                }
+            }
+        } else if let Some(value) = attr.value_str() {
+            let sink = match name {
+                sym::passes => {
+                    report_deprecated_attr("passes = \"...\"", diag);
+                    &mut manual_passes
                 }
+                sym::plugins => {
+                    report_deprecated_attr("plugins = \"...\"", diag);
+                    eprintln!(
+                        "WARNING: `#![doc(plugins = \"...\")]` \
+                            no longer functions; see CVE-2018-1000622"
+                    );
+                    continue;
+                }
+                _ => continue,
+            };
+            for name in value.as_str().split_whitespace() {
+                sink.push(name.to_string());
+            }
+        }
 
-                // Process all of the crate attributes, extracting plugin metadata along
-                // with the passes which we are supposed to run.
-                for attr in krate.module.as_ref().unwrap().attrs.lists(sym::doc) {
-                    let diag = ctxt.sess().diagnostic();
-
-                    let name = attr.name_or_empty();
-                    if attr.is_word() {
-                        if name == sym::no_default_passes {
-                            report_deprecated_attr("no_default_passes", diag);
-                            if default_passes == passes::DefaultPassOption::Default {
-                                default_passes = passes::DefaultPassOption::None;
-                            }
-                        }
-                    } else if let Some(value) = attr.value_str() {
-                        let sink = match name {
-                            sym::passes => {
-                                report_deprecated_attr("passes = \"...\"", diag);
-                                &mut manual_passes
-                            }
-                            sym::plugins => {
-                                report_deprecated_attr("plugins = \"...\"", diag);
-                                eprintln!(
-                                    "WARNING: `#![doc(plugins = \"...\")]` \
-                                      no longer functions; see CVE-2018-1000622"
-                                );
-                                continue;
-                            }
-                            _ => continue,
-                        };
-                        for name in value.as_str().split_whitespace() {
-                            sink.push(name.to_string());
-                        }
-                    }
+        if attr.is_word() && name == sym::document_private_items {
+            ctxt.render_options.document_private = true;
+        }
+    }
 
-                    if attr.is_word() && name == sym::document_private_items {
-                        ctxt.render_options.document_private = true;
-                    }
-                }
+    let passes = passes::defaults(default_passes).iter().copied().chain(
+        manual_passes.into_iter().flat_map(|name| {
+            if let Some(pass) = passes::find_pass(&name) {
+                Some(ConditionalPass::always(pass))
+            } else {
+                error!("unknown pass {}, skipping", name);
+                None
+            }
+        }),
+    );
 
-                let passes = passes::defaults(default_passes).iter().copied().chain(
-                    manual_passes.into_iter().flat_map(|name| {
-                        if let Some(pass) = passes::find_pass(&name) {
-                            Some(ConditionalPass::always(pass))
-                        } else {
-                            error!("unknown pass {}, skipping", name);
-                            None
-                        }
-                    }),
-                );
-
-                info!("Executing passes");
-
-                for p in passes {
-                    let run = match p.condition {
-                        Always => true,
-                        WhenDocumentPrivate => ctxt.render_options.document_private,
-                        WhenNotDocumentPrivate => !ctxt.render_options.document_private,
-                        WhenNotDocumentHidden => !ctxt.render_options.document_hidden,
-                    };
-                    if run {
-                        debug!("running pass {}", p.pass.name);
-                        krate = (p.pass.run)(krate, &ctxt);
-                    }
-                }
+    info!("Executing passes");
 
-                ctxt.sess().abort_if_errors();
+    for p in passes {
+        let run = match p.condition {
+            Always => true,
+            WhenDocumentPrivate => ctxt.render_options.document_private,
+            WhenNotDocumentPrivate => !ctxt.render_options.document_private,
+            WhenNotDocumentHidden => !ctxt.render_options.document_hidden,
+        };
+        if run {
+            debug!("running pass {}", p.pass.name);
+            krate = ctxt.tcx.sess.time(p.pass.name, || (p.pass.run)(krate, &ctxt));
+        }
+    }
 
-                (krate, ctxt.renderinfo.into_inner(), ctxt.render_options)
-            })
-        })
-    })
+    ctxt.sess().abort_if_errors();
+
+    (krate, ctxt.renderinfo.into_inner(), ctxt.render_options)
 }
 
 /// Due to https://github.com/rust-lang/rust/pull/73566,
index bd919205dd1761b76c9cd010df00fbd57cc5f1af..d17961521c87d33f14b2899a8f2bd13978dbcf3d 100644 (file)
@@ -3612,7 +3612,7 @@ fn doc_impl_item(
         };
 
         let (is_hidden, extra_class) =
-            if (trait_.is_none() || item.doc_value().is_some() || item.inner.is_associated())
+            if (trait_.is_none() || item.doc_value().is_some() || item.inner.is_type_alias())
                 && !is_default_item
             {
                 (false, "")
index 3dfa7b529e34cc42e084af05fe31f2e8294e5b87..b5e246b5d17a56a1f3d5d29a63d2654f8ac1a074 100644 (file)
@@ -9,7 +9,6 @@
 #![feature(nll)]
 #![feature(or_patterns)]
 #![feature(test)]
-#![feature(ptr_offset_from)]
 #![feature(crate_visibility_modifier)]
 #![feature(never_type)]
 #![feature(once_cell)]
@@ -473,7 +472,7 @@ fn run_renderer<T: formats::FormatRenderer>(
 }
 
 fn main_options(options: config::Options) -> MainResult {
-    let diag = core::new_handler(options.error_format, None, &options.debugging_options);
+    let diag = core::new_handler(options.error_format, None, &options.debugging_opts);
 
     match (options.should_test, options.markdown_input()) {
         (true, true) => return wrap_return(&diag, markdown::test(options)),
@@ -489,7 +488,7 @@ fn main_options(options: config::Options) -> MainResult {
 
     // need to move these items separately because we lose them by the time the closure is called,
     // but we can't crates the Handler ahead of time because it's not Send
-    let diag_opts = (options.error_format, options.edition, options.debugging_options.clone());
+    let diag_opts = (options.error_format, options.edition, options.debugging_opts.clone());
     let show_coverage = options.show_coverage;
 
     // First, parse the crate and extract all relevant information.
@@ -502,7 +501,7 @@ fn main_options(options: config::Options) -> MainResult {
     let crate_name = options.crate_name.clone();
     let crate_version = options.crate_version.clone();
     let output_format = options.output_format;
-    let (mut krate, renderinfo, renderopts) = core::run_core(options);
+    let (mut krate, renderinfo, renderopts, sess) = core::run_core(options);
 
     info!("finished with rustc");
 
@@ -525,11 +524,11 @@ fn main_options(options: config::Options) -> MainResult {
     let (error_format, edition, debugging_options) = diag_opts;
     let diag = core::new_handler(error_format, None, &debugging_options);
     match output_format {
-        None | Some(config::OutputFormat::Html) => {
+        None | Some(config::OutputFormat::Html) => sess.time("render_html", || {
             run_renderer::<html::render::Context>(krate, renderopts, renderinfo, &diag, edition)
-        }
-        Some(config::OutputFormat::Json) => {
+        }),
+        Some(config::OutputFormat::Json) => sess.time("render_json", || {
             run_renderer::<json::JsonRenderer>(krate, renderopts, renderinfo, &diag, edition)
-        }
+        }),
     }
 }
index 0a836f46c0eb85bc96bc861e94f3af109e58eb1c..671e082556722e8e08ef94c0700cbc52135e6d24 100644 (file)
@@ -3,7 +3,7 @@
 use crate::core::DocContext;
 use crate::fold::{self, DocFolder};
 use crate::html::markdown::{find_testable_code, ErrorCodes};
-use crate::passes::doc_test_lints::Tests;
+use crate::passes::doc_test_lints::{should_have_doc_example, Tests};
 use crate::passes::Pass;
 use rustc_span::symbol::sym;
 use rustc_span::FileName;
@@ -27,20 +27,29 @@ fn calculate_doc_coverage(krate: clean::Crate, ctx: &DocContext<'_>) -> clean::C
     krate
 }
 
-#[derive(Default, Copy, Clone, Serialize)]
+#[derive(Default, Copy, Clone, Serialize, Debug)]
 struct ItemCount {
     total: u64,
     with_docs: u64,
+    total_examples: u64,
     with_examples: u64,
 }
 
 impl ItemCount {
-    fn count_item(&mut self, has_docs: bool, has_doc_example: bool) {
+    fn count_item(
+        &mut self,
+        has_docs: bool,
+        has_doc_example: bool,
+        should_have_doc_examples: bool,
+    ) {
         self.total += 1;
 
         if has_docs {
             self.with_docs += 1;
         }
+        if should_have_doc_examples || has_doc_example {
+            self.total_examples += 1;
+        }
         if has_doc_example {
             self.with_examples += 1;
         }
@@ -55,8 +64,8 @@ fn percentage(&self) -> Option<f64> {
     }
 
     fn examples_percentage(&self) -> Option<f64> {
-        if self.total > 0 {
-            Some((self.with_examples as f64 * 100.0) / self.total as f64)
+        if self.total_examples > 0 {
+            Some((self.with_examples as f64 * 100.0) / self.total_examples as f64)
         } else {
             None
         }
@@ -70,6 +79,7 @@ fn sub(self, rhs: Self) -> Self {
         ItemCount {
             total: self.total - rhs.total,
             with_docs: self.with_docs - rhs.with_docs,
+            total_examples: self.total_examples - rhs.total_examples,
             with_examples: self.with_examples - rhs.with_examples,
         }
     }
@@ -79,6 +89,7 @@ impl ops::AddAssign for ItemCount {
     fn add_assign(&mut self, rhs: Self) {
         self.total += rhs.total;
         self.with_docs += rhs.with_docs;
+        self.total_examples += rhs.total_examples;
         self.with_examples += rhs.with_examples;
     }
 }
@@ -121,7 +132,7 @@ fn print_results(&self, output_format: Option<OutputFormat>) {
         let mut total = ItemCount::default();
 
         fn print_table_line() {
-            println!("+-{0:->35}-+-{0:->10}-+-{0:->10}-+-{0:->10}-+-{0:->10}-+-{0:->10}-+", "");
+            println!("+-{0:->35}-+-{0:->10}-+-{0:->10}-+-{0:->10}-+-{0:->10}-+", "");
         }
 
         fn print_table_record(
@@ -131,32 +142,25 @@ fn print_table_record(
             examples_percentage: f64,
         ) {
             println!(
-                "| {:<35} | {:>10} | {:>10} | {:>9.1}% | {:>10} | {:>9.1}% |",
-                name,
-                count.with_docs,
-                count.total,
-                percentage,
-                count.with_examples,
-                examples_percentage,
+                "| {:<35} | {:>10} | {:>9.1}% | {:>10} | {:>9.1}% |",
+                name, count.with_docs, percentage, count.with_examples, examples_percentage,
             );
         }
 
         print_table_line();
         println!(
-            "| {:<35} | {:>10} | {:>10} | {:>10} | {:>10} | {:>10} |",
-            "File", "Documented", "Total", "Percentage", "Examples", "Percentage",
+            "| {:<35} | {:>10} | {:>10} | {:>10} | {:>10} |",
+            "File", "Documented", "Percentage", "Examples", "Percentage",
         );
         print_table_line();
 
         for (file, &count) in &self.items {
-            if let (Some(percentage), Some(examples_percentage)) =
-                (count.percentage(), count.examples_percentage())
-            {
+            if let Some(percentage) = count.percentage() {
                 print_table_record(
                     &limit_filename_len(file.to_string()),
                     count,
                     percentage,
-                    examples_percentage,
+                    count.examples_percentage().unwrap_or(0.),
                 );
 
                 total += count;
@@ -176,19 +180,6 @@ fn print_table_record(
 
 impl fold::DocFolder for CoverageCalculator {
     fn fold_item(&mut self, i: clean::Item) -> Option<clean::Item> {
-        let has_docs = !i.attrs.doc_strings.is_empty();
-        let mut tests = Tests { found_tests: 0 };
-
-        find_testable_code(
-            &i.attrs.doc_strings.iter().map(|d| d.as_str()).collect::<Vec<_>>().join("\n"),
-            &mut tests,
-            ErrorCodes::No,
-            false,
-            None,
-        );
-
-        let has_doc_example = tests.found_tests != 0;
-
         match i.inner {
             _ if !i.def_id.is_local() => {
                 // non-local items are skipped because they can be out of the users control,
@@ -237,11 +228,24 @@ fn fold_item(&mut self, i: clean::Item) -> Option<clean::Item> {
                 }
             }
             _ => {
+                let has_docs = !i.attrs.doc_strings.is_empty();
+                let mut tests = Tests { found_tests: 0 };
+
+                find_testable_code(
+                    &i.attrs.doc_strings.iter().map(|d| d.as_str()).collect::<Vec<_>>().join("\n"),
+                    &mut tests,
+                    ErrorCodes::No,
+                    false,
+                    None,
+                );
+
+                let has_doc_example = tests.found_tests != 0;
                 debug!("counting {:?} {:?} in {}", i.type_(), i.name, i.source.filename);
-                self.items
-                    .entry(i.source.filename.clone())
-                    .or_default()
-                    .count_item(has_docs, has_doc_example);
+                self.items.entry(i.source.filename.clone()).or_default().count_item(
+                    has_docs,
+                    has_doc_example,
+                    should_have_doc_example(&i.inner),
+                );
             }
         }
 
index 97b9fcce05b362e72d2ddd06926a5151256cea00..bf091a0a624ddabb9be98d87e3d3066affeb4a7c 100644 (file)
@@ -1,4 +1,5 @@
 use rustc_ast as ast;
+use rustc_data_structures::stable_set::FxHashSet;
 use rustc_errors::{Applicability, DiagnosticBuilder};
 use rustc_expand::base::SyntaxExtensionKind;
 use rustc_feature::UnstableFeatures;
@@ -180,12 +181,10 @@ fn macro_resolve(&self, path_str: &str, parent_id: Option<DefId>) -> Option<Res>
     fn resolve(
         &self,
         path_str: &str,
-        disambiguator: Option<Disambiguator>,
         ns: Namespace,
         current_item: &Option<String>,
         parent_id: Option<DefId>,
         extra_fragment: &Option<String>,
-        item_opt: Option<&Item>,
     ) -> Result<(Res, Option<String>), ErrorKind> {
         let cx = self.cx;
 
@@ -218,18 +217,6 @@ fn resolve(
                         return Ok((res, Some(path_str.to_owned())));
                     }
                     Res::Def(DefKind::Mod, _) => {
-                        // This resolved to a module, but we want primitive types to take precedence instead.
-                        if matches!(
-                            disambiguator,
-                            None | Some(Disambiguator::Namespace(Namespace::TypeNS))
-                        ) {
-                            if let Some((path, prim)) = is_primitive(path_str, ns) {
-                                if extra_fragment.is_some() {
-                                    return Err(ErrorKind::AnchorFailure(AnchorFailure::Primitive));
-                                }
-                                return Ok((prim, Some(path.to_owned())));
-                            }
-                        }
                         return Ok((res, extra_fragment.clone()));
                     }
                     _ => {
@@ -245,13 +232,6 @@ fn resolve(
                     return Err(ErrorKind::AnchorFailure(AnchorFailure::Primitive));
                 }
                 return Ok((prim, Some(path.to_owned())));
-            } else {
-                // If resolution failed, it may still be a method
-                // because methods are not handled by the resolver
-                // If so, bail when we're not looking for a value.
-                if ns != ValueNS {
-                    return Err(ErrorKind::ResolutionFailure);
-                }
             }
 
             // Try looking for methods and associated items.
@@ -299,65 +279,56 @@ fn resolve(
                 })
                 .map_err(|_| ErrorKind::ResolutionFailure)?;
             if let Res::Err = ty_res {
-                return self.variant_field(path_str, current_item, module_id);
+                return if ns == Namespace::ValueNS {
+                    self.variant_field(path_str, current_item, module_id)
+                } else {
+                    Err(ErrorKind::ResolutionFailure)
+                };
             }
             let ty_res = ty_res.map_id(|_| panic!("unexpected node_id"));
-            match ty_res {
+            let res = match ty_res {
                 Res::Def(
                     DefKind::Struct | DefKind::Union | DefKind::Enum | DefKind::TyAlias,
                     did,
                 ) => {
+                    debug!("looking for associated item named {} for item {:?}", item_name, did);
                     // Checks if item_name belongs to `impl SomeItem`
-                    let impl_item = cx
+                    let kind = cx
                         .tcx
                         .inherent_impls(did)
                         .iter()
-                        .flat_map(|imp| cx.tcx.associated_items(*imp).in_definition_order())
-                        .find(|item| item.ident.name == item_name);
-                    let trait_item = item_opt
-                        .and_then(|item| self.cx.as_local_hir_id(item.def_id))
-                        .and_then(|item_hir| {
-                            // Checks if item_name belongs to `impl SomeTrait for SomeItem`
-                            let parent_hir = self.cx.tcx.hir().get_parent_item(item_hir);
-                            let item_parent = self.cx.tcx.hir().find(parent_hir);
-                            match item_parent {
-                                Some(hir::Node::Item(hir::Item {
-                                    kind: hir::ItemKind::Impl { of_trait: Some(_), self_ty, .. },
-                                    ..
-                                })) => cx
-                                    .tcx
-                                    .associated_item_def_ids(self_ty.hir_id.owner)
-                                    .iter()
-                                    .map(|child| {
-                                        let associated_item = cx.tcx.associated_item(*child);
-                                        associated_item
-                                    })
-                                    .find(|child| child.ident.name == item_name),
-                                _ => None,
-                            }
+                        .flat_map(|&imp| {
+                            cx.tcx.associated_items(imp).find_by_name_and_namespace(
+                                cx.tcx,
+                                Ident::with_dummy_span(item_name),
+                                ns,
+                                imp,
+                            )
+                        })
+                        .map(|item| item.kind)
+                        // There should only ever be one associated item that matches from any inherent impl
+                        .next()
+                        // Check if item_name belongs to `impl SomeTrait for SomeItem`
+                        // This gives precedence to `impl SomeItem`:
+                        // Although having both would be ambiguous, use impl version for compat. sake.
+                        // To handle that properly resolve() would have to support
+                        // something like [`ambi_fn`](<SomeStruct as SomeTrait>::ambi_fn)
+                        .or_else(|| {
+                            let kind = resolve_associated_trait_item(
+                                did, module_id, item_name, ns, &self.cx,
+                            );
+                            debug!("got associated item kind {:?}", kind);
+                            kind
                         });
-                    let item = match (impl_item, trait_item) {
-                        (Some(from_impl), Some(_)) => {
-                            // Although it's ambiguous, return impl version for compat. sake.
-                            // To handle that properly resolve() would have to support
-                            // something like
-                            // [`ambi_fn`](<SomeStruct as SomeTrait>::ambi_fn)
-                            Some(from_impl)
-                        }
-                        (None, Some(from_trait)) => Some(from_trait),
-                        (Some(from_impl), None) => Some(from_impl),
-                        _ => None,
-                    };
-
-                    if let Some(item) = item {
-                        let out = match item.kind {
-                            ty::AssocKind::Fn if ns == ValueNS => "method",
-                            ty::AssocKind::Const if ns == ValueNS => "associatedconstant",
-                            ty::AssocKind::Type if ns == ValueNS => "associatedtype",
-                            _ => return self.variant_field(path_str, current_item, module_id),
+
+                    if let Some(kind) = kind {
+                        let out = match kind {
+                            ty::AssocKind::Fn => "method",
+                            ty::AssocKind::Const => "associatedconstant",
+                            ty::AssocKind::Type => "associatedtype",
                         };
-                        if extra_fragment.is_some() {
-                            Err(ErrorKind::AnchorFailure(if item.kind == ty::AssocKind::Fn {
+                        Some(if extra_fragment.is_some() {
+                            Err(ErrorKind::AnchorFailure(if kind == ty::AssocKind::Fn {
                                 AnchorFailure::Method
                             } else {
                                 AnchorFailure::AssocConstant
@@ -366,20 +337,21 @@ fn resolve(
                             // HACK(jynelson): `clean` expects the type, not the associated item.
                             // but the disambiguator logic expects the associated item.
                             // Store the kind in a side channel so that only the disambiguator logic looks at it.
-                            self.kind_side_channel.replace(Some(item.kind.as_def_kind()));
+                            self.kind_side_channel.set(Some(kind.as_def_kind()));
                             Ok((ty_res, Some(format!("{}.{}", out, item_name))))
-                        }
-                    } else {
+                        })
+                    } else if ns == Namespace::ValueNS {
                         match cx.tcx.type_of(did).kind {
                             ty::Adt(def, _) => {
-                                if let Some(item) = if def.is_enum() {
+                                let field = if def.is_enum() {
                                     def.all_fields().find(|item| item.ident.name == item_name)
                                 } else {
                                     def.non_enum_variant()
                                         .fields
                                         .iter()
                                         .find(|item| item.ident.name == item_name)
-                                } {
+                                };
+                                field.map(|item| {
                                     if extra_fragment.is_some() {
                                         Err(ErrorKind::AnchorFailure(if def.is_enum() {
                                             AnchorFailure::Variant
@@ -400,31 +372,31 @@ fn resolve(
                                             )),
                                         ))
                                     }
-                                } else {
-                                    self.variant_field(path_str, current_item, module_id)
-                                }
+                                })
                             }
-                            _ => self.variant_field(path_str, current_item, module_id),
+                            _ => None,
                         }
+                    } else {
+                        // We already know this isn't in ValueNS, so no need to check variant_field
+                        return Err(ErrorKind::ResolutionFailure);
                     }
                 }
-                Res::Def(DefKind::Trait, did) => {
-                    let item = cx
-                        .tcx
-                        .associated_item_def_ids(did)
-                        .iter()
-                        .map(|item| cx.tcx.associated_item(*item))
-                        .find(|item| item.ident.name == item_name);
-                    if let Some(item) = item {
-                        let kind =
-                            match item.kind {
-                                ty::AssocKind::Const if ns == ValueNS => "associatedconstant",
-                                ty::AssocKind::Type if ns == TypeNS => "associatedtype",
-                                ty::AssocKind::Fn if ns == ValueNS => {
-                                    if item.defaultness.has_value() { "method" } else { "tymethod" }
+                Res::Def(DefKind::Trait, did) => cx
+                    .tcx
+                    .associated_items(did)
+                    .find_by_name_and_namespace(cx.tcx, Ident::with_dummy_span(item_name), ns, did)
+                    .map(|item| {
+                        let kind = match item.kind {
+                            ty::AssocKind::Const => "associatedconstant",
+                            ty::AssocKind::Type => "associatedtype",
+                            ty::AssocKind::Fn => {
+                                if item.defaultness.has_value() {
+                                    "method"
+                                } else {
+                                    "tymethod"
                                 }
-                                _ => return self.variant_field(path_str, current_item, module_id),
-                            };
+                            }
+                        };
 
                         if extra_fragment.is_some() {
                             Err(ErrorKind::AnchorFailure(if item.kind == ty::AssocKind::Const {
@@ -438,12 +410,16 @@ fn resolve(
                             let res = Res::Def(item.kind.as_def_kind(), item.def_id);
                             Ok((res, Some(format!("{}.{}", kind, item_name))))
                         }
-                    } else {
-                        self.variant_field(path_str, current_item, module_id)
-                    }
+                    }),
+                _ => None,
+            };
+            res.unwrap_or_else(|| {
+                if ns == Namespace::ValueNS {
+                    self.variant_field(path_str, current_item, module_id)
+                } else {
+                    Err(ErrorKind::ResolutionFailure)
                 }
-                _ => self.variant_field(path_str, current_item, module_id),
-            }
+            })
         } else {
             debug!("attempting to resolve item without parent module: {}", path_str);
             Err(ErrorKind::ResolutionFailure)
@@ -451,6 +427,134 @@ fn resolve(
     }
 }
 
+fn resolve_associated_trait_item(
+    did: DefId,
+    module: DefId,
+    item_name: Symbol,
+    ns: Namespace,
+    cx: &DocContext<'_>,
+) -> Option<ty::AssocKind> {
+    let ty = cx.tcx.type_of(did);
+    // First consider automatic impls: `impl From<T> for T`
+    let implicit_impls = crate::clean::get_auto_trait_and_blanket_impls(cx, ty, did);
+    let mut candidates: Vec<_> = implicit_impls
+        .flat_map(|impl_outer| {
+            match impl_outer.inner {
+                ImplItem(impl_) => {
+                    debug!("considering auto or blanket impl for trait {:?}", impl_.trait_);
+                    // Give precedence to methods that were overridden
+                    if !impl_.provided_trait_methods.contains(&*item_name.as_str()) {
+                        let mut items = impl_.items.into_iter().filter_map(|assoc| {
+                            if assoc.name.as_deref() != Some(&*item_name.as_str()) {
+                                return None;
+                            }
+                            let kind = assoc
+                                .inner
+                                .as_assoc_kind()
+                                .expect("inner items for a trait should be associated items");
+                            if kind.namespace() != ns {
+                                return None;
+                            }
+
+                            trace!("considering associated item {:?}", assoc.inner);
+                            // We have a slight issue: normal methods come from `clean` types,
+                            // but provided methods come directly from `tcx`.
+                            // Fortunately, we don't need the whole method, we just need to know
+                            // what kind of associated item it is.
+                            Some((assoc.def_id, kind))
+                        });
+                        let assoc = items.next();
+                        debug_assert_eq!(items.count(), 0);
+                        assoc
+                    } else {
+                        // These are provided methods or default types:
+                        // ```
+                        // trait T {
+                        //   type A = usize;
+                        //   fn has_default() -> A { 0 }
+                        // }
+                        // ```
+                        let trait_ = impl_.trait_.unwrap().def_id().unwrap();
+                        cx.tcx
+                            .associated_items(trait_)
+                            .find_by_name_and_namespace(
+                                cx.tcx,
+                                Ident::with_dummy_span(item_name),
+                                ns,
+                                trait_,
+                            )
+                            .map(|assoc| (assoc.def_id, assoc.kind))
+                    }
+                }
+                _ => panic!("get_impls returned something that wasn't an impl"),
+            }
+        })
+        .collect();
+
+    // Next consider explicit impls: `impl MyTrait for MyType`
+    // Give precedence to inherent impls.
+    if candidates.is_empty() {
+        let traits = traits_implemented_by(cx, did, module);
+        debug!("considering traits {:?}", traits);
+        candidates.extend(traits.iter().filter_map(|&trait_| {
+            cx.tcx
+                .associated_items(trait_)
+                .find_by_name_and_namespace(cx.tcx, Ident::with_dummy_span(item_name), ns, trait_)
+                .map(|assoc| (assoc.def_id, assoc.kind))
+        }));
+    }
+    // FIXME: warn about ambiguity
+    debug!("the candidates were {:?}", candidates);
+    candidates.pop().map(|(_, kind)| kind)
+}
+
+/// Given a type, return all traits in scope in `module` implemented by that type.
+///
+/// NOTE: this cannot be a query because more traits could be available when more crates are compiled!
+/// So it is not stable to serialize cross-crate.
+fn traits_implemented_by(cx: &DocContext<'_>, type_: DefId, module: DefId) -> FxHashSet<DefId> {
+    let mut cache = cx.module_trait_cache.borrow_mut();
+    let in_scope_traits = cache.entry(module).or_insert_with(|| {
+        cx.enter_resolver(|resolver| {
+            resolver.traits_in_scope(module).into_iter().map(|candidate| candidate.def_id).collect()
+        })
+    });
+
+    let ty = cx.tcx.type_of(type_);
+    let iter = in_scope_traits.iter().flat_map(|&trait_| {
+        trace!("considering explicit impl for trait {:?}", trait_);
+        let mut saw_impl = false;
+        // Look at each trait implementation to see if it's an impl for `did`
+        cx.tcx.for_each_relevant_impl(trait_, ty, |impl_| {
+            // FIXME: this is inefficient, find a way to short-circuit for_each_* so this doesn't take as long
+            if saw_impl {
+                return;
+            }
+
+            let trait_ref = cx.tcx.impl_trait_ref(impl_).expect("this is not an inherent impl");
+            // Check if these are the same type.
+            let impl_type = trait_ref.self_ty();
+            debug!(
+                "comparing type {} with kind {:?} against type {:?}",
+                impl_type, impl_type.kind, type_
+            );
+            // Fast path: if this is a primitive simple `==` will work
+            saw_impl = impl_type == ty
+                || match impl_type.kind {
+                    // Check if these are the same def_id
+                    ty::Adt(def, _) => {
+                        debug!("adt def_id: {:?}", def.did);
+                        def.did == type_
+                    }
+                    ty::Foreign(def_id) => def_id == type_,
+                    _ => false,
+                };
+        });
+        if saw_impl { Some(trait_) } else { None }
+    });
+    iter.collect()
+}
+
 /// Check for resolve collisions between a trait and its derive
 ///
 /// These are common and we should just resolve to the trait in that case
@@ -596,7 +700,7 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> {
             let resolved_self;
             let mut path_str;
             let disambiguator;
-            let (res, fragment) = {
+            let (mut res, mut fragment) = {
                 path_str = if let Ok((d, path)) = Disambiguator::from_str(&link) {
                     disambiguator = Some(d);
                     path
@@ -636,16 +740,9 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> {
                 }
 
                 match disambiguator.map(Disambiguator::ns) {
-                    Some(ns @ ValueNS) => {
-                        match self.resolve(
-                            path_str,
-                            disambiguator,
-                            ns,
-                            &current_item,
-                            base_node,
-                            &extra_fragment,
-                            Some(&item),
-                        ) {
+                    Some(ns @ (ValueNS | TypeNS)) => {
+                        match self.resolve(path_str, ns, &current_item, base_node, &extra_fragment)
+                        {
                             Ok(res) => res,
                             Err(ErrorKind::ResolutionFailure) => {
                                 resolution_failure(cx, &item, path_str, &dox, link_range);
@@ -660,28 +757,6 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> {
                             }
                         }
                     }
-                    Some(ns @ TypeNS) => {
-                        match self.resolve(
-                            path_str,
-                            disambiguator,
-                            ns,
-                            &current_item,
-                            base_node,
-                            &extra_fragment,
-                            Some(&item),
-                        ) {
-                            Ok(res) => res,
-                            Err(ErrorKind::ResolutionFailure) => {
-                                resolution_failure(cx, &item, path_str, &dox, link_range);
-                                // This could just be a normal link.
-                                continue;
-                            }
-                            Err(ErrorKind::AnchorFailure(msg)) => {
-                                anchor_failure(cx, &item, &ori_link, &dox, link_range, msg);
-                                continue;
-                            }
-                        }
-                    }
                     None => {
                         // Try everything!
                         let mut candidates = PerNS {
@@ -690,33 +765,34 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> {
                                 .map(|res| (res, extra_fragment.clone())),
                             type_ns: match self.resolve(
                                 path_str,
-                                disambiguator,
                                 TypeNS,
                                 &current_item,
                                 base_node,
                                 &extra_fragment,
-                                Some(&item),
                             ) {
+                                Ok(res) => {
+                                    debug!("got res in TypeNS: {:?}", res);
+                                    Some(res)
+                                }
                                 Err(ErrorKind::AnchorFailure(msg)) => {
                                     anchor_failure(cx, &item, &ori_link, &dox, link_range, msg);
                                     continue;
                                 }
-                                x => x.ok(),
+                                Err(ErrorKind::ResolutionFailure) => None,
                             },
                             value_ns: match self.resolve(
                                 path_str,
-                                disambiguator,
                                 ValueNS,
                                 &current_item,
                                 base_node,
                                 &extra_fragment,
-                                Some(&item),
                             ) {
+                                Ok(res) => Some(res),
                                 Err(ErrorKind::AnchorFailure(msg)) => {
                                     anchor_failure(cx, &item, &ori_link, &dox, link_range, msg);
                                     continue;
                                 }
-                                x => x.ok(),
+                                Err(ErrorKind::ResolutionFailure) => None,
                             }
                             .and_then(|(res, fragment)| {
                                 // Constructors are picked up in the type namespace.
@@ -751,13 +827,18 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> {
                             if is_derive_trait_collision(&candidates) {
                                 candidates.macro_ns = None;
                             }
+                            let candidates =
+                                candidates.map(|candidate| candidate.map(|(res, _)| res));
+                            let candidates = [TypeNS, ValueNS, MacroNS]
+                                .iter()
+                                .filter_map(|&ns| candidates[ns].map(|res| (res, ns)));
                             ambiguity_error(
                                 cx,
                                 &item,
                                 path_str,
                                 &dox,
                                 link_range,
-                                candidates.map(|candidate| candidate.map(|(res, _)| res)),
+                                candidates.collect(),
                             );
                             continue;
                         }
@@ -773,13 +854,81 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> {
                 }
             };
 
+            // Check for a primitive which might conflict with a module
+            // Report the ambiguity and require that the user specify which one they meant.
+            // FIXME: could there ever be a primitive not in the type namespace?
+            if matches!(
+                disambiguator,
+                None | Some(Disambiguator::Namespace(Namespace::TypeNS) | Disambiguator::Primitive)
+            ) && !matches!(res, Res::PrimTy(_))
+            {
+                if let Some((path, prim)) = is_primitive(path_str, TypeNS) {
+                    // `prim@char`
+                    if matches!(disambiguator, Some(Disambiguator::Primitive)) {
+                        if fragment.is_some() {
+                            anchor_failure(
+                                cx,
+                                &item,
+                                path_str,
+                                &dox,
+                                link_range,
+                                AnchorFailure::Primitive,
+                            );
+                            continue;
+                        }
+                        res = prim;
+                        fragment = Some(path.to_owned());
+                    } else {
+                        // `[char]` when a `char` module is in scope
+                        let candidates = vec![(res, TypeNS), (prim, TypeNS)];
+                        ambiguity_error(cx, &item, path_str, &dox, link_range, candidates);
+                        continue;
+                    }
+                }
+            }
+
+            let report_mismatch = |specified: Disambiguator, resolved: Disambiguator| {
+                // The resolved item did not match the disambiguator; give a better error than 'not found'
+                let msg = format!("incompatible link kind for `{}`", path_str);
+                report_diagnostic(cx, &msg, &item, &dox, link_range.clone(), |diag, sp| {
+                    let note = format!(
+                        "this link resolved to {} {}, which is not {} {}",
+                        resolved.article(),
+                        resolved.descr(),
+                        specified.article(),
+                        specified.descr()
+                    );
+                    let suggestion = resolved.display_for(path_str);
+                    let help_msg =
+                        format!("to link to the {}, use its disambiguator", resolved.descr());
+                    diag.note(&note);
+                    if let Some(sp) = sp {
+                        diag.span_suggestion(
+                            sp,
+                            &help_msg,
+                            suggestion,
+                            Applicability::MaybeIncorrect,
+                        );
+                    } else {
+                        diag.help(&format!("{}: {}", help_msg, suggestion));
+                    }
+                });
+            };
             if let Res::PrimTy(_) = res {
-                item.attrs.links.push((ori_link, None, fragment));
+                match disambiguator {
+                    Some(Disambiguator::Primitive | Disambiguator::Namespace(_)) | None => {
+                        item.attrs.links.push((ori_link, None, fragment))
+                    }
+                    Some(other) => {
+                        report_mismatch(other, Disambiguator::Primitive);
+                        continue;
+                    }
+                }
             } else {
                 debug!("intra-doc link to {} resolved to {:?}", path_str, res);
 
                 // Disallow e.g. linking to enums with `struct@`
-                if let Res::Def(kind, id) = res {
+                if let Res::Def(kind, _) = res {
                     debug!("saw kind {:?} with disambiguator {:?}", kind, disambiguator);
                     match (self.kind_side_channel.take().unwrap_or(kind), disambiguator) {
                         | (DefKind::Const | DefKind::ConstParam | DefKind::AssocConst | DefKind::AnonConst, Some(Disambiguator::Kind(DefKind::Const)))
@@ -793,22 +942,8 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> {
                         // All of these are valid, so do nothing
                         => {}
                         (actual, Some(Disambiguator::Kind(expected))) if actual == expected => {}
-                        (_, Some(Disambiguator::Kind(expected))) => {
-                            // The resolved item did not match the disambiguator; give a better error than 'not found'
-                            let msg = format!("incompatible link kind for `{}`", path_str);
-                            report_diagnostic(cx, &msg, &item, &dox, link_range, |diag, sp| {
-                                // HACK(jynelson): by looking at the source I saw the DefId we pass
-                                // for `expected.descr()` doesn't matter, since it's not a crate
-                                let note = format!("this link resolved to {} {}, which is not {} {}", kind.article(), kind.descr(id), expected.article(), expected.descr(id));
-                                let suggestion = Disambiguator::display_for(kind, path_str);
-                                let help_msg = format!("to link to the {}, use its disambiguator", kind.descr(id));
-                                diag.note(&note);
-                                if let Some(sp) = sp {
-                                    diag.span_suggestion(sp, &help_msg, suggestion, Applicability::MaybeIncorrect);
-                                } else {
-                                    diag.help(&format!("{}: {}", help_msg, suggestion));
-                                }
-                            });
+                        (_, Some(specified @ Disambiguator::Kind(_) | specified @ Disambiguator::Primitive)) => {
+                            report_mismatch(specified, Disambiguator::Kind(kind));
                             continue;
                         }
                     }
@@ -864,6 +999,7 @@ fn fold_crate(&mut self, mut c: Crate) -> Crate {
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
 enum Disambiguator {
+    Primitive,
     Kind(DefKind),
     Namespace(Namespace),
 }
@@ -871,7 +1007,7 @@ enum Disambiguator {
 impl Disambiguator {
     /// (disambiguator, path_str)
     fn from_str(link: &str) -> Result<(Self, &str), ()> {
-        use Disambiguator::{Kind, Namespace as NS};
+        use Disambiguator::{Kind, Namespace as NS, Primitive};
 
         let find_suffix = || {
             let suffixes = [
@@ -902,6 +1038,7 @@ fn from_str(link: &str) -> Result<(Self, &str), ()> {
                 "type" => NS(Namespace::TypeNS),
                 "value" => NS(Namespace::ValueNS),
                 "macro" => NS(Namespace::MacroNS),
+                "prim" | "primitive" => Primitive,
                 _ => return find_suffix(),
             };
             Ok((d, &rest[1..]))
@@ -910,7 +1047,12 @@ fn from_str(link: &str) -> Result<(Self, &str), ()> {
         }
     }
 
-    fn display_for(kind: DefKind, path_str: &str) -> String {
+    fn display_for(self, path_str: &str) -> String {
+        let kind = match self {
+            Disambiguator::Primitive => return format!("prim@{}", path_str),
+            Disambiguator::Kind(kind) => kind,
+            Disambiguator::Namespace(_) => panic!("display_for cannot be used on namespaces"),
+        };
         if kind == DefKind::Macro(MacroKind::Bang) {
             return format!("{}!", path_str);
         } else if kind == DefKind::Fn || kind == DefKind::AssocFn {
@@ -946,6 +1088,25 @@ fn ns(self) -> Namespace {
             Self::Kind(k) => {
                 k.ns().expect("only DefKinds with a valid namespace can be disambiguators")
             }
+            Self::Primitive => TypeNS,
+        }
+    }
+
+    fn article(self) -> &'static str {
+        match self {
+            Self::Namespace(_) => panic!("article() doesn't make sense for namespaces"),
+            Self::Kind(k) => k.article(),
+            Self::Primitive => "a",
+        }
+    }
+
+    fn descr(self) -> &'static str {
+        match self {
+            Self::Namespace(n) => n.descr(),
+            // HACK(jynelson): by looking at the source I saw the DefId we pass
+            // for `expected.descr()` doesn't matter, since it's not a crate
+            Self::Kind(k) => k.descr(DefId::local(hir::def_id::DefIndex::from_usize(0))),
+            Self::Primitive => "builtin type",
         }
     }
 }
@@ -1086,14 +1247,10 @@ fn ambiguity_error(
     path_str: &str,
     dox: &str,
     link_range: Option<Range<usize>>,
-    candidates: PerNS<Option<Res>>,
+    candidates: Vec<(Res, Namespace)>,
 ) {
     let mut msg = format!("`{}` is ", path_str);
 
-    let candidates = [TypeNS, ValueNS, MacroNS]
-        .iter()
-        .filter_map(|&ns| candidates[ns].map(|res| (res, ns)))
-        .collect::<Vec<_>>();
     match candidates.as_slice() {
         [(first_def, _), (second_def, _)] => {
             msg += &format!(
@@ -1132,6 +1289,7 @@ fn ambiguity_error(
                     }
                     _ => {
                         let type_ = match (res, ns) {
+                            (Res::PrimTy(_), _) => "prim",
                             (Res::Def(DefKind::Const, _), _) => "const",
                             (Res::Def(DefKind::Static, _), _) => "static",
                             (Res::Def(DefKind::Struct, _), _) => "struct",
index 24baff46dcfa5404d33ceea58e156f042083a163..b2c4c30d8ff089f17f1797d95315eb557e492051 100644 (file)
@@ -29,7 +29,9 @@ pub fn collect_trait_impls(krate: Crate, cx: &DocContext<'_>) -> Crate {
 
     for &cnum in cx.tcx.crates().iter() {
         for &(did, _) in cx.tcx.all_trait_implementations(cnum).iter() {
-            inline::build_impl(cx, did, None, &mut new_items);
+            cx.tcx.sess.time("build_extern_trait_impl", || {
+                inline::build_impl(cx, did, None, &mut new_items);
+            });
         }
     }
 
@@ -87,7 +89,9 @@ pub fn collect_trait_impls(krate: Crate, cx: &DocContext<'_>) -> Crate {
     for &trait_did in cx.tcx.all_traits(LOCAL_CRATE).iter() {
         for &impl_node in cx.tcx.hir().trait_impls(trait_did) {
             let impl_did = cx.tcx.hir().local_def_id(impl_node);
-            inline::build_impl(cx, impl_did.to_def_id(), None, &mut new_items);
+            cx.tcx.sess.time("build_local_trait_impl", || {
+                inline::build_impl(cx, impl_did.to_def_id(), None, &mut new_items);
+            });
         }
     }
 
index 1fdc4ee247adfc6a34b39c0f14051d59b9fae37d..a465a5f681f5c16e5e1da949b604aa7757e0b846 100644 (file)
@@ -4,6 +4,7 @@
 //! - PRIVATE_DOC_TESTS: this looks for private items with doc-tests.
 
 use super::{span_of_attrs, Pass};
+use crate::clean;
 use crate::clean::*;
 use crate::core::DocContext;
 use crate::fold::DocFolder;
@@ -59,6 +60,22 @@ fn add_test(&mut self, _: String, _: LangString, _: usize) {
     }
 }
 
+pub fn should_have_doc_example(item_kind: &clean::ItemEnum) -> bool {
+    !matches!(item_kind,
+        clean::StructFieldItem(_)
+        | clean::VariantItem(_)
+        | clean::AssocConstItem(_, _)
+        | clean::AssocTypeItem(_, _)
+        | clean::TypedefItem(_, _)
+        | clean::StaticItem(_)
+        | clean::ConstantItem(_)
+        | clean::ExternCrateItem(_, _)
+        | clean::ImportItem(_)
+        | clean::PrimitiveItem(_)
+        | clean::KeywordItem(_)
+    )
+}
+
 pub fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item) {
     let hir_id = match cx.as_local_hir_id(item.def_id) {
         Some(hir_id) => hir_id,
@@ -73,13 +90,7 @@ pub fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item) {
     find_testable_code(&dox, &mut tests, ErrorCodes::No, false, None);
 
     if tests.found_tests == 0 {
-        use ItemEnum::*;
-
-        let should_report = match item.inner {
-            ExternCrateItem(_, _) | ImportItem(_) | PrimitiveItem(_) | KeywordItem(_) => false,
-            _ => true,
-        };
-        if should_report {
+        if should_have_doc_example(&item.inner) {
             debug!("reporting error for {:?} (hir_id={:?})", item, hir_id);
             let sp = span_of_attrs(&item.attrs).unwrap_or(item.source.span());
             cx.tcx.struct_span_lint_hir(
index 693d5b9fb0736c22efc149f294da4372a429c467..7b7c152d8abbf65e6c57a9b3dc41d9b712fff52e 100644 (file)
@@ -281,7 +281,7 @@ fn run_test(
     for codegen_options_str in &options.codegen_options_strs {
         compiler.arg("-C").arg(&codegen_options_str);
     }
-    for debugging_option_str in &options.debugging_options_strs {
+    for debugging_option_str in &options.debugging_opts_strs {
         compiler.arg("-Z").arg(&debugging_option_str);
     }
     if no_run && !compile_fail {
index 86b120e6f302d39cd6973b6391fb299d7bc22122..45790d79496be37fbce6ec57abad5af8fa7a34d7 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 86b120e6f302d39cd6973b6391fb299d7bc22122
+Subproject commit 45790d79496be37fbce6ec57abad5af8fa7a34d7
index 4d15e31df15a3edbe90d443e8833e47b2e1bb65f..81aba0cbf7d42a8a0da5f41f3855f9c42a329522 100644 (file)
@@ -3,6 +3,7 @@
 #include "llvm/ProfileData/Coverage/CoverageMappingWriter.h"
 #include "llvm/ProfileData/InstrProf.h"
 #include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/LEB128.h"
 
 #include <iostream>
 
@@ -12,14 +13,15 @@ extern "C" void LLVMRustCoverageWriteFilenamesSectionToBuffer(
     const char* const Filenames[],
     size_t FilenamesLen,
     RustStringRef BufferOut) {
-  SmallVector<StringRef,32> FilenameRefs;
+  // LLVM 11's CoverageFilenamesSectionWriter uses its new `Version4` format,
+  // so we're manually writing the `Version3` format ourselves.
+  RawRustStringOstream OS(BufferOut);
+  encodeULEB128(FilenamesLen, OS);
   for (size_t i = 0; i < FilenamesLen; i++) {
-    FilenameRefs.push_back(StringRef(Filenames[i]));
+    StringRef Filename(Filenames[i]);
+    encodeULEB128(Filename.size(), OS);
+    OS << Filename;
   }
-  auto FilenamesWriter = coverage::CoverageFilenamesSectionWriter(
-    makeArrayRef(FilenameRefs));
-  RawRustStringOstream OS(BufferOut);
-  FilenamesWriter.write(OS);
 }
 
 extern "C" void LLVMRustCoverageWriteMappingToBuffer(
@@ -64,5 +66,5 @@ extern "C" void LLVMRustCoverageWriteMappingVarNameToString(RustStringRef Str) {
 }
 
 extern "C" uint32_t LLVMRustCoverageMappingVersion() {
-  return coverage::CovMapVersion::CurrentVersion;
+  return coverage::CovMapVersion::Version3;
 }
index a8df350ef60b2b6d91a1dbfd5800ad7fe349dcfa..e39f74c916c4ad4a7a233a10c701b2ba1ec39621 100644 (file)
@@ -553,3 +553,8 @@ pub unsafe fn $func(x: $ty) -> $ty {
 // CHECK: fmov s0, s0
 // CHECK: //NO_APP
 check_reg!(v0_f64x2 f64x2 "s0" "fmov");
+
+// Regression test for #75761
+pub unsafe fn issue_75761() {
+    asm!("", out("v0") _, out("x30") _);
+}
index 6b6e582442cbcce12f68f77ddbbf3c1f28443bf0..67dda1024fc248568f8a3eebecb39261b160f138 100644 (file)
@@ -55,7 +55,8 @@ pub unsafe fn sym_fn() {
 
 // CHECK-LABEL: sym_static:
 // CHECK: #APP
-// CHECK: lb t0, extern_static
+// CHECK: auipc t0, %pcrel_hi(extern_static)
+// CHECK: lb t0, %pcrel_lo(.Lpcrel_hi0)(t0)
 // CHECK: #NO_APP
 #[no_mangle]
 pub unsafe fn sym_static() {
@@ -98,45 +99,45 @@ pub unsafe fn $func(x: $ty) -> $ty {
 
 // CHECK-LABEL: reg_i8:
 // CHECK: #APP
-// CHECK: mv {{[a-z0-9]+}}, {{[a-z0-9]+}}
+// CHECK: add {{[a-z0-9]+}}, zero, {{[a-z0-9]+}}
 // CHECK: #NO_APP
 check!(reg_i8 i8 reg "mv");
 
 // CHECK-LABEL: reg_i16:
 // CHECK: #APP
-// CHECK: mv {{[a-z0-9]+}}, {{[a-z0-9]+}}
+// CHECK: add {{[a-z0-9]+}}, zero, {{[a-z0-9]+}}
 // CHECK: #NO_APP
 check!(reg_i16 i16 reg "mv");
 
 // CHECK-LABEL: reg_i32:
 // CHECK: #APP
-// CHECK: mv {{[a-z0-9]+}}, {{[a-z0-9]+}}
+// CHECK: add {{[a-z0-9]+}}, zero, {{[a-z0-9]+}}
 // CHECK: #NO_APP
 check!(reg_i32 i32 reg "mv");
 
 // CHECK-LABEL: reg_f32:
 // CHECK: #APP
-// CHECK: mv {{[a-z0-9]+}}, {{[a-z0-9]+}}
+// CHECK: add {{[a-z0-9]+}}, zero, {{[a-z0-9]+}}
 // CHECK: #NO_APP
 check!(reg_f32 f32 reg "mv");
 
 // riscv64-LABEL: reg_i64:
 // riscv64: #APP
-// riscv64: mv {{[a-z0-9]+}}, {{[a-z0-9]+}}
+// riscv64: add {{[a-z0-9]+}}, zero, {{[a-z0-9]+}}
 // riscv64: #NO_APP
 #[cfg(riscv64)]
 check!(reg_i64 i64 reg "mv");
 
 // riscv64-LABEL: reg_f64:
 // riscv64: #APP
-// riscv64: mv {{[a-z0-9]+}}, {{[a-z0-9]+}}
+// riscv64: add {{[a-z0-9]+}}, zero, {{[a-z0-9]+}}
 // riscv64: #NO_APP
 #[cfg(riscv64)]
 check!(reg_f64 f64 reg "mv");
 
 // CHECK-LABEL: reg_ptr:
 // CHECK: #APP
-// CHECK: mv {{[a-z0-9]+}}, {{[a-z0-9]+}}
+// CHECK: add {{[a-z0-9]+}}, zero, {{[a-z0-9]+}}
 // CHECK: #NO_APP
 check!(reg_ptr ptr reg "mv");
 
@@ -154,45 +155,45 @@ pub unsafe fn $func(x: $ty) -> $ty {
 
 // CHECK-LABEL: a0_i8:
 // CHECK: #APP
-// CHECK: mv a0, a0
+// CHECK: add a0, zero, a0
 // CHECK: #NO_APP
 check_reg!(a0_i8 i8 "a0" "mv");
 
 // CHECK-LABEL: a0_i16:
 // CHECK: #APP
-// CHECK: mv a0, a0
+// CHECK: add a0, zero, a0
 // CHECK: #NO_APP
 check_reg!(a0_i16 i16 "a0" "mv");
 
 // CHECK-LABEL: a0_i32:
 // CHECK: #APP
-// CHECK: mv a0, a0
+// CHECK: add a0, zero, a0
 // CHECK: #NO_APP
 check_reg!(a0_i32 i32 "a0" "mv");
 
 // CHECK-LABEL: a0_f32:
 // CHECK: #APP
-// CHECK: mv a0, a0
+// CHECK: add a0, zero, a0
 // CHECK: #NO_APP
 check_reg!(a0_f32 f32 "a0" "mv");
 
 // riscv64-LABEL: a0_i64:
 // riscv64: #APP
-// riscv64: mv a0, a0
+// riscv64: add a0, zero, a0
 // riscv64: #NO_APP
 #[cfg(riscv64)]
 check_reg!(a0_i64 i64 "a0" "mv");
 
 // riscv64-LABEL: a0_f64:
 // riscv64: #APP
-// riscv64: mv a0, a0
+// riscv64: add a0, zero, a0
 // riscv64: #NO_APP
 #[cfg(riscv64)]
 check_reg!(a0_f64 f64 "a0" "mv");
 
 // CHECK-LABEL: a0_ptr:
 // CHECK: #APP
-// CHECK: mv a0, a0
+// CHECK: add a0, zero, a0
 // CHECK: #NO_APP
 check_reg!(a0_ptr ptr "a0" "mv");
 
index d91ee7f816dede3620fc035ff1d2bbbe9c56e2cd..4704c8ad797d8a5a3fc347073c522009948e6925 100644 (file)
@@ -24,8 +24,9 @@ pub fn pair_i32_bool(pair: (i32, bool)) -> (i32, bool) {
 #[no_mangle]
 pub fn pair_and_or((a, b): (bool, bool)) -> (bool, bool) {
     // Make sure it can operate directly on the unpacked args
-    // CHECK: and i1 %_1.0, %_1.1
-    // CHECK: or i1 %_1.0, %_1.1
+    // (but it might not be using simple and/or instructions)
+    // CHECK-DAG: %_1.0
+    // CHECK-DAG: %_1.1
     (a && b, a || b)
 }
 
index 2397210ded5e1b679ded36e53719b7ce71b99eb8..2216c2bc92a55635744fbb8e8881efae3d58a25d 100644 (file)
@@ -36,7 +36,7 @@ fn main() -> () {
         StorageLive(_5);                 // scope 3 at $DIR/array-index-is-temporary.rs:16:12: 16:29
         StorageLive(_6);                 // scope 4 at $DIR/array-index-is-temporary.rs:16:25: 16:26
         _6 = _3;                         // scope 4 at $DIR/array-index-is-temporary.rs:16:25: 16:26
-        _5 = const foo(move _6) -> bb1;  // scope 4 at $DIR/array-index-is-temporary.rs:16:21: 16:27
+        _5 = foo(move _6) -> bb1;        // scope 4 at $DIR/array-index-is-temporary.rs:16:21: 16:27
                                          // mir::Constant
                                          // + span: $DIR/array-index-is-temporary.rs:16:21: 16:24
                                          // + literal: Const { ty: unsafe fn(*mut usize) -> u32 {foo}, val: Value(Scalar(<ZST>)) }
index 2397210ded5e1b679ded36e53719b7ce71b99eb8..2216c2bc92a55635744fbb8e8881efae3d58a25d 100644 (file)
@@ -36,7 +36,7 @@ fn main() -> () {
         StorageLive(_5);                 // scope 3 at $DIR/array-index-is-temporary.rs:16:12: 16:29
         StorageLive(_6);                 // scope 4 at $DIR/array-index-is-temporary.rs:16:25: 16:26
         _6 = _3;                         // scope 4 at $DIR/array-index-is-temporary.rs:16:25: 16:26
-        _5 = const foo(move _6) -> bb1;  // scope 4 at $DIR/array-index-is-temporary.rs:16:21: 16:27
+        _5 = foo(move _6) -> bb1;        // scope 4 at $DIR/array-index-is-temporary.rs:16:21: 16:27
                                          // mir::Constant
                                          // + span: $DIR/array-index-is-temporary.rs:16:21: 16:24
                                          // + literal: Const { ty: unsafe fn(*mut usize) -> u32 {foo}, val: Value(Scalar(<ZST>)) }
index dee3e4f7832f64279a10d0276464254bd2082e2f..46dbb997ef4a22d83d06cc62753a8e92f39e3116 100644 (file)
@@ -14,7 +14,7 @@ fn main() -> () {
         StorageLive(_1);                 // scope 0 at $DIR/box_expr.rs:7:9: 7:10
         StorageLive(_2);                 // scope 0 at $DIR/box_expr.rs:7:13: 7:25
         _2 = Box(S);                     // scope 0 at $DIR/box_expr.rs:7:13: 7:25
-        (*_2) = const S::new() -> [return: bb2, unwind: bb3]; // scope 0 at $DIR/box_expr.rs:7:17: 7:25
+        (*_2) = S::new() -> [return: bb2, unwind: bb3]; // scope 0 at $DIR/box_expr.rs:7:17: 7:25
                                          // mir::Constant
                                          // + span: $DIR/box_expr.rs:7:17: 7:23
                                          // + literal: Const { ty: fn() -> S {S::new}, val: Value(Scalar(<ZST>)) }
@@ -38,7 +38,7 @@ fn main() -> () {
         StorageLive(_3);                 // scope 1 at $DIR/box_expr.rs:8:5: 8:12
         StorageLive(_4);                 // scope 1 at $DIR/box_expr.rs:8:10: 8:11
         _4 = move _1;                    // scope 1 at $DIR/box_expr.rs:8:10: 8:11
-        _3 = const std::mem::drop::<std::boxed::Box<S>>(move _4) -> [return: bb5, unwind: bb7]; // scope 1 at $DIR/box_expr.rs:8:5: 8:12
+        _3 = std::mem::drop::<std::boxed::Box<S>>(move _4) -> [return: bb5, unwind: bb7]; // scope 1 at $DIR/box_expr.rs:8:5: 8:12
                                          // mir::Constant
                                          // + span: $DIR/box_expr.rs:8:5: 8:9
                                          // + literal: Const { ty: fn(std::boxed::Box<S>) {std::mem::drop::<std::boxed::Box<S>>}, val: Value(Scalar(<ZST>)) }
index 45302087f2d151ede404c6b09113d4adf148ac64..6acb8e46e75c175c38e3c574f431075e22b454b2 100644 (file)
@@ -33,7 +33,7 @@
 +                                          // + literal: Const { ty: &[&i32; 1], val: Unevaluated(WithOptConstParam { did: DefId(0:6 ~ const_promotion_extern_static[317d]::BAR[0]), const_param_did: None }, [], Some(promoted[0])) }
 +         _2 = &(*_6);                     // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
           _1 = move _2 as &[&i32] (Pointer(Unsize)); // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
-          _0 = const core::slice::<impl [&i32]>::as_ptr(move _1) -> [return: bb2, unwind: bb1]; // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:44
+          _0 = core::slice::<impl [&i32]>::as_ptr(move _1) -> [return: bb2, unwind: bb1]; // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:44
                                            // mir::Constant
                                            // + span: $DIR/const-promotion-extern-static.rs:9:36: 9:42
                                            // + literal: Const { ty: for<'r> fn(&'r [&i32]) -> *const &i32 {core::slice::<impl [&i32]>::as_ptr}, val: Value(Scalar(<ZST>)) }
index faf86bed9d5c77959e1b23b48d418eaadbe9f5d8..2f7a2d7288447f6b136a989d2b51df780ab52606 100644 (file)
@@ -35,7 +35,7 @@
 +                                          // + literal: Const { ty: &[&i32; 1], val: Unevaluated(WithOptConstParam { did: DefId(0:7 ~ const_promotion_extern_static[317d]::FOO[0]), const_param_did: None }, [], Some(promoted[0])) }
 +         _2 = &(*_6);                     // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46
           _1 = move _2 as &[&i32] (Pointer(Unsize)); // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46
-          _0 = const core::slice::<impl [&i32]>::as_ptr(move _1) -> [return: bb2, unwind: bb1]; // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:55
+          _0 = core::slice::<impl [&i32]>::as_ptr(move _1) -> [return: bb2, unwind: bb1]; // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:55
                                            // mir::Constant
                                            // + span: $DIR/const-promotion-extern-static.rs:13:47: 13:53
                                            // + literal: Const { ty: for<'r> fn(&'r [&i32]) -> *const &i32 {core::slice::<impl [&i32]>::as_ptr}, val: Value(Scalar(<ZST>)) }
index a1bc0c7aa4fce804367ca91ba09a1a5cc4304fb5..bfc848bbfc93d0f6dd53da3e55de22a4b09cbea9 100644 (file)
@@ -30,7 +30,7 @@
           StorageLive(_4);                 // scope 1 at $DIR/const_prop_fails_gracefully.rs:8:5: 8:12
           StorageLive(_5);                 // scope 1 at $DIR/const_prop_fails_gracefully.rs:8:10: 8:11
           _5 = _1;                         // scope 1 at $DIR/const_prop_fails_gracefully.rs:8:10: 8:11
-          _4 = const read(move _5) -> bb1; // scope 1 at $DIR/const_prop_fails_gracefully.rs:8:5: 8:12
+          _4 = read(move _5) -> bb1;       // scope 1 at $DIR/const_prop_fails_gracefully.rs:8:5: 8:12
                                            // mir::Constant
                                            // + span: $DIR/const_prop_fails_gracefully.rs:8:5: 8:9
                                            // + literal: Const { ty: fn(usize) {read}, val: Value(Scalar(<ZST>)) }
index df03cb2935fa3de97bca92b883b337cce6d08277..b55e3a63533f8b77b5b1a04ae35ae3a52923b54e 100644 (file)
@@ -22,7 +22,7 @@
   
       bb2: {
           StorageLive(_2);                 // scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-          const std::rt::begin_panic::<&str>(const "explicit panic"); // scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
+          std::rt::begin_panic::<&str>(const "explicit panic"); // scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/std/src/macros.rs:LL:COL
                                            // + literal: Const { ty: fn(&str) -> ! {std::rt::begin_panic::<&str>}, val: Value(Scalar(<ZST>)) }
index f6453a4a5a2bb7a1b110a9bc9daf17e9bc225915..6bf553bc580156bbbee36d1bc95277e8dc2309c4 100644 (file)
@@ -16,7 +16,7 @@
           (_2.1: u8) = const 0_u8;         // scope 0 at $DIR/issue-66971.rs:16:12: 16:22
           (_2.2: u8) = const 0_u8;         // scope 0 at $DIR/issue-66971.rs:16:12: 16:22
           StorageDead(_3);                 // scope 0 at $DIR/issue-66971.rs:16:21: 16:22
-          _1 = const encode(move _2) -> bb1; // scope 0 at $DIR/issue-66971.rs:16:5: 16:23
+          _1 = encode(move _2) -> bb1;     // scope 0 at $DIR/issue-66971.rs:16:5: 16:23
                                            // mir::Constant
                                            // + span: $DIR/issue-66971.rs:16:5: 16:11
                                            // + literal: Const { ty: fn(((), u8, u8)) {encode}, val: Value(Scalar(<ZST>)) }
index 0550627c0df834d2cba445c3c430e3cbf58b0ac3..492938fc206bd69e165d756831738df916ae333e 100644 (file)
@@ -22,7 +22,7 @@
 +                                          // + span: $DIR/issue-67019.rs:11:10: 11:19
 +                                          // + literal: Const { ty: (u8, u8), val: Value(ByRef { alloc: Allocation { bytes: [1, 2], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [3], len: Size { raw: 2 } }, size: Size { raw: 2 }, align: Align { pow2: 0 }, mutability: Not, extra: () }, offset: Size { raw: 0 } }) }
           StorageDead(_3);                 // scope 0 at $DIR/issue-67019.rs:11:18: 11:19
-          _1 = const test(move _2) -> bb1; // scope 0 at $DIR/issue-67019.rs:11:5: 11:20
+          _1 = test(move _2) -> bb1;       // scope 0 at $DIR/issue-67019.rs:11:5: 11:20
                                            // mir::Constant
                                            // + span: $DIR/issue-67019.rs:11:5: 11:9
                                            // + literal: Const { ty: fn(((u8, u8),)) {test}, val: Value(Scalar(<ZST>)) }
index d887f3f0dc13c559f565c11c436c0c2e7ab1eee1..08dd2d4da31e186c0cddfda4b463eb9a8745a76e 100644 (file)
@@ -14,7 +14,7 @@
   
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:5:9: 5:14
-          _1 = const foo() -> bb1;         // scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:5:29: 5:34
+          _1 = foo() -> bb1;               // scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:5:29: 5:34
                                            // mir::Constant
                                            // + span: $DIR/mutable_variable_aggregate_partial_read.rs:5:29: 5:32
                                            // + literal: Const { ty: fn() -> (i32, i32) {foo}, val: Value(Scalar(<ZST>)) }
index cb7becc3b9be3a845152afc9485bd9637978983a..63bdcb2bc11b4dc36d85e9f2a4a1c221c3ea29cb 100644 (file)
@@ -23,7 +23,7 @@
   
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/mutable_variable_unprop_assign.rs:5:9: 5:10
-          _1 = const foo() -> bb1;         // scope 0 at $DIR/mutable_variable_unprop_assign.rs:5:13: 5:18
+          _1 = foo() -> bb1;               // scope 0 at $DIR/mutable_variable_unprop_assign.rs:5:13: 5:18
                                            // mir::Constant
                                            // + span: $DIR/mutable_variable_unprop_assign.rs:5:13: 5:16
                                            // + literal: Const { ty: fn() -> i32 {foo}, val: Value(Scalar(<ZST>)) }
index aab1bf3b3119ac43e7a1b493ddd04661552a1326..02eb3155be9f313d64aad8585e958dd2a1f3f8e7 100644 (file)
@@ -13,7 +13,7 @@
           StorageLive(_1);                 // scope 0 at $DIR/reify_fn_ptr.rs:4:13: 4:41
           StorageLive(_2);                 // scope 0 at $DIR/reify_fn_ptr.rs:4:13: 4:26
           StorageLive(_3);                 // scope 0 at $DIR/reify_fn_ptr.rs:4:13: 4:17
-          _3 = const main as fn() (Pointer(ReifyFnPointer)); // scope 0 at $DIR/reify_fn_ptr.rs:4:13: 4:17
+          _3 = main as fn() (Pointer(ReifyFnPointer)); // scope 0 at $DIR/reify_fn_ptr.rs:4:13: 4:17
                                            // mir::Constant
                                            // + span: $DIR/reify_fn_ptr.rs:4:13: 4:17
                                            // + literal: Const { ty: fn() {main}, val: Value(Scalar(<ZST>)) }
index b4b83281201f613672728a8fd0032e3018221d82..a4232d178a32e6ab8e148c86af3739a5c24b9a44 100644 (file)
@@ -16,9 +16,9 @@
           StorageLive(_2);                 // scope 1 at $DIR/scalar_literal_propagation.rs:4:5: 4:15
           StorageLive(_3);                 // scope 1 at $DIR/scalar_literal_propagation.rs:4:13: 4:14
 -         _3 = _1;                         // scope 1 at $DIR/scalar_literal_propagation.rs:4:13: 4:14
--         _2 = const consume(move _3) -> bb1; // scope 1 at $DIR/scalar_literal_propagation.rs:4:5: 4:15
+-         _2 = consume(move _3) -> bb1;    // scope 1 at $DIR/scalar_literal_propagation.rs:4:5: 4:15
 +         _3 = const 1_u32;                // scope 1 at $DIR/scalar_literal_propagation.rs:4:13: 4:14
-+         _2 = const consume(const 1_u32) -> bb1; // scope 1 at $DIR/scalar_literal_propagation.rs:4:5: 4:15
++         _2 = consume(const 1_u32) -> bb1; // scope 1 at $DIR/scalar_literal_propagation.rs:4:5: 4:15
                                            // mir::Constant
                                            // + span: $DIR/scalar_literal_propagation.rs:4:5: 4:12
                                            // + literal: Const { ty: fn(u32) {consume}, val: Value(Scalar(<ZST>)) }
index 8dff267c2f3b5b745f4bedaaeb4bd0f6cd85e0c9..f51df7ae821ce35548135ee92af48cd81e6c7248 100644 (file)
       }
   
       bb1: {
-          _0 = const foo(const -1_i32) -> bb3; // scope 0 at $DIR/switch_int.rs:9:14: 9:21
+          _0 = foo(const -1_i32) -> bb3;   // scope 0 at $DIR/switch_int.rs:9:14: 9:21
                                            // mir::Constant
                                            // + span: $DIR/switch_int.rs:9:14: 9:17
                                            // + literal: Const { ty: fn(i32) {foo}, val: Value(Scalar(<ZST>)) }
       }
   
       bb2: {
-          _0 = const foo(const 0_i32) -> bb3; // scope 0 at $DIR/switch_int.rs:8:14: 8:20
+          _0 = foo(const 0_i32) -> bb3;    // scope 0 at $DIR/switch_int.rs:8:14: 8:20
                                            // mir::Constant
                                            // + span: $DIR/switch_int.rs:8:14: 8:17
                                            // + literal: Const { ty: fn(i32) {foo}, val: Value(Scalar(<ZST>)) }
index fb88cd3f96ca470c6f71560ed345707734d25fd2..a444956ad1d0a8dd1a4e765c741e6f94e83dbf3d 100644 (file)
       }
   
       bb1: {
-          _0 = const foo(const -1_i32) -> bb3; // scope 0 at $DIR/switch_int.rs:9:14: 9:21
+          _0 = foo(const -1_i32) -> bb3;   // scope 0 at $DIR/switch_int.rs:9:14: 9:21
                                            // mir::Constant
                                            // + span: $DIR/switch_int.rs:9:14: 9:17
                                            // + literal: Const { ty: fn(i32) {foo}, val: Value(Scalar(<ZST>)) }
       }
   
       bb2: {
-          _0 = const foo(const 0_i32) -> bb3; // scope 0 at $DIR/switch_int.rs:8:14: 8:20
+          _0 = foo(const 0_i32) -> bb3;    // scope 0 at $DIR/switch_int.rs:8:14: 8:20
                                            // mir::Constant
                                            // + span: $DIR/switch_int.rs:8:14: 8:17
                                            // + literal: Const { ty: fn(i32) {foo}, val: Value(Scalar(<ZST>)) }
index c4c6d82856f273b4cf24f53e003ecbf379b254bb..2de1ab19b7c3de491497c3d2a1394edb0de6305b 100644 (file)
@@ -24,7 +24,7 @@
 +                                          // mir::Constant
 +                                          // + span: $DIR/tuple_literal_propagation.rs:5:13: 5:14
 +                                          // + literal: Const { ty: (u32, u32), val: Value(ByRef { alloc: Allocation { bytes: [1, 0, 0, 0, 2, 0, 0, 0], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, size: Size { raw: 8 }, align: Align { pow2: 2 }, mutability: Not, extra: () }, offset: Size { raw: 0 } }) }
-          _2 = const consume(move _3) -> bb1; // scope 1 at $DIR/tuple_literal_propagation.rs:5:5: 5:15
+          _2 = consume(move _3) -> bb1;    // scope 1 at $DIR/tuple_literal_propagation.rs:5:5: 5:15
                                            // mir::Constant
                                            // + span: $DIR/tuple_literal_propagation.rs:5:5: 5:12
                                            // + literal: Const { ty: fn((u32, u32)) {consume}, val: Value(Scalar(<ZST>)) }
index e8d835ffe391ec1637641f09f2bab18799961a75..fb793e53ea8a7977ce0e8fc837aa0fe30700c203 100644 (file)
@@ -11,7 +11,7 @@
           StorageLive(_2);                 // scope 0 at $DIR/copy_propagation_arg.rs:16:5: 16:13
           StorageLive(_3);                 // scope 0 at $DIR/copy_propagation_arg.rs:16:11: 16:12
           _3 = _1;                         // scope 0 at $DIR/copy_propagation_arg.rs:16:11: 16:12
-          _2 = const dummy(move _3) -> bb1; // scope 0 at $DIR/copy_propagation_arg.rs:16:5: 16:13
+          _2 = dummy(move _3) -> bb1;      // scope 0 at $DIR/copy_propagation_arg.rs:16:5: 16:13
                                            // mir::Constant
                                            // + span: $DIR/copy_propagation_arg.rs:16:5: 16:10
                                            // + literal: Const { ty: fn(u8) -> u8 {dummy}, val: Value(Scalar(<ZST>)) }
index 2d97a3698512445ef20f0c0212132753463c43a9..d07a4c0541e1b191b00bccc066bcd0107cf82817 100644 (file)
@@ -11,7 +11,7 @@
           StorageLive(_2);                 // scope 0 at $DIR/copy_propagation_arg.rs:11:9: 11:17
           StorageLive(_3);                 // scope 0 at $DIR/copy_propagation_arg.rs:11:15: 11:16
           _3 = _1;                         // scope 0 at $DIR/copy_propagation_arg.rs:11:15: 11:16
-          _2 = const dummy(move _3) -> bb1; // scope 0 at $DIR/copy_propagation_arg.rs:11:9: 11:17
+          _2 = dummy(move _3) -> bb1;      // scope 0 at $DIR/copy_propagation_arg.rs:11:9: 11:17
                                            // mir::Constant
                                            // + span: $DIR/copy_propagation_arg.rs:11:9: 11:14
                                            // + literal: Const { ty: fn(u8) -> u8 {dummy}, val: Value(Scalar(<ZST>)) }
index 309153114427707fde0a87214039b1b0cff9da75..9bf666bc7614ba88155cda89ebe7706f7292a162 100644 (file)
@@ -38,7 +38,7 @@
           StorageLive(_4);                 // scope 0 at $DIR/funky_arms.rs:15:9: 15:19
           StorageLive(_5);                 // scope 0 at $DIR/funky_arms.rs:15:22: 15:25
           _5 = &(*_1);                     // scope 0 at $DIR/funky_arms.rs:15:22: 15:25
-          _4 = const std::fmt::Formatter::sign_plus(move _5) -> bb1; // scope 0 at $DIR/funky_arms.rs:15:22: 15:37
+          _4 = std::fmt::Formatter::sign_plus(move _5) -> bb1; // scope 0 at $DIR/funky_arms.rs:15:22: 15:37
                                            // mir::Constant
                                            // + span: $DIR/funky_arms.rs:15:26: 15:35
                                            // + literal: Const { ty: for<'r> fn(&'r std::fmt::Formatter) -> bool {std::fmt::Formatter::sign_plus}, val: Value(Scalar(<ZST>)) }
@@ -64,7 +64,7 @@
           StorageLive(_7);                 // scope 2 at $DIR/funky_arms.rs:24:30: 24:45
           StorageLive(_8);                 // scope 2 at $DIR/funky_arms.rs:24:30: 24:33
           _8 = &(*_1);                     // scope 2 at $DIR/funky_arms.rs:24:30: 24:33
-          _7 = const std::fmt::Formatter::precision(move _8) -> bb5; // scope 2 at $DIR/funky_arms.rs:24:30: 24:45
+          _7 = std::fmt::Formatter::precision(move _8) -> bb5; // scope 2 at $DIR/funky_arms.rs:24:30: 24:45
                                            // mir::Constant
                                            // + span: $DIR/funky_arms.rs:24:34: 24:43
                                            // + literal: Const { ty: for<'r> fn(&'r std::fmt::Formatter) -> std::option::Option<usize> {std::fmt::Formatter::precision}, val: Value(Scalar(<ZST>)) }
@@ -85,7 +85,7 @@
           _20 = _6;                        // scope 2 at $DIR/funky_arms.rs:28:56: 28:60
           StorageLive(_21);                // scope 2 at $DIR/funky_arms.rs:28:62: 28:67
           _21 = _3;                        // scope 2 at $DIR/funky_arms.rs:28:62: 28:67
-          _0 = const float_to_exponential_common_shortest::<T>(move _18, move _19, move _20, move _21) -> bb9; // scope 2 at $DIR/funky_arms.rs:28:9: 28:68
+          _0 = float_to_exponential_common_shortest::<T>(move _18, move _19, move _20, move _21) -> bb9; // scope 2 at $DIR/funky_arms.rs:28:9: 28:68
                                            // mir::Constant
                                            // + span: $DIR/funky_arms.rs:28:9: 28:45
                                            // + literal: Const { ty: for<'r, 's, 't0> fn(&'r mut std::fmt::Formatter<'s>, &'t0 T, core::num::flt2dec::Sign, bool) -> std::result::Result<(), std::fmt::Error> {float_to_exponential_common_shortest::<T>}, val: Value(Scalar(<ZST>)) }
           StorageDead(_15);                // scope 3 at $DIR/funky_arms.rs:26:78: 26:79
           StorageLive(_17);                // scope 3 at $DIR/funky_arms.rs:26:81: 26:86
           _17 = _3;                        // scope 3 at $DIR/funky_arms.rs:26:81: 26:86
-          _0 = const float_to_exponential_common_exact::<T>(move _11, move _12, move _13, move _14, move _17) -> bb8; // scope 3 at $DIR/funky_arms.rs:26:9: 26:87
+          _0 = float_to_exponential_common_exact::<T>(move _11, move _12, move _13, move _14, move _17) -> bb8; // scope 3 at $DIR/funky_arms.rs:26:9: 26:87
                                            // mir::Constant
                                            // + span: $DIR/funky_arms.rs:26:9: 26:42
                                            // + literal: Const { ty: for<'r, 's, 't0> fn(&'r mut std::fmt::Formatter<'s>, &'t0 T, core::num::flt2dec::Sign, u32, bool) -> std::result::Result<(), std::fmt::Error> {float_to_exponential_common_exact::<T>}, val: Value(Scalar(<ZST>)) }
index 044fb3827cda2b62af01494034e6414417271458..b6cda80683171469be29363c4ae646764cb322fa 100644 (file)
@@ -39,7 +39,7 @@ yields ()
         StorageLive(_7);                 // scope 2 at $DIR/generator-storage-dead-unwind.rs:26:9: 26:16
         StorageLive(_8);                 // scope 2 at $DIR/generator-storage-dead-unwind.rs:26:14: 26:15
         _8 = move _3;                    // scope 2 at $DIR/generator-storage-dead-unwind.rs:26:14: 26:15
-        _7 = const take::<Foo>(move _8) -> [return: bb7, unwind: bb9]; // scope 2 at $DIR/generator-storage-dead-unwind.rs:26:9: 26:16
+        _7 = take::<Foo>(move _8) -> [return: bb7, unwind: bb9]; // scope 2 at $DIR/generator-storage-dead-unwind.rs:26:9: 26:16
                                          // mir::Constant
                                          // + span: $DIR/generator-storage-dead-unwind.rs:26:9: 26:13
                                          // + literal: Const { ty: fn(Foo) {take::<Foo>}, val: Value(Scalar(<ZST>)) }
@@ -72,7 +72,7 @@ yields ()
         StorageLive(_9);                 // scope 2 at $DIR/generator-storage-dead-unwind.rs:27:9: 27:16
         StorageLive(_10);                // scope 2 at $DIR/generator-storage-dead-unwind.rs:27:14: 27:15
         _10 = move _4;                   // scope 2 at $DIR/generator-storage-dead-unwind.rs:27:14: 27:15
-        _9 = const take::<Bar>(move _10) -> [return: bb10, unwind: bb11]; // scope 2 at $DIR/generator-storage-dead-unwind.rs:27:9: 27:16
+        _9 = take::<Bar>(move _10) -> [return: bb10, unwind: bb11]; // scope 2 at $DIR/generator-storage-dead-unwind.rs:27:9: 27:16
                                          // mir::Constant
                                          // + span: $DIR/generator-storage-dead-unwind.rs:27:9: 27:13
                                          // + literal: Const { ty: fn(Bar) {take::<Bar>}, val: Value(Scalar(<ZST>)) }
index 527618cef3e798bc8b15f1a3cfac04ffd6a66501..691f5eedad82b4034d88eed79f3d5809bb506952 100644 (file)
@@ -51,7 +51,7 @@ fn main::{{closure}}#0(_1: std::pin::Pin<&mut [generator@$DIR/generator-tiny.rs:
         StorageDead(_7);                 // scope 1 at $DIR/generator-tiny.rs:22:17: 22:18
         StorageDead(_6);                 // scope 1 at $DIR/generator-tiny.rs:22:18: 22:19
         StorageLive(_8);                 // scope 1 at $DIR/generator-tiny.rs:23:13: 23:21
-        _8 = const callee() -> bb4;      // scope 1 at $DIR/generator-tiny.rs:23:13: 23:21
+        _8 = callee() -> bb4;            // scope 1 at $DIR/generator-tiny.rs:23:13: 23:21
                                          // mir::Constant
                                          // + span: $DIR/generator-tiny.rs:23:13: 23:19
                                          // + literal: Const { ty: fn() {callee}, val: Value(Scalar(<ZST>)) }
index c0bd1b706f870dfdec1e46d40f5d57594d58dfe5..9d490f047f7356a287bada5f72c01b8409c303f8 100644 (file)
@@ -16,7 +16,7 @@ fn bar() -> bool {
 
     bb0: {
         StorageLive(_1);                 // scope 0 at $DIR/inline-any-operand.rs:11:9: 11:10
-        _1 = const foo;                  // scope 0 at $DIR/inline-any-operand.rs:11:13: 11:16
+        _1 = foo;                        // scope 0 at $DIR/inline-any-operand.rs:11:13: 11:16
                                          // mir::Constant
                                          // + span: $DIR/inline-any-operand.rs:11:13: 11:16
                                          // + literal: Const { ty: fn(i32, i32) -> bool {foo}, val: Value(Scalar(<ZST>)) }
index e032e185b2e7387ac841f7cd9df0a1965f684ed8..0957698820fcd5df269362794af498b119de1ea3 100644 (file)
@@ -17,7 +17,7 @@
           StorageLive(_1);                 // scope 0 at $DIR/inline-into-box-place.rs:8:9: 8:11
           StorageLive(_2);                 // scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43
           _2 = Box(std::vec::Vec<u32>);    // scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43
--         (*_2) = const std::vec::Vec::<u32>::new() -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43
+-         (*_2) = std::vec::Vec::<u32>::new() -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43
 +         _4 = &mut (*_2);                 // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43
 +         ((*_4).0: alloc::raw_vec::RawVec<u32>) = const alloc::raw_vec::RawVec::<u32> { ptr: std::ptr::Unique::<u32> { pointer: {0x4 as *const u32}, _marker: std::marker::PhantomData::<u32> }, cap: 0_usize, alloc: std::alloc::Global }; // scope 2 at $SRC_DIR/alloc/src/vec.rs:LL:COL
 +                                          // ty::Const
@@ -54,7 +54,7 @@
 -     }
 - 
 -     bb4 (cleanup): {
--         _3 = const alloc::alloc::box_free::<std::vec::Vec<u32>>(move (_2.0: std::ptr::Unique<std::vec::Vec<u32>>)) -> bb1; // scope 0 at $DIR/inline-into-box-place.rs:8:42: 8:43
+-         _3 = alloc::alloc::box_free::<std::vec::Vec<u32>>(move (_2.0: std::ptr::Unique<std::vec::Vec<u32>>)) -> bb1; // scope 0 at $DIR/inline-into-box-place.rs:8:42: 8:43
 -                                          // mir::Constant
 -                                          // + span: $DIR/inline-into-box-place.rs:8:42: 8:43
 -                                          // + literal: Const { ty: unsafe fn(std::ptr::Unique<std::vec::Vec<u32>>) {alloc::alloc::box_free::<std::vec::Vec<u32>>}, val: Value(Scalar(<ZST>)) }
index 9b65e51d7772c68c3d1db0d284adcc0a01dfdfc6..ab065fc3d250f58da7b8996a666a078fd7d5a2ae 100644 (file)
@@ -17,7 +17,7 @@
           StorageLive(_1);                 // scope 0 at $DIR/inline-into-box-place.rs:8:9: 8:11
           StorageLive(_2);                 // scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43
           _2 = Box(std::vec::Vec<u32>);    // scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43
--         (*_2) = const std::vec::Vec::<u32>::new() -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43
+-         (*_2) = std::vec::Vec::<u32>::new() -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43
 +         _4 = &mut (*_2);                 // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43
 +         ((*_4).0: alloc::raw_vec::RawVec<u32>) = const alloc::raw_vec::RawVec::<u32> { ptr: std::ptr::Unique::<u32> { pointer: {0x4 as *const u32}, _marker: std::marker::PhantomData::<u32> }, cap: 0_usize, alloc: std::alloc::Global }; // scope 2 at $SRC_DIR/alloc/src/vec.rs:LL:COL
 +                                          // ty::Const
@@ -54,7 +54,7 @@
 -     }
 - 
 -     bb4 (cleanup): {
--         _3 = const alloc::alloc::box_free::<std::vec::Vec<u32>>(move (_2.0: std::ptr::Unique<std::vec::Vec<u32>>)) -> bb1; // scope 0 at $DIR/inline-into-box-place.rs:8:42: 8:43
+-         _3 = alloc::alloc::box_free::<std::vec::Vec<u32>>(move (_2.0: std::ptr::Unique<std::vec::Vec<u32>>)) -> bb1; // scope 0 at $DIR/inline-into-box-place.rs:8:42: 8:43
 -                                          // mir::Constant
 -                                          // + span: $DIR/inline-into-box-place.rs:8:42: 8:43
 -                                          // + literal: Const { ty: unsafe fn(std::ptr::Unique<std::vec::Vec<u32>>) {alloc::alloc::box_free::<std::vec::Vec<u32>>}, val: Value(Scalar(<ZST>)) }
index 78e7dfcc970ad203fd38aeee65e8715b8745cbb8..29327108f3e0edf6f96e3bd867baf1d9de16f302 100644 (file)
@@ -24,7 +24,7 @@ fn bar() -> bool {
 
     bb0: {
         StorageLive(_1);                 // scope 0 at $DIR/inline-retag.rs:11:9: 11:10
-        _1 = const foo;                  // scope 0 at $DIR/inline-retag.rs:11:13: 11:16
+        _1 = foo;                        // scope 0 at $DIR/inline-retag.rs:11:13: 11:16
                                          // mir::Constant
                                          // + span: $DIR/inline-retag.rs:11:13: 11:16
                                          // + literal: Const { ty: for<'r, 's> fn(&'r i32, &'s i32) -> bool {foo}, val: Value(Scalar(<ZST>)) }
index 8d7cad0c69a72b4617fd271f6d5dbb61ac4f7c43..e97191b53e5d16477758975a7988eb9a1cf9166e 100644 (file)
@@ -12,7 +12,7 @@
   
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/inline-specialization.rs:5:9: 5:10
--         _1 = const <std::vec::Vec<()> as Foo>::bar() -> bb1; // scope 0 at $DIR/inline-specialization.rs:5:13: 5:38
+-         _1 = <std::vec::Vec<()> as Foo>::bar() -> bb1; // scope 0 at $DIR/inline-specialization.rs:5:13: 5:38
 -                                          // mir::Constant
 -                                          // + span: $DIR/inline-specialization.rs:5:13: 5:36
 -                                          // + literal: Const { ty: fn() -> u32 {<std::vec::Vec<()> as Foo>::bar}, val: Value(Scalar(<ZST>)) }
index 4e9d17cbb8bd16dc00cbd5419c473e1f53b3f1ca..eada5ac13476e072cceca649cfa0a7eedb2267f4 100644 (file)
@@ -8,7 +8,7 @@ fn test(_1: &dyn X) -> u32 {
     bb0: {
         StorageLive(_2);                 // scope 0 at $DIR/inline-trait-method.rs:9:5: 9:6
         _2 = &(*_1);                     // scope 0 at $DIR/inline-trait-method.rs:9:5: 9:6
-        _0 = const <dyn X as X>::y(move _2) -> bb1; // scope 0 at $DIR/inline-trait-method.rs:9:5: 9:10
+        _0 = <dyn X as X>::y(move _2) -> bb1; // scope 0 at $DIR/inline-trait-method.rs:9:5: 9:10
                                          // mir::Constant
                                          // + span: $DIR/inline-trait-method.rs:9:7: 9:8
                                          // + literal: Const { ty: for<'r> fn(&'r dyn X) -> u32 {<dyn X as X>::y}, val: Value(Scalar(<ZST>)) }
index af47fbac7629931b0f988152d8aba99ea3129754..00e3ef06a49e6cdcc5ec70fe0cbcf5b7525a3fc6 100644 (file)
@@ -15,7 +15,7 @@ fn test2(_1: &dyn X) -> bool {
         _3 = &(*_1);                     // scope 0 at $DIR/inline-trait-method_2.rs:5:10: 5:11
         _2 = move _3 as &dyn X (Pointer(Unsize)); // scope 0 at $DIR/inline-trait-method_2.rs:5:10: 5:11
         StorageDead(_3);                 // scope 0 at $DIR/inline-trait-method_2.rs:5:10: 5:11
-        _0 = const <dyn X as X>::y(move _2) -> bb1; // scope 1 at $DIR/inline-trait-method_2.rs:10:5: 10:10
+        _0 = <dyn X as X>::y(move _2) -> bb1; // scope 1 at $DIR/inline-trait-method_2.rs:10:5: 10:10
                                          // mir::Constant
                                          // + span: $DIR/inline-trait-method_2.rs:10:7: 10:8
                                          // + literal: Const { ty: for<'r> fn(&'r dyn X) -> bool {<dyn X as X>::y}, val: Value(Scalar(<ZST>)) }
index f6556077067aded9356cded3aac166f819b8c716..43c8be8f45dbb6786eab3a09f204789f9e6276bc 100644 (file)
@@ -14,7 +14,7 @@
   
       bb1: {
           StorageLive(_2);                 // scope 0 at /the/src/instrument_coverage.rs:12:12: 12:17
-          _2 = const bar() -> [return: bb3, unwind: bb2]; // scope 0 at /the/src/instrument_coverage.rs:12:12: 12:17
+          _2 = bar() -> [return: bb3, unwind: bb2]; // scope 0 at /the/src/instrument_coverage.rs:12:12: 12:17
                                            // mir::Constant
                                            // + span: /the/src/instrument_coverage.rs:12:12: 12:15
                                            // + literal: Const { ty: fn() -> bool {bar}, val: Value(Scalar(<ZST>)) }
index 49f6b6692016f93c0d76ea18314694a292f508cc..04dea1672b34ca4e29530abc27bd7f9d659ad6b5 100644 (file)
@@ -20,7 +20,7 @@ fn main() -> () {
         StorageLive(_3);                 // scope 0 at $DIR/issue-41110.rs:8:21: 8:27
         StorageLive(_4);                 // scope 0 at $DIR/issue-41110.rs:8:21: 8:22
         _4 = S;                          // scope 0 at $DIR/issue-41110.rs:8:21: 8:22
-        _3 = const S::id(move _4) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue-41110.rs:8:21: 8:27
+        _3 = S::id(move _4) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue-41110.rs:8:21: 8:27
                                          // mir::Constant
                                          // + span: $DIR/issue-41110.rs:8:23: 8:25
                                          // + literal: Const { ty: fn(S) -> S {S::id}, val: Value(Scalar(<ZST>)) }
@@ -33,7 +33,7 @@ fn main() -> () {
     bb2: {
         StorageDead(_4);                 // scope 0 at $DIR/issue-41110.rs:8:26: 8:27
         _5 = const false;                // scope 0 at $DIR/issue-41110.rs:8:13: 8:28
-        _1 = const S::other(move _2, move _3) -> [return: bb6, unwind: bb5]; // scope 0 at $DIR/issue-41110.rs:8:13: 8:28
+        _1 = S::other(move _2, move _3) -> [return: bb6, unwind: bb5]; // scope 0 at $DIR/issue-41110.rs:8:13: 8:28
                                          // mir::Constant
                                          // + span: $DIR/issue-41110.rs:8:15: 8:20
                                          // + literal: Const { ty: fn(S, S) {S::other}, val: Value(Scalar(<ZST>)) }
index 534ff89b2aa3f1a18351d294bce099939d5fdc5c..c4a2e7a0ae3c0a2da00456c86507273f127aeb49 100644 (file)
@@ -25,7 +25,7 @@ fn test() -> () {
         StorageLive(_3);                 // scope 2 at $DIR/issue-41110.rs:17:5: 17:12
         StorageLive(_4);                 // scope 2 at $DIR/issue-41110.rs:17:10: 17:11
         _4 = move _2;                    // scope 2 at $DIR/issue-41110.rs:17:10: 17:11
-        _3 = const std::mem::drop::<S>(move _4) -> [return: bb2, unwind: bb5]; // scope 2 at $DIR/issue-41110.rs:17:5: 17:12
+        _3 = std::mem::drop::<S>(move _4) -> [return: bb2, unwind: bb5]; // scope 2 at $DIR/issue-41110.rs:17:5: 17:12
                                          // mir::Constant
                                          // + span: $DIR/issue-41110.rs:17:5: 17:9
                                          // + literal: Const { ty: fn(S) {std::mem::drop::<S>}, val: Value(Scalar(<ZST>)) }
index cc978845d37dc3edbf13ef44c413362747f35511..84ba4d78ba041ba55af790a514cd1b430f25d92b 100644 (file)
@@ -26,7 +26,7 @@ fn main() -> () {
         _8 = const false;                // scope 0 at $DIR/issue-41888.rs:7:9: 7:10
         StorageLive(_1);                 // scope 0 at $DIR/issue-41888.rs:7:9: 7:10
         StorageLive(_2);                 // scope 1 at $DIR/issue-41888.rs:8:8: 8:14
-        _2 = const cond() -> [return: bb2, unwind: bb3]; // scope 1 at $DIR/issue-41888.rs:8:8: 8:14
+        _2 = cond() -> [return: bb2, unwind: bb3]; // scope 1 at $DIR/issue-41888.rs:8:8: 8:14
                                          // mir::Constant
                                          // + span: $DIR/issue-41888.rs:8:8: 8:12
                                          // + literal: Const { ty: fn() -> bool {cond}, val: Value(Scalar(<ZST>)) }
index c14057df79ff4622e274ef205920c50d70888625..8d76835c636030a76298d5d0a271f0fc53374854 100644 (file)
@@ -74,7 +74,7 @@ fn main() -> () {
         StorageLive(_5);                 // scope 1 at $DIR/issue-49232.rs:13:9: 13:22
         StorageLive(_6);                 // scope 1 at $DIR/issue-49232.rs:13:14: 13:21
         _6 = &_2;                        // scope 1 at $DIR/issue-49232.rs:13:14: 13:21
-        _5 = const std::mem::drop::<&i32>(move _6) -> [return: bb13, unwind: bb4]; // scope 1 at $DIR/issue-49232.rs:13:9: 13:22
+        _5 = std::mem::drop::<&i32>(move _6) -> [return: bb13, unwind: bb4]; // scope 1 at $DIR/issue-49232.rs:13:9: 13:22
                                          // mir::Constant
                                          // + span: $DIR/issue-49232.rs:13:9: 13:13
                                          // + literal: Const { ty: fn(&i32) {std::mem::drop::<&i32>}, val: Value(Scalar(<ZST>)) }
index 28779ab9876b69c48eb902abda2e8bc48020c3da..c71ae934622ec6f1731cdcfb0b5779d9db1e7a02 100644 (file)
@@ -30,7 +30,7 @@ fn test() -> std::option::Option<std::boxed::Box<u32>> {
         StorageLive(_3);                 // scope 0 at $DIR/issue-62289.rs:9:15: 9:20
         StorageLive(_4);                 // scope 0 at $DIR/issue-62289.rs:9:15: 9:19
         _4 = std::option::Option::<u32>::None; // scope 0 at $DIR/issue-62289.rs:9:15: 9:19
-        _3 = const <std::option::Option<u32> as std::ops::Try>::into_result(move _4) -> [return: bb2, unwind: bb3]; // scope 0 at $DIR/issue-62289.rs:9:15: 9:20
+        _3 = <std::option::Option<u32> as std::ops::Try>::into_result(move _4) -> [return: bb2, unwind: bb3]; // scope 0 at $DIR/issue-62289.rs:9:15: 9:20
                                          // mir::Constant
                                          // + span: $DIR/issue-62289.rs:9:15: 9:20
                                          // + literal: Const { ty: fn(std::option::Option<u32>) -> std::result::Result<<std::option::Option<u32> as std::ops::Try>::Ok, <std::option::Option<u32> as std::ops::Try>::Error> {<std::option::Option<u32> as std::ops::Try>::into_result}, val: Value(Scalar(<ZST>)) }
@@ -69,7 +69,7 @@ fn test() -> std::option::Option<std::boxed::Box<u32>> {
         StorageLive(_8);                 // scope 2 at $DIR/issue-62289.rs:9:19: 9:20
         StorageLive(_9);                 // scope 2 at $DIR/issue-62289.rs:9:19: 9:20
         _9 = _6;                         // scope 2 at $DIR/issue-62289.rs:9:19: 9:20
-        _8 = const <std::option::NoneError as std::convert::From<std::option::NoneError>>::from(move _9) -> [return: bb8, unwind: bb3]; // scope 2 at $DIR/issue-62289.rs:9:19: 9:20
+        _8 = <std::option::NoneError as std::convert::From<std::option::NoneError>>::from(move _9) -> [return: bb8, unwind: bb3]; // scope 2 at $DIR/issue-62289.rs:9:19: 9:20
                                          // mir::Constant
                                          // + span: $DIR/issue-62289.rs:9:19: 9:20
                                          // + literal: Const { ty: fn(std::option::NoneError) -> std::option::NoneError {<std::option::NoneError as std::convert::From<std::option::NoneError>>::from}, val: Value(Scalar(<ZST>)) }
@@ -81,7 +81,7 @@ fn test() -> std::option::Option<std::boxed::Box<u32>> {
 
     bb8: {
         StorageDead(_9);                 // scope 2 at $DIR/issue-62289.rs:9:19: 9:20
-        _0 = const <std::option::Option<std::boxed::Box<u32>> as std::ops::Try>::from_error(move _8) -> [return: bb9, unwind: bb3]; // scope 2 at $DIR/issue-62289.rs:9:19: 9:20
+        _0 = <std::option::Option<std::boxed::Box<u32>> as std::ops::Try>::from_error(move _8) -> [return: bb9, unwind: bb3]; // scope 2 at $DIR/issue-62289.rs:9:19: 9:20
                                          // mir::Constant
                                          // + span: $DIR/issue-62289.rs:9:15: 9:20
                                          // + literal: Const { ty: fn(<std::option::Option<std::boxed::Box<u32>> as std::ops::Try>::Error) -> std::option::Option<std::boxed::Box<u32>> {<std::option::Option<std::boxed::Box<u32>> as std::ops::Try>::from_error}, val: Value(Scalar(<ZST>)) }
index 8b867781861818a4ba1685c42fbba1187fba7ed3..89b60121496f47e3b8b8b2de4af4120cf1a2aa80 100644 (file)
@@ -22,7 +22,7 @@ fn main() -> () {
 
     bb0: {
         StorageLive(_1);                 // scope 0 at $DIR/issue-72181.rs:24:13: 24:34
-        _1 = const std::mem::size_of::<Foo>() -> [return: bb2, unwind: bb1]; // scope 0 at $DIR/issue-72181.rs:24:13: 24:34
+        _1 = std::mem::size_of::<Foo>() -> [return: bb2, unwind: bb1]; // scope 0 at $DIR/issue-72181.rs:24:13: 24:34
                                          // mir::Constant
                                          // + span: $DIR/issue-72181.rs:24:13: 24:32
                                          // + literal: Const { ty: fn() -> usize {std::mem::size_of::<Foo>}, val: Value(Scalar(<ZST>)) }
index 8b867781861818a4ba1685c42fbba1187fba7ed3..89b60121496f47e3b8b8b2de4af4120cf1a2aa80 100644 (file)
@@ -22,7 +22,7 @@ fn main() -> () {
 
     bb0: {
         StorageLive(_1);                 // scope 0 at $DIR/issue-72181.rs:24:13: 24:34
-        _1 = const std::mem::size_of::<Foo>() -> [return: bb2, unwind: bb1]; // scope 0 at $DIR/issue-72181.rs:24:13: 24:34
+        _1 = std::mem::size_of::<Foo>() -> [return: bb2, unwind: bb1]; // scope 0 at $DIR/issue-72181.rs:24:13: 24:34
                                          // mir::Constant
                                          // + span: $DIR/issue-72181.rs:24:13: 24:32
                                          // + literal: Const { ty: fn() -> usize {std::mem::size_of::<Foo>}, val: Value(Scalar(<ZST>)) }
index e501b5a9056a9ced48f83819c80a3df543083456..b3aea29f13cfcf50a5cafb41c878ccd125522c6e 100644 (file)
@@ -21,7 +21,7 @@ fn main() -> () {
         StorageLive(_2);                 // scope 0 at $DIR/issue-72181-1.rs:16:9: 16:10
         StorageLive(_3);                 // scope 2 at $DIR/issue-72181-1.rs:17:41: 17:43
         _3 = ();                         // scope 2 at $DIR/issue-72181-1.rs:17:41: 17:43
-        _2 = const std::intrinsics::transmute::<(), Void>(move _3) -> [return: bb2, unwind: bb1]; // scope 2 at $DIR/issue-72181-1.rs:17:9: 17:44
+        _2 = std::intrinsics::transmute::<(), Void>(move _3) -> [return: bb2, unwind: bb1]; // scope 2 at $DIR/issue-72181-1.rs:17:9: 17:44
                                          // mir::Constant
                                          // + span: $DIR/issue-72181-1.rs:17:9: 17:40
                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(()) -> Void {std::intrinsics::transmute::<(), Void>}, val: Value(Scalar(<ZST>)) }
@@ -38,7 +38,7 @@ fn main() -> () {
         StorageLive(_4);                 // scope 1 at $DIR/issue-72181-1.rs:20:5: 20:9
         StorageLive(_5);                 // scope 1 at $DIR/issue-72181-1.rs:20:7: 20:8
         _5 = move _2;                    // scope 1 at $DIR/issue-72181-1.rs:20:7: 20:8
-        const f(move _5) -> bb1;         // scope 1 at $DIR/issue-72181-1.rs:20:5: 20:9
+        f(move _5) -> bb1;               // scope 1 at $DIR/issue-72181-1.rs:20:5: 20:9
                                          // mir::Constant
                                          // + span: $DIR/issue-72181-1.rs:20:5: 20:6
                                          // + literal: Const { ty: fn(Void) -> ! {f}, val: Value(Scalar(<ZST>)) }
index debf1c40110fd871df1170d3fd666e317f928f25..b940f1a929ddf6c8580f764b64cc12aaa66da7f4 100644 (file)
           _22 = (_18.0: &&i32);            // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           _23 = (_18.1: &&i32);            // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           StorageLive(_24);                // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _25 = const <&i32 as std::fmt::Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _25 = <&i32 as std::fmt::Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {<&i32 as std::fmt::Debug>::fmt}, val: Value(Scalar(<ZST>)) }
           StorageLive(_28);                // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          _28 = const std::intrinsics::transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _25) -> bb3; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          _28 = std::intrinsics::transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _25) -> bb3; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) -> for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {std::intrinsics::transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>}, val: Value(Scalar(<ZST>)) }
   
       bb3: {
           StorageLive(_29);                // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          _29 = const std::intrinsics::transmute::<&&i32, &core::fmt::Opaque>(move _22) -> bb4; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          _29 = std::intrinsics::transmute::<&&i32, &core::fmt::Opaque>(move _22) -> bb4; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(&&i32) -> &core::fmt::Opaque {std::intrinsics::transmute::<&&i32, &core::fmt::Opaque>}, val: Value(Scalar(<ZST>)) }
           StorageDead(_29);                // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
           StorageDead(_28);                // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
           StorageLive(_26);                // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _27 = const <&i32 as std::fmt::Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _27 = <&i32 as std::fmt::Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {<&i32 as std::fmt::Debug>::fmt}, val: Value(Scalar(<ZST>)) }
           StorageLive(_30);                // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          _30 = const std::intrinsics::transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _27) -> bb5; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          _30 = std::intrinsics::transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _27) -> bb5; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) -> for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {std::intrinsics::transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>}, val: Value(Scalar(<ZST>)) }
   
       bb5: {
           StorageLive(_31);                // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          _31 = const std::intrinsics::transmute::<&&i32, &core::fmt::Opaque>(move _23) -> bb6; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          _31 = std::intrinsics::transmute::<&&i32, &core::fmt::Opaque>(move _23) -> bb6; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(&&i32) -> &core::fmt::Opaque {std::intrinsics::transmute::<&&i32, &core::fmt::Opaque>}, val: Value(Scalar(<ZST>)) }
           (_13.2: &[std::fmt::ArgumentV1]) = move _15; // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
           StorageDead(_32);                // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
           _12 = &_13;                      // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          const std::rt::begin_panic_fmt(move _12); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          std::rt::begin_panic_fmt(move _12); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/std/src/macros.rs:LL:COL
                                            // + literal: Const { ty: for<'r, 's> fn(&'r std::fmt::Arguments<'s>) -> ! {std::rt::begin_panic_fmt}, val: Value(Scalar(<ZST>)) }
index debf1c40110fd871df1170d3fd666e317f928f25..b940f1a929ddf6c8580f764b64cc12aaa66da7f4 100644 (file)
           _22 = (_18.0: &&i32);            // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           _23 = (_18.1: &&i32);            // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           StorageLive(_24);                // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _25 = const <&i32 as std::fmt::Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _25 = <&i32 as std::fmt::Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {<&i32 as std::fmt::Debug>::fmt}, val: Value(Scalar(<ZST>)) }
           StorageLive(_28);                // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          _28 = const std::intrinsics::transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _25) -> bb3; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          _28 = std::intrinsics::transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _25) -> bb3; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) -> for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {std::intrinsics::transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>}, val: Value(Scalar(<ZST>)) }
   
       bb3: {
           StorageLive(_29);                // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          _29 = const std::intrinsics::transmute::<&&i32, &core::fmt::Opaque>(move _22) -> bb4; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          _29 = std::intrinsics::transmute::<&&i32, &core::fmt::Opaque>(move _22) -> bb4; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(&&i32) -> &core::fmt::Opaque {std::intrinsics::transmute::<&&i32, &core::fmt::Opaque>}, val: Value(Scalar(<ZST>)) }
           StorageDead(_29);                // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
           StorageDead(_28);                // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
           StorageLive(_26);                // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _27 = const <&i32 as std::fmt::Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _27 = <&i32 as std::fmt::Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {<&i32 as std::fmt::Debug>::fmt}, val: Value(Scalar(<ZST>)) }
           StorageLive(_30);                // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          _30 = const std::intrinsics::transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _27) -> bb5; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          _30 = std::intrinsics::transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _27) -> bb5; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) -> for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {std::intrinsics::transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>}, val: Value(Scalar(<ZST>)) }
   
       bb5: {
           StorageLive(_31);                // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          _31 = const std::intrinsics::transmute::<&&i32, &core::fmt::Opaque>(move _23) -> bb6; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          _31 = std::intrinsics::transmute::<&&i32, &core::fmt::Opaque>(move _23) -> bb6; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(&&i32) -> &core::fmt::Opaque {std::intrinsics::transmute::<&&i32, &core::fmt::Opaque>}, val: Value(Scalar(<ZST>)) }
           (_13.2: &[std::fmt::ArgumentV1]) = move _15; // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
           StorageDead(_32);                // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
           _12 = &_13;                      // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          const std::rt::begin_panic_fmt(move _12); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          std::rt::begin_panic_fmt(move _12); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/std/src/macros.rs:LL:COL
                                            // + literal: Const { ty: for<'r, 's> fn(&'r std::fmt::Arguments<'s>) -> ! {std::rt::begin_panic_fmt}, val: Value(Scalar(<ZST>)) }
index 1bc6482134673dc03faf78486eb42c573e78ee8c..586a9f7624c4424692e50193d5b2cab02c81dba2 100644 (file)
           StorageLive(_39);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           _39 = _36;                       // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           StorageLive(_40);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _40 = const <&i32 as std::fmt::Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _40 = <&i32 as std::fmt::Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {<&i32 as std::fmt::Debug>::fmt}, val: Value(Scalar(<ZST>)) }
           StorageLive(_46);                // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
           StorageLive(_47);                // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
           _47 = _40;                       // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          _46 = const std::intrinsics::transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _47) -> bb6; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          _46 = std::intrinsics::transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _47) -> bb6; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) -> for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {std::intrinsics::transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>}, val: Value(Scalar(<ZST>)) }
           StorageLive(_48);                // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
           StorageLive(_49);                // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
           _49 = _39;                       // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          _48 = const std::intrinsics::transmute::<&&i32, &core::fmt::Opaque>(move _49) -> bb7; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          _48 = std::intrinsics::transmute::<&&i32, &core::fmt::Opaque>(move _49) -> bb7; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(&&i32) -> &core::fmt::Opaque {std::intrinsics::transmute::<&&i32, &core::fmt::Opaque>}, val: Value(Scalar(<ZST>)) }
           StorageLive(_42);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           _42 = _37;                       // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           StorageLive(_43);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _43 = const <&i32 as std::fmt::Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _43 = <&i32 as std::fmt::Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {<&i32 as std::fmt::Debug>::fmt}, val: Value(Scalar(<ZST>)) }
           StorageLive(_50);                // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
           StorageLive(_51);                // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
           _51 = _43;                       // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          _50 = const std::intrinsics::transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _51) -> bb8; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          _50 = std::intrinsics::transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _51) -> bb8; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) -> for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {std::intrinsics::transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>}, val: Value(Scalar(<ZST>)) }
           StorageLive(_52);                // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
           StorageLive(_53);                // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
           _53 = _42;                       // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          _52 = const std::intrinsics::transmute::<&&i32, &core::fmt::Opaque>(move _53) -> bb9; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          _52 = std::intrinsics::transmute::<&&i32, &core::fmt::Opaque>(move _53) -> bb9; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(&&i32) -> &core::fmt::Opaque {std::intrinsics::transmute::<&&i32, &core::fmt::Opaque>}, val: Value(Scalar(<ZST>)) }
           StorageDead(_23);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
           _21 = &_22;                      // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
           _20 = _21;                       // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          const std::rt::begin_panic_fmt(move _20); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          std::rt::begin_panic_fmt(move _20); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/std/src/macros.rs:LL:COL
                                            // + literal: Const { ty: for<'r, 's> fn(&'r std::fmt::Arguments<'s>) -> ! {std::rt::begin_panic_fmt}, val: Value(Scalar(<ZST>)) }
index 1bc6482134673dc03faf78486eb42c573e78ee8c..586a9f7624c4424692e50193d5b2cab02c81dba2 100644 (file)
           StorageLive(_39);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           _39 = _36;                       // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           StorageLive(_40);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _40 = const <&i32 as std::fmt::Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _40 = <&i32 as std::fmt::Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {<&i32 as std::fmt::Debug>::fmt}, val: Value(Scalar(<ZST>)) }
           StorageLive(_46);                // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
           StorageLive(_47);                // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
           _47 = _40;                       // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          _46 = const std::intrinsics::transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _47) -> bb6; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          _46 = std::intrinsics::transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _47) -> bb6; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) -> for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {std::intrinsics::transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>}, val: Value(Scalar(<ZST>)) }
           StorageLive(_48);                // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
           StorageLive(_49);                // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
           _49 = _39;                       // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          _48 = const std::intrinsics::transmute::<&&i32, &core::fmt::Opaque>(move _49) -> bb7; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          _48 = std::intrinsics::transmute::<&&i32, &core::fmt::Opaque>(move _49) -> bb7; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(&&i32) -> &core::fmt::Opaque {std::intrinsics::transmute::<&&i32, &core::fmt::Opaque>}, val: Value(Scalar(<ZST>)) }
           StorageLive(_42);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           _42 = _37;                       // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           StorageLive(_43);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _43 = const <&i32 as std::fmt::Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _43 = <&i32 as std::fmt::Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {<&i32 as std::fmt::Debug>::fmt}, val: Value(Scalar(<ZST>)) }
           StorageLive(_50);                // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
           StorageLive(_51);                // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
           _51 = _43;                       // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          _50 = const std::intrinsics::transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _51) -> bb8; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          _50 = std::intrinsics::transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _51) -> bb8; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) -> for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {std::intrinsics::transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>}, val: Value(Scalar(<ZST>)) }
           StorageLive(_52);                // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
           StorageLive(_53);                // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
           _53 = _42;                       // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          _52 = const std::intrinsics::transmute::<&&i32, &core::fmt::Opaque>(move _53) -> bb9; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          _52 = std::intrinsics::transmute::<&&i32, &core::fmt::Opaque>(move _53) -> bb9; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(&&i32) -> &core::fmt::Opaque {std::intrinsics::transmute::<&&i32, &core::fmt::Opaque>}, val: Value(Scalar(<ZST>)) }
           StorageDead(_23);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
           _21 = &_22;                      // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
           _20 = _21;                       // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          const std::rt::begin_panic_fmt(move _20); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          std::rt::begin_panic_fmt(move _20); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/std/src/macros.rs:LL:COL
                                            // + literal: Const { ty: for<'r, 's> fn(&'r std::fmt::Arguments<'s>) -> ! {std::rt::begin_panic_fmt}, val: Value(Scalar(<ZST>)) }
index 8a057534056aa22ecb1732dc4e4e945800174602..c0249d134f29f03d8d642e601bb59ec057c70223 100644 (file)
@@ -65,7 +65,7 @@ fn full_tested_match() -> () {
         _6 = &(((*_11) as Some).0: i32); // scope 0 at $DIR/match_false_edges.rs:16:14: 16:15
         _4 = &shallow _2;                // scope 0 at $DIR/match_false_edges.rs:15:19: 15:27
         StorageLive(_7);                 // scope 0 at $DIR/match_false_edges.rs:16:20: 16:27
-        _7 = const guard() -> [return: bb7, unwind: bb1]; // scope 0 at $DIR/match_false_edges.rs:16:20: 16:27
+        _7 = guard() -> [return: bb7, unwind: bb1]; // scope 0 at $DIR/match_false_edges.rs:16:20: 16:27
                                          // mir::Constant
                                          // + span: $DIR/match_false_edges.rs:16:20: 16:25
                                          // + literal: Const { ty: fn() -> bool {guard}, val: Value(Scalar(<ZST>)) }
index 75199884b6e019542639d24d6bee335c9f1c4674..a2ad5be265d88dfb581a063f9039aad48a3ec0a9 100644 (file)
@@ -63,7 +63,7 @@ fn full_tested_match2() -> () {
         _6 = &((_2 as Some).0: i32);     // scope 0 at $DIR/match_false_edges.rs:27:14: 27:15
         _4 = &shallow _2;                // scope 0 at $DIR/match_false_edges.rs:26:19: 26:27
         StorageLive(_7);                 // scope 0 at $DIR/match_false_edges.rs:27:20: 27:27
-        _7 = const guard() -> [return: bb7, unwind: bb1]; // scope 0 at $DIR/match_false_edges.rs:27:20: 27:27
+        _7 = guard() -> [return: bb7, unwind: bb1]; // scope 0 at $DIR/match_false_edges.rs:27:20: 27:27
                                          // mir::Constant
                                          // + span: $DIR/match_false_edges.rs:27:20: 27:25
                                          // + literal: Const { ty: fn() -> bool {guard}, val: Value(Scalar(<ZST>)) }
index 3381b454080762cc6863780e752a628d990cf640..b7322e7da0f6b4a639d8f739d66c2e9e7cf9dac1 100644 (file)
@@ -71,7 +71,7 @@ fn main() -> () {
         _7 = &((_2 as Some).0: i32);     // scope 0 at $DIR/match_false_edges.rs:36:14: 36:16
         _5 = &shallow _2;                // scope 0 at $DIR/match_false_edges.rs:35:19: 35:26
         StorageLive(_8);                 // scope 0 at $DIR/match_false_edges.rs:36:21: 36:28
-        _8 = const guard() -> [return: bb7, unwind: bb1]; // scope 0 at $DIR/match_false_edges.rs:36:21: 36:28
+        _8 = guard() -> [return: bb7, unwind: bb1]; // scope 0 at $DIR/match_false_edges.rs:36:21: 36:28
                                          // mir::Constant
                                          // + span: $DIR/match_false_edges.rs:36:21: 36:26
                                          // + literal: Const { ty: fn() -> bool {guard}, val: Value(Scalar(<ZST>)) }
@@ -114,7 +114,7 @@ fn main() -> () {
         StorageLive(_12);                // scope 0 at $DIR/match_false_edges.rs:38:20: 38:29
         StorageLive(_13);                // scope 0 at $DIR/match_false_edges.rs:38:27: 38:28
         _13 = (*_11);                    // scope 0 at $DIR/match_false_edges.rs:38:27: 38:28
-        _12 = const guard2(move _13) -> [return: bb12, unwind: bb1]; // scope 0 at $DIR/match_false_edges.rs:38:20: 38:29
+        _12 = guard2(move _13) -> [return: bb12, unwind: bb1]; // scope 0 at $DIR/match_false_edges.rs:38:20: 38:29
                                          // mir::Constant
                                          // + span: $DIR/match_false_edges.rs:38:20: 38:26
                                          // + literal: Const { ty: fn(i32) -> bool {guard2}, val: Value(Scalar(<ZST>)) }
index 8cb7374468aafc65264fe584cd3db6ab4b59929a..2885dd8eb78453a3a4a15aeebbf4962675c86989 100644 (file)
@@ -77,7 +77,7 @@ fn main() -> () {
 
     bb4: {
         StorageLive(_10);                // bb4[0]: scope 3 at $DIR/region-subtyping-basic.rs:23:9: 23:18
-        _10 = const Const(Value(Scalar(<ZST>)): fn(usize) -> bool {use_x})(const Const(Value(Scalar(0x00000016)): usize)) -> [return: bb7, unwind: bb1]; // bb4[1]: scope 3 at $DIR/region-subtyping-basic.rs:23:9: 23:18
+        _10 = Const(Value(Scalar(<ZST>)): fn(usize) -> bool {use_x})(const Const(Value(Scalar(0x00000016)): usize)) -> [return: bb7, unwind: bb1]; // bb4[1]: scope 3 at $DIR/region-subtyping-basic.rs:23:9: 23:18
                                          // mir::Constant
                                          // + span: $DIR/region-subtyping-basic.rs:23:9: 23:14
                                          // + literal: Const { ty: fn(usize) -> bool {use_x}, val: Value(Scalar(<ZST>)) }
@@ -87,7 +87,7 @@ fn main() -> () {
         StorageLive(_8);                 // bb5[0]: scope 3 at $DIR/region-subtyping-basic.rs:21:9: 21:18
         StorageLive(_9);                 // bb5[1]: scope 3 at $DIR/region-subtyping-basic.rs:21:15: 21:17
         _9 = (*_6);                      // bb5[2]: scope 3 at $DIR/region-subtyping-basic.rs:21:15: 21:17
-        _8 = const Const(Value(Scalar(<ZST>)): fn(usize) -> bool {use_x})(move _9) -> [return: bb6, unwind: bb1]; // bb5[3]: scope 3 at $DIR/region-subtyping-basic.rs:21:9: 21:18
+        _8 = Const(Value(Scalar(<ZST>)): fn(usize) -> bool {use_x})(move _9) -> [return: bb6, unwind: bb1]; // bb5[3]: scope 3 at $DIR/region-subtyping-basic.rs:21:9: 21:18
                                          // mir::Constant
                                          // + span: $DIR/region-subtyping-basic.rs:21:9: 21:14
                                          // + literal: Const { ty: fn(usize) -> bool {use_x}, val: Value(Scalar(<ZST>)) }
index 6b1b74930aff1c73c54eecba361804d0fce8d77c..3820f70d5153e09269b58481e06f4f6d848d0b28 100644 (file)
@@ -77,7 +77,7 @@ fn main() -> () {
 
     bb4: {
         StorageLive(_10);                // bb4[0]: scope 3 at $DIR/region-subtyping-basic.rs:23:9: 23:18
-        _10 = const Const(Value(Scalar(<ZST>)): fn(usize) -> bool {use_x})(const Const(Value(Scalar(0x0000000000000016)): usize)) -> [return: bb7, unwind: bb1]; // bb4[1]: scope 3 at $DIR/region-subtyping-basic.rs:23:9: 23:18
+        _10 = Const(Value(Scalar(<ZST>)): fn(usize) -> bool {use_x})(const Const(Value(Scalar(0x0000000000000016)): usize)) -> [return: bb7, unwind: bb1]; // bb4[1]: scope 3 at $DIR/region-subtyping-basic.rs:23:9: 23:18
                                          // mir::Constant
                                          // + span: $DIR/region-subtyping-basic.rs:23:9: 23:14
                                          // + literal: Const { ty: fn(usize) -> bool {use_x}, val: Value(Scalar(<ZST>)) }
@@ -87,7 +87,7 @@ fn main() -> () {
         StorageLive(_8);                 // bb5[0]: scope 3 at $DIR/region-subtyping-basic.rs:21:9: 21:18
         StorageLive(_9);                 // bb5[1]: scope 3 at $DIR/region-subtyping-basic.rs:21:15: 21:17
         _9 = (*_6);                      // bb5[2]: scope 3 at $DIR/region-subtyping-basic.rs:21:15: 21:17
-        _8 = const Const(Value(Scalar(<ZST>)): fn(usize) -> bool {use_x})(move _9) -> [return: bb6, unwind: bb1]; // bb5[3]: scope 3 at $DIR/region-subtyping-basic.rs:21:9: 21:18
+        _8 = Const(Value(Scalar(<ZST>)): fn(usize) -> bool {use_x})(move _9) -> [return: bb6, unwind: bb1]; // bb5[3]: scope 3 at $DIR/region-subtyping-basic.rs:21:9: 21:18
                                          // mir::Constant
                                          // + span: $DIR/region-subtyping-basic.rs:21:9: 21:14
                                          // + literal: Const { ty: fn(usize) -> bool {use_x}, val: Value(Scalar(<ZST>)) }
index c073fad9420085dad172d10effc12175079bed9b..e90364c1ccf0250af6290720962d7489046ade5e 100644 (file)
@@ -20,7 +20,7 @@ fn unwrap(_1: std::option::Option<T>) -> T {
 
     bb1: {
         StorageLive(_4);                 // scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-        const std::rt::begin_panic::<&str>(const "explicit panic") -> bb4; // scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
+        std::rt::begin_panic::<&str>(const "explicit panic") -> bb4; // scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
                                          // mir::Constant
                                          // + span: $SRC_DIR/std/src/macros.rs:LL:COL
                                          // + literal: Const { ty: fn(&str) -> ! {std::rt::begin_panic::<&str>}, val: Value(Scalar(<ZST>)) }
index a16fb9416e8681546dddaa4e9baccc7e38ae0710..5e1866fbc5370c6632a77f81d2cb06bea6243833 100644 (file)
@@ -20,7 +20,7 @@ fn main() -> () {
                                          // + span: $DIR/no-spurious-drop-after-call.rs:9:20: 9:22
                                          // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [], len: Size { raw: 0 } }, size: Size { raw: 0 }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 0 }) }
         _3 = &(*_4);                     // scope 0 at $DIR/no-spurious-drop-after-call.rs:9:20: 9:22
-        _2 = const <str as std::string::ToString>::to_string(move _3) -> bb2; // scope 0 at $DIR/no-spurious-drop-after-call.rs:9:20: 9:34
+        _2 = <str as std::string::ToString>::to_string(move _3) -> bb2; // scope 0 at $DIR/no-spurious-drop-after-call.rs:9:20: 9:34
                                          // mir::Constant
                                          // + span: $DIR/no-spurious-drop-after-call.rs:9:23: 9:32
                                          // + literal: Const { ty: for<'r> fn(&'r str) -> std::string::String {<str as std::string::ToString>::to_string}, val: Value(Scalar(<ZST>)) }
@@ -32,7 +32,7 @@ fn main() -> () {
 
     bb2: {
         StorageDead(_3);                 // scope 0 at $DIR/no-spurious-drop-after-call.rs:9:33: 9:34
-        _1 = const std::mem::drop::<std::string::String>(move _2) -> [return: bb3, unwind: bb4]; // scope 0 at $DIR/no-spurious-drop-after-call.rs:9:5: 9:35
+        _1 = std::mem::drop::<std::string::String>(move _2) -> [return: bb3, unwind: bb4]; // scope 0 at $DIR/no-spurious-drop-after-call.rs:9:5: 9:35
                                          // mir::Constant
                                          // + span: $DIR/no-spurious-drop-after-call.rs:9:5: 9:19
                                          // + literal: Const { ty: fn(std::string::String) {std::mem::drop::<std::string::String>}, val: Value(Scalar(<ZST>)) }
index 7769a9630d9369cce64e401dcf94838263cb025e..b10ca21831495c9a32975579b59a427d67ae00db 100644 (file)
@@ -8,7 +8,7 @@ fn std::intrinsics::drop_in_place(_1: *mut Test) -> () {
     bb0: {
         Retag([raw] _1);                 // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
         _2 = &mut (*_1);                 // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-        _3 = const <Test as std::ops::Drop>::drop(move _2) -> bb1; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+        _3 = <Test as std::ops::Drop>::drop(move _2) -> bb1; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
                                          // mir::Constant
                                          // + span: $SRC_DIR/core/src/ptr/mod.rs:LL:COL
                                          // + literal: Const { ty: for<'r> fn(&'r mut Test) {<Test as std::ops::Drop>::drop}, val: Value(Scalar(<ZST>)) }
index 87bade416cb8a9d639857613e4699a6f8045a21d..5a79466ede532c2925e8617e6bda6c33eb47b592 100644 (file)
@@ -70,7 +70,7 @@ fn main() -> () {
         Retag(_7);                       // scope 1 at $DIR/retag.rs:32:29: 32:35
         _6 = &mut (*_7);                 // scope 1 at $DIR/retag.rs:32:29: 32:35
         Retag([2phase] _6);              // scope 1 at $DIR/retag.rs:32:29: 32:35
-        _3 = const Test::foo(move _4, move _6) -> [return: bb2, unwind: bb3]; // scope 1 at $DIR/retag.rs:32:17: 32:36
+        _3 = Test::foo(move _4, move _6) -> [return: bb2, unwind: bb3]; // scope 1 at $DIR/retag.rs:32:17: 32:36
                                          // mir::Constant
                                          // + span: $DIR/retag.rs:32:25: 32:28
                                          // + literal: Const { ty: for<'r, 'x> fn(&'r Test, &'x mut i32) -> &'x mut i32 {Test::foo}, val: Value(Scalar(<ZST>)) }
@@ -166,7 +166,7 @@ fn main() -> () {
         Retag(_23);                      // scope 7 at $DIR/retag.rs:47:21: 47:23
         _22 = &(*_23);                   // scope 7 at $DIR/retag.rs:47:21: 47:23
         Retag(_22);                      // scope 7 at $DIR/retag.rs:47:21: 47:23
-        _19 = const Test::foo_shr(move _20, move _22) -> [return: bb6, unwind: bb7]; // scope 7 at $DIR/retag.rs:47:5: 47:24
+        _19 = Test::foo_shr(move _20, move _22) -> [return: bb6, unwind: bb7]; // scope 7 at $DIR/retag.rs:47:5: 47:24
                                          // mir::Constant
                                          // + span: $DIR/retag.rs:47:13: 47:20
                                          // + literal: Const { ty: for<'r, 'x> fn(&'r Test, &'x i32) -> &'x i32 {Test::foo_shr}, val: Value(Scalar(<ZST>)) }
index 52c0a195e9983ebbfc0b5a776b6dcf92e65bb62a..ede081f85dede52908752307dda057602306026a 100644 (file)
@@ -13,8 +13,8 @@
 - 
 -     bb1: {
           StorageLive(_2);                 // scope 0 at $DIR/simplify_cfg.rs:7:12: 7:17
--         _2 = const bar() -> bb3;         // scope 0 at $DIR/simplify_cfg.rs:7:12: 7:17
-+         _2 = const bar() -> bb1;         // scope 0 at $DIR/simplify_cfg.rs:7:12: 7:17
+-         _2 = bar() -> bb3;               // scope 0 at $DIR/simplify_cfg.rs:7:12: 7:17
++         _2 = bar() -> bb1;               // scope 0 at $DIR/simplify_cfg.rs:7:12: 7:17
                                            // mir::Constant
                                            // + span: $DIR/simplify_cfg.rs:7:12: 7:15
                                            // + literal: Const { ty: fn() -> bool {bar}, val: Value(Scalar(<ZST>)) }
index d3d2002cf2158617f46291501054ed818b3ff864..e8cdd390ff8f0623c25d3e07c2affdd8fa01d6c4 100644 (file)
@@ -22,8 +22,8 @@
 - 
 -     bb3: {
           StorageLive(_2);                 // scope 0 at $DIR/simplify_cfg.rs:7:12: 7:17
--         _2 = const bar() -> [return: bb5, unwind: bb4]; // scope 0 at $DIR/simplify_cfg.rs:7:12: 7:17
-+         _2 = const bar() -> [return: bb3, unwind: bb2]; // scope 0 at $DIR/simplify_cfg.rs:7:12: 7:17
+-         _2 = bar() -> [return: bb5, unwind: bb4]; // scope 0 at $DIR/simplify_cfg.rs:7:12: 7:17
++         _2 = bar() -> [return: bb3, unwind: bb2]; // scope 0 at $DIR/simplify_cfg.rs:7:12: 7:17
                                            // mir::Constant
                                            // + span: $DIR/simplify_cfg.rs:7:12: 7:15
                                            // + literal: Const { ty: fn() -> bool {bar}, val: Value(Scalar(<ZST>)) }
index 49aa7fcb698299ba10167ba72bf126d4d36811ff..aeb319a4904bf733a7f4b95f5f43bcf3f2ab0855 100644 (file)
@@ -20,7 +20,7 @@
   
       bb2: {
           StorageLive(_2);                 // scope 0 at $DIR/simplify_if.rs:7:9: 7:15
-          _2 = const noop() -> bb3;        // scope 0 at $DIR/simplify_if.rs:7:9: 7:15
+          _2 = noop() -> bb3;              // scope 0 at $DIR/simplify_if.rs:7:9: 7:15
                                            // mir::Constant
                                            // + span: $DIR/simplify_if.rs:7:9: 7:13
                                            // + literal: Const { ty: fn() {noop}, val: Value(Scalar(<ZST>)) }
index a33aa085fcd3af3aa888eab0e6730df6e664f992..3064e92f90007c1d1327e3f1c86b133c4d328475 100644 (file)
@@ -36,9 +36,9 @@
 -         (_5.1: ()) = const ();           // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:13: 14:21
 -         StorageDead(_7);                 // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:20: 14:21
 -         StorageDead(_6);                 // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:20: 14:21
--         _4 = const use_zst(const ((), ())) -> bb1; // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:5: 14:22
+-         _4 = use_zst(const ((), ())) -> bb1; // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:5: 14:22
 +         StorageLive(_1);                 // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:5: 14:22
-+         _1 = const use_zst(const ((), ())) -> bb1; // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:5: 14:22
++         _1 = use_zst(const ((), ())) -> bb1; // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:5: 14:22
                                            // mir::Constant
                                            // + span: $DIR/simplify-locals-removes-unused-consts.rs:14:5: 14:12
                                            // + literal: Const { ty: fn(((), ())) {use_zst}, val: Value(Scalar(<ZST>)) }
 -         _10 = const 40_u8;               // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:12: 16:30
 -         _9 = const 42_u8;                // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:12: 16:34
 -         StorageDead(_10);                // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:33: 16:34
--         _8 = const use_u8(const 42_u8) -> bb2; // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:5: 16:35
+-         _8 = use_u8(const 42_u8) -> bb2; // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:5: 16:35
 +         StorageDead(_1);                 // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:22: 14:23
 +         StorageLive(_2);                 // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:5: 16:35
-+         _2 = const use_u8(const 42_u8) -> bb2; // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:5: 16:35
++         _2 = use_u8(const 42_u8) -> bb2; // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:5: 16:35
                                            // mir::Constant
                                            // + span: $DIR/simplify-locals-removes-unused-consts.rs:16:5: 16:11
                                            // + literal: Const { ty: fn(u8) {use_u8}, val: Value(Scalar(<ZST>)) }
index 10b97ca35956618b88db6c2d50fba542af1dc537..0fdc364514b4b710bd759cf7645cc781aff3d165 100644 (file)
@@ -26,7 +26,7 @@
       }
   
       bb2: {
-          _0 = const noop() -> bb3;        // scope 0 at $DIR/simplify_match.rs:7:17: 7:23
+          _0 = noop() -> bb3;              // scope 0 at $DIR/simplify_match.rs:7:17: 7:23
                                            // mir::Constant
                                            // + span: $DIR/simplify_match.rs:7:17: 7:21
                                            // + literal: Const { ty: fn() {noop}, val: Value(Scalar(<ZST>)) }
index 6a1bb7096c5ef1c507f99a030b4b8f570f304ce4..51a1e6ba4c3c37134c726633b32dbf495c9b72f5 100644 (file)
@@ -35,7 +35,7 @@
           StorageLive(_5);                 // scope 1 at $DIR/simplify_try_if_let.rs:26:43: 26:60
           StorageLive(_6);                 // scope 1 at $DIR/simplify_try_if_let.rs:26:43: 26:53
           _6 = &mut ((*_2).0: std::option::Option<std::ptr::NonNull<Node>>); // scope 1 at $DIR/simplify_try_if_let.rs:26:43: 26:53
-          _5 = const std::option::Option::<std::ptr::NonNull<Node>>::take(move _6) -> bb4; // scope 1 at $DIR/simplify_try_if_let.rs:26:43: 26:60
+          _5 = std::option::Option::<std::ptr::NonNull<Node>>::take(move _6) -> bb4; // scope 1 at $DIR/simplify_try_if_let.rs:26:43: 26:60
                                            // mir::Constant
                                            // + span: $DIR/simplify_try_if_let.rs:26:54: 26:58
                                            // + literal: Const { ty: for<'r> fn(&'r mut std::option::Option<std::ptr::NonNull<Node>>) -> std::option::Option<std::ptr::NonNull<Node>> {std::option::Option::<std::ptr::NonNull<Node>>::take}, val: Value(Scalar(<ZST>)) }
@@ -73,7 +73,7 @@
           StorageLive(_11);                // scope 3 at $DIR/simplify_try_if_let.rs:28:25: 28:38
           StorageLive(_12);                // scope 3 at $DIR/simplify_try_if_let.rs:28:25: 28:29
           _12 = &mut _4;                   // scope 3 at $DIR/simplify_try_if_let.rs:28:25: 28:29
-          _11 = const std::ptr::NonNull::<Node>::as_mut(move _12) -> bb7; // scope 3 at $DIR/simplify_try_if_let.rs:28:25: 28:38
+          _11 = std::ptr::NonNull::<Node>::as_mut(move _12) -> bb7; // scope 3 at $DIR/simplify_try_if_let.rs:28:25: 28:38
                                            // mir::Constant
                                            // + span: $DIR/simplify_try_if_let.rs:28:30: 28:36
                                            // + literal: Const { ty: for<'r> unsafe fn(&'r mut std::ptr::NonNull<Node>) -> &'r mut Node {std::ptr::NonNull::<Node>::as_mut}, val: Value(Scalar(<ZST>)) }
index 2e1bae73a403da183f705bb44dc626f630a865da..37ff5c6ee3bbdc4f6202c122ab07d5a6a38ee92a 100644 (file)
@@ -19,7 +19,7 @@
   
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/unreachable.rs:9:23: 9:30
-          _1 = const empty() -> bb1;       // scope 0 at $DIR/unreachable.rs:9:23: 9:30
+          _1 = empty() -> bb1;             // scope 0 at $DIR/unreachable.rs:9:23: 9:30
                                            // mir::Constant
                                            // + span: $DIR/unreachable.rs:9:23: 9:28
                                            // + literal: Const { ty: fn() -> std::option::Option<Empty> {empty}, val: Value(Scalar(<ZST>)) }
index da50cfe63fa4178e4885746535241321767aa2a6..5caacf84ca657f06f1ac205e03493658d78f1e20 100644 (file)
@@ -22,7 +22,7 @@
   
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/unreachable_asm.rs:11:23: 11:30
-          _1 = const empty() -> bb1;       // scope 0 at $DIR/unreachable_asm.rs:11:23: 11:30
+          _1 = empty() -> bb1;             // scope 0 at $DIR/unreachable_asm.rs:11:23: 11:30
                                            // mir::Constant
                                            // + span: $DIR/unreachable_asm.rs:11:23: 11:28
                                            // + literal: Const { ty: fn() -> std::option::Option<Empty> {empty}, val: Value(Scalar(<ZST>)) }
index b22a697ad8790bc811a606a846963c4722cb28ab..07ed81b35f53d14cf7c97868f73b27ece17f36b2 100644 (file)
@@ -25,7 +25,7 @@
   
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/unreachable_asm_2.rs:11:23: 11:30
-          _1 = const empty() -> bb1;       // scope 0 at $DIR/unreachable_asm_2.rs:11:23: 11:30
+          _1 = empty() -> bb1;             // scope 0 at $DIR/unreachable_asm_2.rs:11:23: 11:30
                                            // mir::Constant
                                            // + span: $DIR/unreachable_asm_2.rs:11:23: 11:28
                                            // + literal: Const { ty: fn() -> std::option::Option<Empty> {empty}, val: Value(Scalar(<ZST>)) }
index 2a9575aa998a01d8435afbe03c54bc12ad07500a..c809483d8c2c400b364e334854a6d8ee5a6bc762 100644 (file)
@@ -21,7 +21,7 @@
           StorageLive(_1);                 // scope 0 at $DIR/unreachable_diverging.rs:13:9: 13:10
           _1 = const true;                 // scope 0 at $DIR/unreachable_diverging.rs:13:13: 13:17
           StorageLive(_2);                 // scope 1 at $DIR/unreachable_diverging.rs:14:25: 14:32
-          _2 = const empty() -> bb1;       // scope 1 at $DIR/unreachable_diverging.rs:14:25: 14:32
+          _2 = empty() -> bb1;             // scope 1 at $DIR/unreachable_diverging.rs:14:25: 14:32
                                            // mir::Constant
                                            // + span: $DIR/unreachable_diverging.rs:14:25: 14:30
                                            // + literal: Const { ty: fn() -> std::option::Option<Empty> {empty}, val: Value(Scalar(<ZST>)) }
@@ -55,8 +55,8 @@
 -     }
 - 
 -     bb5: {
--         _5 = const loop_forever() -> bb6; // scope 2 at $DIR/unreachable_diverging.rs:16:13: 16:27
-+         _5 = const loop_forever() -> bb5; // scope 2 at $DIR/unreachable_diverging.rs:16:13: 16:27
+-         _5 = loop_forever() -> bb6;      // scope 2 at $DIR/unreachable_diverging.rs:16:13: 16:27
++         _5 = loop_forever() -> bb5;      // scope 2 at $DIR/unreachable_diverging.rs:16:13: 16:27
                                            // mir::Constant
                                            // + span: $DIR/unreachable_diverging.rs:16:13: 16:25
                                            // + literal: Const { ty: fn() {loop_forever}, val: Value(Scalar(<ZST>)) }
index d843bef6a95bfe7e5b116158e7b416fa38c2cc63..1f5804e0b2c8f6c76cfd4961b9a798cbf57daf09 100644 (file)
@@ -35,7 +35,7 @@ fn std::intrinsics::drop_in_place(_1: *mut std::vec::Vec<i32>) -> () {
 
     bb7: {
         _2 = &mut (*_1);                 // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-        _3 = const <std::vec::Vec<i32> as std::ops::Drop>::drop(move _2) -> [return: bb6, unwind: bb5]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+        _3 = <std::vec::Vec<i32> as std::ops::Drop>::drop(move _2) -> [return: bb6, unwind: bb5]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
                                          // mir::Constant
                                          // + span: $SRC_DIR/core/src/ptr/mod.rs:LL:COL
                                          // + literal: Const { ty: for<'r> fn(&'r mut std::vec::Vec<i32>) {<std::vec::Vec<i32> as std::ops::Drop>::drop}, val: Value(Scalar(<ZST>)) }
index d843bef6a95bfe7e5b116158e7b416fa38c2cc63..1f5804e0b2c8f6c76cfd4961b9a798cbf57daf09 100644 (file)
@@ -35,7 +35,7 @@ fn std::intrinsics::drop_in_place(_1: *mut std::vec::Vec<i32>) -> () {
 
     bb7: {
         _2 = &mut (*_1);                 // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-        _3 = const <std::vec::Vec<i32> as std::ops::Drop>::drop(move _2) -> [return: bb6, unwind: bb5]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+        _3 = <std::vec::Vec<i32> as std::ops::Drop>::drop(move _2) -> [return: bb6, unwind: bb5]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
                                          // mir::Constant
                                          // + span: $SRC_DIR/core/src/ptr/mod.rs:LL:COL
                                          // + literal: Const { ty: for<'r> fn(&'r mut std::vec::Vec<i32>) {<std::vec::Vec<i32> as std::ops::Drop>::drop}, val: Value(Scalar(<ZST>)) }
index 48c18679c0accdc64b2a87ab0a06287413ca5a42..f4a7ffe50b37c8a6a4f0bcd727c6fdb1db902c85 100644 (file)
@@ -12,7 +12,7 @@ fn while_loop(_1: bool) -> () {
         StorageLive(_2);                 // scope 0 at $DIR/while-storage.rs:10:11: 10:22
         StorageLive(_3);                 // scope 0 at $DIR/while-storage.rs:10:20: 10:21
         _3 = _1;                         // scope 0 at $DIR/while-storage.rs:10:20: 10:21
-        _2 = const get_bool(move _3) -> bb1; // scope 0 at $DIR/while-storage.rs:10:11: 10:22
+        _2 = get_bool(move _3) -> bb1;   // scope 0 at $DIR/while-storage.rs:10:11: 10:22
                                          // mir::Constant
                                          // + span: $DIR/while-storage.rs:10:11: 10:19
                                          // + literal: Const { ty: fn(bool) -> bool {get_bool}, val: Value(Scalar(<ZST>)) }
@@ -32,7 +32,7 @@ fn while_loop(_1: bool) -> () {
         StorageLive(_4);                 // scope 0 at $DIR/while-storage.rs:11:12: 11:23
         StorageLive(_5);                 // scope 0 at $DIR/while-storage.rs:11:21: 11:22
         _5 = _1;                         // scope 0 at $DIR/while-storage.rs:11:21: 11:22
-        _4 = const get_bool(move _5) -> bb4; // scope 0 at $DIR/while-storage.rs:11:12: 11:23
+        _4 = get_bool(move _5) -> bb4;   // scope 0 at $DIR/while-storage.rs:11:12: 11:23
                                          // mir::Constant
                                          // + span: $DIR/while-storage.rs:11:12: 11:20
                                          // + literal: Const { ty: fn(bool) -> bool {get_bool}, val: Value(Scalar(<ZST>)) }
index 5881cf4b7dbbc6eefa64b4f83e9a26b17e1bb830..75bec80bdf8864a12540aaa863cbbec986302ce6 100644 (file)
@@ -55,5 +55,5 @@
     }
   ],
   "type": "llvm.coverage.json.export",
-  "version": "2.0.0"
+  "version": "2.0.1"
 }
diff --git a/src/test/rustdoc-ui/assoc-item-not-in-scope.rs b/src/test/rustdoc-ui/assoc-item-not-in-scope.rs
new file mode 100644 (file)
index 0000000..c5bb430
--- /dev/null
@@ -0,0 +1,22 @@
+#![deny(broken_intra_doc_links)]
+
+#[derive(Debug)]
+/// Link to [`S::fmt`]
+//~^ ERROR unresolved link
+pub struct S;
+
+pub mod inner {
+    use std::fmt::Debug;
+    use super::S;
+
+    /// Link to [`S::fmt`]
+    pub fn f() {}
+}
+
+pub mod ambiguous {
+    use std::fmt::{Display, Debug};
+    use super::S;
+
+    /// Link to [`S::fmt`]
+    pub fn f() {}
+}
diff --git a/src/test/rustdoc-ui/assoc-item-not-in-scope.stderr b/src/test/rustdoc-ui/assoc-item-not-in-scope.stderr
new file mode 100644 (file)
index 0000000..8827c93
--- /dev/null
@@ -0,0 +1,15 @@
+error: unresolved link to `S::fmt`
+  --> $DIR/assoc-item-not-in-scope.rs:4:14
+   |
+LL | /// Link to [`S::fmt`]
+   |              ^^^^^^^^ unresolved link
+   |
+note: the lint level is defined here
+  --> $DIR/assoc-item-not-in-scope.rs:1:9
+   |
+LL | #![deny(broken_intra_doc_links)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: aborting due to previous error
+
index 7e795acc575bccd51debfbea00fdd055b534cf23..3c602b3da4c7c8952347566f6acb16fbcf7ebea4 100644 (file)
@@ -1,7 +1,7 @@
-+-------------------------------------+------------+------------+------------+------------+------------+
-| File                                | Documented |      Total | Percentage |   Examples | Percentage |
-+-------------------------------------+------------+------------+------------+------------+------------+
-| ...est/rustdoc-ui/coverage/basic.rs |          7 |         14 |      50.0% |          0 |       0.0% |
-+-------------------------------------+------------+------------+------------+------------+------------+
-| Total                               |          7 |         14 |      50.0% |          0 |       0.0% |
-+-------------------------------------+------------+------------+------------+------------+------------+
++-------------------------------------+------------+------------+------------+------------+
+| File                                | Documented | Percentage |   Examples | Percentage |
++-------------------------------------+------------+------------+------------+------------+
+| ...est/rustdoc-ui/coverage/basic.rs |          7 |      50.0% |          0 |       0.0% |
++-------------------------------------+------------+------------+------------+------------+
+| Total                               |          7 |      50.0% |          0 |       0.0% |
++-------------------------------------+------------+------------+------------+------------+
diff --git a/src/test/rustdoc-ui/coverage/doc-examples-json.rs b/src/test/rustdoc-ui/coverage/doc-examples-json.rs
new file mode 100644 (file)
index 0000000..1da1813
--- /dev/null
@@ -0,0 +1,13 @@
+// check-pass
+// compile-flags:-Z unstable-options --output-format json --show-coverage
+
+// This check ensures that only one doc example is counted since they're "optional" on
+// certain items.
+
+/// ```
+/// let x = 12;
+/// ```
+pub const Foo: u32 = 0;
+
+/// doc
+pub const Bar: u32 = 0;
diff --git a/src/test/rustdoc-ui/coverage/doc-examples-json.stdout b/src/test/rustdoc-ui/coverage/doc-examples-json.stdout
new file mode 100644 (file)
index 0000000..92f5855
--- /dev/null
@@ -0,0 +1 @@
+{"$DIR/doc-examples-json.rs":{"total":3,"with_docs":2,"total_examples":2,"with_examples":1}}
index f25cf79a3f35d45876f1989e0633376e6acb4773..10ed13c9ff566c76d169649cc58949d7031dd442 100644 (file)
@@ -1,7 +1,7 @@
-+-------------------------------------+------------+------------+------------+------------+------------+
-| File                                | Documented |      Total | Percentage |   Examples | Percentage |
-+-------------------------------------+------------+------------+------------+------------+------------+
-| ...tdoc-ui/coverage/doc-examples.rs |          4 |          4 |     100.0% |          2 |      50.0% |
-+-------------------------------------+------------+------------+------------+------------+------------+
-| Total                               |          4 |          4 |     100.0% |          2 |      50.0% |
-+-------------------------------------+------------+------------+------------+------------+------------+
++-------------------------------------+------------+------------+------------+------------+
+| File                                | Documented | Percentage |   Examples | Percentage |
++-------------------------------------+------------+------------+------------+------------+
+| ...tdoc-ui/coverage/doc-examples.rs |          4 |     100.0% |          2 |      50.0% |
++-------------------------------------+------------+------------+------------+------------+
+| Total                               |          4 |     100.0% |          2 |      50.0% |
++-------------------------------------+------------+------------+------------+------------+
index 2a6a2231e5b5727e009ce2751fcee1431298d250..890a7d56e162d09bb8e0cc933a75d261cc634a26 100644 (file)
@@ -1,7 +1,7 @@
-+-------------------------------------+------------+------------+------------+------------+------------+
-| File                                | Documented |      Total | Percentage |   Examples | Percentage |
-+-------------------------------------+------------+------------+------------+------------+------------+
-| ...est/rustdoc-ui/coverage/empty.rs |          0 |          1 |       0.0% |          0 |       0.0% |
-+-------------------------------------+------------+------------+------------+------------+------------+
-| Total                               |          0 |          1 |       0.0% |          0 |       0.0% |
-+-------------------------------------+------------+------------+------------+------------+------------+
++-------------------------------------+------------+------------+------------+------------+
+| File                                | Documented | Percentage |   Examples | Percentage |
++-------------------------------------+------------+------------+------------+------------+
+| ...est/rustdoc-ui/coverage/empty.rs |          0 |       0.0% |          0 |       0.0% |
++-------------------------------------+------------+------------+------------+------------+
+| Total                               |          0 |       0.0% |          0 |       0.0% |
++-------------------------------------+------------+------------+------------+------------+
index dd86f61f8d5014f31b286581d0cc76cc4f1c508b..64c012c1f66e3dfea1eea7a743511b78a08e0f5f 100644 (file)
@@ -1,7 +1,7 @@
-+-------------------------------------+------------+------------+------------+------------+------------+
-| File                                | Documented |      Total | Percentage |   Examples | Percentage |
-+-------------------------------------+------------+------------+------------+------------+------------+
-| ...est/rustdoc-ui/coverage/enums.rs |          6 |          8 |      75.0% |          0 |       0.0% |
-+-------------------------------------+------------+------------+------------+------------+------------+
-| Total                               |          6 |          8 |      75.0% |          0 |       0.0% |
-+-------------------------------------+------------+------------+------------+------------+------------+
++-------------------------------------+------------+------------+------------+------------+
+| File                                | Documented | Percentage |   Examples | Percentage |
++-------------------------------------+------------+------------+------------+------------+
+| ...est/rustdoc-ui/coverage/enums.rs |          6 |      75.0% |          0 |       0.0% |
++-------------------------------------+------------+------------+------------+------------+
+| Total                               |          6 |      75.0% |          0 |       0.0% |
++-------------------------------------+------------+------------+------------+------------+
index f920a3abd36bb6dbcee91e32d4a98856bac68480..e282ff128437513e3a88564d4c564db7ce263d8c 100644 (file)
@@ -1,8 +1,8 @@
-+-------------------------------------+------------+------------+------------+------------+------------+
-| File                                | Documented |      Total | Percentage |   Examples | Percentage |
-+-------------------------------------+------------+------------+------------+------------+------------+
-| ...st/rustdoc-ui/coverage/exotic.rs |          1 |          1 |     100.0% |          0 |       0.0% |
-| <anon>                              |          2 |          2 |     100.0% |          0 |       0.0% |
-+-------------------------------------+------------+------------+------------+------------+------------+
-| Total                               |          3 |          3 |     100.0% |          0 |       0.0% |
-+-------------------------------------+------------+------------+------------+------------+------------+
++-------------------------------------+------------+------------+------------+------------+
+| File                                | Documented | Percentage |   Examples | Percentage |
++-------------------------------------+------------+------------+------------+------------+
+| ...st/rustdoc-ui/coverage/exotic.rs |          1 |     100.0% |          0 |       0.0% |
+| <anon>                              |          2 |     100.0% |          0 |       0.0% |
++-------------------------------------+------------+------------+------------+------------+
+| Total                               |          3 |     100.0% |          0 |       0.0% |
++-------------------------------------+------------+------------+------------+------------+
index 2bd6a312ab58366207acc87b14237d58f23ffcba..a591cd5dba406ec1a0a29f72b163d9e6dab3eaae 100644 (file)
@@ -12,16 +12,54 @@ pub enum Bar { A }
 pub struct X;
 
 /// Bar
+///
+/// ```
+/// let x = 12;
+/// ```
 pub mod bar {
     /// bar
     pub struct Bar;
     /// X
-    pub enum X { Y }
+    pub enum X {
+        /// ```
+        /// let x = "should be ignored!";
+        /// ```
+        Y
+    }
 }
 
 /// yolo
+///
+/// ```text
+/// should not be counted as a code example!
+/// ```
 pub enum Yolo { X }
 
+impl Yolo {
+    /// ```
+    /// let x = "should be ignored!";
+    /// ```
+    pub const Const: u32 = 0;
+}
+
 pub struct Xo<T: Clone> {
+    /// ```
+    /// let x = "should be ignored!";
+    /// ```
     x: T,
 }
+
+/// ```
+/// let x = "should be ignored!";
+/// ```
+pub static StaticFoo: u32 = 0;
+
+/// ```
+/// let x = "should be ignored!";
+/// ```
+pub const ConstFoo: u32 = 0;
+
+/// ```
+/// let x = "should be ignored!";
+/// ```
+pub type TypeFoo = u32;
index 7b5b083e1584c01a1e6fde7688feec686921acb7..c2be73ce3edd7c14b99a46e3445948ed27187041 100644 (file)
@@ -1 +1 @@
-{"$DIR/json.rs":{"total":13,"with_docs":7,"with_examples":0}}
+{"$DIR/json.rs":{"total":17,"with_docs":12,"total_examples":15,"with_examples":6}}
index bca3d51da59d066bc3eff24336d57c2fc405fbe9..37a0f5187b5122fc745e20f6a195db081dd36a43 100644 (file)
@@ -1,7 +1,7 @@
-+-------------------------------------+------------+------------+------------+------------+------------+
-| File                                | Documented |      Total | Percentage |   Examples | Percentage |
-+-------------------------------------+------------+------------+------------+------------+------------+
-| ...t/rustdoc-ui/coverage/private.rs |          4 |          7 |      57.1% |          0 |       0.0% |
-+-------------------------------------+------------+------------+------------+------------+------------+
-| Total                               |          4 |          7 |      57.1% |          0 |       0.0% |
-+-------------------------------------+------------+------------+------------+------------+------------+
++-------------------------------------+------------+------------+------------+------------+
+| File                                | Documented | Percentage |   Examples | Percentage |
++-------------------------------------+------------+------------+------------+------------+
+| ...t/rustdoc-ui/coverage/private.rs |          4 |      57.1% |          0 |       0.0% |
++-------------------------------------+------------+------------+------------+------------+
+| Total                               |          4 |      57.1% |          0 |       0.0% |
++-------------------------------------+------------+------------+------------+------------+
index 31b48cc602a76246763bf371fa0ac6935abeaf5a..dbea3a3ea23cf5f98a59f1611d89ed805545b647 100644 (file)
@@ -1,7 +1,7 @@
-+-------------------------------------+------------+------------+------------+------------+------------+
-| File                                | Documented |      Total | Percentage |   Examples | Percentage |
-+-------------------------------------+------------+------------+------------+------------+------------+
-| ...oc-ui/coverage/statics-consts.rs |          6 |          7 |      85.7% |          0 |       0.0% |
-+-------------------------------------+------------+------------+------------+------------+------------+
-| Total                               |          6 |          7 |      85.7% |          0 |       0.0% |
-+-------------------------------------+------------+------------+------------+------------+------------+
++-------------------------------------+------------+------------+------------+------------+
+| File                                | Documented | Percentage |   Examples | Percentage |
++-------------------------------------+------------+------------+------------+------------+
+| ...oc-ui/coverage/statics-consts.rs |          6 |      85.7% |          0 |       0.0% |
++-------------------------------------+------------+------------+------------+------------+
+| Total                               |          6 |      85.7% |          0 |       0.0% |
++-------------------------------------+------------+------------+------------+------------+
index ac63b65023d0b302449627c4a4699ddf71374d6a..e04d48b4980c4c299859b70d16bee676c0745c4e 100644 (file)
@@ -1,7 +1,7 @@
-+-------------------------------------+------------+------------+------------+------------+------------+
-| File                                | Documented |      Total | Percentage |   Examples | Percentage |
-+-------------------------------------+------------+------------+------------+------------+------------+
-| ...st/rustdoc-ui/coverage/traits.rs |          6 |          7 |      85.7% |          0 |       0.0% |
-+-------------------------------------+------------+------------+------------+------------+------------+
-| Total                               |          6 |          7 |      85.7% |          0 |       0.0% |
-+-------------------------------------+------------+------------+------------+------------+------------+
++-------------------------------------+------------+------------+------------+------------+
+| File                                | Documented | Percentage |   Examples | Percentage |
++-------------------------------------+------------+------------+------------+------------+
+| ...st/rustdoc-ui/coverage/traits.rs |          6 |      85.7% |          0 |       0.0% |
++-------------------------------------+------------+------------+------------+------------+
+| Total                               |          6 |      85.7% |          0 |       0.0% |
++-------------------------------------+------------+------------+------------+------------+
diff --git a/src/test/rustdoc-ui/intra-link-prim-conflict.rs b/src/test/rustdoc-ui/intra-link-prim-conflict.rs
new file mode 100644 (file)
index 0000000..34276fb
--- /dev/null
@@ -0,0 +1,30 @@
+#![deny(broken_intra_doc_links)]
+//~^ NOTE lint level is defined
+
+/// [char]
+//~^ ERROR both a module and a builtin type
+//~| NOTE ambiguous link
+//~| HELP to link to the module
+//~| HELP to link to the builtin type
+
+/// [type@char]
+//~^ ERROR both a module and a builtin type
+//~| NOTE ambiguous link
+//~| HELP to link to the module
+//~| HELP to link to the builtin type
+
+/// [mod@char] // ok
+/// [prim@char] // ok
+
+/// [struct@char]
+//~^ ERROR incompatible link
+//~| HELP use its disambiguator
+//~| NOTE resolved to a module
+pub mod char {}
+
+pub mod inner {
+    //! [struct@char]
+    //~^ ERROR incompatible link
+    //~| HELP use its disambiguator
+    //~| NOTE resolved to a builtin type
+}
diff --git a/src/test/rustdoc-ui/intra-link-prim-conflict.stderr b/src/test/rustdoc-ui/intra-link-prim-conflict.stderr
new file mode 100644 (file)
index 0000000..b28a442
--- /dev/null
@@ -0,0 +1,53 @@
+error: `char` is both a module and a builtin type
+  --> $DIR/intra-link-prim-conflict.rs:4:6
+   |
+LL | /// [char]
+   |      ^^^^ ambiguous link
+   |
+note: the lint level is defined here
+  --> $DIR/intra-link-prim-conflict.rs:1:9
+   |
+LL | #![deny(broken_intra_doc_links)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+help: to link to the module, prefix with the item type
+   |
+LL | /// [module@char]
+   |      ^^^^^^^^^^^
+help: to link to the builtin type, prefix with the item type
+   |
+LL | /// [prim@char]
+   |      ^^^^^^^^^
+
+error: `char` is both a module and a builtin type
+  --> $DIR/intra-link-prim-conflict.rs:10:6
+   |
+LL | /// [type@char]
+   |      ^^^^^^^^^ ambiguous link
+   |
+help: to link to the module, prefix with the item type
+   |
+LL | /// [module@char]
+   |      ^^^^^^^^^^^
+help: to link to the builtin type, prefix with the item type
+   |
+LL | /// [prim@char]
+   |      ^^^^^^^^^
+
+error: incompatible link kind for `char`
+  --> $DIR/intra-link-prim-conflict.rs:19:6
+   |
+LL | /// [struct@char]
+   |      ^^^^^^^^^^^ help: to link to the module, use its disambiguator: `mod@char`
+   |
+   = note: this link resolved to a module, which is not a struct
+
+error: incompatible link kind for `char`
+  --> $DIR/intra-link-prim-conflict.rs:26:10
+   |
+LL |     //! [struct@char]
+   |          ^^^^^^^^^^^ help: to link to the builtin type, use its disambiguator: `prim@char`
+   |
+   = note: this link resolved to a builtin type, which is not a struct
+
+error: aborting due to 4 previous errors
+
index ffe0ddcd8c9b2fc800d724db7a371c10a95f36fb..ebe7a242211bf50aa9dbbba4e00709068516a0b7 100644 (file)
@@ -38,3 +38,34 @@ pub mod module3 {
   //~^ ERROR
   pub fn test() {}
 }
+
+/// Doc, but no code example and it's fine!
+pub const Const: u32 = 0;
+/// Doc, but no code example and it's fine!
+pub static Static: u32 = 0;
+/// Doc, but no code example and it's fine!
+pub type Type = u32;
+
+/// Doc
+//~^ ERROR
+pub struct Struct {
+    /// Doc, but no code example and it's fine!
+    pub field: u32,
+}
+
+/// Doc
+//~^ ERROR
+pub enum Enum {
+    /// Doc, but no code example and it's fine!
+    X,
+}
+
+/// Doc
+//~^ ERROR
+#[repr(C)]
+union Union {
+    /// Doc, but no code example and it's fine!
+    a: i32,
+    /// Doc, but no code example and it's fine!
+    b: f32,
+}
index 3fcfc1808e079aa8f035a33a2da9aaea631770c0..32756c99e7f9fde9822c46b2829ebdb58a872eb9 100644 (file)
@@ -1,9 +1,8 @@
 error: missing code example in this documentation
-  --> $DIR/lint-missing-doc-code-example.rs:19:1
+  --> $DIR/lint-missing-doc-code-example.rs:49:1
    |
-LL | / mod module1 {
-LL | | }
-   | |_^
+LL | /// Doc
+   | ^^^^^^^
    |
 note: the lint level is defined here
   --> $DIR/lint-missing-doc-code-example.rs:2:9
@@ -11,11 +10,30 @@ note: the lint level is defined here
 LL | #![deny(missing_doc_code_examples)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
 
+error: missing code example in this documentation
+  --> $DIR/lint-missing-doc-code-example.rs:63:1
+   |
+LL | /// Doc
+   | ^^^^^^^
+
+error: missing code example in this documentation
+  --> $DIR/lint-missing-doc-code-example.rs:56:1
+   |
+LL | /// Doc
+   | ^^^^^^^
+
+error: missing code example in this documentation
+  --> $DIR/lint-missing-doc-code-example.rs:19:1
+   |
+LL | / mod module1 {
+LL | | }
+   | |_^
+
 error: missing code example in this documentation
   --> $DIR/lint-missing-doc-code-example.rs:37:3
    |
 LL |   /// doc
    |   ^^^^^^^
 
-error: aborting due to 2 previous errors
+error: aborting due to 5 previous errors
 
diff --git a/src/test/rustdoc-ui/unknown-renamed-lints.rs b/src/test/rustdoc-ui/unknown-renamed-lints.rs
new file mode 100644 (file)
index 0000000..7faa82e
--- /dev/null
@@ -0,0 +1,8 @@
+#![deny(unknown_lints)]
+//~^ NOTE lint level is defined
+#![deny(renamed_and_removed_lints)]
+//~^ NOTE lint level is defined
+#![deny(x)]
+//~^ ERROR unknown lint
+#![deny(intra_doc_link_resolution_failure)]
+//~^ ERROR lint `intra_doc_link_resolution_failure` has been renamed
diff --git a/src/test/rustdoc-ui/unknown-renamed-lints.stderr b/src/test/rustdoc-ui/unknown-renamed-lints.stderr
new file mode 100644 (file)
index 0000000..f0917f1
--- /dev/null
@@ -0,0 +1,28 @@
+error: unknown lint: `x`
+  --> $DIR/unknown-renamed-lints.rs:5:9
+   |
+LL | #![deny(x)]
+   |         ^
+   |
+note: the lint level is defined here
+  --> $DIR/unknown-renamed-lints.rs:1:9
+   |
+LL | #![deny(unknown_lints)]
+   |         ^^^^^^^^^^^^^
+
+error: lint `intra_doc_link_resolution_failure` has been renamed to `broken_intra_doc_links`
+  --> $DIR/unknown-renamed-lints.rs:7:9
+   |
+LL | #![deny(intra_doc_link_resolution_failure)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `broken_intra_doc_links`
+   |
+note: the lint level is defined here
+  --> $DIR/unknown-renamed-lints.rs:3:9
+   |
+LL | #![deny(renamed_and_removed_lints)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: Compilation failed, aborting rustdoc
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/rustdoc/intra-link-associated-defaults.rs b/src/test/rustdoc/intra-link-associated-defaults.rs
new file mode 100644 (file)
index 0000000..2051129
--- /dev/null
@@ -0,0 +1,27 @@
+// ignore-tidy-linelength
+#![deny(intra_doc_link_resolution_failure)]
+#![feature(associated_type_defaults)]
+
+pub trait TraitWithDefault {
+    type T = usize;
+    fn f() -> Self::T {
+        0
+    }
+}
+
+/// Link to [UsesDefaults::T] and [UsesDefaults::f]
+// @has 'intra_link_associated_defaults/struct.UsesDefaults.html' '//a[@href="../intra_link_associated_defaults/struct.UsesDefaults.html#associatedtype.T"]' 'UsesDefaults::T'
+// @has 'intra_link_associated_defaults/struct.UsesDefaults.html' '//a[@href="../intra_link_associated_defaults/struct.UsesDefaults.html#method.f"]' 'UsesDefaults::f'
+pub struct UsesDefaults;
+impl TraitWithDefault for UsesDefaults {}
+
+/// Link to [OverridesDefaults::T] and [OverridesDefaults::f]
+// @has 'intra_link_associated_defaults/struct.OverridesDefaults.html' '//a[@href="../intra_link_associated_defaults/struct.OverridesDefaults.html#associatedtype.T"]' 'OverridesDefaults::T'
+// @has 'intra_link_associated_defaults/struct.OverridesDefaults.html' '//a[@href="../intra_link_associated_defaults/struct.OverridesDefaults.html#method.f"]' 'OverridesDefaults::f'
+pub struct OverridesDefaults;
+impl TraitWithDefault for OverridesDefaults {
+    type T = bool;
+    fn f() -> bool {
+        true
+    }
+}
diff --git a/src/test/rustdoc/intra-link-associated-items.rs b/src/test/rustdoc/intra-link-associated-items.rs
new file mode 100644 (file)
index 0000000..16a21e3
--- /dev/null
@@ -0,0 +1,59 @@
+// ignore-tidy-linelength
+#![deny(intra_doc_link_resolution_failure)]
+
+/// [`std::collections::BTreeMap::into_iter`]
+/// [`String::from`] is ambiguous as to which `From` impl
+// @has 'intra_link_associated_items/fn.foo.html' '//a[@href="https://doc.rust-lang.org/nightly/alloc/collections/btree/map/struct.BTreeMap.html#method.into_iter"]' 'std::collections::BTreeMap::into_iter'
+// @has 'intra_link_associated_items/fn.foo.html' '//a[@href="https://doc.rust-lang.org/nightly/alloc/string/struct.String.html#method.from"]' 'String::from'
+pub fn foo() {}
+
+/// Link to [MyStruct], [link from struct][MyStruct::method], [MyStruct::clone], [MyStruct::Input]
+// @has 'intra_link_associated_items/struct.MyStruct.html' '//a[@href="../intra_link_associated_items/struct.MyStruct.html"]' 'MyStruct'
+// @has 'intra_link_associated_items/struct.MyStruct.html' '//a[@href="../intra_link_associated_items/struct.MyStruct.html#method.method"]' 'link from struct'
+// @has 'intra_link_associated_items/struct.MyStruct.html' '//a[@href="../intra_link_associated_items/struct.MyStruct.html#method.clone"]' 'MyStruct::clone'
+// @has 'intra_link_associated_items/struct.MyStruct.html' '//a[@href="../intra_link_associated_items/struct.MyStruct.html#associatedtype.Input"]' 'MyStruct::Input'
+pub struct MyStruct { foo: () }
+
+impl Clone for MyStruct {
+    fn clone(&self) -> Self {
+        MyStruct
+    }
+}
+
+pub trait T {
+    type Input;
+    fn method(i: Self::Input);
+}
+
+impl T for MyStruct {
+    type Input = usize;
+
+    /// [link from method][MyStruct::method] on method
+    // @has 'intra_link_associated_items/struct.MyStruct.html' '//a[@href="../intra_link_associated_items/struct.MyStruct.html#method.method"]' 'link from method'
+    fn method(i: usize) {
+    }
+}
+
+/// Ambiguity between which trait to use
+pub trait T1 {
+    fn ambiguous_method();
+}
+
+pub trait T2 {
+    fn ambiguous_method();
+}
+
+/// Link to [S::ambiguous_method]
+// FIXME: there is no way to disambiguate these.
+// Since we have `#[deny(intra_doc_failure)]`, we still know it was one or the other.
+pub struct S;
+
+impl T1 for S {
+    fn ambiguous_method() {}
+}
+
+impl T2 for S {
+    fn ambiguous_method() {}
+}
+
+fn main() {}
index 15ea1232fd6fb826b746ac042e88eaca15aa0caa..0a4e57ef643e7824145262785828b4f9216192f0 100644 (file)
@@ -1,17 +1,17 @@
 // ignore-tidy-linelength
 #![deny(broken_intra_doc_links)]
 
-pub mod char {}
+pub mod char {
+    /// [char]
+    // @has intra_link_prim_precedence/char/struct.Inner.html '//a/@href' 'https://doc.rust-lang.org/nightly/std/primitive.char.html'
+    pub struct Inner;
+}
 
-/// See also [type@char]
+/// See [prim@char]
 // @has intra_link_prim_precedence/struct.MyString.html '//a/@href' 'https://doc.rust-lang.org/nightly/std/primitive.char.html'
 pub struct MyString;
 
-/// See also [char]
-// @has intra_link_prim_precedence/struct.MyString2.html '//a/@href' 'https://doc.rust-lang.org/nightly/std/primitive.char.html'
-pub struct MyString2;
-
 /// See also [crate::char] and [mod@char]
-// @has intra_link_prim_precedence/struct.MyString3.html '//*[@href="../intra_link_prim_precedence/char/index.html"]' 'crate::char'
+// @has intra_link_prim_precedence/struct.MyString2.html '//*[@href="../intra_link_prim_precedence/char/index.html"]' 'crate::char'
 // @has - '//*[@href="../intra_link_prim_precedence/char/index.html"]' 'mod@char'
-pub struct MyString3;
+pub struct MyString2;
index 5ece425196c777cba7e326998a661cea4798bcdd..b709fae5a8e569ebd09a5bff0a0c8dd487243974 100644 (file)
@@ -2,7 +2,7 @@ error: fatal error triggered by #[rustc_error]
   --> $DIR/bound-lifetime-in-binding-only.rs:71:1
    |
 LL | fn main() { }
-   | ^^^^^^^^^^^^^
+   | ^^^^^^^^^
 
 error: aborting due to previous error
 
index 8c0980983119b9e2eba30177d3da56d5d9f190e8..1c0d3ac105852a78f56f2c75c0c382f8348c981b 100644 (file)
@@ -2,7 +2,7 @@ error: fatal error triggered by #[rustc_error]
   --> $DIR/bound-lifetime-in-return-only.rs:49:1
    |
 LL | fn main() { }
-   | ^^^^^^^^^^^^^
+   | ^^^^^^^^^
 
 error: aborting due to previous error
 
index baa8e6f82f646fa0fa55d7355d370c4285656b18..ed900079cfc223970ce1e4f502b5b363cc05d45e 100644 (file)
@@ -2,7 +2,7 @@ error: fatal error triggered by #[rustc_error]
   --> $DIR/project-fn-ret-contravariant.rs:50:1
    |
 LL | fn main() { }
-   | ^^^^^^^^^^^^^
+   | ^^^^^^^^^
 
 error: aborting due to previous error
 
index baa8e6f82f646fa0fa55d7355d370c4285656b18..ed900079cfc223970ce1e4f502b5b363cc05d45e 100644 (file)
@@ -2,7 +2,7 @@ error: fatal error triggered by #[rustc_error]
   --> $DIR/project-fn-ret-contravariant.rs:50:1
    |
 LL | fn main() { }
-   | ^^^^^^^^^^^^^
+   | ^^^^^^^^^
 
 error: aborting due to previous error
 
index 2156ecb17393f2e96bb850086d7ea8552665cb66..c340850094857f62b2aed2e42d2fa07b5dfa31f0 100644 (file)
@@ -2,7 +2,7 @@ error: fatal error triggered by #[rustc_error]
   --> $DIR/project-fn-ret-invariant.rs:60:1
    |
 LL | fn main() {}
-   | ^^^^^^^^^^^^
+   | ^^^^^^^^^
 
 error: aborting due to previous error
 
index 63d88543607f3635f7db9156f21ed684138742cd..1dc41a2165fff9ce5a8d317bbcf2de779e1d721d 100644 (file)
@@ -1,11 +1,8 @@
 error: fatal error triggered by #[rustc_error]
   --> $DIR/higher-ranked-projection.rs:24:1
    |
-LL | / fn main() {
-LL | |     foo(());
-LL | |
-LL | | }
-   | |_^
+LL | fn main() {
+   | ^^^^^^^^^
 
 error: aborting due to previous error
 
index c8c2702ec447efd85b05c5d797ecbecb00e586aa..b7a976a0af6967188eb6f1537723d863cb466930 100644 (file)
@@ -8,7 +8,7 @@ fn full(self) {}
 
     async fn crash(self) {
         Self::partial(self.0);
-        Self::full(self); //~ ERROR use of moved value: `self`
+        Self::full(self); //~ ERROR use of partially moved value: `self`
     }
 }
 
index 9177b83dd48d776ac5d7601808db5a6e0233177a..e2a73539874e03577b0d46da8d5797da04ef7abb 100644 (file)
@@ -1,12 +1,12 @@
-error[E0382]: use of moved value: `self`
+error[E0382]: use of partially moved value: `self`
   --> $DIR/issue-66958-non-copy-infered-type-arg.rs:11:20
    |
 LL |         Self::partial(self.0);
-   |                       ------ value moved here
+   |                       ------ value partially moved here
 LL |         Self::full(self);
    |                    ^^^^ value used here after partial move
    |
-   = note: move occurs because `self.0` has type `S`, which does not implement the `Copy` trait
+   = note: partial move occurs because `self.0` has type `S`, which does not implement the `Copy` trait
 
 error: aborting due to previous error
 
index da584e8ad4e0d2dd1907ca5491fd4158073381c9..f65bbeaa31a732b0d0593093569e79d054f0b056 100644 (file)
@@ -25,28 +25,16 @@ LL | async fn async_ret_impl_trait<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'
 error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
   --> $DIR/ret-impl-trait-no-fg.rs:9:1
    |
-LL | / async fn async_ret_impl_trait<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a, 'b> {
-LL | |
-LL | |
-LL | |
-...  |
-LL | |     (a, b)
-LL | | }
-   | |_^
+LL | async fn async_ret_impl_trait<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a, 'b> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: hidden type `(&u8, &u8)` captures lifetime '_#5r
 
 error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
   --> $DIR/ret-impl-trait-no-fg.rs:9:1
    |
-LL | / async fn async_ret_impl_trait<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a, 'b> {
-LL | |
-LL | |
-LL | |
-...  |
-LL | |     (a, b)
-LL | | }
-   | |_^
+LL | async fn async_ret_impl_trait<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a, 'b> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: hidden type `(&u8, &u8)` captures lifetime '_#6r
 
index 2a7a721324d69f18b0687912188389550afc8bef..489bf70d920a3b0ae3ee2ec88b44f32e1e1ffeed 100644 (file)
@@ -8,26 +8,26 @@ LL |     drop(m);
 LL |     match m { _ => { } } // #53114: should eventually be accepted too
    |           ^ value used here after move
 
-error[E0382]: use of moved value: `mm`
+error[E0382]: use of partially moved value: `mm`
   --> $DIR/issue-53114-borrow-checks.rs:27:11
    |
 LL |     match mm { (_x, _) => { } }
-   |                 -- value moved here
+   |                 -- value partially moved here
 LL |     match mm { (_, _y) => { } }
    |           ^^ value used here after partial move
    |
-   = note: move occurs because `mm.0` has type `M`, which does not implement the `Copy` trait
+   = note: partial move occurs because `mm.0` has type `M`, which does not implement the `Copy` trait
 
-error[E0382]: use of moved value: `mm`
+error[E0382]: use of partially moved value: `mm`
   --> $DIR/issue-53114-borrow-checks.rs:29:11
    |
 LL |     match mm { (_, _y) => { } }
-   |                    -- value moved here
+   |                    -- value partially moved here
 LL |
 LL |     match mm { (_, _) => { } }
    |           ^^ value used here after partial move
    |
-   = note: move occurs because `mm.1` has type `M`, which does not implement the `Copy` trait
+   = note: partial move occurs because `mm.1` has type `M`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `m`
   --> $DIR/issue-53114-borrow-checks.rs:36:16
@@ -39,26 +39,26 @@ LL |     drop(m);
 LL |     if let _ = m { } // #53114: should eventually be accepted too
    |                ^ value used here after move
 
-error[E0382]: use of moved value: `mm`
+error[E0382]: use of partially moved value: `mm`
   --> $DIR/issue-53114-borrow-checks.rs:41:22
    |
 LL |     if let (_x, _) = mm { }
-   |             -- value moved here
+   |             -- value partially moved here
 LL |     if let (_, _y) = mm { }
    |                      ^^ value used here after partial move
    |
-   = note: move occurs because `mm.0` has type `M`, which does not implement the `Copy` trait
+   = note: partial move occurs because `mm.0` has type `M`, which does not implement the `Copy` trait
 
-error[E0382]: use of moved value: `mm`
+error[E0382]: use of partially moved value: `mm`
   --> $DIR/issue-53114-borrow-checks.rs:43:21
    |
 LL |     if let (_, _y) = mm { }
-   |                -- value moved here
+   |                -- value partially moved here
 LL |
 LL |     if let (_, _) = mm { }
    |                     ^^ value used here after partial move
    |
-   = note: move occurs because `mm.1` has type `M`, which does not implement the `Copy` trait
+   = note: partial move occurs because `mm.1` has type `M`, which does not implement the `Copy` trait
 
 error: aborting due to 6 previous errors
 
index f9c890b0ed82a7891692311213f0767f5b5fba79..560c9c2fbef4ff9c6ca6b3a7b6a7b3aa72aac907 100644 (file)
@@ -12,16 +12,13 @@ LL |     |y| x + y
 error[E0618]: expected function, found `()`
   --> $DIR/issue-20862.rs:7:13
    |
-LL | / fn foo(x: i32) {
-LL | |     |y| x + y
-LL | |
-LL | | }
-   | |_- `foo` defined here returns `()`
+LL | fn foo(x: i32) {
+   | -------------- `foo` defined here returns `()`
 ...
-LL |       let x = foo(5)(2);
-   |               ^^^^^^---
-   |               |
-   |               call expression requires function
+LL |     let x = foo(5)(2);
+   |             ^^^^^^---
+   |             |
+   |             call expression requires function
 
 error: aborting due to 2 previous errors
 
index c1513fcba8a66819626769f73a6d17796d043bef..ced4d002b384e7b5c276406eb01a5c5bb2c062fe 100644 (file)
@@ -20,7 +20,7 @@ fn move_out_from_begin_field_and_end() {
         [_, _, (_x, _)] => {}
     }
     match a {
-        [.., _y] => {} //~ ERROR use of moved value
+        [.., _y] => {} //~ ERROR use of partially moved value
     }
 }
 
@@ -42,7 +42,7 @@ fn move_out_by_const_index_and_subslice() {
         [_x, _, _] => {}
     }
     match a {
-        //~^ ERROR use of moved value
+        //~^ ERROR use of partially moved value
         [_y @ .., _, _] => {}
     }
 }
@@ -53,7 +53,7 @@ fn move_out_by_const_index_end_and_subslice() {
         [.., _x] => {}
     }
     match a {
-        //~^ ERROR use of moved value
+        //~^ ERROR use of partially moved value
         [_, _, _y @ ..] => {}
     }
 }
@@ -64,7 +64,7 @@ fn move_out_by_const_index_field_and_subslice() {
         [(_x, _), _, _] => {}
     }
     match a {
-        //~^ ERROR use of moved value
+        //~^ ERROR use of partially moved value
         [_y @ .., _, _] => {}
     }
 }
@@ -75,7 +75,7 @@ fn move_out_by_const_index_end_field_and_subslice() {
         [.., (_x, _)] => {}
     }
     match a {
-        //~^ ERROR use of moved value
+        //~^ ERROR use of partially moved value
         [_, _, _y @ ..] => {}
     }
 }
@@ -108,7 +108,7 @@ fn move_out_by_subslice_and_subslice() {
         [x @ .., _] => {}
     }
     match a {
-        //~^ ERROR use of moved value
+        //~^ ERROR use of partially moved value
         [_, _y @ ..] => {}
     }
 }
index 84930b000ccb3a5a122c1fa25b438d2a39b727d4..d63f03a71dbfeb8bec2e90bd3f1c6c6decc5ae2e 100644 (file)
@@ -9,16 +9,16 @@ LL |         [.., _y] => {}
    |
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
-error[E0382]: use of moved value: `a[..]`
+error[E0382]: use of partially moved value: `a[..]`
   --> $DIR/borrowck-move-out-from-array-match.rs:23:14
    |
 LL |         [_, _, (_x, _)] => {}
-   |                 -- value moved here
+   |                 -- value partially moved here
 ...
 LL |         [.., _y] => {}
    |              ^^ value used here after partial move
    |
-   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+   = note: partial move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a[..].0`
   --> $DIR/borrowck-move-out-from-array-match.rs:33:15
@@ -31,49 +31,49 @@ LL |         [.., (_y, _)] => {}
    |
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
-error[E0382]: use of moved value: `a`
+error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-match.rs:44:11
    |
 LL |         [_x, _, _] => {}
-   |          -- value moved here
+   |          -- value partially moved here
 LL |     }
 LL |     match a {
    |           ^ value used here after partial move
    |
-   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+   = note: partial move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
-error[E0382]: use of moved value: `a`
+error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-match.rs:55:11
    |
 LL |         [.., _x] => {}
-   |              -- value moved here
+   |              -- value partially moved here
 LL |     }
 LL |     match a {
    |           ^ value used here after partial move
    |
-   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+   = note: partial move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
-error[E0382]: use of moved value: `a`
+error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-match.rs:66:11
    |
 LL |         [(_x, _), _, _] => {}
-   |           -- value moved here
+   |           -- value partially moved here
 LL |     }
 LL |     match a {
    |           ^ value used here after partial move
    |
-   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+   = note: partial move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
-error[E0382]: use of moved value: `a`
+error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-match.rs:77:11
    |
 LL |         [.., (_x, _)] => {}
-   |               -- value moved here
+   |               -- value partially moved here
 LL |     }
 LL |     match a {
    |           ^ value used here after partial move
    |
-   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+   = note: partial move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a[..].0`
   --> $DIR/borrowck-move-out-from-array-match.rs:89:11
@@ -97,16 +97,16 @@ LL |         [.., (_x, _)] => {}
    |
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
-error[E0382]: use of moved value: `a`
+error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-match.rs:110:11
    |
 LL |         [x @ .., _] => {}
-   |          ------ value moved here
+   |          ------ value partially moved here
 LL |     }
 LL |     match a {
    |           ^ value used here after partial move
    |
-   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+   = note: partial move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error: aborting due to 10 previous errors
 
index 056b8e672bd93a5cab6658e05ce651added16f80..97db70f34cc7405eb52f6b32e15cbbddfc9a1cee 100644 (file)
@@ -15,7 +15,7 @@ fn move_out_from_begin_and_one_from_end() {
         [_, _, _x] => {}
     }
     match a {
-        //~^ ERROR use of moved value
+        //~^ ERROR use of partially moved value
         [.., _y, _] => {}
     }
 }
@@ -26,7 +26,7 @@ fn move_out_from_begin_field_and_end_field() {
         [_, _, (_x, _)] => {}
     }
     match a {
-        //~^ ERROR use of moved value
+        //~^ ERROR use of partially moved value
         [.., (_, _y)] => {}
     }
 }
@@ -39,7 +39,7 @@ fn move_out_by_const_index_and_subslice() {
         [_x, _, _] => {}
     }
     match a {
-        //~^ ERROR use of moved value
+        //~^ ERROR use of partially moved value
         [_, _y @ ..] => {}
     }
 }
@@ -50,7 +50,7 @@ fn move_out_by_const_index_end_and_subslice() {
         [.., _x] => {}
     }
     match a {
-        //~^ ERROR use of moved value
+        //~^ ERROR use of partially moved value
         [_y @ .., _] => {}
     }
 }
@@ -61,7 +61,7 @@ fn move_out_by_const_index_field_and_subslice() {
         [(_x, _), _, _] => {}
     }
     match a {
-        //~^ ERROR use of moved value
+        //~^ ERROR use of partially moved value
         [_, _y @ ..] => {}
     }
 }
@@ -72,7 +72,7 @@ fn move_out_by_const_index_end_field_and_subslice() {
         [.., (_x, _)] => {}
     }
     match a {
-        //~^ ERROR use of moved value
+        //~^ ERROR use of partially moved value
         [_y @ .., _] => {}
     }
 }
@@ -83,7 +83,7 @@ fn move_out_by_const_subslice_and_index_field() {
         [_, _y @ ..] => {}
     }
     match a {
-        //~^ ERROR use of moved value
+        //~^ ERROR use of partially moved value
         [(_x, _), _, _] => {}
     }
 }
@@ -94,7 +94,7 @@ fn move_out_by_const_subslice_and_end_index_field() {
         [_y @ .., _] => {}
     }
     match a {
-        //~^ ERROR use of moved value
+        //~^ ERROR use of partially moved value
         [.., (_x, _)] => {}
     }
 }
@@ -107,7 +107,7 @@ fn move_out_by_subslice_and_subslice() {
         [x @ .., _, _] => {}
     }
     match a {
-        //~^ ERROR use of moved value
+        //~^ ERROR use of partially moved value
         [_, _y @ ..] => {}
     }
 }
index ff5eab2442c83312dd43695f0b9e89cf68191efe..7c675149894a11fc6e15beaf04cc35c83f9b2d15 100644 (file)
-error[E0382]: use of moved value: `a`
+error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:17:11
    |
 LL |         [_, _, _x] => {}
-   |                -- value moved here
+   |                -- value partially moved here
 LL |     }
 LL |     match a {
    |           ^ value used here after partial move
    |
-   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+   = note: partial move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
-error[E0382]: use of moved value: `a`
+error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:28:11
    |
 LL |         [_, _, (_x, _)] => {}
-   |                 -- value moved here
+   |                 -- value partially moved here
 LL |     }
 LL |     match a {
    |           ^ value used here after partial move
    |
-   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+   = note: partial move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
-error[E0382]: use of moved value: `a`
+error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:41:11
    |
 LL |         [_x, _, _] => {}
-   |          -- value moved here
+   |          -- value partially moved here
 LL |     }
 LL |     match a {
    |           ^ value used here after partial move
    |
-   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+   = note: partial move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
-error[E0382]: use of moved value: `a`
+error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:52:11
    |
 LL |         [.., _x] => {}
-   |              -- value moved here
+   |              -- value partially moved here
 LL |     }
 LL |     match a {
    |           ^ value used here after partial move
    |
-   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+   = note: partial move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
-error[E0382]: use of moved value: `a`
+error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:63:11
    |
 LL |         [(_x, _), _, _] => {}
-   |           -- value moved here
+   |           -- value partially moved here
 LL |     }
 LL |     match a {
    |           ^ value used here after partial move
    |
-   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+   = note: partial move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
-error[E0382]: use of moved value: `a`
+error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:74:11
    |
 LL |         [.., (_x, _)] => {}
-   |               -- value moved here
+   |               -- value partially moved here
 LL |     }
 LL |     match a {
    |           ^ value used here after partial move
    |
-   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+   = note: partial move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
-error[E0382]: use of moved value: `a`
+error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:85:11
    |
 LL |         [_, _y @ ..] => {}
-   |             ------- value moved here
+   |             ------- value partially moved here
 LL |     }
 LL |     match a {
    |           ^ value used here after partial move
    |
-   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+   = note: partial move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
-error[E0382]: use of moved value: `a`
+error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:96:11
    |
 LL |         [_y @ .., _] => {}
-   |          ------- value moved here
+   |          ------- value partially moved here
 LL |     }
 LL |     match a {
    |           ^ value used here after partial move
    |
-   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+   = note: partial move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
-error[E0382]: use of moved value: `a`
+error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:109:11
    |
 LL |         [x @ .., _, _] => {}
-   |          ------ value moved here
+   |          ------ value partially moved here
 LL |     }
 LL |     match a {
    |           ^ value used here after partial move
    |
-   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+   = note: partial move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error: aborting due to 9 previous errors
 
index 0ef63105cfbd3212953a94c654a134be6c6c1906..806354b0116ce58084dcf38f46a67f2e7fdfa867 100644 (file)
@@ -9,16 +9,16 @@ LL |         [.., ref _y] => {}
    |
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
-error[E0382]: borrow of moved value: `a[..]`
+error[E0382]: borrow of partially moved value: `a[..]`
   --> $DIR/borrowck-move-out-from-array-use-match.rs:23:14
    |
 LL |         [_, _, (_x, _)] => {}
-   |                 -- value moved here
+   |                 -- value partially moved here
 ...
 LL |         [.., ref _y] => {}
    |              ^^^^^^ value borrowed here after partial move
    |
-   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+   = note: partial move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `a[..].0`
   --> $DIR/borrowck-move-out-from-array-use-match.rs:33:15
@@ -31,49 +31,49 @@ LL |         [.., (ref _y, _)] => {}
    |
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
-error[E0382]: use of moved value: `a`
+error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-use-match.rs:44:11
    |
 LL |         [_x, _, _] => {}
-   |          -- value moved here
+   |          -- value partially moved here
 LL |     }
 LL |     match a {
    |           ^ value used here after partial move
    |
-   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+   = note: partial move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
-error[E0382]: use of moved value: `a`
+error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-use-match.rs:55:11
    |
 LL |         [.., _x] => {}
-   |              -- value moved here
+   |              -- value partially moved here
 LL |     }
 LL |     match a {
    |           ^ value used here after partial move
    |
-   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+   = note: partial move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
-error[E0382]: use of moved value: `a`
+error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-use-match.rs:66:11
    |
 LL |         [(_x, _), _, _] => {}
-   |           -- value moved here
+   |           -- value partially moved here
 LL |     }
 LL |     match a {
    |           ^ value used here after partial move
    |
-   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+   = note: partial move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
-error[E0382]: use of moved value: `a`
+error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-use-match.rs:77:11
    |
 LL |         [.., (_x, _)] => {}
-   |               -- value moved here
+   |               -- value partially moved here
 LL |     }
 LL |     match a {
    |           ^ value used here after partial move
    |
-   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+   = note: partial move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `a[..]`
   --> $DIR/borrowck-move-out-from-array-use-match.rs:89:11
@@ -97,60 +97,60 @@ LL |         [.., (ref _x, _)] => {}
    |
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
-error[E0382]: use of moved value: `a`
+error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-use-match.rs:110:11
    |
 LL |         [x @ .., _] => {}
-   |          ------ value moved here
+   |          ------ value partially moved here
 LL |     }
 LL |     match a {
    |           ^ value used here after partial move
    |
-   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+   = note: partial move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
-error[E0382]: use of moved value: `a`
+error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-use-match.rs:123:5
    |
 LL |         [_, _, _x] => {}
-   |                -- value moved here
+   |                -- value partially moved here
 LL |     }
 LL |     a[2] = Default::default();
    |     ^^^^ value used here after partial move
    |
-   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+   = note: partial move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
-error[E0382]: use of moved value: `a`
+error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-use-match.rs:131:5
    |
 LL |         [_, _, (_x, _)] => {}
-   |                 -- value moved here
+   |                 -- value partially moved here
 LL |     }
 LL |     a[2].1 = Default::default();
    |     ^^^^ value used here after partial move
    |
-   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+   = note: partial move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
-error[E0382]: use of moved value: `a`
+error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-use-match.rs:139:5
    |
 LL |         [_, _, _x @ ..] => {}
-   |                ------- value moved here
+   |                ------- value partially moved here
 LL |     }
 LL |     a[0] = Default::default();
    |     ^^^^ value used here after partial move
    |
-   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+   = note: partial move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
-error[E0382]: use of moved value: `a`
+error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-use-match.rs:147:5
    |
 LL |         [_, _, _x @ ..] => {}
-   |                ------- value moved here
+   |                ------- value partially moved here
 LL |     }
 LL |     a[0].1 = Default::default();
    |     ^^^^ value used here after partial move
    |
-   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+   = note: partial move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error: aborting due to 14 previous errors
 
index 5afd6835dcfb60b0c98bd8b4bccf4887eb631174..017ca90b81a3f75e218d82fabcc6808b2d36be29 100644 (file)
@@ -15,7 +15,7 @@ fn move_out_from_begin_and_one_from_end() {
         [_, _, _x] => {}
     }
     match a {
-        //~^ ERROR use of moved value
+        //~^ ERROR use of partially moved value
         [.., ref _y, _] => {}
     }
 }
@@ -26,7 +26,7 @@ fn move_out_from_begin_field_and_end_field() {
         [_, _, (_x, _)] => {}
     }
     match a {
-        //~^ ERROR use of moved value
+        //~^ ERROR use of partially moved value
         [.., (_, ref _y)] => {}
     }
 }
@@ -39,7 +39,7 @@ fn move_out_by_const_index_and_subslice() {
         [_x, _, _] => {}
     }
     match a {
-        //~^ ERROR use of moved value
+        //~^ ERROR use of partially moved value
         [_, ref _y @ ..] => {}
     }
 }
@@ -50,7 +50,7 @@ fn move_out_by_const_index_end_and_subslice() {
         [.., _x] => {}
     }
     match a {
-        //~^ ERROR use of moved value
+        //~^ ERROR use of partially moved value
         [ref _y @ .., _] => {}
     }
 }
@@ -61,7 +61,7 @@ fn move_out_by_const_index_field_and_subslice() {
         [(_x, _), _, _] => {}
     }
     match a {
-        //~^ ERROR use of moved value
+        //~^ ERROR use of partially moved value
         [_, ref _y @ ..] => {}
     }
 }
@@ -72,7 +72,7 @@ fn move_out_by_const_index_end_field_and_subslice() {
         [.., (_x, _)] => {}
     }
     match a {
-        //~^ ERROR use of moved value
+        //~^ ERROR use of partially moved value
         [ref _y @ .., _] => {}
     }
 }
@@ -83,7 +83,7 @@ fn move_out_by_const_subslice_and_index_field() {
         [_, _y @ ..] => {}
     }
     match a {
-        //~^ ERROR use of moved value
+        //~^ ERROR use of partially moved value
         [(ref _x, _), _, _] => {}
     }
 }
@@ -94,7 +94,7 @@ fn move_out_by_const_subslice_and_end_index_field() {
         [_y @ .., _] => {}
     }
     match a {
-        //~^ ERROR use of moved value
+        //~^ ERROR use of partially moved value
         [.., (ref _x, _)] => {}
     }
 }
@@ -107,7 +107,7 @@ fn move_out_by_subslice_and_subslice() {
         [x @ .., _, _] => {}
     }
     match a {
-        //~^ ERROR use of moved value
+        //~^ ERROR use of partially moved value
         [_, ref _y @ ..] => {}
     }
 }
index a4042ce7db336192c64086777a9a6105cc62be34..53f815db140d2c220dc2dd1d70cd0f12ddff0f73 100644 (file)
-error[E0382]: use of moved value: `a`
+error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:17:11
    |
 LL |         [_, _, _x] => {}
-   |                -- value moved here
+   |                -- value partially moved here
 LL |     }
 LL |     match a {
    |           ^ value used here after partial move
    |
-   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+   = note: partial move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
-error[E0382]: use of moved value: `a`
+error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:28:11
    |
 LL |         [_, _, (_x, _)] => {}
-   |                 -- value moved here
+   |                 -- value partially moved here
 LL |     }
 LL |     match a {
    |           ^ value used here after partial move
    |
-   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+   = note: partial move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
-error[E0382]: use of moved value: `a`
+error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:41:11
    |
 LL |         [_x, _, _] => {}
-   |          -- value moved here
+   |          -- value partially moved here
 LL |     }
 LL |     match a {
    |           ^ value used here after partial move
    |
-   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+   = note: partial move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
-error[E0382]: use of moved value: `a`
+error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:52:11
    |
 LL |         [.., _x] => {}
-   |              -- value moved here
+   |              -- value partially moved here
 LL |     }
 LL |     match a {
    |           ^ value used here after partial move
    |
-   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+   = note: partial move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
-error[E0382]: use of moved value: `a`
+error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:63:11
    |
 LL |         [(_x, _), _, _] => {}
-   |           -- value moved here
+   |           -- value partially moved here
 LL |     }
 LL |     match a {
    |           ^ value used here after partial move
    |
-   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+   = note: partial move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
-error[E0382]: use of moved value: `a`
+error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:74:11
    |
 LL |         [.., (_x, _)] => {}
-   |               -- value moved here
+   |               -- value partially moved here
 LL |     }
 LL |     match a {
    |           ^ value used here after partial move
    |
-   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+   = note: partial move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
-error[E0382]: use of moved value: `a`
+error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:85:11
    |
 LL |         [_, _y @ ..] => {}
-   |             ------- value moved here
+   |             ------- value partially moved here
 LL |     }
 LL |     match a {
    |           ^ value used here after partial move
    |
-   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+   = note: partial move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
-error[E0382]: use of moved value: `a`
+error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:96:11
    |
 LL |         [_y @ .., _] => {}
-   |          ------- value moved here
+   |          ------- value partially moved here
 LL |     }
 LL |     match a {
    |           ^ value used here after partial move
    |
-   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+   = note: partial move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
-error[E0382]: use of moved value: `a`
+error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:109:11
    |
 LL |         [x @ .., _, _] => {}
-   |          ------ value moved here
+   |          ------ value partially moved here
 LL |     }
 LL |     match a {
    |           ^ value used here after partial move
    |
-   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+   = note: partial move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error: aborting due to 9 previous errors
 
index 7ad4116645e9351d87f1eef6d814f3cd85c9ca15..004cc433b3459b24f583824905ab390084a525c7 100644 (file)
@@ -8,15 +8,15 @@ LL |     let [.., ref _y] = a;
    |
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
-error[E0382]: borrow of moved value: `a[..]`
+error[E0382]: borrow of partially moved value: `a[..]`
   --> $DIR/borrowck-move-out-from-array-use.rs:16:14
    |
 LL |     let [_, _, (_x, _)] = a;
-   |                 -- value moved here
+   |                 -- value partially moved here
 LL |     let [.., ref _y] = a;
    |              ^^^^^^ value borrowed here after partial move
    |
-   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+   = note: partial move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `a[..].0`
   --> $DIR/borrowck-move-out-from-array-use.rs:22:15
@@ -28,45 +28,45 @@ LL |     let [.., (ref _y, _)] = a;
    |
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
-error[E0382]: borrow of moved value: `a`
+error[E0382]: borrow of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-use.rs:30:10
    |
 LL |     let [_x, _, _] = a;
-   |          -- value moved here
+   |          -- value partially moved here
 LL |     let [ref _y @ .., _, _] = a;
    |          ^^^^^^^^^^^ value borrowed here after partial move
    |
-   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+   = note: partial move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
-error[E0382]: borrow of moved value: `a`
+error[E0382]: borrow of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-use.rs:36:16
    |
 LL |     let [.., _x] = a;
-   |              -- value moved here
+   |              -- value partially moved here
 LL |     let [_, _, ref _y @ ..] = a;
    |                ^^^^^^^^^^^ value borrowed here after partial move
    |
-   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+   = note: partial move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
-error[E0382]: borrow of moved value: `a`
+error[E0382]: borrow of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-use.rs:42:10
    |
 LL |     let [(_x, _), _, _] = a;
-   |           -- value moved here
+   |           -- value partially moved here
 LL |     let [ref _y @ .., _, _] = a;
    |          ^^^^^^^^^^^ value borrowed here after partial move
    |
-   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+   = note: partial move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
-error[E0382]: borrow of moved value: `a`
+error[E0382]: borrow of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-use.rs:48:16
    |
 LL |     let [.., (_x, _)] = a;
-   |               -- value moved here
+   |               -- value partially moved here
 LL |     let [_, _, ref _y @ ..] = a;
    |                ^^^^^^^^^^^ value borrowed here after partial move
    |
-   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+   = note: partial move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `a[..]`
   --> $DIR/borrowck-move-out-from-array-use.rs:54:11
@@ -88,55 +88,55 @@ LL |     let [.., (ref _x, _)] = a;
    |
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
-error[E0382]: borrow of moved value: `a`
+error[E0382]: borrow of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-use.rs:68:13
    |
 LL |     let [x @ .., _] = a;
-   |          ------ value moved here
+   |          ------ value partially moved here
 LL |     let [_, ref _y @ ..] = a;
    |             ^^^^^^^^^^^ value borrowed here after partial move
    |
-   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+   = note: partial move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
-error[E0382]: use of moved value: `a`
+error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-use.rs:76:5
    |
 LL |     let [_, _, _x] = a;
-   |                -- value moved here
+   |                -- value partially moved here
 LL |     a[2] = Default::default();
    |     ^^^^ value used here after partial move
    |
-   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+   = note: partial move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
-error[E0382]: use of moved value: `a`
+error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-use.rs:82:5
    |
 LL |     let [_, _, (_x, _)] = a;
-   |                 -- value moved here
+   |                 -- value partially moved here
 LL |     a[2].1 = Default::default();
    |     ^^^^ value used here after partial move
    |
-   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+   = note: partial move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
-error[E0382]: use of moved value: `a`
+error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-use.rs:88:5
    |
 LL |     let [_, _, _x @ ..] = a;
-   |                ------- value moved here
+   |                ------- value partially moved here
 LL |     a[0] = Default::default();
    |     ^^^^ value used here after partial move
    |
-   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+   = note: partial move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
-error[E0382]: use of moved value: `a`
+error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array-use.rs:94:5
    |
 LL |     let [_, _, _x @ ..] = a;
-   |                ------- value moved here
+   |                ------- value partially moved here
 LL |     a[0].1 = Default::default();
    |     ^^^^ value used here after partial move
    |
-   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+   = note: partial move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error: aborting due to 14 previous errors
 
index b7babd93ed7a638244a594ff060fc62fad8a86cb..d3eb3e9f76144c8a7f93b16da853e8c1c3f969ce 100644 (file)
@@ -8,15 +8,15 @@ LL |     let [.., _y] = a;
    |
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
-error[E0382]: use of moved value: `a[..]`
+error[E0382]: use of partially moved value: `a[..]`
   --> $DIR/borrowck-move-out-from-array.rs:16:14
    |
 LL |     let [_, _, (_x, _)] = a;
-   |                 -- value moved here
+   |                 -- value partially moved here
 LL |     let [.., _y] = a;
    |              ^^ value used here after partial move
    |
-   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+   = note: partial move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a[..].0`
   --> $DIR/borrowck-move-out-from-array.rs:22:15
@@ -28,45 +28,45 @@ LL |     let [.., (_y, _)] = a;
    |
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
-error[E0382]: use of moved value: `a`
+error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array.rs:30:10
    |
 LL |     let [_x, _, _] = a;
-   |          -- value moved here
+   |          -- value partially moved here
 LL |     let [_y @ .., _, _] = a;
    |          ^^^^^^^ value used here after partial move
    |
-   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+   = note: partial move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
-error[E0382]: use of moved value: `a`
+error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array.rs:36:16
    |
 LL |     let [.., _x] = a;
-   |              -- value moved here
+   |              -- value partially moved here
 LL |     let [_, _, _y @ ..] = a;
    |                ^^^^^^^ value used here after partial move
    |
-   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+   = note: partial move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
-error[E0382]: use of moved value: `a`
+error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array.rs:42:10
    |
 LL |     let [(_x, _), _, _] = a;
-   |           -- value moved here
+   |           -- value partially moved here
 LL |     let [_y @ .., _, _] = a;
    |          ^^^^^^^ value used here after partial move
    |
-   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+   = note: partial move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
-error[E0382]: use of moved value: `a`
+error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array.rs:48:16
    |
 LL |     let [.., (_x, _)] = a;
-   |               -- value moved here
+   |               -- value partially moved here
 LL |     let [_, _, _y @ ..] = a;
    |                ^^^^^^^ value used here after partial move
    |
-   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+   = note: partial move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a[..].0`
   --> $DIR/borrowck-move-out-from-array.rs:54:11
@@ -88,15 +88,15 @@ LL |     let [.., (_x, _)] = a;
    |
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
-error[E0382]: use of moved value: `a`
+error[E0382]: use of partially moved value: `a`
   --> $DIR/borrowck-move-out-from-array.rs:68:13
    |
 LL |     let [x @ .., _] = a;
-   |          ------ value moved here
+   |          ------ value partially moved here
 LL |     let [_, _y @ ..] = a;
    |             ^^^^^^^ value used here after partial move
    |
-   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+   = note: partial move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error: aborting due to 10 previous errors
 
index 9f35a4a8d83bd82e3d52c41088e6c13c8e7074bb..7951a5b1b5d70e6dfd2d236f4cadc78299608b7d 100644 (file)
@@ -14,15 +14,15 @@ LL |     let _ = line1.origin.x + 1;
    |
    = note: move occurs because `line1.origin` has type `Point`, which does not implement the `Copy` trait
 
-error[E0382]: use of moved value: `line2`
+error[E0382]: use of partially moved value: `line2`
   --> $DIR/borrowck-uninit-field-access.rs:29:5
    |
 LL |     let _moved = (line2.origin, line2.middle);
-   |                                 ------------ value moved here
+   |                                 ------------ value partially moved here
 LL |     line2.consume();
    |     ^^^^^ value used here after partial move
    |
-   = note: move occurs because `line2.middle` has type `Point`, which does not implement the `Copy` trait
+   = note: partial move occurs because `line2.middle` has type `Point`, which does not implement the `Copy` trait
 
 error: aborting due to 3 previous errors
 
index 175eb3b7a04d1168237ec991cbbd658f9abfb48b..b5c275bf28caf444b9fdd144cda811cd67b4a681 100644 (file)
@@ -15,9 +15,9 @@ fn main() {
     if let Some(mut x) = s {
         x = S;
     }
-    foo(s); //~ ERROR use of moved value: `s`
+    foo(s); //~ ERROR use of partially moved value: `s`
     let mut e = E::V { s: S };
     let E::V { s: mut x } = e;
     x = S;
-    bar(e); //~ ERROR use of moved value: `e`
+    bar(e); //~ ERROR use of partially moved value: `e`
 }
index 391638444c3bdcf06791fddc991dcb2960801a5b..17bc5492756e6fd47d9ec486e2fc979268b81b4b 100644 (file)
@@ -1,28 +1,28 @@
-error[E0382]: use of moved value: `s`
+error[E0382]: use of partially moved value: `s`
   --> $DIR/move-in-pattern-mut.rs:18:9
    |
 LL |     if let Some(mut x) = s {
-   |                 ----- value moved here
+   |                 ----- value partially moved here
 ...
 LL |     foo(s);
    |         ^ value used here after partial move
    |
-   = note: move occurs because value has type `S`, which does not implement the `Copy` trait
+   = note: partial move occurs because value has type `S`, which does not implement the `Copy` trait
 help: borrow this field in the pattern to avoid moving `s.0`
    |
 LL |     if let Some(ref mut x) = s {
    |                 ^^^
 
-error[E0382]: use of moved value: `e`
+error[E0382]: use of partially moved value: `e`
   --> $DIR/move-in-pattern-mut.rs:22:9
    |
 LL |     let E::V { s: mut x } = e;
-   |                   ----- value moved here
+   |                   ----- value partially moved here
 LL |     x = S;
 LL |     bar(e);
    |         ^ value used here after partial move
    |
-   = note: move occurs because value has type `S`, which does not implement the `Copy` trait
+   = note: partial move occurs because value has type `S`, which does not implement the `Copy` trait
 help: borrow this field in the pattern to avoid moving `e.s`
    |
 LL |     let E::V { s: ref mut x } = e;
index f55fdcc5f90e80f1dcca0613b180131d1af9b194..145893d3343bcf8feacded7ab4ac59a2bf1b905e 100644 (file)
@@ -16,9 +16,9 @@ fn main() {
     if let Some(ref x) = s {
         let _ = x;
     }
-    foo(s); //~ ERROR use of moved value: `s`
+    foo(s); //~ ERROR use of partially moved value: `s`
     let e = E::V { s: S };
     let E::V { s: ref x } = e;
     let _ = x;
-    bar(e); //~ ERROR use of moved value: `e`
+    bar(e); //~ ERROR use of partially moved value: `e`
 }
index 7ad04b9490c25167f83569d050585933fa11b008..14851d0f6fcffeaee16abf16277a86f431bef061 100644 (file)
@@ -16,9 +16,9 @@ fn main() {
     if let Some(x) = s {
         let _ = x;
     }
-    foo(s); //~ ERROR use of moved value: `s`
+    foo(s); //~ ERROR use of partially moved value: `s`
     let e = E::V { s: S };
     let E::V { s: x } = e;
     let _ = x;
-    bar(e); //~ ERROR use of moved value: `e`
+    bar(e); //~ ERROR use of partially moved value: `e`
 }
index c5cb24455eb61ee5c83fd7b05b6c904a21073eaa..21ba92f1fc41cbac70c52b26758e437bee2a232a 100644 (file)
@@ -1,28 +1,28 @@
-error[E0382]: use of moved value: `s`
+error[E0382]: use of partially moved value: `s`
   --> $DIR/move-in-pattern.rs:19:9
    |
 LL |     if let Some(x) = s {
-   |                 - value moved here
+   |                 - value partially moved here
 ...
 LL |     foo(s);
    |         ^ value used here after partial move
    |
-   = note: move occurs because value has type `S`, which does not implement the `Copy` trait
+   = note: partial move occurs because value has type `S`, which does not implement the `Copy` trait
 help: borrow this field in the pattern to avoid moving `s.0`
    |
 LL |     if let Some(ref x) = s {
    |                 ^^^
 
-error[E0382]: use of moved value: `e`
+error[E0382]: use of partially moved value: `e`
   --> $DIR/move-in-pattern.rs:23:9
    |
 LL |     let E::V { s: x } = e;
-   |                   - value moved here
+   |                   - value partially moved here
 LL |     let _ = x;
 LL |     bar(e);
    |         ^ value used here after partial move
    |
-   = note: move occurs because value has type `S`, which does not implement the `Copy` trait
+   = note: partial move occurs because value has type `S`, which does not implement the `Copy` trait
 help: borrow this field in the pattern to avoid moving `e.s`
    |
 LL |     let E::V { s: ref x } = e;
index a60be6f23c415d1e1602b65711f8e918343e05d0..2c1c3c2dc967d53f3982e7fed9bd3dc12f74c591 100644 (file)
@@ -2,9 +2,9 @@ error[E0592]: duplicate definitions with name `f`
   --> $DIR/coherence-overlapping-inherent-impl-trait.rs:4:14
    |
 LL | impl dyn C { fn f() {} }
-   |              ^^^^^^^^^ duplicate definitions for `f`
+   |              ^^^^^^ duplicate definitions for `f`
 LL | impl dyn C { fn f() {} }
-   |              --------- other definition for `f`
+   |              ------ other definition for `f`
 
 error: aborting due to previous error
 
index 8fe24bae7c6ca1e995cca02707235bf511608406..6fca12e1823ddfd452398448d24e41e05cf59064 100644 (file)
@@ -2,28 +2,28 @@ error[E0592]: duplicate definitions with name `id`
   --> $DIR/overlapping_inherent_impls.rs:9:5
    |
 LL |     fn id() {}
-   |     ^^^^^^^^^^ duplicate definitions for `id`
+   |     ^^^^^^^ duplicate definitions for `id`
 ...
 LL |     fn id() {}
-   |     ---------- other definition for `id`
+   |     ------- other definition for `id`
 
 error[E0592]: duplicate definitions with name `bar`
   --> $DIR/overlapping_inherent_impls.rs:19:5
    |
 LL |     fn bar(&self) {}
-   |     ^^^^^^^^^^^^^^^^ duplicate definitions for `bar`
+   |     ^^^^^^^^^^^^^ duplicate definitions for `bar`
 ...
 LL |     fn bar(&self) {}
-   |     ---------------- other definition for `bar`
+   |     ------------- other definition for `bar`
 
 error[E0592]: duplicate definitions with name `baz`
   --> $DIR/overlapping_inherent_impls.rs:29:5
    |
 LL |     fn baz(&self) {}
-   |     ^^^^^^^^^^^^^^^^ duplicate definitions for `baz`
+   |     ^^^^^^^^^^^^^ duplicate definitions for `baz`
 ...
 LL |     fn baz(&self) {}
-   |     ---------------- other definition for `baz`
+   |     ------------- other definition for `baz`
    |
    = note: upstream crates may add a new impl of trait `std::marker::Copy` for type `std::vec::Vec<_>` in future versions
 
index 6ea0b89be74d334a74ff804c66013cc5e9b2eb57..4701bc0b139736890b28c68d26394124c6c0deb4 100644 (file)
@@ -2,10 +2,10 @@ error[E0592]: duplicate definitions with name `method1`
   --> $DIR/coherence-inherited-subtyping.rs:14:5
    |
 LL |     fn method1(&self) {}
-   |     ^^^^^^^^^^^^^^^^^^^^ duplicate definitions for `method1`
+   |     ^^^^^^^^^^^^^^^^^ duplicate definitions for `method1`
 ...
 LL |     fn method1(&self) {}
-   |     -------------------- other definition for `method1`
+   |     ----------------- other definition for `method1`
    |
    = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details
 
index 6ea0b89be74d334a74ff804c66013cc5e9b2eb57..4701bc0b139736890b28c68d26394124c6c0deb4 100644 (file)
@@ -2,10 +2,10 @@ error[E0592]: duplicate definitions with name `method1`
   --> $DIR/coherence-inherited-subtyping.rs:14:5
    |
 LL |     fn method1(&self) {}
-   |     ^^^^^^^^^^^^^^^^^^^^ duplicate definitions for `method1`
+   |     ^^^^^^^^^^^^^^^^^ duplicate definitions for `method1`
 ...
 LL |     fn method1(&self) {}
-   |     -------------------- other definition for `method1`
+   |     ----------------- other definition for `method1`
    |
    = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details
 
index 4cb7390453c8826f7152e83a2bcb90aacf6ace52..bbce4b530b4d6558845e285ef57a97a8b128afd5 100644 (file)
@@ -2,19 +2,19 @@ error[E0592]: duplicate definitions with name `dummy`
   --> $DIR/coherence-overlap-downstream-inherent.rs:7:26
    |
 LL | impl<T:Sugar> Sweet<T> { fn dummy(&self) { } }
-   |                          ^^^^^^^^^^^^^^^^^^^ duplicate definitions for `dummy`
+   |                          ^^^^^^^^^^^^^^^ duplicate definitions for `dummy`
 LL |
 LL | impl<T:Fruit> Sweet<T> { fn dummy(&self) { } }
-   |                          ------------------- other definition for `dummy`
+   |                          --------------- other definition for `dummy`
 
 error[E0592]: duplicate definitions with name `f`
   --> $DIR/coherence-overlap-downstream-inherent.rs:13:38
    |
 LL | impl<X, T> A<T, X> where T: Bar<X> { fn f(&self) {} }
-   |                                      ^^^^^^^^^^^^^^ duplicate definitions for `f`
+   |                                      ^^^^^^^^^^^ duplicate definitions for `f`
 LL |
 LL | impl<X> A<i32, X> { fn f(&self) {} }
-   |                     -------------- other definition for `f`
+   |                     ----------- other definition for `f`
    |
    = note: downstream crates may implement trait `Bar<_>` for type `i32`
 
index e63f8a997af67f565232ff675f2d0dbfaded7297..3ad818cbc36dd789a82d2bfb11c041ddca4f451f 100644 (file)
@@ -2,10 +2,10 @@ error[E0592]: duplicate definitions with name `dummy`
   --> $DIR/coherence-overlap-issue-23516-inherent.rs:9:25
    |
 LL | impl<T:Sugar> Cake<T> { fn dummy(&self) { } }
-   |                         ^^^^^^^^^^^^^^^^^^^ duplicate definitions for `dummy`
+   |                         ^^^^^^^^^^^^^^^ duplicate definitions for `dummy`
 LL |
 LL | impl<U:Sugar> Cake<Box<U>> { fn dummy(&self) { } }
-   |                              ------------------- other definition for `dummy`
+   |                              --------------- other definition for `dummy`
    |
    = note: downstream crates may implement trait `Sugar` for type `std::boxed::Box<_>`
 
index 51316f249756c1c776f9600088cb57f11378bfc7..f355c6e855ce1f535538c8797fc1520b10c12a2e 100644 (file)
@@ -2,10 +2,10 @@ error[E0592]: duplicate definitions with name `dummy`
   --> $DIR/coherence-overlap-upstream-inherent.rs:12:32
    |
 LL | impl<T> A<T> where T: Remote { fn dummy(&self) { } }
-   |                                ^^^^^^^^^^^^^^^^^^^ duplicate definitions for `dummy`
+   |                                ^^^^^^^^^^^^^^^ duplicate definitions for `dummy`
 LL |
 LL | impl A<i16> { fn dummy(&self) { } }
-   |               ------------------- other definition for `dummy`
+   |               --------------- other definition for `dummy`
    |
    = note: upstream crates may add a new impl of trait `coherence_lib::Remote` for type `i16` in future versions
 
index 6962ccdec73eea52e084c6a99f9be43598792e87..8a6f7de1c9fbd3562990e8b592b7828a1f14656d 100644 (file)
@@ -9,7 +9,8 @@
 // normalize-stderr-test "note: rustc.*running on.*\n\n" -> ""
 // normalize-stderr-test "thread.*panicked.*\n" -> ""
 // normalize-stderr-test "stack backtrace:\n" -> ""
-// normalize-stderr-test "  \d{1,}: .*\n" -> ""
+// normalize-stderr-test "\s\d{1,}: .*\n" -> ""
+// normalize-stderr-test "\s at .*\n" -> ""
 // normalize-stderr-test ".*note: Some details.*\n" -> ""
 
 #![allow(unconditional_panic)]
index 32233a0f6eeb71183ac1da766e3aa8d09faf0805..dc2661ee796856816b8865c3361dccf17717a507 100644 (file)
@@ -1,5 +1,5 @@
 error: reaching this expression at runtime will panic or abort
-  --> $DIR/const-eval-query-stack.rs:18:28
+  --> $DIR/const-eval-query-stack.rs:19:28
    |
 LL |     let x: &'static i32 = &(1 / 0);
    |                           -^^^^^^^
index 7f6af051e1748b70ff7b43d1bd60015f00a6d679..a9e2bcdbdd1504493a13f0fcf132c789c6215134 100644 (file)
@@ -1,4 +1,4 @@
-error[E0723]: can only call other `const fn` within a `const fn`, but `const regular_in_block` is not stable as `const fn`
+error[E0723]: can only call other `const fn` within a `const fn`, but `regular_in_block` is not stable as `const fn`
   --> $DIR/const-extern-fn-call-extern-fn.rs:9:9
    |
 LL |         regular_in_block();
@@ -7,7 +7,7 @@ LL |         regular_in_block();
    = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
    = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
-error[E0723]: can only call other `const fn` within a `const fn`, but `const regular` is not stable as `const fn`
+error[E0723]: can only call other `const fn` within a `const fn`, but `regular` is not stable as `const fn`
   --> $DIR/const-extern-fn-call-extern-fn.rs:18:9
    |
 LL |         regular();
diff --git a/src/test/ui/consts/const-float-bits-conv.rs b/src/test/ui/consts/const-float-bits-conv.rs
new file mode 100644 (file)
index 0000000..2dfc6de
--- /dev/null
@@ -0,0 +1,93 @@
+// compile-flags: -Zmir-opt-level=0
+// run-pass
+
+#![feature(const_panic)]
+#![feature(const_float_bits_conv)]
+#![feature(const_float_classify)]
+
+// Don't promote
+const fn nop<T>(x: T) -> T { x }
+
+macro_rules! const_assert {
+    ($a:expr) => {
+        {
+            const _: () = assert!($a);
+            assert!(nop($a));
+        }
+    };
+    ($a:expr, $b:expr) => {
+        {
+            const _: () = assert!($a == $b);
+            assert_eq!(nop($a), nop($b));
+        }
+    };
+}
+
+fn f32() {
+    const_assert!((1f32).to_bits(), 0x3f800000);
+    const_assert!(u32::from_be_bytes(1f32.to_be_bytes()), 0x3f800000);
+    const_assert!((12.5f32).to_bits(), 0x41480000);
+    const_assert!(u32::from_le_bytes(12.5f32.to_le_bytes()), 0x41480000);
+    const_assert!((1337f32).to_bits(), 0x44a72000);
+    const_assert!(u32::from_ne_bytes(1337f32.to_ne_bytes()), 0x44a72000);
+    const_assert!((-14.25f32).to_bits(), 0xc1640000);
+    const_assert!(f32::from_bits(0x3f800000), 1.0);
+    const_assert!(f32::from_be_bytes(0x3f800000u32.to_be_bytes()), 1.0);
+    const_assert!(f32::from_bits(0x41480000), 12.5);
+    const_assert!(f32::from_le_bytes(0x41480000u32.to_le_bytes()), 12.5);
+    const_assert!(f32::from_bits(0x44a72000), 1337.0);
+    const_assert!(f32::from_ne_bytes(0x44a72000u32.to_ne_bytes()), 1337.0);
+    const_assert!(f32::from_bits(0xc1640000), -14.25);
+
+    // Check that NaNs roundtrip their bits regardless of signalingness
+    // 0xA is 0b1010; 0x5 is 0b0101 -- so these two together clobbers all the mantissa bits
+    const MASKED_NAN1: u32 = f32::NAN.to_bits() ^ 0x002A_AAAA;
+    const MASKED_NAN2: u32 = f32::NAN.to_bits() ^ 0x0055_5555;
+
+    const_assert!(f32::from_bits(MASKED_NAN1).is_nan());
+    const_assert!(f32::from_bits(MASKED_NAN1).is_nan());
+
+    // LLVM does not guarantee that loads and stores of NaNs preserve their exact bit pattern.
+    // In practice, this seems to only cause a problem on x86, since the most widely used calling
+    // convention mandates that floating point values are returned on the x87 FPU stack. See #73328.
+    if !cfg!(target_arch = "x86") {
+        const_assert!(f32::from_bits(MASKED_NAN1).to_bits(), MASKED_NAN1);
+        const_assert!(f32::from_bits(MASKED_NAN2).to_bits(), MASKED_NAN2);
+    }
+}
+
+fn f64() {
+    const_assert!((1f64).to_bits(), 0x3ff0000000000000);
+    const_assert!(u64::from_be_bytes(1f64.to_be_bytes()), 0x3ff0000000000000);
+    const_assert!((12.5f64).to_bits(), 0x4029000000000000);
+    const_assert!(u64::from_le_bytes(12.5f64.to_le_bytes()), 0x4029000000000000);
+    const_assert!((1337f64).to_bits(), 0x4094e40000000000);
+    const_assert!(u64::from_ne_bytes(1337f64.to_ne_bytes()), 0x4094e40000000000);
+    const_assert!((-14.25f64).to_bits(), 0xc02c800000000000);
+    const_assert!(f64::from_bits(0x3ff0000000000000), 1.0);
+    const_assert!(f64::from_be_bytes(0x3ff0000000000000u64.to_be_bytes()), 1.0);
+    const_assert!(f64::from_bits(0x4029000000000000), 12.5);
+    const_assert!(f64::from_le_bytes(0x4029000000000000u64.to_le_bytes()), 12.5);
+    const_assert!(f64::from_bits(0x4094e40000000000), 1337.0);
+    const_assert!(f64::from_ne_bytes(0x4094e40000000000u64.to_ne_bytes()), 1337.0);
+    const_assert!(f64::from_bits(0xc02c800000000000), -14.25);
+
+    // Check that NaNs roundtrip their bits regardless of signalingness
+    // 0xA is 0b1010; 0x5 is 0b0101 -- so these two together clobbers all the mantissa bits
+    const MASKED_NAN1: u64 = f64::NAN.to_bits() ^ 0x000A_AAAA_AAAA_AAAA;
+    const MASKED_NAN2: u64 = f64::NAN.to_bits() ^ 0x0005_5555_5555_5555;
+
+    const_assert!(f64::from_bits(MASKED_NAN1).is_nan());
+    const_assert!(f64::from_bits(MASKED_NAN1).is_nan());
+
+    // See comment above.
+    if !cfg!(target_arch = "x86") {
+        const_assert!(f64::from_bits(MASKED_NAN1).to_bits(), MASKED_NAN1);
+        const_assert!(f64::from_bits(MASKED_NAN2).to_bits(), MASKED_NAN2);
+    }
+}
+
+fn main() {
+    f32();
+    f64();
+}
diff --git a/src/test/ui/consts/const-float-classify.rs b/src/test/ui/consts/const-float-classify.rs
new file mode 100644 (file)
index 0000000..36fec99
--- /dev/null
@@ -0,0 +1,77 @@
+// compile-flags: -Zmir-opt-level=0
+// run-pass
+
+#![feature(const_panic)]
+#![feature(const_float_bits_conv)]
+#![feature(const_float_classify)]
+#![feature(const_trait_impl)]
+#![allow(incomplete_features)]
+
+// Don't promote
+const fn nop<T>(x: T) -> T { x }
+
+macro_rules! const_assert {
+    ($a:expr, $b:expr) => {
+        {
+            const _: () = assert!($a == $b);
+            assert_eq!(nop($a), nop($b));
+        }
+    };
+}
+
+macro_rules! suite {
+    ( $( $tt:tt )* ) => {
+        fn f32() {
+            suite_inner!(f32 $($tt)*);
+        }
+
+        fn f64() {
+            suite_inner!(f64 $($tt)*);
+        }
+    }
+
+}
+
+macro_rules! suite_inner {
+    (
+        $ty:ident [$( $fn:ident ),*]
+        $val:expr => [$($out:ident),*]
+
+        $( $tail:tt )*
+    ) => {
+        $( const_assert!($ty::$fn($val), $out); )*
+        suite_inner!($ty [$($fn),*] $($tail)*)
+    };
+
+    ( $ty:ident [$( $fn:ident ),*]) => {};
+}
+
+#[derive(Debug)]
+struct NonDet;
+
+impl const PartialEq<NonDet> for bool {
+    fn eq(&self, _: &NonDet) -> bool {
+        true
+    }
+}
+
+// The result of the `is_sign` methods are not checked for correctness, since LLVM does not
+// guarantee anything about the signedness of NaNs. See
+// https://github.com/rust-lang/rust/issues/55131.
+
+suite! {
+                   [is_nan, is_infinite, is_finite, is_normal, is_sign_positive, is_sign_negative]
+     -0.0 / 0.0 => [  true,       false,     false,     false,           NonDet,           NonDet]
+      0.0 / 0.0 => [  true,       false,     false,     false,           NonDet,           NonDet]
+            1.0 => [ false,       false,      true,      true,             true,            false]
+           -1.0 => [ false,       false,      true,      true,            false,             true]
+            0.0 => [ false,       false,      true,     false,             true,            false]
+           -0.0 => [ false,       false,      true,     false,            false,             true]
+      1.0 / 0.0 => [ false,        true,     false,     false,             true,            false]
+     -1.0 / 0.0 => [ false,        true,     false,     false,            false,             true]
+}
+
+fn main() {
+    f32();
+    f64();
+}
index b82ae40d6876ebea5673811f5381f26d6f8d9e98..bef4f240eeb8b45ae4a9e09d7105a5f61735b022 100644 (file)
@@ -1,4 +1,4 @@
-error[E0723]: can only call other `const fn` within a `const fn`, but `const foo` is not stable as `const fn`
+error[E0723]: can only call other `const fn` within a `const fn`, but `foo` is not stable as `const fn`
   --> $DIR/min_const_fn_libstd_stability.rs:16:25
    |
 LL | const fn bar() -> u32 { foo() }
@@ -7,7 +7,7 @@ LL | const fn bar() -> u32 { foo() }
    = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
    = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
-error[E0723]: can only call other `const fn` within a `const fn`, but `const foo2` is not stable as `const fn`
+error[E0723]: can only call other `const fn` within a `const fn`, but `foo2` is not stable as `const fn`
   --> $DIR/min_const_fn_libstd_stability.rs:24:26
    |
 LL | const fn bar2() -> u32 { foo2() }
@@ -25,7 +25,7 @@ LL | const fn bar3() -> u32 { (5f32 + 6f32) as u32 }
    = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
    = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
-error[E0723]: can only call other `const fn` within a `const fn`, but `const foo2_gated` is not stable as `const fn`
+error[E0723]: can only call other `const fn` within a `const fn`, but `foo2_gated` is not stable as `const fn`
   --> $DIR/min_const_fn_libstd_stability.rs:38:32
    |
 LL | const fn bar2_gated() -> u32 { foo2_gated() }
index 00975a80b2263f335545484b3375db91c8f9c5e9..c5ff340dfc6b759a2003bf82466439d924a33d74 100644 (file)
@@ -1,4 +1,4 @@
-error[E0723]: can only call other `const fn` within a `const fn`, but `const foo` is not stable as `const fn`
+error[E0723]: can only call other `const fn` within a `const fn`, but `foo` is not stable as `const fn`
   --> $DIR/min_const_unsafe_fn_libstd_stability.rs:16:41
    |
 LL | const unsafe fn bar() -> u32 { unsafe { foo() } }
@@ -7,7 +7,7 @@ LL | const unsafe fn bar() -> u32 { unsafe { foo() } }
    = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
    = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
-error[E0723]: can only call other `const fn` within a `const fn`, but `const foo2` is not stable as `const fn`
+error[E0723]: can only call other `const fn` within a `const fn`, but `foo2` is not stable as `const fn`
   --> $DIR/min_const_unsafe_fn_libstd_stability.rs:24:42
    |
 LL | const unsafe fn bar2() -> u32 { unsafe { foo2() } }
@@ -25,7 +25,7 @@ LL | const unsafe fn bar3() -> u32 { (5f32 + 6f32) as u32 }
    = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
    = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
-error[E0723]: can only call other `const fn` within a `const fn`, but `const foo2_gated` is not stable as `const fn`
+error[E0723]: can only call other `const fn` within a `const fn`, but `foo2_gated` is not stable as `const fn`
   --> $DIR/min_const_unsafe_fn_libstd_stability.rs:38:48
    |
 LL | const unsafe fn bar2_gated() -> u32 { unsafe { foo2_gated() } }
index 5014eed06fac524db6b1fa7272b095579d712f9f..31ad12c95511365a4a9cf5ab274dbe610eb2d99b 100644 (file)
@@ -1,4 +1,4 @@
-error[E0723]: can only call other `const fn` within a `const fn`, but `const foo` is not stable as `const fn`
+error[E0723]: can only call other `const fn` within a `const fn`, but `foo` is not stable as `const fn`
   --> $DIR/min_const_unsafe_fn_libstd_stability2.rs:16:32
    |
 LL | const unsafe fn bar() -> u32 { foo() }
@@ -7,7 +7,7 @@ LL | const unsafe fn bar() -> u32 { foo() }
    = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
    = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
-error[E0723]: can only call other `const fn` within a `const fn`, but `const foo2` is not stable as `const fn`
+error[E0723]: can only call other `const fn` within a `const fn`, but `foo2` is not stable as `const fn`
   --> $DIR/min_const_unsafe_fn_libstd_stability2.rs:24:33
    |
 LL | const unsafe fn bar2() -> u32 { foo2() }
@@ -16,7 +16,7 @@ LL | const unsafe fn bar2() -> u32 { foo2() }
    = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
    = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
-error[E0723]: can only call other `const fn` within a `const fn`, but `const foo2_gated` is not stable as `const fn`
+error[E0723]: can only call other `const fn` within a `const fn`, but `foo2_gated` is not stable as `const fn`
   --> $DIR/min_const_unsafe_fn_libstd_stability2.rs:33:39
    |
 LL | const unsafe fn bar2_gated() -> u32 { foo2_gated() }
index f64242d568e318a8b43cfb945030877e74788ae6..a491f1c92d3e10b0cbd812bdd1c2e421cf152a90 100644 (file)
@@ -1,7 +1,6 @@
 // run-pass
 #![feature(const_ptr_offset)]
 #![feature(const_ptr_offset_from)]
-#![feature(ptr_offset_from)]
 use std::ptr;
 
 #[repr(C)]
index 8c1b27842628d991d1a709cd7fffb3e1498de9d5..8d501e0d9533783f0e83a46f637b794affbb6e71 100644 (file)
@@ -2,7 +2,6 @@
 
 #![feature(const_raw_ptr_deref)]
 #![feature(const_ptr_offset_from)]
-#![feature(ptr_offset_from)]
 
 struct Struct {
     field: (),
index a7902f20467a134aafd46bfcda2c6c4114b49d23..b73191d56a6129d840d3ede8f745f4de6ceaea05 100644 (file)
@@ -1,6 +1,5 @@
 #![feature(const_raw_ptr_deref)]
 #![feature(const_ptr_offset_from)]
-#![feature(ptr_offset_from)]
 
 #[repr(C)]
 struct Struct {
index bd57e68e137ddc7e5b0bd0acb4e623ee9cc3f1e9..a89dcefd839205542f1563f69bb3d4f168c0fccc 100644 (file)
@@ -6,9 +6,9 @@ LL |           unsafe { intrinsics::ptr_offset_from(self, origin) }
    |                    |
    |                    ptr_offset_from cannot compute offset of pointers into different allocations.
    |                    inside `std::ptr::const_ptr::<impl *const Struct>::offset_from` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |                    inside `DIFFERENT_ALLOC` at $DIR/offset_from_ub.rs:17:27
+   |                    inside `DIFFERENT_ALLOC` at $DIR/offset_from_ub.rs:16:27
    | 
-  ::: $DIR/offset_from_ub.rs:11:1
+  ::: $DIR/offset_from_ub.rs:10:1
    |
 LL | / pub const DIFFERENT_ALLOC: usize = {
 LL | |
@@ -29,9 +29,9 @@ LL |           unsafe { intrinsics::ptr_offset_from(self, origin) }
    |                    |
    |                    unable to turn bytes into a pointer
    |                    inside `std::ptr::const_ptr::<impl *const u8>::offset_from` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |                    inside `NOT_PTR` at $DIR/offset_from_ub.rs:23:14
+   |                    inside `NOT_PTR` at $DIR/offset_from_ub.rs:22:14
    | 
-  ::: $DIR/offset_from_ub.rs:21:1
+  ::: $DIR/offset_from_ub.rs:20:1
    |
 LL | / pub const NOT_PTR: usize = {
 LL | |
@@ -47,9 +47,9 @@ LL |           unsafe { intrinsics::ptr_offset_from(self, origin) }
    |                    |
    |                    exact_div: 1_isize cannot be divided by 2_isize without remainder
    |                    inside `std::ptr::const_ptr::<impl *const u16>::offset_from` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |                    inside `NOT_MULTIPLE_OF_SIZE` at $DIR/offset_from_ub.rs:31:14
+   |                    inside `NOT_MULTIPLE_OF_SIZE` at $DIR/offset_from_ub.rs:30:14
    | 
-  ::: $DIR/offset_from_ub.rs:26:1
+  ::: $DIR/offset_from_ub.rs:25:1
    |
 LL | / pub const NOT_MULTIPLE_OF_SIZE: isize = {
 LL | |
@@ -68,9 +68,9 @@ LL |           unsafe { intrinsics::ptr_offset_from(self, origin) }
    |                    |
    |                    inbounds test failed: 0x0 is not a valid pointer
    |                    inside `std::ptr::const_ptr::<impl *const u8>::offset_from` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |                    inside `OFFSET_FROM_NULL` at $DIR/offset_from_ub.rs:37:14
+   |                    inside `OFFSET_FROM_NULL` at $DIR/offset_from_ub.rs:36:14
    | 
-  ::: $DIR/offset_from_ub.rs:34:1
+  ::: $DIR/offset_from_ub.rs:33:1
    |
 LL | / pub const OFFSET_FROM_NULL: isize = {
 LL | |
@@ -87,9 +87,9 @@ LL |           unsafe { intrinsics::ptr_offset_from(self, origin) }
    |                    |
    |                    unable to turn bytes into a pointer
    |                    inside `std::ptr::const_ptr::<impl *const u8>::offset_from` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |                    inside `DIFFERENT_INT` at $DIR/offset_from_ub.rs:44:14
+   |                    inside `DIFFERENT_INT` at $DIR/offset_from_ub.rs:43:14
    | 
-  ::: $DIR/offset_from_ub.rs:40:1
+  ::: $DIR/offset_from_ub.rs:39:1
    |
 LL | / pub const DIFFERENT_INT: isize = { // offset_from with two different integers: like DIFFERENT_ALLOC
 LL | |
index cca8b4d25dacc3111984f6594e5104de5d60a90c..933ed5e89e58b35d73294dcfe57dd3c29116cd0b 100644 (file)
@@ -1,10 +1,8 @@
 error: symbol `fail` is already defined
   --> $DIR/dupe-symbols-1.rs:12:1
    |
-LL | / pub fn b() {
-LL | |
-LL | | }
-   | |_^
+LL | pub fn b() {
+   | ^^^^^^^^^^
 
 error: aborting due to previous error
 
index 017aade31291d9ab1aef841a783d2236cf9948de..1b29edfb65598ca853b39a0576a6c4f55a8991de 100644 (file)
@@ -1,10 +1,8 @@
 error: symbol `fail` is already defined
   --> $DIR/dupe-symbols-2.rs:15:5
    |
-LL | /     pub extern fn fail() {
-LL | |
-LL | |     }
-   | |_____^
+LL |     pub extern fn fail() {
+   |     ^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index 2e2ac3a98b88024d63845de7440a1cdc63e429be..6300b4908d1960096d5f652e878c3c30d5a98b01 100644 (file)
@@ -1,10 +1,8 @@
 error: symbol `fail` is already defined
   --> $DIR/dupe-symbols-3.rs:12:1
    |
-LL | / pub fn fail() {
-LL | |
-LL | | }
-   | |_^
+LL | pub fn fail() {
+   | ^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index 10b93891b66a316f126ad75fc961d3d05a2c3e7c..1407a4883e16e8ca4db3f05db35dbfdfe8481df6 100644 (file)
@@ -2,7 +2,7 @@ error: symbol `fail` is already defined
   --> $DIR/dupe-symbols-4.rs:23:5
    |
 LL |     fn fail(self) {}
-   |     ^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index ebeb19f94f6c0b9e80e81b9fa770f4ad3acd6ed5..558f868a0c6212bba4d937f65c66f822a1b40506 100644 (file)
@@ -1,10 +1,8 @@
 error: symbol `fail` is already defined
   --> $DIR/dupe-symbols-5.rs:11:1
    |
-LL | / pub fn b() {
-LL | |
-LL | | }
-   | |_^
+LL | pub fn b() {
+   | ^^^^^^^^^^
 
 error: aborting due to previous error
 
index 2ea5521e0953327b3d7743ca1d34f9a3199acce3..1455f0e75abb7d31250217b2d29fefe941db1de3 100644 (file)
@@ -2,7 +2,7 @@ error: entry symbol `main` declared multiple times
   --> $DIR/dupe-symbols-7.rs:12:1
    |
 LL | fn main(){}
-   | ^^^^^^^^^^^
+   | ^^^^^^^^^
    |
    = help: did you use `#[no_mangle]` on `fn main`? Use `#[start]` instead
 
index f001201b8d0cf3d04b557482d7fba168306b1887..8d6a79e12d9e834e1272472dcfb6cd4f09e26e1e 100644 (file)
@@ -1,13 +1,8 @@
 error: entry symbol `main` declared multiple times
   --> $DIR/dupe-symbols-8.rs:7:1
    |
-LL | / fn main() {
-LL | |     extern "Rust" {
-LL | |      fn main();
-LL | |     }
-LL | |     unsafe { main(); }
-LL | | }
-   | |_^
+LL | fn main() {
+   | ^^^^^^^^^
    |
    = help: did you use `#[no_mangle]` on `fn main`? Use `#[start]` instead
 
index 61cccf40ed8a5133526ea9658019b050c7f4c6a2..6d078dfbd20536cb806e2a600e425002cb955dd8 100644 (file)
@@ -1,11 +1,8 @@
 error[E0152]: found duplicate lang item `panic_impl`
   --> $DIR/duplicate_entry_error.rs:11:1
    |
-LL | / fn panic_impl(info: &PanicInfo) -> ! {
-LL | |
-LL | |     loop {}
-LL | | }
-   | |_^
+LL | fn panic_impl(info: &PanicInfo) -> ! {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: the lang item is first defined in crate `std` (which `duplicate_entry_error` depends on)
    = note: first definition in `std` loaded from SYSROOT/libstd-*.rlib
index d0d6ebe16c7f7cbcf5325fae4d2f471a5c6de1ad..953a626bf9556438f6ed7aa5dcfd14715f4166d1 100644 (file)
@@ -14,7 +14,7 @@ error[E0445]: private trait `Foo` in public interface
   --> $DIR/E0445.rs:9:1
    |
 LL | pub fn foo<T: Foo> (t: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait
 
 error: aborting due to 3 previous errors
 
index a0f5f7079b34c3a62ef70678689e783a94f3c6b3..bb009260979741ba17f7064708712a37b0c3eb38 100644 (file)
@@ -1,13 +1,11 @@
 error[E0446]: private type `foo::Bar` in public interface
   --> $DIR/E0446.rs:4:5
    |
-LL |       struct Bar(u32);
-   |       - `foo::Bar` declared as private
+LL |     struct Bar(u32);
+   |     - `foo::Bar` declared as private
 LL | 
-LL | /     pub fn bar() -> Bar {
-LL | |         Bar(0)
-LL | |     }
-   | |_____^ can't leak private type
+LL |     pub fn bar() -> Bar {
+   |     ^^^^^^^^^^^^^^^^^^^ can't leak private type
 
 error: aborting due to previous error
 
index 948375566104becb71af12379dc710934c685e3c..2bf78d122903aabd5a55cfaa116bf6994cd98e31 100644 (file)
@@ -1,14 +1,8 @@
 error: fatal error triggered by #[rustc_error]
   --> $DIR/hr-subtype.rs:102:1
    |
-LL | / fn main() {
-LL | |
-LL | |
-LL | |
-...  |
-LL | |
-LL | | }
-   | |_^
+LL | fn main() {
+   | ^^^^^^^^^
 
 error: aborting due to previous error
 
index 948375566104becb71af12379dc710934c685e3c..2bf78d122903aabd5a55cfaa116bf6994cd98e31 100644 (file)
@@ -1,14 +1,8 @@
 error: fatal error triggered by #[rustc_error]
   --> $DIR/hr-subtype.rs:102:1
    |
-LL | / fn main() {
-LL | |
-LL | |
-LL | |
-...  |
-LL | |
-LL | | }
-   | |_^
+LL | fn main() {
+   | ^^^^^^^^^
 
 error: aborting due to previous error
 
index 948375566104becb71af12379dc710934c685e3c..2bf78d122903aabd5a55cfaa116bf6994cd98e31 100644 (file)
@@ -1,14 +1,8 @@
 error: fatal error triggered by #[rustc_error]
   --> $DIR/hr-subtype.rs:102:1
    |
-LL | / fn main() {
-LL | |
-LL | |
-LL | |
-...  |
-LL | |
-LL | | }
-   | |_^
+LL | fn main() {
+   | ^^^^^^^^^
 
 error: aborting due to previous error
 
index 948375566104becb71af12379dc710934c685e3c..2bf78d122903aabd5a55cfaa116bf6994cd98e31 100644 (file)
@@ -1,14 +1,8 @@
 error: fatal error triggered by #[rustc_error]
   --> $DIR/hr-subtype.rs:102:1
    |
-LL | / fn main() {
-LL | |
-LL | |
-LL | |
-...  |
-LL | |
-LL | | }
-   | |_^
+LL | fn main() {
+   | ^^^^^^^^^
 
 error: aborting due to previous error
 
index 948375566104becb71af12379dc710934c685e3c..2bf78d122903aabd5a55cfaa116bf6994cd98e31 100644 (file)
@@ -1,14 +1,8 @@
 error: fatal error triggered by #[rustc_error]
   --> $DIR/hr-subtype.rs:102:1
    |
-LL | / fn main() {
-LL | |
-LL | |
-LL | |
-...  |
-LL | |
-LL | | }
-   | |_^
+LL | fn main() {
+   | ^^^^^^^^^
 
 error: aborting due to previous error
 
index 948375566104becb71af12379dc710934c685e3c..2bf78d122903aabd5a55cfaa116bf6994cd98e31 100644 (file)
@@ -1,14 +1,8 @@
 error: fatal error triggered by #[rustc_error]
   --> $DIR/hr-subtype.rs:102:1
    |
-LL | / fn main() {
-LL | |
-LL | |
-LL | |
-...  |
-LL | |
-LL | | }
-   | |_^
+LL | fn main() {
+   | ^^^^^^^^^
 
 error: aborting due to previous error
 
index 948375566104becb71af12379dc710934c685e3c..2bf78d122903aabd5a55cfaa116bf6994cd98e31 100644 (file)
@@ -1,14 +1,8 @@
 error: fatal error triggered by #[rustc_error]
   --> $DIR/hr-subtype.rs:102:1
    |
-LL | / fn main() {
-LL | |
-LL | |
-LL | |
-...  |
-LL | |
-LL | | }
-   | |_^
+LL | fn main() {
+   | ^^^^^^^^^
 
 error: aborting due to previous error
 
index 948375566104becb71af12379dc710934c685e3c..2bf78d122903aabd5a55cfaa116bf6994cd98e31 100644 (file)
@@ -1,14 +1,8 @@
 error: fatal error triggered by #[rustc_error]
   --> $DIR/hr-subtype.rs:102:1
    |
-LL | / fn main() {
-LL | |
-LL | |
-LL | |
-...  |
-LL | |
-LL | | }
-   | |_^
+LL | fn main() {
+   | ^^^^^^^^^
 
 error: aborting due to previous error
 
index 948375566104becb71af12379dc710934c685e3c..2bf78d122903aabd5a55cfaa116bf6994cd98e31 100644 (file)
@@ -1,14 +1,8 @@
 error: fatal error triggered by #[rustc_error]
   --> $DIR/hr-subtype.rs:102:1
    |
-LL | / fn main() {
-LL | |
-LL | |
-LL | |
-...  |
-LL | |
-LL | | }
-   | |_^
+LL | fn main() {
+   | ^^^^^^^^^
 
 error: aborting due to previous error
 
index c0915808bf523992aadf7ce13cc774862c1f92aa..bd08fc1bfaeead2c20d300194dbd164f7b32b43d 100644 (file)
@@ -5,8 +5,7 @@ LL | / fn f<I>(i: I)
 LL | | where
 LL | |     I: IntoIterator,
 LL | |     I::Item: for<'a> Into<&'a ()>,
-LL | | {}
-   | |__- defined here
+   | |__________________________________- defined here
 ...
 LL |       f(&[f()]);
    |           ^-- supplied 0 arguments
index 7b22393ee7c0f7a7ee856a87c1dbd9d35fd83fca..eb07d8905d60901f782a5de9012c727f163373c8 100644 (file)
@@ -7,13 +7,8 @@ LL |         function(counter - 1, t.to_option());
 note: `function` defined here
   --> $DIR/infinite-instantiation.rs:19:1
    |
-LL | / fn function<T:ToOpt + Clone>(counter: usize, t: T) {
-LL | |     if counter > 0 {
-LL | |         function(counter - 1, t.to_option());
-LL | |
-LL | |     }
-LL | | }
-   | |_^
+LL | fn function<T:ToOpt + Clone>(counter: usize, t: T) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index 4f658330758141f7b842dd7fd1f9c8037267c4b1..6efc12df8fa2cabb23f788d01821411e3b6a1c06 100644 (file)
@@ -7,10 +7,8 @@ LL |         self.a();
 note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 3:5...
   --> $DIR/issue-16683.rs:3:5
    |
-LL | /     fn b(&self) {
-LL | |         self.a();
-LL | |     }
-   | |_____^
+LL |     fn b(&self) {
+   |     ^^^^^^^^^^^
 note: ...so that reference does not outlive borrowed content
   --> $DIR/issue-16683.rs:4:9
    |
index cd1d7f821c706df3c50bfa399ae7dd46a1eeffcb..9fe80232a14213728089cbeb79ad999930a733eb 100644 (file)
@@ -9,14 +9,8 @@ LL |     fn bar(self: &mut Foo) {
 note: the anonymous lifetime #2 defined on the method body at 6:5...
   --> $DIR/issue-17740.rs:6:5
    |
-LL | /     fn bar(self: &mut Foo) {
-LL | |
-LL | |
-LL | |
-...  |
-LL | |
-LL | |     }
-   | |_____^
+LL |     fn bar(self: &mut Foo) {
+   |     ^^^^^^^^^^^^^^^^^^^^^^
 note: ...does not necessarily outlive the lifetime `'a` as defined on the impl at 5:7
   --> $DIR/issue-17740.rs:5:7
    |
@@ -39,14 +33,8 @@ LL | impl <'a> Foo<'a>{
 note: ...does not necessarily outlive the anonymous lifetime #2 defined on the method body at 6:5
   --> $DIR/issue-17740.rs:6:5
    |
-LL | /     fn bar(self: &mut Foo) {
-LL | |
-LL | |
-LL | |
-...  |
-LL | |
-LL | |     }
-   | |_____^
+LL |     fn bar(self: &mut Foo) {
+   |     ^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
index 31788cfa61c4cf262ebb3f3628363134e65bb503..f82e0f53a23df2f7b600a5b665082ce6c14c2d35 100644 (file)
@@ -7,11 +7,8 @@ LL |         self.foo();
 note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 6:5...
   --> $DIR/issue-17758.rs:6:5
    |
-LL | /     fn bar(&self) {
-LL | |         self.foo();
-LL | |
-LL | |     }
-   | |_____^
+LL |     fn bar(&self) {
+   |     ^^^^^^^^^^^^^
 note: ...so that reference does not outlive borrowed content
   --> $DIR/issue-17758.rs:7:9
    |
index f347c26f066e0fa66715e0b0540534d65df9b7f6..c762a4ab496c91780403d09bf125e8f2dd43ea25 100644 (file)
@@ -9,12 +9,8 @@ LL |     fn say(self: &Pair<&str, isize>) {
 note: the anonymous lifetime #2 defined on the method body at 8:5...
   --> $DIR/issue-17905-2.rs:8:5
    |
-LL | /     fn say(self: &Pair<&str, isize>) {
-LL | |
-LL | |
-LL | |         println!("{:?}", self);
-LL | |     }
-   | |_____^
+LL |     fn say(self: &Pair<&str, isize>) {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...does not necessarily outlive the lifetime `'_` as defined on the impl at 5:5
   --> $DIR/issue-17905-2.rs:5:5
    |
@@ -37,12 +33,8 @@ LL |     &str,
 note: ...does not necessarily outlive the anonymous lifetime #2 defined on the method body at 8:5
   --> $DIR/issue-17905-2.rs:8:5
    |
-LL | /     fn say(self: &Pair<&str, isize>) {
-LL | |
-LL | |
-LL | |         println!("{:?}", self);
-LL | |     }
-   | |_____^
+LL |     fn say(self: &Pair<&str, isize>) {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
index e7c1dcc5d698c9e35da163ee206b903601665fd2..1ab89e818e31e5409482adbf3799b312b7a1fbd1 100644 (file)
@@ -15,14 +15,8 @@ LL | |     }
 note: the anonymous lifetime #2 defined on the method body at 28:5...
   --> $DIR/issue-20831-debruijn.rs:28:5
    |
-LL | /     fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
-LL | |         // Not obvious, but there is an implicit lifetime here -------^
-LL | |
-LL | |
-...  |
-LL | |         self.sub = t;
-LL | |     }
-   | |_____^
+LL |     fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...does not necessarily outlive the lifetime `'a` as defined on the impl at 26:6
   --> $DIR/issue-20831-debruijn.rs:26:6
    |
@@ -51,14 +45,8 @@ LL | impl<'a> Publisher<'a> for MyStruct<'a> {
 note: ...does not necessarily outlive the anonymous lifetime #2 defined on the method body at 28:5
   --> $DIR/issue-20831-debruijn.rs:28:5
    |
-LL | /     fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
-LL | |         // Not obvious, but there is an implicit lifetime here -------^
-LL | |
-LL | |
-...  |
-LL | |         self.sub = t;
-LL | |     }
-   | |_____^
+LL |     fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
   --> $DIR/issue-20831-debruijn.rs:28:33
@@ -69,14 +57,8 @@ LL |     fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher
 note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the method body at 28:5...
   --> $DIR/issue-20831-debruijn.rs:28:5
    |
-LL | /     fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
-LL | |         // Not obvious, but there is an implicit lifetime here -------^
-LL | |
-LL | |
-...  |
-LL | |         self.sub = t;
-LL | |     }
-   | |_____^
+LL |     fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...but the lifetime must also be valid for the lifetime `'a` as defined on the impl at 26:6...
   --> $DIR/issue-20831-debruijn.rs:26:6
    |
@@ -99,14 +81,8 @@ LL |     fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher
 note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the method body at 28:5...
   --> $DIR/issue-20831-debruijn.rs:28:5
    |
-LL | /     fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
-LL | |         // Not obvious, but there is an implicit lifetime here -------^
-LL | |
-LL | |
-...  |
-LL | |         self.sub = t;
-LL | |     }
-   | |_____^
+LL |     fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...but the lifetime must also be valid for the lifetime `'a` as defined on the impl at 26:6...
   --> $DIR/issue-20831-debruijn.rs:26:6
    |
index 41965d6b35536bda7e47306563a299febf18a068..b0df46b11fadb30b787b6fe4d4f5f052300ed6c2 100644 (file)
@@ -1,12 +1,8 @@
 error: reached the type-length limit while instantiating `D::matches::$CLOSURE`
   --> $DIR/issue-22638.rs:53:5
    |
-LL | /     pub fn matches<F: Fn()>(&self, f: &F) {
-LL | |
-LL | |         let &D(ref a) = self;
-LL | |         a.matches(f)
-LL | |     }
-   | |_____^
+LL |     pub fn matches<F: Fn()>(&self, f: &F) {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: consider adding a `#![type_length_limit="30408681"]` attribute to your crate
 
index f4a530124ff34a857706f1fed365682a2ec7e37e..e67f297ffa77a65ceeee121679dbcf23218160f0 100644 (file)
@@ -2,7 +2,7 @@ warning: private type `m1::Priv` in public interface (error E0446)
   --> $DIR/issue-30079.rs:6:9
    |
 LL |         pub fn f(_: Priv) {}
-   |         ^^^^^^^^^^^^^^^^^^^^
+   |         ^^^^^^^^^^^^^^^^^
    |
    = note: `#[warn(private_in_public)]` on by default
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
index 6c3ba63e6f6f24b03bf29a36f4c0503b5950d3a6..9a900d2fc9404b108d038512d9691a11c459b5e3 100644 (file)
@@ -19,15 +19,11 @@ LL | impl Trait2 for dyn Sync + Send + Sync {
 error[E0592]: duplicate definitions with name `abc`
   --> $DIR/issue-33140.rs:29:5
    |
-LL | /     fn abc() -> bool {
-LL | |         false
-LL | |     }
-   | |_____^ duplicate definitions for `abc`
+LL |     fn abc() -> bool {
+   |     ^^^^^^^^^^^^^^^^ duplicate definitions for `abc`
 ...
-LL | /     fn abc() -> bool {
-LL | |         true
-LL | |     }
-   | |_____- other definition for `abc`
+LL |     fn abc() -> bool {
+   |     ---------------- other definition for `abc`
 
 error: aborting due to 3 previous errors
 
index 7a4b59b56339317b48015db630a6bec18c9bf3b8..6229d90d4b477112990c56b6c480c44c029720a7 100644 (file)
@@ -1,10 +1,8 @@
 error: reached the type-length limit while instantiating `<(&(&(&(&(&(&(&(&(&(&(&(&(&(&(&(...))))))))))))))) as Foo>::recurse`
   --> $DIR/issue-37311.rs:15:5
    |
-LL | /     fn recurse(&self) {
-LL | |         (self, self).recurse();
-LL | |     }
-   | |_____^
+LL |     fn recurse(&self) {
+   |     ^^^^^^^^^^^^^^^^^
    |
    = note: consider adding a `#![type_length_limit="2097149"]` attribute to your crate
 
index 703cdf0854808c5359fd476da3ad339a2d166e21..5baa245b3cc2810b934e291507dc3b80dd996cb2 100644 (file)
@@ -14,13 +14,8 @@ LL | |     }
 note: the anonymous lifetime #1 defined on the method body at 6:5...
   --> $DIR/issue-37884.rs:6:5
    |
-LL | /     fn next(&'a mut self) -> Option<Self::Item>
-LL | |
-LL | |
-LL | |     {
-LL | |         Some(&mut self.0)
-LL | |     }
-   | |_____^
+LL |     fn next(&'a mut self) -> Option<Self::Item>
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...does not necessarily outlive the lifetime `'a` as defined on the impl at 3:6
   --> $DIR/issue-37884.rs:3:6
    |
index 3bb2016f07d24f03fc2f609343be749f589e3408..8243e52039d489233b0d61fd2c1d5212426bb5a7 100644 (file)
@@ -10,11 +10,7 @@ note: `rec` defined here
 LL | / fn rec<T>(mut it: T)
 LL | | where
 LL | |     T: Iterator,
-LL | | {
-...  |
-LL | |     }
-LL | | }
-   | |_^
+   | |________________^
 
 error: aborting due to previous error
 
index 70709fd33ac3ac170f287fbeaaf70ce118c59c2f..59008151f1a5b711bf4f8475e13f1e353a72215c 100644 (file)
@@ -18,10 +18,8 @@ LL |     generic::<Option<T>>();
 note: `generic` defined here
   --> $DIR/issue-8727.rs:6:1
    |
-LL | / fn generic<T>() {
-LL | |     generic::<Option<T>>();
-LL | | }
-   | |_^
+LL | fn generic<T>() {
+   | ^^^^^^^^^^^^^^^
 
 error: aborting due to previous error; 1 warning emitted
 
index d6ac7ccccc77b1c6b111ac80855efa81d0d5eb16..44cef19b0d34bd581690e14a3fce899022ca1240 100644 (file)
@@ -285,3 +285,26 @@ mod b {
         }
     }
 }
+
+#[allow(improper_ctypes)]
+mod unknown_layout {
+    mod a {
+        extern "C" {
+            pub fn generic(l: Link<u32>);
+        }
+        pub struct Link<T> {
+            pub item: T,
+            pub next: *const Link<T>,
+        }
+    }
+
+    mod b {
+        extern "C" {
+            pub fn generic(l: Link<u32>);
+        }
+        pub struct Link<T> {
+            pub item: T,
+            pub next: *const Link<T>,
+        }
+    }
+}
index 68434c13110c459b43f425ae263c521693ca0978..ae7d5a98b0872afbc74d210803552ff6f3ff70fc 100644 (file)
@@ -32,7 +32,7 @@ error[E0714]: marker traits cannot have associated items
   --> $DIR/marker-trait-with-associated-items.rs:36:5
    |
 LL |     fn foo() {}
-   |     ^^^^^^^^^^^
+   |     ^^^^^^^^
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/match/match-incompat-type-semi.rs b/src/test/ui/match/match-incompat-type-semi.rs
new file mode 100644 (file)
index 0000000..9ab40fa
--- /dev/null
@@ -0,0 +1,42 @@
+// Diagnostic enhancement explained in issue #75418.
+// Point at the last statement in the block if there's no tail expression,
+// and suggest removing the semicolon if appropriate.
+
+fn main() {
+    let _ = match Some(42) {
+        Some(x) => {
+            x
+        },
+        None => {
+            0;
+            //~^ ERROR incompatible types
+            //~| HELP consider removing this semicolon
+        },
+    };
+
+    let _ = if let Some(x) = Some(42) {
+        x
+    } else {
+        0;
+        //~^ ERROR incompatible types
+        //~| HELP consider removing this semicolon
+    };
+
+    let _ = match Some(42) {
+        Some(x) => {
+            x
+        },
+        None => {
+            ();
+            //~^ ERROR incompatible types
+        },
+    };
+
+    let _ = match Some(42) {
+        Some(x) => {
+            x
+        },
+        None => { //~ ERROR incompatible types
+        },
+    };
+}
diff --git a/src/test/ui/match/match-incompat-type-semi.stderr b/src/test/ui/match/match-incompat-type-semi.stderr
new file mode 100644 (file)
index 0000000..701f15f
--- /dev/null
@@ -0,0 +1,74 @@
+error[E0308]: `match` arms have incompatible types
+  --> $DIR/match-incompat-type-semi.rs:11:13
+   |
+LL |       let _ = match Some(42) {
+   |  _____________-
+LL | |         Some(x) => {
+LL | |             x
+   | |             - this is found to be of type `{integer}`
+LL | |         },
+LL | |         None => {
+LL | |             0;
+   | |             ^-
+   | |             ||
+   | |             |help: consider removing this semicolon
+   | |             expected integer, found `()`
+...  |
+LL | |         },
+LL | |     };
+   | |_____- `match` arms have incompatible types
+
+error[E0308]: `if` and `else` have incompatible types
+  --> $DIR/match-incompat-type-semi.rs:20:9
+   |
+LL |       let _ = if let Some(x) = Some(42) {
+   |  _____________-
+LL | |         x
+   | |         - expected because of this
+LL | |     } else {
+LL | |         0;
+   | |         ^-
+   | |         ||
+   | |         |help: consider removing this semicolon
+   | |         expected integer, found `()`
+LL | |
+LL | |
+LL | |     };
+   | |_____- `if` and `else` have incompatible types
+
+error[E0308]: `match` arms have incompatible types
+  --> $DIR/match-incompat-type-semi.rs:30:13
+   |
+LL |       let _ = match Some(42) {
+   |  _____________-
+LL | |         Some(x) => {
+LL | |             x
+   | |             - this is found to be of type `{integer}`
+LL | |         },
+LL | |         None => {
+LL | |             ();
+   | |             ^^^ expected integer, found `()`
+LL | |
+LL | |         },
+LL | |     };
+   | |_____- `match` arms have incompatible types
+
+error[E0308]: `match` arms have incompatible types
+  --> $DIR/match-incompat-type-semi.rs:39:17
+   |
+LL |        let _ = match Some(42) {
+   |   _____________-
+LL |  |         Some(x) => {
+LL |  |             x
+   |  |             - this is found to be of type `{integer}`
+LL |  |         },
+LL |  |         None => {
+   |  |_________________^
+LL | ||         },
+   | ||_________^ expected integer, found `()`
+LL |  |     };
+   |  |_____- `match` arms have incompatible types
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
index b070671cb250e4d1ee07f8d4fb2b7819ef40607b..4417fb926d96dff7cdb93903b019e86fa0560369 100644 (file)
@@ -10,7 +10,7 @@ fn foo(node: Box<List>) -> isize {
         Some(right) => consume(right),
         None => 0
     };
-    consume(node) + r //~ ERROR use of moved value: `node`
+    consume(node) + r //~ ERROR use of partially moved value: `node`
 }
 
 fn consume(v: Box<List>) -> isize {
index 952985fcddee6c18268718248bf22ad9e355ff07..49964e2a947c813069671b8d6790e2f7ea530b20 100644 (file)
@@ -1,13 +1,13 @@
-error[E0382]: use of moved value: `node`
+error[E0382]: use of partially moved value: `node`
   --> $DIR/moves-based-on-type-cyclic-types-issue-4821.rs:13:13
    |
 LL |         Some(right) => consume(right),
-   |              ----- value moved here
+   |              ----- value partially moved here
 ...
 LL |     consume(node) + r
    |             ^^^^ value used here after partial move
    |
-   = note: move occurs because value has type `std::boxed::Box<List>`, which does not implement the `Copy` trait
+   = note: partial move occurs because value has type `std::boxed::Box<List>`, which does not implement the `Copy` trait
 help: borrow this field in the pattern to avoid moving `node.next.0`
    |
 LL |         Some(ref right) => consume(right),
index 1290d4a25abc4d8e52f6a4846fb8e197d2d47109..75fc6085f0aaaf3e168a7decdf1f99f7cbc604bf 100644 (file)
@@ -13,9 +13,9 @@ fn f10() {
         Foo {f} => {}
     };
 
-    touch(&x); //~ ERROR borrow of moved value: `x`
+    touch(&x); //~ ERROR borrow of partially moved value: `x`
     //~^ value borrowed here after partial move
-    //~| move occurs because `x.f` has type `std::string::String`
+    //~| partial move occurs because `x.f` has type `std::string::String`
 }
 
 fn main() {}
index 322999a1f0ff9bd20114d695f580fa1aee700bbf..2ee8d8d0b755cebdee8c5dcf25c90039ed7e1844 100644 (file)
@@ -1,13 +1,13 @@
-error[E0382]: borrow of moved value: `x`
+error[E0382]: borrow of partially moved value: `x`
   --> $DIR/moves-based-on-type-match-bindings.rs:16:11
    |
 LL |         Foo {f} => {}
-   |              - value moved here
+   |              - value partially moved here
 ...
 LL |     touch(&x);
    |           ^^ value borrowed here after partial move
    |
-   = note: move occurs because `x.f` has type `std::string::String`, which does not implement the `Copy` trait
+   = note: partial move occurs because `x.f` has type `std::string::String`, which does not implement the `Copy` trait
 
 error: aborting due to previous error
 
index 0cdc2d9443926f55b0011a9e2d3e93280bac7368..7631ca61e5e15d4c7e2e8420fd354ef2a1881a0b 100644 (file)
@@ -12,11 +12,8 @@ LL | impl Foo<'_, '_> {
 note: ...but the borrowed content is only valid for the anonymous lifetime #2 defined on the method body at 13:5
   --> $DIR/issue-52742.rs:13:5
    |
-LL | /     fn take_bar(&mut self, b: Bar<'_>) {
-LL | |         self.y = b.z
-LL | |
-LL | |     }
-   | |_____^
+LL |     fn take_bar(&mut self, b: Bar<'_>) {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index ba8d91b8455bfab7a77a05b319372f28cc83a3ed..e24ef176db01e004b41b607b44d5af64c05d0c56 100644 (file)
@@ -7,10 +7,8 @@ LL |         Foo { bar }
 note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 8:5...
   --> $DIR/issue-55394.rs:8:5
    |
-LL | /     fn new(bar: &mut Bar) -> Self {
-LL | |         Foo { bar }
-LL | |     }
-   | |_____^
+LL |     fn new(bar: &mut Bar) -> Self {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...so that reference does not outlive borrowed content
   --> $DIR/issue-55394.rs:9:15
    |
index e7caf89e78391d2b50eec6e068edd5afbe67764e..d266c6bb6584ffc019980b83dc180f802e12bea1 100644 (file)
@@ -1,5 +1,5 @@
 fn main() {
     let x = (vec![1, 2, 3], );
     drop(x.0);
-    drop(x); //~ ERROR use of moved value
+    drop(x); //~ ERROR use of partially moved value
 }
index 7030d5b3305f1181990d13e7b20844d6deabcf1d..d86801cf296b599b2cb82cfdc28ec577d7cdc0fa 100644 (file)
@@ -1,12 +1,12 @@
-error[E0382]: use of moved value: `x`
+error[E0382]: use of partially moved value: `x`
   --> $DIR/move-subpaths-moves-root.rs:4:10
    |
 LL |     drop(x.0);
-   |          --- value moved here
+   |          --- value partially moved here
 LL |     drop(x);
    |          ^ value used here after partial move
    |
-   = note: move occurs because `x.0` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
+   = note: partial move occurs because `x.0` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
 
 error: aborting due to previous error
 
index 3317aae83bb08a2e621e552d0d573b0c0e9dcdb0..65ce05811211940ac04a507fe5fce3afdb24dda3 100644 (file)
@@ -7,10 +7,8 @@ LL |         C { f: b }
 note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 16:5...
   --> $DIR/type-alias-free-regions.rs:16:5
    |
-LL | /     fn from_box(b: Box<B>) -> Self {
-LL | |         C { f: b }
-LL | |     }
-   | |_____^
+LL |     fn from_box(b: Box<B>) -> Self {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...so that the expression is assignable
   --> $DIR/type-alias-free-regions.rs:17:16
    |
@@ -40,10 +38,8 @@ LL |         C { f: Box::new(b.0) }
 note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 26:5...
   --> $DIR/type-alias-free-regions.rs:26:5
    |
-LL | /     fn from_tuple(b: (B,)) -> Self {
-LL | |         C { f: Box::new(b.0) }
-LL | |     }
-   | |_____^
+LL |     fn from_tuple(b: (B,)) -> Self {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...so that the expression is assignable
   --> $DIR/type-alias-free-regions.rs:27:25
    |
index cbbb2adf15f91acc80b398a281e3eac4c5704eaf..aa59c119706ea690ad56a1288b4fd0f4ea8ce259 100644 (file)
@@ -1,7 +1,5 @@
 // run-pass
 
-#![feature(ptr_offset_from)]
-
 fn main() {
     let mut a = [0; 5];
     let ptr1: *mut i32 = &mut a[1];
index 3a5fc76efbbd4158ea565c589cb8ad93734f55cc..5e46da12142ff8b6b32df5f308d5e767e8361758 100644 (file)
@@ -1,11 +1,8 @@
 error: should have no type parameters
   --> $DIR/panic-handler-bad-signature-4.rs:9:1
    |
-LL | / fn panic<T>(pi: &PanicInfo) -> ! {
-LL | |
-LL | |     loop {}
-LL | | }
-   | |_^
+LL | fn panic<T>(pi: &PanicInfo) -> ! {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index 8603ef91beffdee8e54bad91cd6f87493fd5d66e..8cdc4888d022e1ff35d8db89772f660d776a0a98 100644 (file)
@@ -1,18 +1,14 @@
 error[E0152]: found duplicate lang item `panic_impl`
   --> $DIR/panic-handler-duplicate.rs:15:1
    |
-LL | / fn panic2(info: &PanicInfo) -> ! {
-LL | |     loop {}
-LL | | }
-   | |_^
+LL | fn panic2(info: &PanicInfo) -> ! {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: the lang item is first defined here
   --> $DIR/panic-handler-duplicate.rs:10:1
    |
-LL | / fn panic(info: &PanicInfo) -> ! {
-LL | |     loop {}
-LL | | }
-   | |_^
+LL | fn panic(info: &PanicInfo) -> ! {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index bb656089bcaffb0e20f3754722c2fd285dcda829..e4069b196ff04a31e3709d85b947fd0bda8f1141 100644 (file)
@@ -1,10 +1,8 @@
 error[E0152]: found duplicate lang item `panic_impl`
   --> $DIR/panic-handler-std.rs:8:1
    |
-LL | / fn panic(info: PanicInfo) -> ! {
-LL | |     loop {}
-LL | | }
-   | |_^
+LL | fn panic(info: PanicInfo) -> ! {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: the lang item is first defined in crate `std` (which `panic_handler_std` depends on)
    = note: first definition in `std` loaded from SYSROOT/libstd-*.rlib
diff --git a/src/test/ui/parser/struct-literal-in-match-guard.rs b/src/test/ui/parser/struct-literal-in-match-guard.rs
new file mode 100644 (file)
index 0000000..bf0551b
--- /dev/null
@@ -0,0 +1,18 @@
+// check-pass
+
+// Unlike `if` condition, `match` guards accept struct literals.
+// This is detected in <https://github.com/rust-lang/rust/pull/74566#issuecomment-663613705>.
+
+#[derive(PartialEq)]
+struct Foo {
+    x: isize,
+}
+
+fn foo(f: Foo) {
+    match () {
+        () if f == Foo { x: 42 } => {}
+        _ => {}
+    }
+}
+
+fn main() {}
index 441a4d5cffd4976f594c0078495f30013c4a1857..377bd58b54c6420d7d16243bdf4c1cc199c41e3a 100644 (file)
@@ -5,7 +5,7 @@ LL |     struct Priv;
    |     - `m1::Priv` declared as private
 ...
 LL |         pub fn f() -> Priv {Priv}
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
+   |         ^^^^^^^^^^^^^^^^^^ can't leak private type
 
 error[E0446]: private type `m2::Priv` in public interface
   --> $DIR/private-in-public-lint.rs:15:9
@@ -14,7 +14,7 @@ LL |     struct Priv;
    |     - `m2::Priv` declared as private
 ...
 LL |         pub fn f() -> Priv {Priv}
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
+   |         ^^^^^^^^^^^^^^^^^^ can't leak private type
 
 error: aborting due to 2 previous errors
 
index 43469f74538ea0900f2549ddb40d9e57044bd055..5b4123ea82aaf02b838ba97429fd049b08ff436b 100644 (file)
@@ -2,7 +2,7 @@ warning: private trait `PrivNonPrincipal` in public interface (error E0445)
   --> $DIR/private-in-public-non-principal.rs:7:1
    |
 LL | pub fn leak_dyn_nonprincipal() -> Box<dyn PubPrincipal + PrivNonPrincipal> { loop {} }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `#[warn(private_in_public)]` on by default
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
index 38081295e7eabaf2d702e929e4c9415b5b1dd978..4905e2951958fd182b31317773b4b17dca2c487a 100644 (file)
@@ -52,7 +52,7 @@ error: private type `types::Priv` in public interface (error E0446)
   --> $DIR/private-in-public-warn.rs:27:9
    |
 LL |         fn f1(arg: Priv) {}
-   |         ^^^^^^^^^^^^^^^^^^^
+   |         ^^^^^^^^^^^^^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
@@ -61,7 +61,7 @@ error: private type `types::Priv` in public interface (error E0446)
   --> $DIR/private-in-public-warn.rs:29:9
    |
 LL |         fn f2() -> Priv { panic!() }
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |         ^^^^^^^^^^^^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
@@ -148,7 +148,7 @@ error: private trait `traits::PrivTr` in public interface (error E0445)
   --> $DIR/private-in-public-warn.rs:61:9
    |
 LL |         fn f<T: PrivTr>(arg: T) {}
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
@@ -193,7 +193,7 @@ error: private trait `traits_where::PrivTr` in public interface (error E0445)
   --> $DIR/private-in-public-warn.rs:83:9
    |
 LL |         fn f<T>(arg: T) where T: PrivTr {}
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
@@ -265,7 +265,7 @@ error: private type `aliases_pub::Priv` in public interface (error E0446)
   --> $DIR/private-in-public-warn.rs:206:9
    |
 LL |         pub fn f(arg: Priv) {}
-   |         ^^^^^^^^^^^^^^^^^^^^^^
+   |         ^^^^^^^^^^^^^^^^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
index e3fa4c145c3dde42f22033d2242a71ec050612b3..4750fe8687ecd3d13b490f52e068b1d0b93cea6b 100644 (file)
@@ -23,7 +23,7 @@ LL |     struct Priv;
    |     - `types::Priv` declared as private
 ...
 LL |     pub fn f1(arg: Priv) {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
+   |     ^^^^^^^^^^^^^^^^^^^^ can't leak private type
 
 error[E0446]: private type `types::Priv` in public interface
   --> $DIR/private-in-public.rs:16:5
@@ -32,7 +32,7 @@ LL |     struct Priv;
    |     - `types::Priv` declared as private
 ...
 LL |     pub fn f2() -> Priv { panic!() }
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
+   |     ^^^^^^^^^^^^^^^^^^^ can't leak private type
 
 error[E0446]: private type `types::Priv` in public interface
   --> $DIR/private-in-public.rs:17:19
@@ -68,7 +68,7 @@ LL |     struct Priv;
    |     - `types::Priv` declared as private
 ...
 LL |         pub fn f1(arg: Priv) {}
-   |         ^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
+   |         ^^^^^^^^^^^^^^^^^^^^ can't leak private type
 
 error[E0446]: private type `types::Priv` in public interface
   --> $DIR/private-in-public.rs:22:9
@@ -77,7 +77,7 @@ LL |     struct Priv;
    |     - `types::Priv` declared as private
 ...
 LL |         pub fn f2() -> Priv { panic!() }
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
+   |         ^^^^^^^^^^^^^^^^^^^ can't leak private type
 
 error[E0445]: private trait `traits::PrivTr` in public interface
   --> $DIR/private-in-public.rs:31:5
@@ -95,7 +95,7 @@ LL |     trait PrivTr {}
    |     - `traits::PrivTr` declared as private
 ...
 LL |     pub fn f<T: PrivTr>(arg: T) {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait
 
 error[E0445]: private trait `traits::PrivTr` in public interface
   --> $DIR/private-in-public.rs:33:5
@@ -124,7 +124,7 @@ LL |     trait PrivTr {}
    |     - `traits::PrivTr` declared as private
 ...
 LL |         pub fn f<U: PrivTr>(arg: U) {}
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait
 
 error[E0445]: private trait `traits_where::PrivTr` in public interface
   --> $DIR/private-in-public.rs:44:5
@@ -142,7 +142,7 @@ LL |     trait PrivTr {}
    |     - `traits_where::PrivTr` declared as private
 ...
 LL |     pub fn f<T>(arg: T) where T: PrivTr {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait
 
 error[E0445]: private trait `traits_where::PrivTr` in public interface
   --> $DIR/private-in-public.rs:48:5
@@ -173,7 +173,7 @@ LL |     trait PrivTr {}
    |     - `traits_where::PrivTr` declared as private
 ...
 LL |         pub fn f<U>(arg: U) where U: PrivTr {}
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait
 
 error[E0446]: private type `generics::Priv` in public interface
   --> $DIR/private-in-public.rs:63:5
@@ -182,7 +182,7 @@ LL |     struct Priv<T = u8>(T);
    |     - `generics::Priv` declared as private
 ...
 LL |     pub fn f1(arg: [Priv; 1]) {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
 
 error[E0446]: private type `generics::Priv` in public interface
   --> $DIR/private-in-public.rs:64:5
@@ -191,7 +191,7 @@ LL |     struct Priv<T = u8>(T);
    |     - `generics::Priv` declared as private
 ...
 LL |     pub fn f2(arg: Pub<Priv>) {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
 
 error[E0446]: private type `generics::Priv<generics::Pub>` in public interface
   --> $DIR/private-in-public.rs:65:5
@@ -200,7 +200,7 @@ LL |     struct Priv<T = u8>(T);
    |     - `generics::Priv<generics::Pub>` declared as private
 ...
 LL |     pub fn f3(arg: Priv<Pub>) {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
 
 error[E0446]: private type `impls::Priv` in public interface
   --> $DIR/private-in-public.rs:80:9
@@ -209,7 +209,7 @@ LL |     struct Priv;
    |     - `impls::Priv` declared as private
 ...
 LL |         pub fn f(arg: Priv) {}
-   |         ^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
+   |         ^^^^^^^^^^^^^^^^^^^ can't leak private type
 
 error[E0445]: private trait `aliases_pub::PrivTr` in public interface
   --> $DIR/private-in-public.rs:104:5
@@ -218,7 +218,7 @@ LL |     trait PrivTr {
    |     - `aliases_pub::PrivTr` declared as private
 ...
 LL |     pub fn f3(arg: <Priv as PrivTr>::Assoc) {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait
 
 error[E0446]: private type `aliases_pub::Priv` in public interface
   --> $DIR/private-in-public.rs:104:5
@@ -227,7 +227,7 @@ LL |     struct Priv;
    |     - `aliases_pub::Priv` declared as private
 ...
 LL |     pub fn f3(arg: <Priv as PrivTr>::Assoc) {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
 
 error[E0446]: private type `aliases_pub::Priv` in public interface
   --> $DIR/private-in-public.rs:109:9
@@ -236,7 +236,7 @@ LL |     struct Priv;
    |     - `aliases_pub::Priv` declared as private
 ...
 LL |         pub fn f(arg: Priv) {}
-   |         ^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
+   |         ^^^^^^^^^^^^^^^^^^^ can't leak private type
 
 error[E0446]: private type `aliases_priv::Priv1` in public interface
   --> $DIR/private-in-public.rs:131:5
@@ -245,7 +245,7 @@ LL |     struct Priv1;
    |     - `aliases_priv::Priv1` declared as private
 ...
 LL |     pub fn f1(arg: PrivUseAlias) {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
 
 error[E0446]: private type `aliases_priv::Priv2` in public interface
   --> $DIR/private-in-public.rs:132:5
@@ -254,7 +254,7 @@ LL |     struct Priv2;
    |     - `aliases_priv::Priv2` declared as private
 ...
 LL |     pub fn f2(arg: PrivAlias) {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
 
 error[E0445]: private trait `aliases_priv::PrivTr` in public interface
   --> $DIR/private-in-public.rs:133:5
@@ -263,7 +263,7 @@ LL |     trait PrivTr {
    |     - `aliases_priv::PrivTr` declared as private
 ...
 LL |     pub fn f3(arg: <Priv as PrivTr>::Assoc) {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait
 
 error[E0446]: private type `aliases_priv::Priv` in public interface
   --> $DIR/private-in-public.rs:133:5
@@ -272,7 +272,7 @@ LL |     struct Priv;
    |     - `aliases_priv::Priv` declared as private
 ...
 LL |     pub fn f3(arg: <Priv as PrivTr>::Assoc) {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
 
 error[E0446]: private type `aliases_params::Priv` in public interface
   --> $DIR/private-in-public.rs:143:5
@@ -281,7 +281,7 @@ LL |     struct Priv;
    |     - `aliases_params::Priv` declared as private
 ...
 LL |     pub fn f2(arg: PrivAliasGeneric) {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
 
 error[E0446]: private type `aliases_params::Priv` in public interface
   --> $DIR/private-in-public.rs:145:5
@@ -290,7 +290,7 @@ LL |     struct Priv;
    |     - `aliases_params::Priv` declared as private
 ...
 LL |     pub fn f3(arg: Result<u8>) {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
 
 error: aborting due to 32 previous errors
 
index 010969c03afdaac9d5705fe0460b7625131e670e..727134bd51d4784edd9e60774fbd8701e900a135 100644 (file)
@@ -14,7 +14,7 @@ error: type `priv_dep::OtherType` from private dependency 'priv_dep' in public i
   --> $DIR/pub-priv1.rs:27:5
    |
 LL |     pub fn pub_fn(param: OtherType) {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: trait `priv_dep::OtherTrait` from private dependency 'priv_dep' in public interface
   --> $DIR/pub-priv1.rs:33:1
index 87c96d31f09293fd1d26a211da85ed352cba2819..c597935e7f0a4c43ad1c75286b2bd7aa3a3d45c8 100644 (file)
@@ -5,7 +5,7 @@ LL |     struct Priv;
    |     - `foo::Priv` declared as private
 ...
 LL |         pub(crate) fn g(_: Priv) {}
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
 
 error[E0446]: private type `foo::Priv` in public interface
   --> $DIR/private-in-public.rs:9:9
@@ -14,7 +14,7 @@ LL |     struct Priv;
    |     - `foo::Priv` declared as private
 ...
 LL |         crate fn h(_: Priv) {}
-   |         ^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
+   |         ^^^^^^^^^^^^^^^^^^^ can't leak private type
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/proc-macro/group-compat-hack/auxiliary/group-compat-hack.rs b/src/test/ui/proc-macro/group-compat-hack/auxiliary/group-compat-hack.rs
new file mode 100644 (file)
index 0000000..5cd3b40
--- /dev/null
@@ -0,0 +1,13 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::TokenStream;
+
+#[proc_macro_attribute]
+pub fn my_macro(_attr: TokenStream, input: TokenStream) -> TokenStream {
+    println!("Called proc_macro_hack with {:?}", input);
+    input
+}
diff --git a/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.rs b/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.rs
new file mode 100644 (file)
index 0000000..35c1015
--- /dev/null
@@ -0,0 +1,30 @@
+// check-pass
+// aux-build:group-compat-hack.rs
+// compile-flags: -Z span-debug
+
+#![no_std] // Don't load unnecessary hygiene information from std
+extern crate std;
+
+#[macro_use] extern crate group_compat_hack;
+
+// Tests the backwards compatibility hack added for certain macros
+// When an attribute macro named `proc_macro_hack` or `wasm_bindgen`
+// has an `NtIdent` named `$name`, we pass a plain `Ident` token in
+// place of a `None`-delimited group. This allows us to maintain
+// backwards compatibility for older versions of these crates.
+
+include!("js-sys/src/lib.rs");
+include!("time-macros-impl/src/lib.rs");
+
+macro_rules! other {
+    ($name:ident) => {
+        #[my_macro] struct Three($name);
+    }
+}
+
+fn main() {
+    struct Foo;
+    impl_macros!(Foo);
+    arrays!(Foo);
+    other!(Foo);
+}
diff --git a/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stdout b/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stdout
new file mode 100644 (file)
index 0000000..d519daa
--- /dev/null
@@ -0,0 +1,3 @@
+Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/time-macros-impl/src/lib.rs:5:21: 5:27 (#5) }, Ident { ident: "One", span: $DIR/time-macros-impl/src/lib.rs:5:28: 5:31 (#5) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:27:18: 27:21 (#0) }], span: $DIR/time-macros-impl/src/lib.rs:5:31: 5:38 (#5) }, Punct { ch: ';', spacing: Alone, span: $DIR/time-macros-impl/src/lib.rs:5:38: 5:39 (#5) }]
+Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/js-sys/src/lib.rs:5:21: 5:27 (#9) }, Ident { ident: "Two", span: $DIR/js-sys/src/lib.rs:5:28: 5:31 (#9) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:28:13: 28:16 (#0) }], span: $DIR/js-sys/src/lib.rs:5:31: 5:38 (#9) }, Punct { ch: ';', spacing: Alone, span: $DIR/js-sys/src/lib.rs:5:38: 5:39 (#9) }]
+Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/group-compat-hack.rs:21:21: 21:27 (#13) }, Ident { ident: "Three", span: $DIR/group-compat-hack.rs:21:28: 21:33 (#13) }, Group { delimiter: Parenthesis, stream: TokenStream [Group { delimiter: None, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:29:12: 29:15 (#0) }], span: $DIR/group-compat-hack.rs:21:34: 21:39 (#13) }], span: $DIR/group-compat-hack.rs:21:33: 21:40 (#13) }, Punct { ch: ';', spacing: Alone, span: $DIR/group-compat-hack.rs:21:40: 21:41 (#13) }]
diff --git a/src/test/ui/proc-macro/group-compat-hack/js-sys/src/lib.rs b/src/test/ui/proc-macro/group-compat-hack/js-sys/src/lib.rs
new file mode 100644 (file)
index 0000000..d1a6694
--- /dev/null
@@ -0,0 +1,7 @@
+// ignore-test this is not a test
+
+macro_rules! arrays {
+    ($name:ident) => {
+        #[my_macro] struct Two($name);
+    }
+}
diff --git a/src/test/ui/proc-macro/group-compat-hack/time-macros-impl/src/lib.rs b/src/test/ui/proc-macro/group-compat-hack/time-macros-impl/src/lib.rs
new file mode 100644 (file)
index 0000000..c94c357
--- /dev/null
@@ -0,0 +1,7 @@
+// ignore-test this is not a test
+
+macro_rules! impl_macros {
+    ($name:ident) => {
+        #[my_macro] struct One($name);
+    }
+}
index 9cf33ba4a9df46b74eae828cb7cf99a8659b4204..a9636cfef82197822add537a8f7d7abc28c797cd 100644 (file)
@@ -15,51 +15,63 @@ PRINT-ATTR INPUT (DISPLAY): const A : u8 = 0 ;
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "const",
-        span: #0 bytes(0..0),
+        span: #3 bytes(416..421),
     },
-    Ident {
-        ident: "A",
-        span: #0 bytes(0..0),
+    Group {
+        delimiter: None,
+        stream: TokenStream [
+            Ident {
+                ident: "A",
+                span: #0 bytes(503..504),
+            },
+        ],
+        span: #3 bytes(422..424),
     },
     Punct {
         ch: ':',
         spacing: Alone,
-        span: #0 bytes(0..0),
+        span: #3 bytes(424..425),
     },
     Ident {
         ident: "u8",
-        span: #0 bytes(0..0),
+        span: #3 bytes(426..428),
     },
     Punct {
         ch: '=',
         spacing: Alone,
-        span: #0 bytes(0..0),
+        span: #3 bytes(429..430),
     },
     Literal {
         kind: Integer,
         symbol: "0",
         suffix: None,
-        span: #0 bytes(0..0),
+        span: #3 bytes(431..432),
     },
     Punct {
         ch: ';',
         spacing: Alone,
-        span: #0 bytes(0..0),
+        span: #3 bytes(432..433),
     },
 ]
 PRINT-DERIVE INPUT (DISPLAY): struct A { }
 PRINT-DERIVE INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
-        span: #0 bytes(0..0),
+        span: #3 bytes(468..474),
     },
-    Ident {
-        ident: "A",
-        span: #0 bytes(0..0),
+    Group {
+        delimiter: None,
+        stream: TokenStream [
+            Ident {
+                ident: "A",
+                span: #0 bytes(503..504),
+            },
+        ],
+        span: #3 bytes(475..477),
     },
     Group {
         delimiter: Brace,
         stream: TokenStream [],
-        span: #0 bytes(0..0),
+        span: #3 bytes(478..480),
     },
 ]
index 5b4d577a1acc42a8919f6ae802169044b46e1fe6..e0c40bbc7344ecb6feebbb3c17e85bfca7232571 100644 (file)
@@ -1,14 +1,13 @@
 // aux-build:first-second.rs
-// FIXME: The spans here are bad, see PR #73084
 
 extern crate first_second;
 use first_second::*;
 
 macro_rules! produce_it {
     ($name:ident) => {
-        #[first] //~ ERROR cannot find type
+        #[first]
         struct $name {
-            field: MissingType
+            field: MissingType //~ ERROR cannot find type
         }
     }
 }
index 4b72d29fe8ae068ee0796a62ab3263dcd5dcb1ed..54a079e4e736af0e9ae1152d3e98bdb8a21dc9a4 100644 (file)
@@ -1,8 +1,13 @@
 error[E0412]: cannot find type `MissingType` in this scope
-  --> $DIR/macro-rules-derive.rs:9:9
+  --> $DIR/macro-rules-derive.rs:10:20
    |
-LL |         #[first]
-   |         ^^^^^^^^ not found in this scope
+LL |             field: MissingType
+   |                    ^^^^^^^^^^^ not found in this scope
+...
+LL | produce_it!(MyName);
+   | -------------------- 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 previous error
 
index 1831300a0d97c2fc8f7326f8842c03d191ace022..a9e5256a0a95d763b10959b2b42781f6136fed0a 100644 (file)
@@ -14,7 +14,7 @@ error: fatal error triggered by #[rustc_error]
   --> $DIR/no-macro-use-attr.rs:10:1
    |
 LL | fn main() {}
-   | ^^^^^^^^^^^^
+   | ^^^^^^^^^
 
 error: aborting due to previous error; 1 warning emitted
 
index 2fcd41f6da05603341e44f0d434e40197d31e998..cdf851b535aa5b083373f50c2334576f82d1120e 100644 (file)
@@ -71,7 +71,6 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
     },
 ]
 PRINT-BANG INPUT (DISPLAY): "hi" "hello".len() + "world".len() (1 + 1)
-PRINT-BANG RE-COLLECTED (DISPLAY): "hi" "hello" . len() + "world" . len() (1 + 1)
 PRINT-BANG INPUT (DEBUG): TokenStream [
     Literal {
         kind: Str,
@@ -82,50 +81,62 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
     Group {
         delimiter: None,
         stream: TokenStream [
-            Literal {
-                kind: Str,
-                symbol: "hello",
-                suffix: None,
-                span: $DIR/nodelim-groups.rs:16:47: 16:51 (#8),
-            },
-            Punct {
-                ch: '.',
-                spacing: Alone,
-                span: $DIR/nodelim-groups.rs:16:47: 16:51 (#8),
-            },
-            Ident {
-                ident: "len",
-                span: $DIR/nodelim-groups.rs:16:47: 16:51 (#8),
-            },
             Group {
-                delimiter: Parenthesis,
-                stream: TokenStream [],
-                span: $DIR/nodelim-groups.rs:16:47: 16:51 (#8),
+                delimiter: None,
+                stream: TokenStream [
+                    Literal {
+                        kind: Str,
+                        symbol: "hello",
+                        suffix: None,
+                        span: $DIR/nodelim-groups.rs:21:17: 21:24 (#0),
+                    },
+                    Punct {
+                        ch: '.',
+                        spacing: Alone,
+                        span: $DIR/nodelim-groups.rs:21:24: 21:25 (#0),
+                    },
+                    Ident {
+                        ident: "len",
+                        span: $DIR/nodelim-groups.rs:21:25: 21:28 (#0),
+                    },
+                    Group {
+                        delimiter: Parenthesis,
+                        stream: TokenStream [],
+                        span: $DIR/nodelim-groups.rs:21:28: 21:30 (#0),
+                    },
+                ],
+                span: $DIR/nodelim-groups.rs:15:49: 15:54 (#7),
             },
             Punct {
                 ch: '+',
                 spacing: Alone,
-                span: $DIR/nodelim-groups.rs:16:47: 16:51 (#8),
-            },
-            Literal {
-                kind: Str,
-                symbol: "world",
-                suffix: None,
-                span: $DIR/nodelim-groups.rs:16:47: 16:51 (#8),
-            },
-            Punct {
-                ch: '.',
-                spacing: Alone,
-                span: $DIR/nodelim-groups.rs:16:47: 16:51 (#8),
-            },
-            Ident {
-                ident: "len",
-                span: $DIR/nodelim-groups.rs:16:47: 16:51 (#8),
+                span: $DIR/nodelim-groups.rs:15:55: 15:56 (#7),
             },
             Group {
-                delimiter: Parenthesis,
-                stream: TokenStream [],
-                span: $DIR/nodelim-groups.rs:16:47: 16:51 (#8),
+                delimiter: None,
+                stream: TokenStream [
+                    Literal {
+                        kind: Str,
+                        symbol: "world",
+                        suffix: None,
+                        span: $DIR/nodelim-groups.rs:21:33: 21:40 (#0),
+                    },
+                    Punct {
+                        ch: '.',
+                        spacing: Alone,
+                        span: $DIR/nodelim-groups.rs:21:40: 21:41 (#0),
+                    },
+                    Ident {
+                        ident: "len",
+                        span: $DIR/nodelim-groups.rs:21:41: 21:44 (#0),
+                    },
+                    Group {
+                        delimiter: Parenthesis,
+                        stream: TokenStream [],
+                        span: $DIR/nodelim-groups.rs:21:44: 21:46 (#0),
+                    },
+                ],
+                span: $DIR/nodelim-groups.rs:15:57: 15:62 (#7),
             },
         ],
         span: $DIR/nodelim-groups.rs:16:47: 16:51 (#8),
index 3f48191b5b26e42c69f67b830a9f78c5461c0979..7ba3f98a7a9a888dbd7dfbfcc9b64e10f1265572 100644 (file)
@@ -1,6 +1,4 @@
 // aux-build:weird-hygiene.rs
-// check-pass
-// FIXME: This should actually error, see PR #73084
 
 #![feature(stmt_expr_attributes)]
 #![feature(proc_macro_hygiene)]
@@ -22,7 +20,7 @@ macro_rules! inner {
 
         #[derive(WeirdDerive)]
         enum MyEnum {
-            Value = (stringify!($tokens + hidden_ident), 1).1
+            Value = (stringify!($tokens + hidden_ident), 1).1 //~ ERROR cannot find
         }
 
         inner!();
@@ -33,7 +31,7 @@ macro_rules! invoke_it {
     ($token:expr) => {
         #[recollect_attr] {
             $token;
-            hidden_ident
+            hidden_ident //~ ERROR cannot find
         }
     }
 }
diff --git a/src/test/ui/proc-macro/weird-hygiene.stderr b/src/test/ui/proc-macro/weird-hygiene.stderr
new file mode 100644 (file)
index 0000000..b17dc28
--- /dev/null
@@ -0,0 +1,25 @@
+error[E0425]: cannot find value `hidden_ident` in this scope
+  --> $DIR/weird-hygiene.rs:23:43
+   |
+LL |             Value = (stringify!($tokens + hidden_ident), 1).1
+   |                                           ^^^^^^^^^^^^ not found in this scope
+...
+LL |     other!(50);
+   |     ----------- in this macro invocation
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0425]: cannot find value `hidden_ident` in this scope
+  --> $DIR/weird-hygiene.rs:34:13
+   |
+LL |             hidden_ident
+   |             ^^^^^^^^^^^^ not found in this scope
+...
+LL |     invoke_it!(25);
+   |     --------------- 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 2 previous errors
+
+For more information about this error, try `rustc --explain E0425`.
index 540b35e0392de1ef5aad30813fc508b5805e6291..7e7a15924b7653128c9c5a2db10d6d7e28fd88f9 100644 (file)
@@ -1,6 +1,5 @@
 // run-pass
 // Test inclusive range syntax.
-#![feature(range_is_empty)]
 #![allow(unused_braces)]
 #![allow(unused_comparisons)]
 
index bdcd47a7260d30f22664b0ba720117a9bea2110b..2e07fdcbe830cd8074492028bd8ed67da90f1549 100644 (file)
@@ -48,7 +48,7 @@ unsafe fn allocate(layout: Layout) -> *mut u8 {
             println!("allocate({:?}) = {:?}", layout, ptr);
         }
 
-        ptr.as_non_null_ptr().as_ptr()
+        ptr.as_mut_ptr()
     }
 
     unsafe fn deallocate(ptr: *mut u8, layout: Layout) {
@@ -65,23 +65,17 @@ unsafe fn reallocate(ptr: *mut u8, old: Layout, new: Layout) -> *mut u8 {
         }
 
         let memory = if new.size() > old.size() {
-            Global.grow(
-                NonNull::new_unchecked(ptr),
-                old,
-                new.size(),
-            )
+            Global.grow(NonNull::new_unchecked(ptr), old, new)
         } else {
-            Global.shrink(NonNull::new_unchecked(ptr), old, new.size())
+            Global.shrink(NonNull::new_unchecked(ptr), old, new)
         };
 
-        let ptr = memory.unwrap_or_else(|_| {
-            handle_alloc_error(Layout::from_size_align_unchecked(new.size(), old.align()))
-        });
+        let ptr = memory.unwrap_or_else(|_| handle_alloc_error(new));
 
         if PRINT {
             println!("reallocate({:?}, old={:?}, new={:?}) = {:?}", ptr, old, new, ptr);
         }
-        ptr.as_non_null_ptr().as_ptr()
+        ptr.as_mut_ptr()
     }
 
     fn idx_to_size(i: usize) -> usize {
index 0c0eba68c83b4d1ac7cd4181db93e553e0c9ca93..db4c99eeb8b167c4691da008cfa8290a9650d70c 100644 (file)
@@ -7,13 +7,8 @@ LL |     _ => {test (n-1, i+1, Cons {head:2*i+1, tail:first}, Cons{head:i*i, tai
 note: `test` defined here
   --> $DIR/recursion.rs:15:1
    |
-LL | / fn test<T:Dot> (n:isize, i:isize, first:T, second:T) ->isize {
-LL | |   match n {    0 => {first.dot(second)}
-LL | |     _ => {test (n-1, i+1, Cons {head:2*i+1, tail:first}, Cons{head:i*i, tail:second})}
-LL | |
-LL | |   }
-LL | | }
-   | |_^
+LL | fn test<T:Dot> (n:isize, i:isize, first:T, second:T) ->isize {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index 49d199cd9e75422731e1334cab1c933eb593da10..346d118f0f9a9dd91140c4442cefcaf195ba2c4b 100644 (file)
@@ -13,5 +13,5 @@ fn main() {
         (Some(y), ()) => {},
         _ => {},
     }
-    x; //~ ERROR use of moved value
+    x; //~ ERROR use of partially moved value
 }
index 97d2c174d9adbf082682c9b7e5d476eb967815ea..313ad087c348ddb83353054702e3f2cd9dbf2529 100644 (file)
@@ -18,16 +18,16 @@ LL |     let mut y = x;
 LL |     x;
    |     ^ value used here after move
 
-error[E0382]: use of moved value: `x`
+error[E0382]: use of partially moved value: `x`
   --> $DIR/ref-suggestion.rs:16:5
    |
 LL |         (Some(y), ()) => {},
-   |               - value moved here
+   |               - value partially moved here
 ...
 LL |     x;
    |     ^ value used here after partial move
    |
-   = note: move occurs because value has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
+   = note: partial move occurs because value has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
 help: borrow this field in the pattern to avoid moving `x.0.0`
    |
 LL |         (Some(ref y), ()) => {},
index 1497c3ed92564a748db99cb263ecc0d8b14d512e..3e196cf8f12e0c1ebd5b373ce2cb96a51dddaf97 100644 (file)
@@ -9,14 +9,8 @@ LL |         self.f = b;
 note: the anonymous lifetime #2 defined on the method body at 21:5...
   --> $DIR/regions-infer-paramd-indirect.rs:21:5
    |
-LL | /     fn set_f_bad(&mut self, b: Box<B>) {
-LL | |         self.f = b;
-LL | |
-LL | |
-LL | |
-LL | |
-LL | |     }
-   | |_____^
+LL |     fn set_f_bad(&mut self, b: Box<B>) {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...does not necessarily outlive the lifetime `'a` as defined on the impl at 16:6
   --> $DIR/regions-infer-paramd-indirect.rs:16:6
    |
index dc93d620ca637b454afe60af8e8b5db111251c8c..10ecb8d526292de9b6ecf0340bf5e3cb8b77e965 100644 (file)
@@ -5,9 +5,7 @@ LL | / fn bar<'a, 'b>()
 LL | |
 LL | |
 LL | |     where <() as Project<'a, 'b>>::Item : Eq
-LL | | {
-LL | | }
-   | |_^
+   | |____________________________________________^
    |
 note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 22:8...
   --> $DIR/regions-normalize-in-where-clause-list.rs:22:8
@@ -26,9 +24,7 @@ LL | / fn bar<'a, 'b>()
 LL | |
 LL | |
 LL | |     where <() as Project<'a, 'b>>::Item : Eq
-LL | | {
-LL | | }
-   | |_^
+   | |____________________________________________^
    = note: expected `Project<'a, 'b>`
               found `Project<'_, '_>`
 
@@ -39,9 +35,7 @@ LL | / fn bar<'a, 'b>()
 LL | |
 LL | |
 LL | |     where <() as Project<'a, 'b>>::Item : Eq
-LL | | {
-LL | | }
-   | |_^
+   | |____________________________________________^
    |
 note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 22:8...
   --> $DIR/regions-normalize-in-where-clause-list.rs:22:8
@@ -60,9 +54,7 @@ LL | / fn bar<'a, 'b>()
 LL | |
 LL | |
 LL | |     where <() as Project<'a, 'b>>::Item : Eq
-LL | | {
-LL | | }
-   | |_^
+   | |____________________________________________^
    = note: expected `Project<'a, 'b>`
               found `Project<'_, '_>`
 
index 60ac7c09f04145ec4784f7b7a75d4509941a1940..92d96a722d4e913e7e9ca0ae1691d1ac7837e35a 100644 (file)
@@ -14,10 +14,8 @@ LL | impl<'a> GetCtxt for HasCtxt<'a> {
 note: ...does not necessarily outlive the anonymous lifetime #1 defined on the method body at 16:5
   --> $DIR/regions-trait-1.rs:16:5
    |
-LL | /     fn get_ctxt(&self) -> &'a Ctxt {
-LL | |         self.c
-LL | |     }
-   | |_____^
+LL |     fn get_ctxt(&self) -> &'a Ctxt {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index f05f88e7d71eace9825dc8ea4ebafad59431d44d..7e2ec35241423c5d4dfd1ed55737d6402da3fbb8 100644 (file)
@@ -1,12 +1,10 @@
 error: `main` function is not allowed to be `#[track_caller]`
   --> $DIR/error-with-main.rs:1:1
    |
-LL |   #[track_caller]
-   |   ^^^^^^^^^^^^^^^
-LL | / fn main() {
-LL | |     panic!("{}: oh no", std::panic::Location::caller());
-LL | | }
-   | |_- `main` function is not allowed to be `#[track_caller]`
+LL | #[track_caller]
+   | ^^^^^^^^^^^^^^^
+LL | fn main() {
+   | --------- `main` function is not allowed to be `#[track_caller]`
 
 error: aborting due to previous error
 
index 1a1f3e0449136d118ab25bc1a3832c5a8104d902..454c98ff934374efc2091428556592ce078d875e 100644 (file)
@@ -1,12 +1,10 @@
 error: `start` is not allowed to be `#[track_caller]`
   --> $DIR/error-with-start.rs:4:1
    |
-LL |   #[track_caller]
-   |   ^^^^^^^^^^^^^^^
-LL | / fn start(_argc: isize, _argv: *const *const u8) -> isize {
-LL | |     panic!("{}: oh no", std::panic::Location::caller());
-LL | | }
-   | |_- `start` is not allowed to be `#[track_caller]`
+LL | #[track_caller]
+   | ^^^^^^^^^^^^^^^
+LL | fn start(_argc: isize, _argv: *const *const u8) -> isize {
+   | -------------------------------------------------------- `start` is not allowed to be `#[track_caller]`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/rfc-2294-if-let-guard/feature-gate.rs b/src/test/ui/rfc-2294-if-let-guard/feature-gate.rs
new file mode 100644 (file)
index 0000000..c0a9bbc
--- /dev/null
@@ -0,0 +1,85 @@
+// gate-test-if_let_guard
+
+use std::ops::Range;
+
+fn _if_let_guard() {
+    match () {
+        () if let 0 = 1 => {}
+        //~^ ERROR `if let` guard is not implemented
+        //~| ERROR `let` expressions are not supported here
+
+        () if (let 0 = 1) => {}
+        //~^ ERROR `let` expressions in this position are experimental
+        //~| ERROR `let` expressions are not supported here
+
+        () if (((let 0 = 1))) => {}
+        //~^ ERROR `let` expressions in this position are experimental
+        //~| ERROR `let` expressions are not supported here
+
+        () if true && let 0 = 1 => {}
+        //~^ ERROR `let` expressions in this position are experimental
+        //~| ERROR `let` expressions are not supported here
+
+        () if let 0 = 1 && true => {}
+        //~^ ERROR `let` expressions in this position are experimental
+        //~| ERROR `let` expressions are not supported here
+
+        () if (let 0 = 1) && true => {}
+        //~^ ERROR `let` expressions in this position are experimental
+        //~| ERROR `let` expressions are not supported here
+
+        () if true && (let 0 = 1) => {}
+        //~^ ERROR `let` expressions in this position are experimental
+        //~| ERROR `let` expressions are not supported here
+
+        () if (let 0 = 1) && (let 0 = 1) => {}
+        //~^ ERROR `let` expressions in this position are experimental
+        //~| ERROR `let` expressions in this position are experimental
+        //~| ERROR `let` expressions are not supported here
+        //~| ERROR `let` expressions are not supported here
+
+        () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
+        //~^ ERROR `let` expressions in this position are experimental
+        //~| ERROR `let` expressions in this position are experimental
+        //~| ERROR `let` expressions in this position are experimental
+        //~| ERROR `let` expressions in this position are experimental
+        //~| ERROR `let` expressions in this position are experimental
+        //~| ERROR `let` expressions are not supported here
+        //~| ERROR `let` expressions are not supported here
+        //~| ERROR `let` expressions are not supported here
+        //~| ERROR `let` expressions are not supported here
+        //~| ERROR `let` expressions are not supported here
+
+        () if let Range { start: _, end: _ } = (true..true) && false => {}
+        //~^ ERROR `let` expressions in this position are experimental
+        //~| ERROR `let` expressions are not supported here
+        _ => {}
+    }
+}
+
+fn _macros() {
+    macro_rules! use_expr {
+        ($e:expr) => {
+            match () {
+                () if $e => {}
+                _ => {}
+            }
+        }
+    }
+    use_expr!((let 0 = 1 && 0 == 0));
+    //~^ ERROR `let` expressions in this position are experimental
+    //~| ERROR `let` expressions are not supported here
+    use_expr!((let 0 = 1));
+    //~^ ERROR `let` expressions in this position are experimental
+    //~| ERROR `let` expressions are not supported here
+    match () {
+        #[cfg(FALSE)]
+        () if let 0 = 1 => {}
+        //~^ ERROR `if let` guard is not implemented
+        _ => {}
+    }
+    use_expr!(let 0 = 1);
+    //~^ ERROR no rules expected the token `let`
+}
+
+fn main() {}
diff --git a/src/test/ui/rfc-2294-if-let-guard/feature-gate.stderr b/src/test/ui/rfc-2294-if-let-guard/feature-gate.stderr
new file mode 100644 (file)
index 0000000..5c7f819
--- /dev/null
@@ -0,0 +1,327 @@
+error: no rules expected the token `let`
+  --> $DIR/feature-gate.rs:81:15
+   |
+LL |     macro_rules! use_expr {
+   |     --------------------- when calling this macro
+...
+LL |     use_expr!(let 0 = 1);
+   |               ^^^ no rules expected this token in macro call
+
+error[E0658]: `if let` guard is not implemented
+  --> $DIR/feature-gate.rs:7:12
+   |
+LL |         () if let 0 = 1 => {}
+   |            ^^^^^^^^^^^^
+   |
+   = note: see issue #51114 <https://github.com/rust-lang/rust/issues/51114> for more information
+   = help: add `#![feature(if_let_guard)]` to the crate attributes to enable
+
+error[E0658]: `if let` guard is not implemented
+  --> $DIR/feature-gate.rs:77:12
+   |
+LL |         () if let 0 = 1 => {}
+   |            ^^^^^^^^^^^^
+   |
+   = note: see issue #51114 <https://github.com/rust-lang/rust/issues/51114> for more information
+   = help: add `#![feature(if_let_guard)]` to the crate attributes to enable
+
+error[E0658]: `let` expressions in this position are experimental
+  --> $DIR/feature-gate.rs:11:16
+   |
+LL |         () if (let 0 = 1) => {}
+   |                ^^^^^^^^^
+   |
+   = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
+   = help: add `#![feature(let_chains)]` to the crate attributes to enable
+
+error[E0658]: `let` expressions in this position are experimental
+  --> $DIR/feature-gate.rs:15:18
+   |
+LL |         () if (((let 0 = 1))) => {}
+   |                  ^^^^^^^^^
+   |
+   = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
+   = help: add `#![feature(let_chains)]` to the crate attributes to enable
+
+error[E0658]: `let` expressions in this position are experimental
+  --> $DIR/feature-gate.rs:19:23
+   |
+LL |         () if true && let 0 = 1 => {}
+   |                       ^^^^^^^^^
+   |
+   = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
+   = help: add `#![feature(let_chains)]` to the crate attributes to enable
+
+error[E0658]: `let` expressions in this position are experimental
+  --> $DIR/feature-gate.rs:23:15
+   |
+LL |         () if let 0 = 1 && true => {}
+   |               ^^^^^^^^^
+   |
+   = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
+   = help: add `#![feature(let_chains)]` to the crate attributes to enable
+
+error[E0658]: `let` expressions in this position are experimental
+  --> $DIR/feature-gate.rs:27:16
+   |
+LL |         () if (let 0 = 1) && true => {}
+   |                ^^^^^^^^^
+   |
+   = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
+   = help: add `#![feature(let_chains)]` to the crate attributes to enable
+
+error[E0658]: `let` expressions in this position are experimental
+  --> $DIR/feature-gate.rs:31:24
+   |
+LL |         () if true && (let 0 = 1) => {}
+   |                        ^^^^^^^^^
+   |
+   = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
+   = help: add `#![feature(let_chains)]` to the crate attributes to enable
+
+error[E0658]: `let` expressions in this position are experimental
+  --> $DIR/feature-gate.rs:35:16
+   |
+LL |         () if (let 0 = 1) && (let 0 = 1) => {}
+   |                ^^^^^^^^^
+   |
+   = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
+   = help: add `#![feature(let_chains)]` to the crate attributes to enable
+
+error[E0658]: `let` expressions in this position are experimental
+  --> $DIR/feature-gate.rs:35:31
+   |
+LL |         () if (let 0 = 1) && (let 0 = 1) => {}
+   |                               ^^^^^^^^^
+   |
+   = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
+   = help: add `#![feature(let_chains)]` to the crate attributes to enable
+
+error[E0658]: `let` expressions in this position are experimental
+  --> $DIR/feature-gate.rs:41:15
+   |
+LL |         () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
+   |               ^^^^^^^^^
+   |
+   = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
+   = help: add `#![feature(let_chains)]` to the crate attributes to enable
+
+error[E0658]: `let` expressions in this position are experimental
+  --> $DIR/feature-gate.rs:41:28
+   |
+LL |         () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
+   |                            ^^^^^^^^^
+   |
+   = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
+   = help: add `#![feature(let_chains)]` to the crate attributes to enable
+
+error[E0658]: `let` expressions in this position are experimental
+  --> $DIR/feature-gate.rs:41:42
+   |
+LL |         () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
+   |                                          ^^^^^^^^^
+   |
+   = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
+   = help: add `#![feature(let_chains)]` to the crate attributes to enable
+
+error[E0658]: `let` expressions in this position are experimental
+  --> $DIR/feature-gate.rs:41:55
+   |
+LL |         () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
+   |                                                       ^^^^^^^^^
+   |
+   = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
+   = help: add `#![feature(let_chains)]` to the crate attributes to enable
+
+error[E0658]: `let` expressions in this position are experimental
+  --> $DIR/feature-gate.rs:41:68
+   |
+LL |         () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
+   |                                                                    ^^^^^^^^^
+   |
+   = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
+   = help: add `#![feature(let_chains)]` to the crate attributes to enable
+
+error[E0658]: `let` expressions in this position are experimental
+  --> $DIR/feature-gate.rs:53:15
+   |
+LL |         () if let Range { start: _, end: _ } = (true..true) && false => {}
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
+   = help: add `#![feature(let_chains)]` to the crate attributes to enable
+
+error[E0658]: `let` expressions in this position are experimental
+  --> $DIR/feature-gate.rs:69:16
+   |
+LL |     use_expr!((let 0 = 1 && 0 == 0));
+   |                ^^^^^^^^^
+   |
+   = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
+   = help: add `#![feature(let_chains)]` to the crate attributes to enable
+
+error[E0658]: `let` expressions in this position are experimental
+  --> $DIR/feature-gate.rs:72:16
+   |
+LL |     use_expr!((let 0 = 1));
+   |                ^^^^^^^^^
+   |
+   = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
+   = help: add `#![feature(let_chains)]` to the crate attributes to enable
+
+error: `let` expressions are not supported here
+  --> $DIR/feature-gate.rs:7:15
+   |
+LL |         () if let 0 = 1 => {}
+   |               ^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: as well as when nested within `&&` and parenthesis in those conditions
+
+error: `let` expressions are not supported here
+  --> $DIR/feature-gate.rs:11:16
+   |
+LL |         () if (let 0 = 1) => {}
+   |                ^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: as well as when nested within `&&` and parenthesis in those conditions
+
+error: `let` expressions are not supported here
+  --> $DIR/feature-gate.rs:15:18
+   |
+LL |         () if (((let 0 = 1))) => {}
+   |                  ^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: as well as when nested within `&&` and parenthesis in those conditions
+
+error: `let` expressions are not supported here
+  --> $DIR/feature-gate.rs:19:23
+   |
+LL |         () if true && let 0 = 1 => {}
+   |                       ^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: as well as when nested within `&&` and parenthesis in those conditions
+
+error: `let` expressions are not supported here
+  --> $DIR/feature-gate.rs:23:15
+   |
+LL |         () if let 0 = 1 && true => {}
+   |               ^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: as well as when nested within `&&` and parenthesis in those conditions
+
+error: `let` expressions are not supported here
+  --> $DIR/feature-gate.rs:27:16
+   |
+LL |         () if (let 0 = 1) && true => {}
+   |                ^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: as well as when nested within `&&` and parenthesis in those conditions
+
+error: `let` expressions are not supported here
+  --> $DIR/feature-gate.rs:31:24
+   |
+LL |         () if true && (let 0 = 1) => {}
+   |                        ^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: as well as when nested within `&&` and parenthesis in those conditions
+
+error: `let` expressions are not supported here
+  --> $DIR/feature-gate.rs:35:16
+   |
+LL |         () if (let 0 = 1) && (let 0 = 1) => {}
+   |                ^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: as well as when nested within `&&` and parenthesis in those conditions
+
+error: `let` expressions are not supported here
+  --> $DIR/feature-gate.rs:35:31
+   |
+LL |         () if (let 0 = 1) && (let 0 = 1) => {}
+   |                               ^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: as well as when nested within `&&` and parenthesis in those conditions
+
+error: `let` expressions are not supported here
+  --> $DIR/feature-gate.rs:41:15
+   |
+LL |         () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
+   |               ^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: as well as when nested within `&&` and parenthesis in those conditions
+
+error: `let` expressions are not supported here
+  --> $DIR/feature-gate.rs:41:28
+   |
+LL |         () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
+   |                            ^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: as well as when nested within `&&` and parenthesis in those conditions
+
+error: `let` expressions are not supported here
+  --> $DIR/feature-gate.rs:41:42
+   |
+LL |         () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
+   |                                          ^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: as well as when nested within `&&` and parenthesis in those conditions
+
+error: `let` expressions are not supported here
+  --> $DIR/feature-gate.rs:41:55
+   |
+LL |         () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
+   |                                                       ^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: as well as when nested within `&&` and parenthesis in those conditions
+
+error: `let` expressions are not supported here
+  --> $DIR/feature-gate.rs:41:68
+   |
+LL |         () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
+   |                                                                    ^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: as well as when nested within `&&` and parenthesis in those conditions
+
+error: `let` expressions are not supported here
+  --> $DIR/feature-gate.rs:53:15
+   |
+LL |         () if let Range { start: _, end: _ } = (true..true) && false => {}
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: as well as when nested within `&&` and parenthesis in those conditions
+
+error: `let` expressions are not supported here
+  --> $DIR/feature-gate.rs:69:16
+   |
+LL |     use_expr!((let 0 = 1 && 0 == 0));
+   |                ^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: as well as when nested within `&&` and parenthesis in those conditions
+
+error: `let` expressions are not supported here
+  --> $DIR/feature-gate.rs:72:16
+   |
+LL |     use_expr!((let 0 = 1));
+   |                ^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: as well as when nested within `&&` and parenthesis in those conditions
+
+error: aborting due to 36 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
index 7fe3a9fd8522cf4cd4ace5fecf173b7c6a04e2a7..b50dd03a861385ae2b576ca833645e6b2519f614 100644 (file)
@@ -1,4 +1,4 @@
-error[E0723]: can only call other `const fn` within a `const fn`, but `const non_const` is not stable as `const fn`
+error[E0723]: can only call other `const fn` within a `const fn`, but `non_const` is not stable as `const fn`
   --> $DIR/const-check-fns-in-const-impl.rs:12:16
    |
 LL |     fn foo() { non_const() }
index e4f4d4262b64d54e21adcf2375edef1f54a362f2..3994bd97c308e125dd0ea73cc72ed3b950bdd289 100644 (file)
@@ -2,7 +2,7 @@ error: fatal error triggered by #[rustc_error]
   --> $DIR/feature-gate.rs:16:1
    |
 LL | fn main() {}
-   | ^^^^^^^^^^^^
+   | ^^^^^^^^^
 
 error: aborting due to previous error
 
index d1ab99e33e99254d62b174e84c8364b28d997367..4c630d33c55163b7eca430c391c21e601613f246 100644 (file)
@@ -2,7 +2,7 @@ error: fatal error triggered by #[rustc_error]
   --> $DIR/feature-gate.rs:14:1
    |
 LL | fn main() {}
-   | ^^^^^^^^^^^^
+   | ^^^^^^^^^
 
 error: aborting due to previous error
 
index 1ecff62955b99b98f2677cc1cb90897bba9b8e8b..e7002a1a045cc2545470c4152c00cdc2dbdc9591 100644 (file)
@@ -10,7 +10,7 @@ LL | |     }
    = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
    = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
-error[E0723]: can only call other `const fn` within a `const fn`, but `const <Int as std::ops::Add>::add` is not stable as `const fn`
+error[E0723]: can only call other `const fn` within a `const fn`, but `<Int as std::ops::Add>::add` is not stable as `const fn`
   --> $DIR/stability.rs:32:5
    |
 LL |     Int(1i32) + Int(2i32)
index fabbfd5c70bb901b9ed0c4cc81e68e698d244c0d..623fd585accb621fed2f16262ddbc8f5ecd6570c 100644 (file)
@@ -1,14 +1,8 @@
 error: fatal error triggered by #[rustc_error]
   --> $DIR/feature-gate.rs:21:1
    |
-LL | / fn main() {
-LL | |     let y = Foo { x: 1 };
-LL | |     match y {
-LL | |         FOO => { }
-LL | |         _ => { }
-LL | |     }
-LL | | }
-   | |_^
+LL | fn main() {
+   | ^^^^^^^^^
 
 error: aborting due to previous error
 
index 5be092204d7c0c5e0ee23ff037c7c91b94272dd7..7dd65701f125c135af39103b7484f6104a77dd43 100644 (file)
@@ -23,7 +23,8 @@ fn close_stdout() {
 #[cfg(windows)]
 fn main() {
     close_stdout();
-    println!("hello world");
+    println!("hello");
+    println!("world");
 }
 
 #[cfg(not(windows))]
index 41a036958bfeab27fbda9acb11d285694a098e9f..53b8fddcf31e0b64001f1262efc953d621b252b0 100644 (file)
@@ -30,5 +30,6 @@ fn close_stdout() {
 
 fn main() {
     close_stdout();
-    println!("hello world");
+    println!("hello");
+    println!("world");
 }
index 413890f436d0f07cda2f0ef0a70d33574c8ff9df..18917fd2556cf08aea3ff4994a4ab5b891c55bed 100644 (file)
@@ -4,7 +4,7 @@ error[E0658]: `#[target_feature(..)]` can only be applied to `unsafe` functions
 LL | #[target_feature(enable = "sse2")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 LL | fn foo() {}
-   | ----------- not an `unsafe` function
+   | -------- not an `unsafe` function
    |
    = note: see issue #69098 <https://github.com/rust-lang/rust/issues/69098> for more information
    = help: add `#![feature(target_feature_11)]` to the crate attributes to enable
index 3c56e0fc5c6e34765b5f5c47c6a160889974d820..07d6e09005906c19cbe33076d7c6193c1ade7337 100644 (file)
@@ -5,7 +5,7 @@ LL |     #[target_feature(enable = "sse2")]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot be applied to safe trait method
 LL |
 LL |     fn foo(&self) {}
-   |     ---------------- not an `unsafe` function
+   |     ------------- not an `unsafe` function
 
 error: aborting due to previous error
 
index 7dfc44492959473f8d5f9c9c61afdad183a828ce..de27e9b8f086d753a0fdd54caa691d929a723d42 100644 (file)
@@ -1,10 +1,8 @@
 error: fatal error triggered by #[rustc_error]
   --> $DIR/rustc-error.rs:4:1
    |
-LL | / fn main() {
-LL | |
-LL | | }
-   | |_^
+LL | fn main() {
+   | ^^^^^^^^^
 
 error: aborting due to previous error
 
index 6adf16de4621aa690ac8e7c5ed2186ff0b6ea128..81efd46cc7fa50aabda82aea8eb66334c60f61ab 100644 (file)
@@ -2,10 +2,10 @@ error[E0592]: duplicate definitions with name `f`
   --> $DIR/specialization-overlap-hygiene.rs:13:4
    |
 LL |     fn f() {}
-   |     --------- other definition for `f`
+   |     ------ other definition for `f`
 ...
 LL |    fn f() {}
-   |    ^^^^^^^^^ duplicate definitions for `f`
+   |    ^^^^^^ duplicate definitions for `f`
 
 error: aborting due to previous error
 
index f81c45e2f8da032871c567649d0d5c9a79259dcf..6e4cee18c1603998b680d2df41642188accb15ef 100644 (file)
@@ -2,7 +2,7 @@ error[E0618]: expected function, found `bool`
   --> $DIR/issue-51055-missing-semicolon-between-call-and-tuple.rs:4:5
    |
 LL |   fn vindictive() -> bool { true }
-   |   -------------------------------- `vindictive` defined here returns `bool`
+   |   ----------------------- `vindictive` defined here returns `bool`
 ...
 LL |       vindictive()
    |       -^^^^^^^^^^^- help: try adding a semicolon: `;`
index 2072b00f7b2cb3f3512cba02809c1166e7dcf4de..1bfcdab5d860d34cbba94812f9a1c225200bbddd 100644 (file)
@@ -32,10 +32,7 @@ LL | / fn bar<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
 LL | |
 LL | | where
 LL | |     G: Get<T>
-...  |
-LL | |     }
-LL | | }
-   | |_^
+   | |_____________^
 
 error[E0311]: the parameter type `G` may not live long enough
   --> $DIR/missing-lifetimes-in-signature.rs:47:45
@@ -50,10 +47,7 @@ LL | / fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
 LL | |
 LL | | where
 LL | |     G: Get<T>
-...  |
-LL | |     }
-LL | | }
-   | |_^
+   | |_____________^
 
 error[E0311]: the parameter type `G` may not live long enough
   --> $DIR/missing-lifetimes-in-signature.rs:59:58
@@ -64,13 +58,8 @@ LL |     fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
 note: the parameter type `G` must be valid for the anonymous lifetime #1 defined on the method body at 59:5...
   --> $DIR/missing-lifetimes-in-signature.rs:59:5
    |
-LL | /     fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
-LL | |
-LL | |         move || {
-LL | |             *dest = g.get();
-LL | |         }
-LL | |     }
-   | |_____^
+LL |     fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0311]: the parameter type `G` may not live long enough
   --> $DIR/missing-lifetimes-in-signature.rs:68:45
@@ -85,10 +74,7 @@ LL | / fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
 LL | |
 LL | | where
 LL | |     G: Get<T>
-...  |
-LL | |     }
-LL | | }
-   | |_^
+   | |_____________^
 
 error[E0621]: explicit lifetime required in the type of `dest`
   --> $DIR/missing-lifetimes-in-signature.rs:73:5
index d7051515f11029c04401888c11f9407e529b5a60..cec01fefca8bda94e429c92001f7871985ff3c34 100644 (file)
@@ -40,10 +40,7 @@ LL | / fn bar<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
 LL | |
 LL | | where
 LL | |     G: Get<T>
-...  |
-LL | |     }
-LL | | }
-   | |_^
+   | |_____________^
 note: ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:30:5: 32:6 g:G, dest:&mut T]` will meet its required lifetime bounds
   --> $DIR/missing-lifetimes-in-signature.rs:25:37
    |
@@ -67,10 +64,7 @@ LL | / fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
 LL | |
 LL | | where
 LL | |     G: Get<T>
-...  |
-LL | |     }
-LL | | }
-   | |_^
+   | |_____________^
 note: ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:52:5: 54:6 g:G, dest:&mut T]` will meet its required lifetime bounds
   --> $DIR/missing-lifetimes-in-signature.rs:47:45
    |
@@ -90,13 +84,8 @@ LL |     fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
 note: the parameter type `G` must be valid for the anonymous lifetime #1 defined on the method body at 59:5...
   --> $DIR/missing-lifetimes-in-signature.rs:59:5
    |
-LL | /     fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
-LL | |
-LL | |         move || {
-LL | |             *dest = g.get();
-LL | |         }
-LL | |     }
-   | |_____^
+LL |     fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:61:9: 63:10 g:G, dest:&mut T]` will meet its required lifetime bounds
   --> $DIR/missing-lifetimes-in-signature.rs:59:58
    |
index f3995f118d3e9c8862be0513f02380b46c556880..3d629afb9a610854002609672e0b6352398acf2c 100644 (file)
@@ -29,7 +29,7 @@ LL | #[target_feature(enable = "sse2")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 ...
 LL | fn bar() {}
-   | ----------- not an `unsafe` function
+   | -------- not an `unsafe` function
    |
    = note: see issue #69098 <https://github.com/rust-lang/rust/issues/69098> for more information
    = help: add `#![feature(target_feature_11)]` to the crate attributes to enable
@@ -113,7 +113,7 @@ LL |     #[target_feature(enable = "sse2")]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 ...
 LL |     fn foo() {}
-   |     ----------- not an `unsafe` function
+   |     -------- not an `unsafe` function
    |
    = note: see issue #69098 <https://github.com/rust-lang/rust/issues/69098> for more information
    = help: add `#![feature(target_feature_11)]` to the crate attributes to enable
index 2570db0212aa107e031b5e762070323933e93c9c..d10e58629cce73d2ba83e4a1de3df6a41d1ccb87 100644 (file)
@@ -2,10 +2,10 @@ error[E0592]: duplicate definitions with name `test`
   --> $DIR/trait-object-auto-dedup-in-impl.rs:14:5
    |
 LL |     fn test(&self) { println!("one"); }
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ duplicate definitions for `test`
+   |     ^^^^^^^^^^^^^^ duplicate definitions for `test`
 ...
 LL |     fn test(&self) { println!("two"); }
-   |     ----------------------------------- other definition for `test`
+   |     -------------- other definition for `test`
 
 error: aborting due to previous error
 
index 87ed997ec59b14b6a77471c705cc87d3fd4646c8..eaa716bc71c3e4ebb17b379c942ecaa6466c5f9c 100644 (file)
@@ -1,18 +1,14 @@
 error: concrete type differs from previous defining opaque type use
   --> $DIR/different_defining_uses.rs:12:1
    |
-LL | / fn bar() -> Foo {
-LL | |     42i32
-LL | | }
-   | |_^ expected `&'static str`, got `i32`
+LL | fn bar() -> Foo {
+   | ^^^^^^^^^^^^^^^ expected `&'static str`, got `i32`
    |
 note: previous use here
   --> $DIR/different_defining_uses.rs:8:1
    |
-LL | / fn foo() -> Foo {
-LL | |     ""
-LL | | }
-   | |_^
+LL | fn foo() -> Foo {
+   | ^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index 5be656e8f446169c989a181a4028562ce7bf66c3..9a587e4f06ee818f2981b6361652eb1d80c4a40e 100644 (file)
@@ -1,34 +1,26 @@
 error: concrete type differs from previous defining opaque type use
   --> $DIR/different_defining_uses_never_type.rs:12:1
    |
-LL | / fn bar() -> Foo {
-LL | |     panic!()
-LL | | }
-   | |_^ expected `&'static str`, got `()`
+LL | fn bar() -> Foo {
+   | ^^^^^^^^^^^^^^^ expected `&'static str`, got `()`
    |
 note: previous use here
   --> $DIR/different_defining_uses_never_type.rs:8:1
    |
-LL | / fn foo() -> Foo {
-LL | |     ""
-LL | | }
-   | |_^
+LL | fn foo() -> Foo {
+   | ^^^^^^^^^^^^^^^
 
 error: concrete type differs from previous defining opaque type use
   --> $DIR/different_defining_uses_never_type.rs:16:1
    |
-LL | / fn boo() -> Foo {
-LL | |     loop {}
-LL | | }
-   | |_^ expected `&'static str`, got `()`
+LL | fn boo() -> Foo {
+   | ^^^^^^^^^^^^^^^ expected `&'static str`, got `()`
    |
 note: previous use here
   --> $DIR/different_defining_uses_never_type.rs:8:1
    |
-LL | / fn foo() -> Foo {
-LL | |     ""
-LL | | }
-   | |_^
+LL | fn foo() -> Foo {
+   | ^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
index 4bcd2e1cb12908a982674e1efbdc53fe8c0af80b..f8a058170e37f3de8d039ee6d78257802a1dd822 100644 (file)
@@ -1,18 +1,14 @@
 error: concrete type differs from previous defining opaque type use
   --> $DIR/generic_different_defining_uses.rs:11:1
    |
-LL | / fn my_iter2<T>(t: T) -> MyIter<T> {
-LL | |     Some(t).into_iter()
-LL | | }
-   | |_^ expected `std::iter::Once<T>`, got `std::option::IntoIter<T>`
+LL | fn my_iter2<T>(t: T) -> MyIter<T> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `std::iter::Once<T>`, got `std::option::IntoIter<T>`
    |
 note: previous use here
   --> $DIR/generic_different_defining_uses.rs:7:1
    |
-LL | / fn my_iter<T>(t: T) -> MyIter<T> {
-LL | |     std::iter::once(t)
-LL | | }
-   | |_^
+LL | fn my_iter<T>(t: T) -> MyIter<T> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index 8170c671f68cdaee02bf427b9d801ff8f2e90540..7900da47ca23db28590a9bf84e48506520674e81 100644 (file)
@@ -1,19 +1,14 @@
 error: concrete type differs from previous defining opaque type use
   --> $DIR/generic_duplicate_param_use2.rs:14:1
    |
-LL | / fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> {
-LL | |
-LL | |     t
-LL | | }
-   | |_^ expected `U`, got `T`
+LL | fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `U`, got `T`
    |
 note: previous use here
   --> $DIR/generic_duplicate_param_use2.rs:10:1
    |
-LL | / fn one<T: Debug>(t: T) -> Two<T, T> {
-LL | |     t
-LL | | }
-   | |_^
+LL | fn one<T: Debug>(t: T) -> Two<T, T> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index 86dd33684005b0bd7f70ab48cee828bd0dcbf661..ac5f7947d51e911f105ef433b58e5a7ffd72457a 100644 (file)
@@ -1,19 +1,14 @@
 error: concrete type differs from previous defining opaque type use
   --> $DIR/generic_duplicate_param_use3.rs:14:1
    |
-LL | / fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> {
-LL | |
-LL | |     t
-LL | | }
-   | |_^ expected `U`, got `T`
+LL | fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `U`, got `T`
    |
 note: previous use here
   --> $DIR/generic_duplicate_param_use3.rs:10:1
    |
-LL | / fn one<T: Debug>(t: T) -> Two<T, T> {
-LL | |     t
-LL | | }
-   | |_^
+LL | fn one<T: Debug>(t: T) -> Two<T, T> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index 589ea749319d1faaec32f386a3070ee67c0df8dc..1ddbc0c8d6a8e25db73f5fd5a40bff4e595ad760 100644 (file)
@@ -1,19 +1,14 @@
 error: concrete type differs from previous defining opaque type use
   --> $DIR/generic_duplicate_param_use5.rs:14:1
    |
-LL | / fn three<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
-LL | |
-LL | |     (u, t)
-LL | | }
-   | |_^ expected `(T, U)`, got `(U, T)`
+LL | fn three<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(T, U)`, got `(U, T)`
    |
 note: previous use here
   --> $DIR/generic_duplicate_param_use5.rs:10:1
    |
-LL | / fn two<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
-LL | |     (t, u)
-LL | | }
-   | |_^
+LL | fn two<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index 7e81d362661bc9ac1f08901fd719a7ea232a22d1..ebd07b7c300f1928c31de04650016a53571e079e 100644 (file)
@@ -1,19 +1,14 @@
 error: concrete type differs from previous defining opaque type use
   --> $DIR/generic_duplicate_param_use6.rs:14:1
    |
-LL | / fn three<T: Copy + Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
-LL | |
-LL | |     (u, t)
-LL | | }
-   | |_^ expected `(T, T)`, got `(U, T)`
+LL | fn three<T: Copy + Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(T, T)`, got `(U, T)`
    |
 note: previous use here
   --> $DIR/generic_duplicate_param_use6.rs:10:1
    |
-LL | / fn two<T: Copy + Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
-LL | |     (t, t)
-LL | | }
-   | |_^
+LL | fn two<T: Copy + Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index 8f4cf4c60847734e4b4f7947d2196cc1f5364e21..4778ee5155cf058c17fa7df52fad2fd1e1a478cf 100644 (file)
@@ -1,19 +1,14 @@
 error: concrete type differs from previous defining opaque type use
   --> $DIR/generic_duplicate_param_use8.rs:13:1
    |
-LL | / fn three<T: Debug, U: Debug>(_: T, u: U) -> Two<T, U> {
-LL | |
-LL | |     (u, 4u32)
-LL | | }
-   | |_^ expected `(T, u32)`, got `(U, u32)`
+LL | fn three<T: Debug, U: Debug>(_: T, u: U) -> Two<T, U> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(T, u32)`, got `(U, u32)`
    |
 note: previous use here
   --> $DIR/generic_duplicate_param_use8.rs:9:1
    |
-LL | / fn two<T: Debug, U: Debug>(t: T, _: U) -> Two<T, U> {
-LL | |     (t, 4u32)
-LL | | }
-   | |_^
+LL | fn two<T: Debug, U: Debug>(t: T, _: U) -> Two<T, U> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index 4d0b03ba5ed65f416e7dc2d98efc2e1cd7b3a827..247b042f61e058af52199e2ae069a4873d483da5 100644 (file)
@@ -1,18 +1,14 @@
 error: concrete type differs from previous defining opaque type use
   --> $DIR/generic_duplicate_param_use9.rs:18:1
    |
-LL | / fn three<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
-LL | |     (t, u, 42)
-LL | | }
-   | |_^ expected `(A, B, <A as Foo>::Bar)`, got `(A, B, i32)`
+LL | fn three<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(A, B, <A as Foo>::Bar)`, got `(A, B, i32)`
    |
 note: previous use here
   --> $DIR/generic_duplicate_param_use9.rs:14:1
    |
-LL | / fn two<T: Debug + Foo, U: Debug>(t: T, u: U) -> Two<T, U> {
-LL | |     (t, u, T::BAR)
-LL | | }
-   | |_^
+LL | fn two<T: Debug + Foo, U: Debug>(t: T, u: U) -> Two<T, U> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index 1333b4c63d18ccb16a1028be06286476fdeb4c4b..13069126bab1b88dfaa5166968c2c54bd9fefe6e 100644 (file)
@@ -8,7 +8,7 @@ note: previous use here
   --> $DIR/issue-52843-closure-constrain.rs:9:5
    |
 LL |     fn _unused() -> Opaque { String::new() }
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index cce861b76c95e8b717b276b790c8b47c0d5dda8f..9ce07a879f058532f6dcc16f1a9082f8369e0e50 100644 (file)
@@ -1,18 +1,14 @@
 error: concrete type differs from previous defining opaque type use
   --> $DIR/not_a_defining_use.rs:29:1
    |
-LL | / fn four<T: Debug, U: Bar>(t: T) -> Two<T, U> {
-LL | |     (t, <U as Bar>::FOO)
-LL | | }
-   | |_^ expected `(T, i8)`, got `(T, <U as Bar>::Blub)`
+LL | fn four<T: Debug, U: Bar>(t: T) -> Two<T, U> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(T, i8)`, got `(T, <U as Bar>::Blub)`
    |
 note: previous use here
   --> $DIR/not_a_defining_use.rs:9:1
    |
-LL | / fn two<T: Debug>(t: T) -> Two<T, u32> {
-LL | |     (t, 4i8)
-LL | | }
-   | |_^
+LL | fn two<T: Debug>(t: T) -> Two<T, u32> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index d1232ad3f320c8d80701d1fde22a7178ad8148e8..d7c4817357190b9cc92529d88d3961c797425cfe 100644 (file)
@@ -37,7 +37,7 @@ note: the anonymous lifetime #1 defined on the method body at 37:5...
   --> $DIR/ufcs-explicit-self-bad.rs:37:5
    |
 LL |     fn dummy2(self: &Bar<T>) {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...does not necessarily outlive the lifetime `'a` as defined on the impl at 35:6
   --> $DIR/ufcs-explicit-self-bad.rs:35:6
    |
@@ -61,7 +61,7 @@ note: ...does not necessarily outlive the anonymous lifetime #1 defined on the m
   --> $DIR/ufcs-explicit-self-bad.rs:37:5
    |
 LL |     fn dummy2(self: &Bar<T>) {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0308]: mismatched `self` parameter type
   --> $DIR/ufcs-explicit-self-bad.rs:39:21
@@ -75,7 +75,7 @@ note: the anonymous lifetime #2 defined on the method body at 39:5...
   --> $DIR/ufcs-explicit-self-bad.rs:39:5
    |
 LL |     fn dummy3(self: &&Bar<T>) {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...does not necessarily outlive the lifetime `'a` as defined on the impl at 35:6
   --> $DIR/ufcs-explicit-self-bad.rs:35:6
    |
@@ -99,7 +99,7 @@ note: ...does not necessarily outlive the anonymous lifetime #2 defined on the m
   --> $DIR/ufcs-explicit-self-bad.rs:39:5
    |
 LL |     fn dummy3(self: &&Bar<T>) {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 7 previous errors
 
index 86834f49407fc74ad8f1d5ce1b76a8ee5a485a22..a0fbbafe25ffbb88e4cb1c0478f061561b605fad 100644 (file)
@@ -7,7 +7,7 @@
 // closure.  As far as I can tell, coding up a recursive closure
 // requires the good ol' [Y Combinator].
 //
-// [Y Combinator]: http://en.wikipedia.org/wiki/Fixed-point_combinator#Y_combinator
+// [Y Combinator]: https://en.wikipedia.org/wiki/Fixed-point_combinator#Y_combinator
 
 struct YCombinator<F,A,R> {
     func: F,
index 906b543e421229e20a3f67af6201b2dd4118193f..13f9507d8db91ad7f1695480e17b9f5d9332e6dd 100644 (file)
@@ -5,7 +5,7 @@ LL |         let y = *x;
    |                 -- value moved here
 LL |         drop_unsized(y);
 LL |         println!("{}", &x);
-   |                        ^^ value borrowed here after partial move
+   |                        ^^ value borrowed here after move
    |
    = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait
 
@@ -27,7 +27,7 @@ LL |         let y = *x;
    |                 -- value moved here
 LL |         y.foo();
 LL |         println!("{}", &x);
-   |                        ^^ value borrowed here after partial move
+   |                        ^^ value borrowed here after move
    |
    = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait
 
index 49b2031c6b9d969a12b82b603d77b3629920697c..5b29314ad55a4ab5490c9ae900b57d5456bee7a7 100644 (file)
@@ -14,7 +14,7 @@ error[E0382]: use of moved value: `x`
 LL |         let _y = *x;
    |                  -- value moved here
 LL |         drop_unsized(x);
-   |                      ^ value used here after partial move
+   |                      ^ value used here after move
    |
    = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait
 
@@ -50,7 +50,7 @@ error[E0382]: use of moved value: `x`
 LL |         let _y = *x;
    |                  -- value moved here
 LL |         x.foo();
-   |         ^ value used here after partial move
+   |         ^ value used here after move
    |
    = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait
 
index 269ab8042c070e0ac0393a050127eee586d94a5c..b65163a3bc9f54fd3c60149b688e7eff8fea8666 100644 (file)
@@ -11,7 +11,7 @@ struct Test {
     packages: &'static [&'static str],
 }
 
-const TEST_REPOS: &'static [Test] = &[
+const TEST_REPOS: &[Test] = &[
     Test {
         name: "iron",
         repo: "https://github.com/iron/iron",
@@ -53,9 +53,9 @@ struct Test {
 
 fn main() {
     let args = env::args().collect::<Vec<_>>();
-    let ref cargo = args[1];
+    let cargo = &args[1];
     let out_dir = Path::new(&args[2]);
-    let ref cargo = Path::new(cargo);
+    let cargo = &Path::new(cargo);
 
     for test in TEST_REPOS.iter().rev() {
         test_repo(cargo, out_dir, test);
@@ -77,7 +77,7 @@ fn clone_repo(test: &Test, out_dir: &Path) -> PathBuf {
     let out_dir = out_dir.join(test.name);
 
     if !out_dir.join(".git").is_dir() {
-        let status = Command::new("git").arg("init").arg(&out_dir).status().expect("");
+        let status = Command::new("git").arg("init").arg(&out_dir).status().unwrap();
         assert!(status.success());
     }
 
@@ -92,7 +92,7 @@ fn clone_repo(test: &Test, out_dir: &Path) -> PathBuf {
                 .arg(&format!("--depth={}", depth))
                 .current_dir(&out_dir)
                 .status()
-                .expect("");
+                .unwrap();
             assert!(status.success());
         }
 
@@ -102,7 +102,7 @@ fn clone_repo(test: &Test, out_dir: &Path) -> PathBuf {
             .arg("--hard")
             .current_dir(&out_dir)
             .status()
-            .expect("");
+            .unwrap();
 
         if status.success() {
             found = true;
@@ -133,7 +133,7 @@ fn run_cargo_test(cargo_path: &Path, crate_path: &Path, packages: &[&str]) -> bo
         .env("RUSTFLAGS", "--cap-lints warn")
         .current_dir(crate_path)
         .status()
-        .expect("");
+        .unwrap();
 
     status.success()
 }
index 7da26f8ff4d477b9ab0cde400eb834b44ee24cde..eee3db9b7d4b04d168958c79ea4fcef45bf30e03 100644 (file)
@@ -3,6 +3,7 @@
 #![feature(range_is_empty)]
 #![warn(clippy::len_zero)]
 #![allow(unused)]
+#![allow(stable_features)] // TODO: https://github.com/rust-lang/rust-clippy/issues/5956
 
 mod issue_3807 {
     // With the feature enabled, `is_empty` should be suggested
index be7b4244bc06c4d27463f35de2181ca23ab2c20a..be2e0f38fd164cbef647318ba40846f0b915acff 100644 (file)
@@ -3,6 +3,7 @@
 #![feature(range_is_empty)]
 #![warn(clippy::len_zero)]
 #![allow(unused)]
+#![allow(stable_features)] // TODO: https://github.com/rust-lang/rust-clippy/issues/5956
 
 mod issue_3807 {
     // With the feature enabled, `is_empty` should be suggested
index 6e5fa41fb08a55c127f9bb7a8e34624498e018d5..acb85f7100a39bbf76d9829949864931e17973d8 100644 (file)
@@ -1,5 +1,5 @@
 error: length comparison to zero
-  --> $DIR/len_zero_ranges.rs:10:17
+  --> $DIR/len_zero_ranges.rs:11:17
    |
 LL |         let _ = (0..42).len() == 0;
    |                 ^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `(0..42).is_empty()`
index 8edc9c9cd038e5c2694a613aa878988e8adac16a..054235ec16dcf92c435c579fbdd3079361c424d1 100644 (file)
@@ -148,7 +148,7 @@ fn parse_expected(
 
     // If we find `//~ ERROR foo` or something like that, skip the first word.
     let kind = first_word.parse::<ErrorKind>().ok();
-    if let Some(_) = kind {
+    if kind.is_some() {
         msg = &msg.trim_start().split_at(first_word.len()).1;
     }
 
index 90a0d8926ad94bfa88e0915422c125131baac92d..0efa668ecc88b373dd8db2f83e2189579b4446c4 100644 (file)
@@ -173,10 +173,8 @@ fn ignore_lldb(config: &Config, line: &str) -> bool {
                     // Ignore if actual version is smaller the minimum required
                     // version
                     actual_version < min_version
-                } else if line.starts_with("rust-lldb") && !config.lldb_native_rust {
-                    true
                 } else {
-                    false
+                    line.starts_with("rust-lldb") && !config.lldb_native_rust
                 }
             } else {
                 false
@@ -657,7 +655,6 @@ fn iter_header<R: Read>(testfile: &Path, cfg: Option<&str>, rdr: R, it: &mut dyn
             it(ln[comment.len()..].trim_start());
         }
     }
-    return;
 }
 
 impl Config {
@@ -819,7 +816,7 @@ fn parse_cfg_name_directive(&self, line: &str, prefix: &str) -> ParsedNameDirect
         let name = line[prefix.len() + 1..].split(&[':', ' '][..]).next().unwrap();
 
         let is_match = name == "test" ||
-            &self.target == name ||                             // triple
+            self.target == name ||                              // triple
             util::matches_os(&self.target, name) ||             // target
             util::matches_env(&self.target, name) ||            // env
             self.target.ends_with(name) ||                      // target and env
@@ -857,10 +854,7 @@ fn parse_name_directive(&self, line: &str, directive: &str) -> bool {
         // Ensure the directive is a whole word. Do not match "ignore-x86" when
         // the line says "ignore-x86_64".
         line.starts_with(directive)
-            && match line.as_bytes().get(directive.len()) {
-                None | Some(&b' ') | Some(&b':') => true,
-                _ => false,
-            }
+            && matches!(line.as_bytes().get(directive.len()), None | Some(&b' ') | Some(&b':'))
     }
 
     pub fn parse_name_value_directive(&self, line: &str, directive: &str) -> Option<String> {
@@ -901,9 +895,9 @@ fn parse_edition(&self, line: &str) -> Option<String> {
 }
 
 fn expand_variables(mut value: String, config: &Config) -> String {
-    const CWD: &'static str = "{{cwd}}";
-    const SRC_BASE: &'static str = "{{src-base}}";
-    const BUILD_BASE: &'static str = "{{build-base}}";
+    const CWD: &str = "{{cwd}}";
+    const SRC_BASE: &str = "{{src-base}}";
+    const BUILD_BASE: &str = "{{build-base}}";
 
     if value.contains(CWD) {
         let cwd = env::current_dir().unwrap();
index 6ac7c3b9b474a9dbacfdd4cb11fef57cb95da684..6a03a76c566ef575313226ac9eee13707533942c 100644 (file)
@@ -75,7 +75,7 @@ pub fn extract_rendered(output: &str) -> String {
             if line.starts_with('{') {
                 if let Ok(diagnostic) = serde_json::from_str::<Diagnostic>(line) {
                     diagnostic.rendered
-                } else if let Ok(_) = serde_json::from_str::<ArtifactNotification>(line) {
+                } else if serde_json::from_str::<ArtifactNotification>(line).is_ok() {
                     // Ignore the notification.
                     None
                 } else {
index 46e16393a24c1c49e3be4fa63b98dfd621f63523..adf2fa7fd8ecc3d0772a33869ee24245d9d81843 100644 (file)
@@ -240,7 +240,7 @@ fn make_absolute(path: PathBuf) -> PathBuf {
         cc: matches.opt_str("cc").unwrap(),
         cxx: matches.opt_str("cxx").unwrap(),
         cflags: matches.opt_str("cflags").unwrap(),
-        ar: matches.opt_str("ar").unwrap_or("ar".into()),
+        ar: matches.opt_str("ar").unwrap_or_else(|| String::from("ar")),
         linker: matches.opt_str("linker"),
         llvm_components: matches.opt_str("llvm-components").unwrap(),
         nodejs: matches.opt_str("nodejs"),
@@ -361,17 +361,13 @@ pub fn run_tests(config: Config) {
 }
 
 fn configure_cdb(config: &Config) -> Option<Config> {
-    if config.cdb.is_none() {
-        return None;
-    }
+    config.cdb.as_ref()?;
 
     Some(Config { debugger: Some(Debugger::Cdb), ..config.clone() })
 }
 
 fn configure_gdb(config: &Config) -> Option<Config> {
-    if config.gdb_version.is_none() {
-        return None;
-    }
+    config.gdb_version?;
 
     if util::matches_env(&config.target, "msvc") {
         return None;
@@ -405,9 +401,7 @@ fn configure_gdb(config: &Config) -> Option<Config> {
 }
 
 fn configure_lldb(config: &Config) -> Option<Config> {
-    if config.lldb_python_dir.is_none() {
-        return None;
-    }
+    config.lldb_python_dir.as_ref()?;
 
     if let Some(350) = config.lldb_version {
         println!(
@@ -455,7 +449,7 @@ pub fn make_tests(config: &Config, tests: &mut Vec<test::TestDescAndFn>) {
     debug!("making tests from {:?}", config.src_base.display());
     let inputs = common_inputs_stamp(config);
     collect_tests_from_dir(config, &config.src_base, &PathBuf::new(), &inputs, tests)
-        .expect(&format!("Could not read tests from {}", config.src_base.display()));
+        .unwrap_or_else(|_| panic!("Could not read tests from {}", config.src_base.display()));
 }
 
 /// Returns a stamp constructed from input files common to all test cases.
@@ -588,7 +582,7 @@ fn make_test(config: &Config, testpaths: &TestPaths, inputs: &Stamp) -> Vec<test
     let revisions = if early_props.revisions.is_empty() || config.mode == Mode::Incremental {
         vec![None]
     } else {
-        early_props.revisions.iter().map(|r| Some(r)).collect()
+        early_props.revisions.iter().map(Some).collect()
     };
     revisions
         .into_iter()
@@ -735,24 +729,24 @@ fn make_test_closure(
 
 /// Returns `true` if the given target is an Android target for the
 /// purposes of GDB testing.
-fn is_android_gdb_target(target: &String) -> bool {
-    match &target[..] {
-        "arm-linux-androideabi" | "armv7-linux-androideabi" | "aarch64-linux-android" => true,
-        _ => false,
-    }
+fn is_android_gdb_target(target: &str) -> bool {
+    matches!(
+        &target[..],
+        "arm-linux-androideabi" | "armv7-linux-androideabi" | "aarch64-linux-android"
+    )
 }
 
 /// Returns `true` if the given target is a MSVC target for the purpouses of CDB testing.
-fn is_pc_windows_msvc_target(target: &String) -> bool {
+fn is_pc_windows_msvc_target(target: &str) -> bool {
     target.ends_with("-pc-windows-msvc")
 }
 
-fn find_cdb(target: &String) -> Option<OsString> {
+fn find_cdb(target: &str) -> Option<OsString> {
     if !(cfg!(windows) && is_pc_windows_msvc_target(target)) {
         return None;
     }
 
-    let pf86 = env::var_os("ProgramFiles(x86)").or(env::var_os("ProgramFiles"))?;
+    let pf86 = env::var_os("ProgramFiles(x86)").or_else(|| env::var_os("ProgramFiles"))?;
     let cdb_arch = if cfg!(target_arch = "x86") {
         "x86"
     } else if cfg!(target_arch = "x86_64") {
@@ -779,14 +773,14 @@ fn find_cdb(target: &String) -> Option<OsString> {
 }
 
 /// Returns Path to CDB
-fn analyze_cdb(cdb: Option<String>, target: &String) -> Option<OsString> {
-    cdb.map(|s| OsString::from(s)).or(find_cdb(target))
+fn analyze_cdb(cdb: Option<String>, target: &str) -> Option<OsString> {
+    cdb.map(OsString::from).or_else(|| find_cdb(target))
 }
 
 /// Returns (Path to GDB, GDB Version, GDB has Rust Support)
 fn analyze_gdb(
     gdb: Option<String>,
-    target: &String,
+    target: &str,
     android_cross_path: &PathBuf,
 ) -> (Option<String>, Option<u32>, bool) {
     #[cfg(not(windows))]
index 8318a0a5ad0451328409226b2a6bb0b74c65d30e..124a9adcab91a786600cc65a4460b97a1ecce057 100644 (file)
@@ -114,7 +114,7 @@ pub struct Mismatch {
 
 impl Mismatch {
     fn new(line_number: u32) -> Mismatch {
-        Mismatch { line_number: line_number, lines: Vec::new() }
+        Mismatch { line_number, lines: Vec::new() }
     }
 }
 
@@ -199,7 +199,7 @@ fn write_diff(expected: &str, actual: &str, context_size: usize) -> String {
                 }
             }
         }
-        writeln!(output, "").unwrap();
+        writeln!(output).unwrap();
     }
     output
 }
@@ -230,7 +230,7 @@ pub fn run(config: Config, testpaths: &TestPaths, revision: Option<&str>) {
     debug!("running {:?}", testpaths.file.display());
     let props = TestProps::from_file(&testpaths.file, revision, &config);
 
-    let cx = TestCx { config: &config, props: &props, testpaths, revision: revision };
+    let cx = TestCx { config: &config, props: &props, testpaths, revision };
     create_dir_all(&cx.output_base_dir()).unwrap();
 
     if config.mode == Incremental {
@@ -578,8 +578,8 @@ fn run_pretty_test(&self) {
         if self.props.pp_exact.is_some() {
             // Now we have to care about line endings
             let cr = "\r".to_owned();
-            actual = actual.replace(&cr, "").to_owned();
-            expected = expected.replace(&cr, "").to_owned();
+            actual = actual.replace(&cr, "");
+            expected = expected.replace(&cr, "");
         }
 
         self.compare_source(&expected, &actual);
@@ -740,7 +740,7 @@ fn run_debuginfo_cdb_test_no_opt(&self) {
         let exe_file = self.make_exe_name();
 
         let prefixes = {
-            static PREFIXES: &'static [&'static str] = &["cdb", "cdbg"];
+            static PREFIXES: &[&str] = &["cdb", "cdbg"];
             // No "native rust support" variation for CDB yet.
             PREFIXES
         };
@@ -811,12 +811,12 @@ fn run_debuginfo_gdb_test(&self) {
     fn run_debuginfo_gdb_test_no_opt(&self) {
         let prefixes = if self.config.gdb_native_rust {
             // GDB with Rust
-            static PREFIXES: &'static [&'static str] = &["gdb", "gdbr"];
+            static PREFIXES: &[&str] = &["gdb", "gdbr"];
             println!("NOTE: compiletest thinks it is using GDB with native rust support");
             PREFIXES
         } else {
             // Generic GDB
-            static PREFIXES: &'static [&'static str] = &["gdb", "gdbg"];
+            static PREFIXES: &[&str] = &["gdb", "gdbg"];
             println!("NOTE: compiletest thinks it is using GDB without native rust support");
             PREFIXES
         };
@@ -875,12 +875,12 @@ fn run_debuginfo_gdb_test_no_opt(&self) {
                 .arg(&exe_file)
                 .arg(&self.config.adb_test_dir)
                 .status()
-                .expect(&format!("failed to exec `{:?}`", adb_path));
+                .unwrap_or_else(|_| panic!("failed to exec `{:?}`", adb_path));
 
             Command::new(adb_path)
                 .args(&["forward", "tcp:5039", "tcp:5039"])
                 .status()
-                .expect(&format!("failed to exec `{:?}`", adb_path));
+                .unwrap_or_else(|_| panic!("failed to exec `{:?}`", adb_path));
 
             let adb_arg = format!(
                 "export LD_LIBRARY_PATH={}; \
@@ -897,7 +897,7 @@ fn run_debuginfo_gdb_test_no_opt(&self) {
                 .stdout(Stdio::piped())
                 .stderr(Stdio::inherit())
                 .spawn()
-                .expect(&format!("failed to exec `{:?}`", adb_path));
+                .unwrap_or_else(|_| panic!("failed to exec `{:?}`", adb_path));
 
             // Wait for the gdbserver to print out "Listening on port ..."
             // at which point we know that it's started and then we can
@@ -922,7 +922,7 @@ fn run_debuginfo_gdb_test_no_opt(&self) {
             let Output { status, stdout, stderr } = Command::new(&gdb_path)
                 .args(debugger_opts)
                 .output()
-                .expect(&format!("failed to exec `{:?}`", gdb_path));
+                .unwrap_or_else(|_| panic!("failed to exec `{:?}`", gdb_path));
             let cmdline = {
                 let mut gdb = Command::new(&format!("{}-gdb", self.config.target));
                 gdb.args(debugger_opts);
@@ -1063,11 +1063,11 @@ fn run_debuginfo_lldb_test_no_opt(&self) {
         }
 
         let prefixes = if self.config.lldb_native_rust {
-            static PREFIXES: &'static [&'static str] = &["lldb", "lldbr"];
+            static PREFIXES: &[&str] = &["lldb", "lldbr"];
             println!("NOTE: compiletest thinks it is using LLDB with native rust support");
             PREFIXES
         } else {
-            static PREFIXES: &'static [&'static str] = &["lldb", "lldbg"];
+            static PREFIXES: &[&str] = &["lldb", "lldbg"];
             println!("NOTE: compiletest thinks it is using LLDB without native rust support");
             PREFIXES
         };
@@ -1842,8 +1842,8 @@ fn compose_and_run(
 
         // Need to be sure to put both the lib_path and the aux path in the dylib
         // search path for the child.
-        let mut path = env::split_paths(&env::var_os(dylib_env_var()).unwrap_or(OsString::new()))
-            .collect::<Vec<_>>();
+        let mut path =
+            env::split_paths(&env::var_os(dylib_env_var()).unwrap_or_default()).collect::<Vec<_>>();
         if let Some(p) = aux_path {
             path.insert(0, PathBuf::from(p))
         }
@@ -1854,7 +1854,7 @@ fn compose_and_run(
         command.env(dylib_env_var(), newpath);
 
         let mut child = disable_error_reporting(|| command.spawn())
-            .expect(&format!("failed to exec `{:?}`", &command));
+            .unwrap_or_else(|_| panic!("failed to exec `{:?}`", &command));
         if let Some(input) = input {
             child.stdin.as_mut().unwrap().write_all(input.as_bytes()).unwrap();
         }
@@ -2446,8 +2446,8 @@ fn run_codegen_units_test(&self) {
 
         self.check_no_compiler_crash(&proc_res, self.props.should_ice);
 
-        const PREFIX: &'static str = "MONO_ITEM ";
-        const CGU_MARKER: &'static str = "@@";
+        const PREFIX: &str = "MONO_ITEM ";
+        const CGU_MARKER: &str = "@@";
 
         let actual: Vec<MonoItem> = proc_res
             .stdout
@@ -2976,7 +2976,7 @@ fn run_ui_test(&self) {
                 Filter::MachineApplicableOnly,
             )
             .unwrap_or_default();
-            if suggestions.len() > 0
+            if !suggestions.is_empty()
                 && !self.props.run_rustfix
                 && !self.props.rustfix_only_machine_applicable
             {
@@ -2990,7 +2990,7 @@ fn run_ui_test(&self) {
                     .open(coverage_file_path.as_path())
                     .expect("could not create or open file");
 
-                if let Err(_) = writeln!(file, "{}", self.testpaths.file.display()) {
+                if writeln!(file, "{}", self.testpaths.file.display()).is_err() {
                     panic!("couldn't write to {}", coverage_file_path.display());
                 }
             }
@@ -3007,10 +3007,9 @@ fn run_ui_test(&self) {
                 },
             )
             .unwrap();
-            let fixed_code = apply_suggestions(&unfixed_code, &suggestions).expect(&format!(
-                "failed to apply suggestions for {:?} with rustfix",
-                self.testpaths.file
-            ));
+            let fixed_code = apply_suggestions(&unfixed_code, &suggestions).unwrap_or_else(|_| {
+                panic!("failed to apply suggestions for {:?} with rustfix", self.testpaths.file)
+            });
 
             errors += self.compare_output("fixed", &fixed_code, &expected_fixed);
         } else if !expected_fixed.is_empty() {
@@ -3519,7 +3518,7 @@ fn prune_duplicate_output(&self, mode: CompareMode, kind: &str, canon_content: &
         let examined_content =
             self.load_expected_output_from_path(&examined_path).unwrap_or_else(|_| String::new());
 
-        if canon_content == &examined_content {
+        if canon_content == examined_content {
             self.delete_file(&examined_path);
         }
     }
index cc4b21f9efb450667f33c59a62b99d5cce729aae..1a727fc2b82ea6e6a1236cbebbae2b0b9f748709 100644 (file)
@@ -9,7 +9,7 @@
 mod tests;
 
 /// Conversion table from triple OS name to Rust SYSNAME
-const OS_TABLE: &'static [(&'static str, &'static str)] = &[
+const OS_TABLE: &[(&str, &str)] = &[
     ("android", "android"),
     ("androideabi", "android"),
     ("cloudabi", "cloudabi"),
@@ -37,7 +37,7 @@
     ("vxworks", "vxworks"),
 ];
 
-const ARCH_TABLE: &'static [(&'static str, &'static str)] = &[
+const ARCH_TABLE: &[(&str, &str)] = &[
     ("aarch64", "aarch64"),
     ("amd64", "x86_64"),
     ("arm", "arm"),
@@ -82,7 +82,7 @@
     ("xcore", "xcore"),
 ];
 
-pub const ASAN_SUPPORTED_TARGETS: &'static [&'static str] = &[
+pub const ASAN_SUPPORTED_TARGETS: &[&str] = &[
     "aarch64-fuchsia",
     "aarch64-unknown-linux-gnu",
     "x86_64-apple-darwin",
     "x86_64-unknown-linux-gnu",
 ];
 
-pub const LSAN_SUPPORTED_TARGETS: &'static [&'static str] =
+pub const LSAN_SUPPORTED_TARGETS: &[&str] =
     &["aarch64-unknown-linux-gnu", "x86_64-apple-darwin", "x86_64-unknown-linux-gnu"];
 
-pub const MSAN_SUPPORTED_TARGETS: &'static [&'static str] =
+pub const MSAN_SUPPORTED_TARGETS: &[&str] =
     &["aarch64-unknown-linux-gnu", "x86_64-unknown-freebsd", "x86_64-unknown-linux-gnu"];
 
-pub const TSAN_SUPPORTED_TARGETS: &'static [&'static str] = &[
+pub const TSAN_SUPPORTED_TARGETS: &[&str] = &[
     "aarch64-unknown-linux-gnu",
     "x86_64-apple-darwin",
     "x86_64-unknown-freebsd",
     "x86_64-unknown-linux-gnu",
 ];
 
-const BIG_ENDIAN: &'static [&'static str] = &[
+const BIG_ENDIAN: &[&str] = &[
     "armebv7r",
     "mips",
     "mips64",
@@ -195,11 +195,11 @@ pub trait PathBufExt {
 
 impl PathBufExt for PathBuf {
     fn with_extra_extension<S: AsRef<OsStr>>(&self, extension: S) -> PathBuf {
-        if extension.as_ref().len() == 0 {
+        if extension.as_ref().is_empty() {
             self.clone()
         } else {
             let mut fname = self.file_name().unwrap().to_os_string();
-            if !extension.as_ref().to_str().unwrap().starts_with(".") {
+            if !extension.as_ref().to_str().unwrap().starts_with('.') {
                 fname.push(".");
             }
             fname.push(extension);
index d8dad8fc789e931ed24cb1c29eaa656609166fd4..f7ff64036a1a96568982d9c5f88def07db5dbd76 100644 (file)
@@ -48,8 +48,8 @@ fn from_args() -> Result<Self, Box<dyn Error>> {
         // Parse CLI arguments
         let args = std::env::args().skip(1).collect::<Vec<_>>();
         let (mode, base) = match args.iter().map(|s| s.as_str()).collect::<Vec<_>>().as_slice() {
-            &["generate", ref base] => (Mode::Generate, PathBuf::from(base)),
-            &["check", ref base] => (Mode::Check, PathBuf::from(base)),
+            ["generate", ref base] => (Mode::Generate, PathBuf::from(base)),
+            ["check", ref base] => (Mode::Check, PathBuf::from(base)),
             _ => {
                 eprintln!("usage: expand-yaml-anchors <source-dir> <dest-dir>");
                 std::process::exit(1);
@@ -138,9 +138,7 @@ fn filter_document(document: Yaml) -> Yaml {
                 .map(|(key, value)| (filter_document(key), filter_document(value)))
                 .collect(),
         ),
-        Yaml::Array(vec) => {
-            Yaml::Array(vec.into_iter().map(|item| filter_document(item)).collect())
-        }
+        Yaml::Array(vec) => Yaml::Array(vec.into_iter().map(filter_document).collect()),
         other => other,
     }
 }
index 194318d7a59b5ec5c9ed56fd8df5f6ae4310084a..b7ceba1e28262ff6a7f36e72e8a6cc5a1ce32fc6 100644 (file)
@@ -172,10 +172,10 @@ fn check(cache: &mut Cache, root: &Path, file: &Path, errors: &mut bool) -> Opti
         {
             return;
         }
-        let mut parts = url.splitn(2, "#");
+        let mut parts = url.splitn(2, '#');
         let url = parts.next().unwrap();
         let fragment = parts.next();
-        let mut parts = url.splitn(2, "?");
+        let mut parts = url.splitn(2, '?');
         let url = parts.next().unwrap();
 
         // Once we've plucked out the URL, parse it using our base url and
@@ -258,7 +258,7 @@ fn check(cache: &mut Cache, root: &Path, file: &Path, errors: &mut bool) -> Opti
                 }
 
                 // These appear to be broken in mdbook right now?
-                if fragment.starts_with("-") {
+                if fragment.starts_with('-') {
                     return;
                 }
 
@@ -324,7 +324,7 @@ fn load_file(
 }
 
 fn maybe_redirect(source: &str) -> Option<String> {
-    const REDIRECT: &'static str = "<p>Redirecting to <a href=";
+    const REDIRECT: &str = "<p>Redirecting to <a href=";
 
     let mut lines = source.lines();
     let redirect_line = lines.nth(6)?;
@@ -345,11 +345,11 @@ fn with_attrs_in_source<F: FnMut(&str, usize, &str)>(contents: &str, attr: &str,
             // we can get away with using one pass.
             let is_base = line[..j].ends_with("<base");
             line = rest;
-            let pos_equals = match rest.find("=") {
+            let pos_equals = match rest.find('=') {
                 Some(i) => i,
                 None => continue,
             };
-            if rest[..pos_equals].trim_start_matches(" ") != "" {
+            if rest[..pos_equals].trim_start_matches(' ') != "" {
                 continue;
             }
 
@@ -361,7 +361,7 @@ fn with_attrs_in_source<F: FnMut(&str, usize, &str)>(contents: &str, attr: &str,
             };
             let quote_delim = rest.as_bytes()[pos_quote] as char;
 
-            if rest[..pos_quote].trim_start_matches(" ") != "" {
+            if rest[..pos_quote].trim_start_matches(' ') != "" {
                 continue;
             }
             let rest = &rest[pos_quote + 1..];
index 72b3df8377abb2f7764d60f831e218750430e156..51416c8ce63649789704368d414397f3f9596feb 100755 (executable)
@@ -275,7 +275,7 @@ def update_latest(
         return message
 
 
-if __name__ == '__main__':
+def main():
     repo = os.environ.get('TOOLSTATE_VALIDATE_MAINTAINERS_REPO')
     if repo:
         github_token = os.environ.get('TOOLSTATE_REPO_ACCESS_TOKEN')
@@ -342,3 +342,11 @@ if __name__ == '__main__':
         }
     ))
     response.read()
+
+
+if __name__ == '__main__':
+    try:
+        main()
+    except urllib2.HTTPError as e:
+        print("HTTPError: %s\n%s" % (e, e.read()))
+        raise
index 0b2b9a5508186c16a2e782f47ce7e0e1c5fb8d33..e65d48d1fb3d4d91d9dc1148a7a836ff5c9a3c87 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 0b2b9a5508186c16a2e782f47ce7e0e1c5fb8d33
+Subproject commit e65d48d1fb3d4d91d9dc1148a7a836ff5c9a3c87
index f984e5b61a5fd5462c812f52abd275763af7c830..ccdb4524d5c5afd7cbf86463431342cf2f9c350b 100644 (file)
@@ -5,7 +5,7 @@ authors = ["Alex Crichton <alex@alexcrichton.com>"]
 edition = "2018"
 
 [dependencies]
-cargo_metadata = "0.9.1"
+cargo_metadata = "0.11"
 regex = "1"
 lazy_static = "1"
 walkdir = "2"
index 4f98944e4c8ebb267f458c2b23fdfd8b691e0953..af3fb403703da8c242ef1b492ade360c37b23222 100644 (file)
     "crossbeam-queue",
     "crossbeam-utils",
     "datafrog",
+    "difference",
     "digest",
     "dlmalloc",
     "either",
     "ena",
     "env_logger",
+    "expect-test",
     "fake-simd",
     "filetime",
     "flate2",
index 2fa0f12d7e8dc5d0c3636e2e33a86a78cb697e10..82a5234ac5b240765fb38beb7e7179814c4366ed 100644 (file)
@@ -47,9 +47,7 @@ fn check_error_code_explanation(
     invalid_compile_fail_format
 }
 
-fn check_if_error_code_is_test_in_explanation(f: &str, err_code: &String) -> bool {
-    let mut can_be_ignored = false;
-
+fn check_if_error_code_is_test_in_explanation(f: &str, err_code: &str) -> bool {
     for line in f.lines() {
         let s = line.trim();
         if s.starts_with("#### Note: this error code is no longer emitted by the compiler") {
@@ -58,13 +56,13 @@ fn check_if_error_code_is_test_in_explanation(f: &str, err_code: &String) -> boo
         if s.starts_with("```") {
             if s.contains("compile_fail") && s.contains(err_code) {
                 return true;
-            } else if s.contains("(") {
+            } else if s.contains('(') {
                 // It's very likely that we can't actually make it fail compilation...
-                can_be_ignored = true;
+                return true;
             }
         }
     }
-    can_be_ignored
+    false
 }
 
 macro_rules! some_or_continue {
index d2d1807b3bb22cb27998099fe0e5d39e0b192582..218e9668df4ae60ce6ec08672aa6e2485f01344a 100644 (file)
@@ -315,7 +315,7 @@ fn version() -> String {
 fn fmt_list<V: std::fmt::Debug>(values: impl IntoIterator<Item = V>) -> String {
     let pieces = values.into_iter().map(|b| format!("{:?}, ", b)).collect::<Vec<_>>();
     let mut out = String::new();
-    let mut line = format!("\n    ");
+    let mut line = String::from("\n    ");
     for piece in pieces {
         if line.len() + piece.len() < 98 {
             line.push_str(&piece);
index 63cc29b670f6b3d4573e4dc017d19ef856babbad..42e7e5fb406051303305f3d059a422ed4898ef85 100644 (file)
@@ -20,7 +20,7 @@ fn blank_line(&mut self) {
         if self.file.is_empty() || self.file.ends_with("\n\n") {
             return;
         }
-        writeln!(&mut self.file, "").unwrap();
+        writeln!(&mut self.file).unwrap();
     }
 
     fn emit_bitset(&mut self, ranges: &[Range<u32>]) {
@@ -161,10 +161,10 @@ pub fn emit_codepoints(emitter: &mut RawEmitter, ranges: &[Range<u32>]) {
 
     if bitset.bytes_used <= skiplist.bytes_used {
         *emitter = bitset;
-        emitter.desc = format!("bitset");
+        emitter.desc = String::from("bitset");
     } else {
         *emitter = skiplist;
-        emitter.desc = format!("skiplist");
+        emitter.desc = String::from("skiplist");
     }
 }
 
@@ -289,7 +289,7 @@ enum UniqueMapping {
                 // Remove the now-canonicalized word from other mappings,
                 // to ensure that we deprioritize them in the next iteration of
                 // the while loop.
-                for (_, mapped) in &mut mappings {
+                for mapped in mappings.values_mut() {
                     let mut i = 0;
                     while i != mapped.len() {
                         if mapped[i].0 == *from {
@@ -309,7 +309,7 @@ enum UniqueMapping {
 
             // Remove the now-canonical word from other mappings, to ensure that
             // we deprioritize them in the next iteration of the while loop.
-            for (_, mapped) in &mut mappings {
+            for mapped in mappings.values_mut() {
                 let mut i = 0;
                 while i != mapped.len() {
                     if mapped[i].0 == to {
index 11617911446ecee0fed0f5ee4e3e830ec9bc5942..5d277e1c41f40df1abdb37c8316e51df44fc00dd 100644 (file)
@@ -94,9 +94,9 @@ fn copy_recursive(from: &Path, to: &Path) {
 }
 
 fn main() {
-    let library_path_str = env::args_os().skip(1).next().expect("library path required");
-    let src_path_str = env::args_os().skip(2).next().expect("source path required");
-    let dest_path_str = env::args_os().skip(3).next().expect("destination path required");
+    let library_path_str = env::args_os().nth(1).expect("library path required");
+    let src_path_str = env::args_os().nth(2).expect("source path required");
+    let dest_path_str = env::args_os().nth(3).expect("destination path required");
     let library_path = Path::new(&library_path_str);
     let src_path = Path::new(&src_path_str);
     let dest_path = Path::new(&dest_path_str);