]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #105694 - ouz-a:issue_105689, r=estebank
authorMatthias Krüger <matthias.krueger@famsik.de>
Thu, 15 Dec 2022 21:02:59 +0000 (22:02 +0100)
committerGitHub <noreply@github.com>
Thu, 15 Dec 2022 21:02:59 +0000 (22:02 +0100)
Don't create dummy if val has escaping bounds var

Skips creating/pushing obligations if val has escaping bounds vars.

Fixes #105689

783 files changed:
.github/workflows/ci.yml
RELEASES.md
compiler/rustc_abi/src/lib.rs
compiler/rustc_ast/src/ast.rs
compiler/rustc_ast/src/token.rs
compiler/rustc_ast_lowering/src/expr.rs
compiler/rustc_ast_lowering/src/item.rs
compiler/rustc_ast_passes/src/feature_gate.rs
compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
compiler/rustc_borrowck/src/diagnostics/mod.rs
compiler/rustc_borrowck/src/diagnostics/move_errors.rs
compiler/rustc_borrowck/src/diagnostics/region_errors.rs
compiler/rustc_borrowck/src/region_infer/mod.rs
compiler/rustc_builtin_macros/src/alloc_error_handler.rs
compiler/rustc_builtin_macros/src/concat_bytes.rs
compiler/rustc_codegen_cranelift/.cirrus.yml
compiler/rustc_codegen_cranelift/.github/workflows/main.yml
compiler/rustc_codegen_cranelift/.github/workflows/nightly-cranelift.yml
compiler/rustc_codegen_cranelift/.github/workflows/rustc.yml
compiler/rustc_codegen_cranelift/.gitignore
compiler/rustc_codegen_cranelift/.vscode/settings.json
compiler/rustc_codegen_cranelift/Cargo.lock
compiler/rustc_codegen_cranelift/Cargo.toml
compiler/rustc_codegen_cranelift/Readme.md
compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock
compiler/rustc_codegen_cranelift/build_system/abi_cafe.rs
compiler/rustc_codegen_cranelift/build_system/build_backend.rs
compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs
compiler/rustc_codegen_cranelift/build_system/mod.rs
compiler/rustc_codegen_cranelift/build_system/path.rs [new file with mode: 0644]
compiler/rustc_codegen_cranelift/build_system/prepare.rs
compiler/rustc_codegen_cranelift/build_system/rustc_info.rs
compiler/rustc_codegen_cranelift/build_system/tests.rs
compiler/rustc_codegen_cranelift/build_system/utils.rs
compiler/rustc_codegen_cranelift/clean_all.sh
compiler/rustc_codegen_cranelift/config.txt
compiler/rustc_codegen_cranelift/docs/usage.md
compiler/rustc_codegen_cranelift/example/issue-72793.rs [new file with mode: 0644]
compiler/rustc_codegen_cranelift/example/mini_core.rs
compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs
compiler/rustc_codegen_cranelift/example/std_example.rs
compiler/rustc_codegen_cranelift/rust-toolchain
compiler/rustc_codegen_cranelift/rustfmt.toml
compiler/rustc_codegen_cranelift/scripts/filter_profile.rs
compiler/rustc_codegen_cranelift/scripts/rustdoc-clif.rs [new file with mode: 0644]
compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh
compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh
compiler/rustc_codegen_cranelift/src/abi/mod.rs
compiler/rustc_codegen_cranelift/src/allocator.rs
compiler/rustc_codegen_cranelift/src/base.rs
compiler/rustc_codegen_cranelift/src/cast.rs
compiler/rustc_codegen_cranelift/src/common.rs
compiler/rustc_codegen_cranelift/src/constant.rs
compiler/rustc_codegen_cranelift/src/debuginfo/unwind.rs
compiler/rustc_codegen_cranelift/src/discriminant.rs
compiler/rustc_codegen_cranelift/src/driver/jit.rs
compiler/rustc_codegen_cranelift/src/driver/mod.rs
compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs
compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs [new file with mode: 0644]
compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs [new file with mode: 0644]
compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
compiler/rustc_codegen_cranelift/src/main_shim.rs
compiler/rustc_codegen_cranelift/src/num.rs
compiler/rustc_codegen_cranelift/src/optimize/peephole.rs
compiler/rustc_codegen_cranelift/src/value_and_place.rs
compiler/rustc_codegen_cranelift/test.sh
compiler/rustc_codegen_cranelift/y.rs
compiler/rustc_codegen_llvm/src/back/archive.rs
compiler/rustc_codegen_llvm/src/back/lto.rs
compiler/rustc_codegen_ssa/src/back/archive.rs
compiler/rustc_codegen_ssa/src/codegen_attrs.rs [new file with mode: 0644]
compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
compiler/rustc_codegen_ssa/src/errors.rs
compiler/rustc_codegen_ssa/src/lib.rs
compiler/rustc_codegen_ssa/src/mir/block.rs
compiler/rustc_codegen_ssa/src/target_features.rs
compiler/rustc_const_eval/src/const_eval/error.rs
compiler/rustc_const_eval/src/const_eval/eval_queries.rs
compiler/rustc_const_eval/src/const_eval/machine.rs
compiler/rustc_const_eval/src/const_eval/valtrees.rs
compiler/rustc_const_eval/src/interpret/eval_context.rs
compiler/rustc_const_eval/src/interpret/intrinsics.rs
compiler/rustc_const_eval/src/interpret/machine.rs
compiler/rustc_const_eval/src/interpret/memory.rs
compiler/rustc_const_eval/src/interpret/place.rs
compiler/rustc_const_eval/src/interpret/validity.rs
compiler/rustc_const_eval/src/transform/validate.rs
compiler/rustc_const_eval/src/util/call_kind.rs
compiler/rustc_const_eval/src/util/might_permit_raw_init.rs
compiler/rustc_const_eval/src/util/type_name.rs
compiler/rustc_data_structures/src/base_n.rs
compiler/rustc_data_structures/src/sorted_map.rs
compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl
compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl
compiler/rustc_error_messages/locales/en-US/monomorphize.ftl
compiler/rustc_error_messages/locales/en-US/parse.ftl
compiler/rustc_errors/src/diagnostic.rs
compiler/rustc_errors/src/emitter.rs
compiler/rustc_errors/src/lib.rs
compiler/rustc_hir/src/hir.rs
compiler/rustc_hir_analysis/src/astconv/mod.rs
compiler/rustc_hir_analysis/src/check/check.rs
compiler/rustc_hir_analysis/src/check/compare_method.rs
compiler/rustc_hir_analysis/src/check/mod.rs
compiler/rustc_hir_analysis/src/check/wfcheck.rs
compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
compiler/rustc_hir_analysis/src/collect.rs
compiler/rustc_hir_analysis/src/collect/lifetimes.rs
compiler/rustc_hir_analysis/src/collect/predicates_of.rs
compiler/rustc_hir_analysis/src/collect/type_of.rs
compiler/rustc_hir_analysis/src/constrained_generic_params.rs
compiler/rustc_hir_analysis/src/errors.rs
compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
compiler/rustc_hir_analysis/src/outlives/utils.rs
compiler/rustc_hir_analysis/src/variance/constraints.rs
compiler/rustc_hir_analysis/src/variance/mod.rs
compiler/rustc_hir_pretty/src/lib.rs
compiler/rustc_hir_typeck/src/_match.rs
compiler/rustc_hir_typeck/src/cast.rs
compiler/rustc_hir_typeck/src/closure.rs
compiler/rustc_hir_typeck/src/coercion.rs
compiler/rustc_hir_typeck/src/expr.rs
compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
compiler/rustc_hir_typeck/src/generator_interior/mod.rs
compiler/rustc_hir_typeck/src/method/mod.rs
compiler/rustc_hir_typeck/src/method/probe.rs
compiler/rustc_hir_typeck/src/method/suggest.rs
compiler/rustc_hir_typeck/src/writeback.rs
compiler/rustc_index/src/bit_set.rs
compiler/rustc_infer/src/errors/mod.rs
compiler/rustc_infer/src/infer/at.rs
compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
compiler/rustc_infer/src/infer/combine.rs
compiler/rustc_infer/src/infer/equate.rs
compiler/rustc_infer/src/infer/error_reporting/mod.rs
compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs
compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
compiler/rustc_infer/src/infer/error_reporting/suggest.rs
compiler/rustc_infer/src/infer/freshen.rs
compiler/rustc_infer/src/infer/glb.rs
compiler/rustc_infer/src/infer/lattice.rs
compiler/rustc_infer/src/infer/lub.rs
compiler/rustc_infer/src/infer/mod.rs
compiler/rustc_infer/src/infer/nll_relate/mod.rs
compiler/rustc_infer/src/infer/opaque_types.rs
compiler/rustc_infer/src/infer/outlives/components.rs
compiler/rustc_infer/src/infer/outlives/obligations.rs
compiler/rustc_infer/src/infer/outlives/verify.rs
compiler/rustc_infer/src/infer/projection.rs
compiler/rustc_infer/src/infer/region_constraints/mod.rs
compiler/rustc_infer/src/infer/sub.rs
compiler/rustc_infer/src/traits/project.rs
compiler/rustc_infer/src/traits/util.rs
compiler/rustc_lexer/src/unescape.rs
compiler/rustc_lint/src/builtin.rs
compiler/rustc_lint/src/context.rs
compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
compiler/rustc_lint/src/types.rs
compiler/rustc_lint/src/unused.rs
compiler/rustc_lint_defs/src/builtin.rs
compiler/rustc_macros/src/diagnostics/diagnostic.rs
compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
compiler/rustc_metadata/src/rmeta/decoder.rs
compiler/rustc_metadata/src/rmeta/encoder.rs
compiler/rustc_middle/src/mir/mod.rs
compiler/rustc_middle/src/mir/mono.rs
compiler/rustc_middle/src/traits/mod.rs
compiler/rustc_middle/src/traits/query.rs
compiler/rustc_middle/src/ty/adjustment.rs
compiler/rustc_middle/src/ty/context.rs
compiler/rustc_middle/src/ty/diagnostics.rs
compiler/rustc_middle/src/ty/error.rs
compiler/rustc_middle/src/ty/fast_reject.rs
compiler/rustc_middle/src/ty/flags.rs
compiler/rustc_middle/src/ty/inhabitedness/mod.rs
compiler/rustc_middle/src/ty/layout.rs
compiler/rustc_middle/src/ty/mod.rs
compiler/rustc_middle/src/ty/print/mod.rs
compiler/rustc_middle/src/ty/print/pretty.rs
compiler/rustc_middle/src/ty/relate.rs
compiler/rustc_middle/src/ty/structural_impls.rs
compiler/rustc_middle/src/ty/sty.rs
compiler/rustc_middle/src/ty/subst.rs
compiler/rustc_middle/src/ty/util.rs
compiler/rustc_middle/src/ty/visit.rs
compiler/rustc_middle/src/ty/walk.rs
compiler/rustc_mir_build/src/build/block.rs
compiler/rustc_mir_build/src/build/custom/mod.rs
compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
compiler/rustc_mir_build/src/build/expr/stmt.rs
compiler/rustc_mir_build/src/build/matches/test.rs
compiler/rustc_mir_build/src/build/mod.rs
compiler/rustc_mir_build/src/check_unsafety.rs
compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
compiler/rustc_mir_dataflow/src/drop_flag_effects.rs
compiler/rustc_mir_dataflow/src/elaborate_drops.rs
compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs
compiler/rustc_mir_transform/src/check_unsafety.rs
compiler/rustc_mir_transform/src/const_prop.rs
compiler/rustc_mir_transform/src/dataflow_const_prop.rs
compiler/rustc_mir_transform/src/dest_prop.rs
compiler/rustc_mir_transform/src/generator.rs
compiler/rustc_mir_transform/src/inline.rs
compiler/rustc_mir_transform/src/remove_zsts.rs
compiler/rustc_mir_transform/src/shim.rs
compiler/rustc_monomorphize/src/errors.rs
compiler/rustc_monomorphize/src/partitioning/mod.rs
compiler/rustc_parse/src/errors.rs
compiler/rustc_parse/src/parser/diagnostics.rs
compiler/rustc_parse/src/parser/expr.rs
compiler/rustc_parse/src/parser/item.rs
compiler/rustc_parse/src/parser/stmt.rs
compiler/rustc_privacy/src/lib.rs
compiler/rustc_query_system/src/error.rs
compiler/rustc_resolve/src/late.rs
compiler/rustc_resolve/src/late/diagnostics.rs
compiler/rustc_session/src/config.rs
compiler/rustc_session/src/errors.rs
compiler/rustc_session/src/options.rs
compiler/rustc_span/src/analyze_source_file.rs
compiler/rustc_span/src/lib.rs
compiler/rustc_span/src/source_map.rs
compiler/rustc_span/src/symbol.rs
compiler/rustc_symbol_mangling/src/legacy.rs
compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
compiler/rustc_symbol_mangling/src/v0.rs
compiler/rustc_target/src/spec/apple_base.rs
compiler/rustc_target/src/spec/powerpc64_ibm_aix.rs
compiler/rustc_trait_selection/src/traits/auto_trait.rs
compiler/rustc_trait_selection/src/traits/coherence.rs
compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs
compiler/rustc_trait_selection/src/traits/error_reporting/method_chain.rs [new file with mode: 0644]
compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
compiler/rustc_trait_selection/src/traits/mod.rs
compiler/rustc_trait_selection/src/traits/object_safety.rs
compiler/rustc_trait_selection/src/traits/project.rs
compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
compiler/rustc_trait_selection/src/traits/query/normalize.rs
compiler/rustc_trait_selection/src/traits/relationships.rs
compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
compiler/rustc_trait_selection/src/traits/select/confirmation.rs
compiler/rustc_trait_selection/src/traits/select/mod.rs
compiler/rustc_trait_selection/src/traits/structural_match.rs
compiler/rustc_trait_selection/src/traits/wf.rs
compiler/rustc_traits/src/chalk/db.rs
compiler/rustc_traits/src/chalk/lowering.rs
compiler/rustc_traits/src/dropck_outlives.rs
compiler/rustc_ty_utils/src/instance.rs
compiler/rustc_ty_utils/src/layout.rs
compiler/rustc_ty_utils/src/needs_drop.rs
compiler/rustc_ty_utils/src/ty.rs
compiler/rustc_type_ir/src/lib.rs
compiler/rustc_type_ir/src/sty.rs
library/core/src/borrow.rs
library/core/src/iter/traits/iterator.rs
library/core/src/option.rs
library/core/src/result.rs
library/core/src/sync/exclusive.rs
library/proc_macro/src/lib.rs
library/std/src/sys/unix/fs.rs
library/std/src/sys/unix/kernel_copy.rs
library/std/src/sys/unix/mod.rs
library/std/src/sys/unix/process/process_unix.rs
library/std/src/sys/unix/stack_overflow.rs
library/std/src/sys/unix/thread.rs
src/bootstrap/cache.rs
src/bootstrap/dist.rs
src/ci/docker/scripts/fuchsia-test-runner.py
src/ci/github-actions/ci.yml
src/librustdoc/clean/auto_trait.rs
src/librustdoc/clean/blanket_impl.rs
src/librustdoc/clean/inline.rs
src/librustdoc/clean/mod.rs
src/librustdoc/clean/types.rs
src/librustdoc/clean/utils.rs
src/librustdoc/formats/item_type.rs
src/librustdoc/html/markdown.rs
src/librustdoc/html/render/context.rs
src/librustdoc/html/render/mod.rs
src/librustdoc/html/render/print_item.rs
src/librustdoc/html/static/css/rustdoc.css
src/librustdoc/html/static/css/themes/ayu.css
src/librustdoc/html/static/css/themes/dark.css
src/librustdoc/html/static/css/themes/light.css
src/librustdoc/html/static/js/main.js
src/librustdoc/markdown.rs
src/librustdoc/passes/collect_intra_doc_links.rs
src/test/codegen/avr/avr-func-addrspace.rs
src/test/incremental/hashes/loop_expressions.rs
src/test/incremental/hashes/while_let_loops.rs
src/test/incremental/hashes/while_loops.rs
src/test/rustdoc-gui/docblock-big-code-mobile.goml
src/test/rustdoc-gui/docblock-code-block-line-number.goml
src/test/rustdoc-gui/help-page.goml
src/test/rustdoc-gui/impl-doc.goml [new file with mode: 0644]
src/test/rustdoc-gui/src/test_docs/lib.rs
src/test/rustdoc-ui/z-help.stdout
src/test/rustdoc/toggle-trait-fn.rs
src/test/ui-fulldeps/internal-lints/ty_tykind_usage.rs
src/test/ui-fulldeps/internal-lints/ty_tykind_usage.stderr
src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
src/test/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr
src/test/ui/anonymous-higher-ranked-lifetime.stderr
src/test/ui/argument-suggestions/display-is-suggestable.rs [new file with mode: 0644]
src/test/ui/argument-suggestions/display-is-suggestable.stderr [new file with mode: 0644]
src/test/ui/array-slice-vec/infer_array_len.stderr
src/test/ui/associated-item/issue-105449.rs [new file with mode: 0644]
src/test/ui/associated-type-bounds/const-projection-err.gce.stderr [new file with mode: 0644]
src/test/ui/associated-type-bounds/const-projection-err.rs [new file with mode: 0644]
src/test/ui/associated-type-bounds/const-projection-err.stock.stderr [new file with mode: 0644]
src/test/ui/associated-type-bounds/issue-99828.stderr
src/test/ui/associated-types/associated-types-overridden-binding-2.rs
src/test/ui/associated-types/associated-types-overridden-binding-2.stderr
src/test/ui/associated-types/defaults-wf.stderr
src/test/ui/associated-types/trait-with-supertraits-needing-sized-self.stderr
src/test/ui/async-await/async-await-let-else.drop-tracking.stderr
src/test/ui/async-await/async-await-let-else.no-drop-tracking.stderr
src/test/ui/async-await/generator-desc.stderr
src/test/ui/async-await/in-trait/async-example-desugared-boxed.rs
src/test/ui/async-await/in-trait/async-example-desugared-boxed.stderr [new file with mode: 0644]
src/test/ui/async-await/in-trait/async-example-desugared-extra.rs [new file with mode: 0644]
src/test/ui/async-await/in-trait/async-example-desugared-manual.rs [new file with mode: 0644]
src/test/ui/async-await/in-trait/async-example-desugared-manual.stderr [new file with mode: 0644]
src/test/ui/async-await/in-trait/async-example-desugared.rs
src/test/ui/async-await/in-trait/fn-not-async-err.rs
src/test/ui/async-await/in-trait/fn-not-async-err.stderr
src/test/ui/async-await/in-trait/fn-not-async-err2.rs
src/test/ui/async-await/in-trait/issue-104678.rs [new file with mode: 0644]
src/test/ui/async-await/issue-70935-complex-spans.no_drop_tracking.stderr
src/test/ui/async-await/issue-72442.stderr
src/test/ui/async-await/issues/issue-65159.stderr
src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.no_drop_tracking.stderr
src/test/ui/async-await/issues/issue-67893.stderr
src/test/ui/async-await/pin-needed-to-poll-2.stderr
src/test/ui/async-await/pin-needed-to-poll.stderr
src/test/ui/async-await/track-caller/async-block.rs [new file with mode: 0644]
src/test/ui/async-await/track-caller/async-block.stderr [new file with mode: 0644]
src/test/ui/async-await/track-caller/async-closure-gate.rs [new file with mode: 0644]
src/test/ui/async-await/track-caller/async-closure-gate.stderr [new file with mode: 0644]
src/test/ui/async-await/track-caller/panic-track-caller.rs
src/test/ui/binop/binop-consume-args.stderr
src/test/ui/binop/binop-move-semantics.stderr
src/test/ui/binop/issue-28837.stderr
src/test/ui/binop/issue-3820.stderr
src/test/ui/borrowck/access-mode-in-closures.stderr
src/test/ui/borrowck/borrowck-for-loop-correct-cmt-for-pattern.stderr
src/test/ui/borrowck/borrowck-issue-2657-2.fixed [new file with mode: 0644]
src/test/ui/borrowck/borrowck-issue-2657-2.rs
src/test/ui/borrowck/borrowck-issue-2657-2.stderr
src/test/ui/borrowck/borrowck-move-error-with-note.fixed [new file with mode: 0644]
src/test/ui/borrowck/borrowck-move-error-with-note.rs
src/test/ui/borrowck/borrowck-move-error-with-note.stderr
src/test/ui/borrowck/borrowck-move-from-unsafe-ptr.stderr
src/test/ui/borrowck/borrowck-move-in-irrefut-pat.stderr
src/test/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.stderr
src/test/ui/borrowck/borrowck-move-out-of-overloaded-deref.stderr
src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.fixed [new file with mode: 0644]
src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.rs
src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.stderr
src/test/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.fixed [new file with mode: 0644]
src/test/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.rs
src/test/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.stderr
src/test/ui/borrowck/borrowck-move-out-of-vec-tail.stderr
src/test/ui/borrowck/borrowck-overloaded-index-move-from-vec.stderr
src/test/ui/borrowck/borrowck-vec-pattern-nesting.rs
src/test/ui/borrowck/borrowck-vec-pattern-nesting.stderr
src/test/ui/borrowck/issue-104639-lifetime-order.rs [new file with mode: 0644]
src/test/ui/borrowck/issue-17718-static-move.stderr
src/test/ui/borrowck/issue-20801.stderr
src/test/ui/borrowck/issue-47215-ice-from-drop-elab.stderr
src/test/ui/borrowck/issue-51301.stderr
src/test/ui/borrowck/issue-51415.fixed [new file with mode: 0644]
src/test/ui/borrowck/issue-51415.rs
src/test/ui/borrowck/issue-51415.stderr
src/test/ui/borrowck/issue-54597-reject-move-out-of-borrow-via-pat.stderr
src/test/ui/borrowck/issue-83760.stderr
src/test/ui/borrowck/issue-87456-point-to-closure.stderr
src/test/ui/borrowck/move-error-snippets.stderr
src/test/ui/borrowck/reborrow-sugg-move-then-borrow.stderr
src/test/ui/borrowck/suggest-as-ref-on-mut-closure.stderr
src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr
src/test/ui/box/into-boxed-slice-fail.stderr
src/test/ui/by-move-pattern-binding.rs
src/test/ui/by-move-pattern-binding.stderr
src/test/ui/c-variadic/issue-86053-1.stderr
src/test/ui/chalkify/bugs/async.stderr
src/test/ui/check-static-values-constraints.stderr
src/test/ui/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.stderr
src/test/ui/closures/closure-expected.stderr
src/test/ui/closures/closure-move-sync.stderr
src/test/ui/closures/coerce-unsafe-to-closure.stderr
src/test/ui/closures/issue-52437.stderr
src/test/ui/closures/issue-78720.stderr
src/test/ui/closures/issue-87461.stderr
src/test/ui/closures/issue-90871.stderr
src/test/ui/closures/multiple-fn-bounds.stderr
src/test/ui/codemap_tests/tab_3.stderr
src/test/ui/confuse-field-and-method/issue-33784.stderr
src/test/ui/const-generics/generic_arg_infer/issue-91614.stderr
src/test/ui/const-generics/generic_const_exprs/issue-105608.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/issue-105608.stderr [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/issue-72787.min.stderr
src/test/ui/const-generics/generic_const_exprs/issue-80742.stderr
src/test/ui/const-generics/invalid-const-arg-for-type-param.stderr
src/test/ui/const-generics/invalid-constant-in-args.stderr
src/test/ui/const-generics/issues/issue-83249.stderr
src/test/ui/const-ptr/forbidden_slices.32bit.stderr
src/test/ui/const-ptr/forbidden_slices.64bit.stderr
src/test/ui/const-ptr/forbidden_slices.rs
src/test/ui/const-ptr/out_of_bounds_read.stderr
src/test/ui/consts/const-eval/ub-ref-ptr.32bit.stderr
src/test/ui/consts/const-eval/ub-ref-ptr.64bit.stderr
src/test/ui/consts/const-eval/ub-ref-ptr.rs
src/test/ui/consts/const-eval/ub-wide-ptr.32bit.stderr
src/test/ui/consts/const-eval/ub-wide-ptr.64bit.stderr
src/test/ui/consts/const-eval/ub-wide-ptr.rs
src/test/ui/consts/const-float-bits-reject-conv.stderr
src/test/ui/consts/const-fn-error.stderr
src/test/ui/consts/const-for.stderr
src/test/ui/consts/const_unsafe_unreachable_ub.stderr
src/test/ui/consts/copy-intrinsic.rs
src/test/ui/consts/extra-const-ub/detect-extra-ub.rs
src/test/ui/consts/extra-const-ub/detect-extra-ub.with_flag.stderr
src/test/ui/consts/issue-miri-1910.stderr
src/test/ui/consts/miri_unleashed/assoc_const.stderr
src/test/ui/consts/miri_unleashed/drop.stderr
src/test/ui/consts/missing_span_in_backtrace.rs
src/test/ui/consts/offset_from_ub.stderr
src/test/ui/consts/offset_ub.stderr
src/test/ui/consts/ptr_comparisons.stderr
src/test/ui/derives/derives-span-Eq-enum-struct-variant.stderr
src/test/ui/derives/derives-span-Eq-enum.stderr
src/test/ui/derives/derives-span-Eq-struct.stderr
src/test/ui/derives/derives-span-Eq-tuple-struct.stderr
src/test/ui/derives/deriving-meta-unknown-trait.stderr
src/test/ui/deriving/issue-103157.stderr
src/test/ui/destructuring-assignment/note-unsupported.stderr
src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.fixed [new file with mode: 0644]
src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.rs
src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.stderr
src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.fixed [new file with mode: 0644]
src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.rs
src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.stderr
src/test/ui/dst/dst-rvalue.stderr
src/test/ui/empty/empty-struct-braces-expr.stderr
src/test/ui/error-codes/E0004-2.stderr
src/test/ui/error-codes/E0005.stderr
src/test/ui/error-codes/E0059.stderr
src/test/ui/error-codes/E0282.stderr
src/test/ui/error-codes/E0297.stderr
src/test/ui/error-codes/E0401.stderr
src/test/ui/error-codes/E0507.stderr
src/test/ui/error-codes/E0508-fail.stderr
src/test/ui/error-codes/E0508.stderr
src/test/ui/error-codes/E0509.stderr
src/test/ui/error-festival.stderr
src/test/ui/expr/malformed_closure/ruby_style_closure.stderr
src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr
src/test/ui/fmt/ifmt-bad-arg.stderr
src/test/ui/fmt/ifmt-unimpl.stderr
src/test/ui/functions-closures/fn-help-with-err.stderr
src/test/ui/generator/issue-102645.stderr
src/test/ui/generator/sized-yield.stderr
src/test/ui/generic-associated-types/issue-101020.stderr
src/test/ui/generics/wrong-number-of-args.stderr
src/test/ui/higher-rank-trait-bounds/hang-on-deeply-nested-dyn.rs [new file with mode: 0644]
src/test/ui/higher-rank-trait-bounds/hang-on-deeply-nested-dyn.stderr [new file with mode: 0644]
src/test/ui/higher-rank-trait-bounds/issue-30786.stderr
src/test/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.stderr
src/test/ui/illegal-sized-bound/mutability-mismatch.rs [new file with mode: 0644]
src/test/ui/illegal-sized-bound/mutability-mismatch.stderr [new file with mode: 0644]
src/test/ui/illegal-sized-bound/regular.rs [new file with mode: 0644]
src/test/ui/illegal-sized-bound/regular.stderr [new file with mode: 0644]
src/test/ui/impl-trait/impl-generic-mismatch.stderr
src/test/ui/impl-trait/in-trait/wf-bounds.stderr
src/test/ui/impl-trait/issues/issue-62742.stderr
src/test/ui/impl-trait/issues/issue-86719.stderr
src/test/ui/impl-trait/issues/issue-92305.stderr
src/test/ui/impl-trait/no-method-suggested-traits.stderr
src/test/ui/imports/extern-prelude-extern-crate-restricted-shadowing.stderr
src/test/ui/inference/erase-type-params-in-label.stderr
src/test/ui/inference/issue-71732.stderr
src/test/ui/inference/issue-72690.stderr
src/test/ui/inline-const/expr-unsafe-err.mir.stderr [new file with mode: 0644]
src/test/ui/inline-const/expr-unsafe-err.rs [new file with mode: 0644]
src/test/ui/inline-const/expr-unsafe-err.thir.stderr [new file with mode: 0644]
src/test/ui/inline-const/expr-unsafe.mir.stderr [new file with mode: 0644]
src/test/ui/inline-const/expr-unsafe.rs [new file with mode: 0644]
src/test/ui/inline-const/expr-unsafe.thir.stderr [new file with mode: 0644]
src/test/ui/inline-const/pat-unsafe-err.rs [new file with mode: 0644]
src/test/ui/inline-const/pat-unsafe.rs [new file with mode: 0644]
src/test/ui/interior-mutability/interior-mutability.stderr
src/test/ui/intrinsics/const-eval-select-bad.stderr
src/test/ui/issues/issue-105330.stderr
src/test/ui/issues/issue-12567.stderr
src/test/ui/issues/issue-14091-2.stderr
src/test/ui/issues/issue-14092.stderr
src/test/ui/issues/issue-16966.stderr
src/test/ui/issues/issue-17546.stderr
src/test/ui/issues/issue-17651.stderr
src/test/ui/issues/issue-18159.stderr
src/test/ui/issues/issue-18423.stderr
src/test/ui/issues/issue-20162.stderr
src/test/ui/issues/issue-20433.stderr
src/test/ui/issues/issue-2151.stderr
src/test/ui/issues/issue-21974.stderr
src/test/ui/issues/issue-23024.stderr
src/test/ui/issues/issue-23966.stderr
src/test/ui/issues/issue-24036.stderr
src/test/ui/issues/issue-24424.stderr
src/test/ui/issues/issue-27033.stderr
src/test/ui/issues/issue-30123.stderr
src/test/ui/issues/issue-3044.stderr
src/test/ui/issues/issue-31173.rs
src/test/ui/issues/issue-31173.stderr
src/test/ui/issues/issue-32655.stderr
src/test/ui/issues/issue-33941.rs
src/test/ui/issues/issue-33941.stderr
src/test/ui/issues/issue-34334.stderr
src/test/ui/issues/issue-34721.stderr
src/test/ui/issues/issue-38857.stderr
src/test/ui/issues/issue-40402-ref-hints/issue-40402-1.stderr
src/test/ui/issues/issue-40402-ref-hints/issue-40402-2.stderr
src/test/ui/issues/issue-41880.stderr
src/test/ui/issues/issue-48364.stderr
src/test/ui/issues/issue-51154.stderr
src/test/ui/issues/issue-61108.stderr
src/test/ui/issues/issue-64559.stderr
src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr
src/test/ui/issues/issue-7607-1.stderr
src/test/ui/issues/issue-83924.stderr
src/test/ui/iterators/collect-into-array.rs
src/test/ui/iterators/collect-into-array.stderr
src/test/ui/iterators/collect-into-slice.rs
src/test/ui/iterators/collect-into-slice.stderr
src/test/ui/iterators/invalid-iterator-chain.rs [new file with mode: 0644]
src/test/ui/iterators/invalid-iterator-chain.stderr [new file with mode: 0644]
src/test/ui/iterators/vec-on-unimplemented.stderr
src/test/ui/lazy-type-alias-impl-trait/branches.stderr
src/test/ui/lazy-type-alias-impl-trait/branches3.stderr
src/test/ui/lazy-type-alias-impl-trait/recursion4.stderr
src/test/ui/lifetimes/conflicting-bounds.rs [new file with mode: 0644]
src/test/ui/lifetimes/conflicting-bounds.stderr [new file with mode: 0644]
src/test/ui/lifetimes/issue-34979.stderr
src/test/ui/limits/issue-55878.stderr
src/test/ui/lint/invalid_value.stderr
src/test/ui/lint/lint-const-item-mutation.stderr
src/test/ui/loops/issue-82916.stderr
src/test/ui/macros/format-args-temporaries-in-write.stderr
src/test/ui/macros/macro-name-typo.stderr
src/test/ui/macros/macro-path-prelude-fail-3.stderr
src/test/ui/macros/unknown-builtin.stderr
src/test/ui/malformed/malformed-derive-entry.stderr
src/test/ui/match/match-unresolved-one-arm.stderr
src/test/ui/methods/method-call-err-msg.stderr
src/test/ui/methods/method-call-lifetime-args-unresolved.stderr
src/test/ui/methods/method-not-found-generic-arg-elision.stderr
src/test/ui/mismatched_types/assignment-operator-unimplemented.stderr
src/test/ui/mismatched_types/closure-arg-count.stderr
src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr
src/test/ui/mismatched_types/issue-35030.stderr
src/test/ui/mismatched_types/issue-36053-2.stderr
src/test/ui/mismatched_types/issue-47706-trait.stderr
src/test/ui/mismatched_types/issue-47706.stderr
src/test/ui/mismatched_types/issue-74918-missing-lifetime.stderr
src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr
src/test/ui/mismatched_types/similar_paths.stderr
src/test/ui/moves/issue-99470-move-out-of-some.stderr
src/test/ui/moves/move-fn-self-receiver.stderr
src/test/ui/moves/move-out-of-array-ref.stderr
src/test/ui/moves/move-out-of-slice-1.stderr
src/test/ui/moves/move-out-of-slice-2.rs
src/test/ui/moves/move-out-of-slice-2.stderr
src/test/ui/moves/moves-based-on-type-access-to-field.stderr
src/test/ui/moves/moves-based-on-type-block-bad.stderr
src/test/ui/moves/moves-based-on-type-exprs.stderr
src/test/ui/never_type/fallback-closure-wrap.fallback.stderr
src/test/ui/never_type/feature-gate-never_type_fallback.stderr
src/test/ui/never_type/issue-52443.stderr
src/test/ui/never_type/issue-96335.stderr
src/test/ui/nll/cannot-move-block-spans.stderr
src/test/ui/nll/issue-52059-report-when-borrow-and-drop-conflict.stderr
src/test/ui/nll/move-errors.stderr
src/test/ui/no-capture-arc.stderr
src/test/ui/no-reuse-move-arc.stderr
src/test/ui/no-send-res-ports.stderr
src/test/ui/not-clone-closure.stderr
src/test/ui/numeric/uppercase-base-prefix-invalid-no-fix.rs [new file with mode: 0644]
src/test/ui/numeric/uppercase-base-prefix-invalid-no-fix.stderr [new file with mode: 0644]
src/test/ui/on-unimplemented/sum.stderr
src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr
src/test/ui/overloaded/overloaded-calls-nontuple.stderr
src/test/ui/parser/increment-autofix-2.fixed [new file with mode: 0644]
src/test/ui/parser/increment-autofix-2.rs [new file with mode: 0644]
src/test/ui/parser/increment-autofix-2.stderr [new file with mode: 0644]
src/test/ui/parser/increment-notfixed.rs [deleted file]
src/test/ui/parser/increment-notfixed.stderr [deleted file]
src/test/ui/parser/issue-104867-inc-dec-2.rs [new file with mode: 0644]
src/test/ui/parser/issue-104867-inc-dec-2.stderr [new file with mode: 0644]
src/test/ui/parser/issue-104867-inc-dec.rs [new file with mode: 0644]
src/test/ui/parser/issue-104867-inc-dec.stderr [new file with mode: 0644]
src/test/ui/parser/issue-105366.fixed [new file with mode: 0644]
src/test/ui/parser/issue-105366.rs [new file with mode: 0644]
src/test/ui/parser/issue-105366.stderr [new file with mode: 0644]
src/test/ui/parser/issues/issue-62894.stderr
src/test/ui/parser/kw-in-trait-bounds.stderr
src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.fixed [new file with mode: 0644]
src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.rs [new file with mode: 0644]
src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.stderr [new file with mode: 0644]
src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes.rs
src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes.stderr
src/test/ui/pattern/pat-tuple-bad-type.stderr
src/test/ui/pattern/rest-pat-semantic-disallowed.stderr
src/test/ui/pattern/suggest-adding-appropriate-missing-pattern-excluding-comments.stderr
src/test/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr
src/test/ui/pattern/usefulness/issue-35609.stderr
src/test/ui/pattern/usefulness/issue-3601.stderr
src/test/ui/pattern/usefulness/match-arm-statics-2.stderr
src/test/ui/pattern/usefulness/match-privately-empty.stderr
src/test/ui/pattern/usefulness/non-exhaustive-match.stderr
src/test/ui/print_type_sizes/async.rs
src/test/ui/print_type_sizes/async.stdout
src/test/ui/print_type_sizes/generator.rs
src/test/ui/print_type_sizes/generator_discr_placement.rs [new file with mode: 0644]
src/test/ui/print_type_sizes/generator_discr_placement.stdout [new file with mode: 0644]
src/test/ui/print_type_sizes/generics.rs
src/test/ui/print_type_sizes/multiple_types.rs
src/test/ui/print_type_sizes/niche-filling.rs
src/test/ui/print_type_sizes/no_duplicates.rs
src/test/ui/print_type_sizes/packed.rs
src/test/ui/print_type_sizes/padding.rs
src/test/ui/print_type_sizes/repr-align.rs
src/test/ui/print_type_sizes/repr_int_c.rs
src/test/ui/print_type_sizes/uninhabited.rs
src/test/ui/print_type_sizes/variants.rs
src/test/ui/print_type_sizes/zero-sized-fields.rs
src/test/ui/privacy/associated-item-privacy-trait.rs
src/test/ui/privacy/associated-item-privacy-trait.stderr
src/test/ui/privacy/private-inferred-type-3.rs
src/test/ui/privacy/private-inferred-type-3.stderr
src/test/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr
src/test/ui/proc-macro/parent-source-spans.stderr
src/test/ui/proc-macro/resolve-error.stderr
src/test/ui/proc-macro/signature.stderr
src/test/ui/proc-macro/span-api-tests.rs
src/test/ui/range/range-1.stderr
src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr
src/test/ui/resolve/issue-104700-inner_scope.rs [new file with mode: 0644]
src/test/ui/resolve/issue-104700-inner_scope.stderr [new file with mode: 0644]
src/test/ui/resolve/issue-85348.stderr
src/test/ui/resolve/levenshtein.stderr
src/test/ui/resolve/resolve-primitive-fallback.stderr
src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr
src/test/ui/rfc-2005-default-binding-mode/for.stderr
src/test/ui/rfc-2361-dbg-macro/dbg-macro-move-semantics.stderr
src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr
src/test/ui/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr
src/test/ui/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr
src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr
src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr
src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr
src/test/ui/span/issue-39018.stderr
src/test/ui/span/issue-71363.rs
src/test/ui/span/method-and-field-eager-resolution.stderr
src/test/ui/span/missing-unit-argument.stderr
src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr
src/test/ui/stability-attribute/stability-in-private-module.stderr
src/test/ui/std-uncopyable-atomics.stderr
src/test/ui/str/str-idx.stderr
src/test/ui/str/str-mut-idx.stderr
src/test/ui/suggestions/args-instead-of-tuple-errors.stderr
src/test/ui/suggestions/args-instead-of-tuple.stderr
src/test/ui/suggestions/as-ref-2.stderr
src/test/ui/suggestions/attribute-typos.stderr
src/test/ui/suggestions/borrow-for-loop-head.stderr
src/test/ui/suggestions/bound-suggestions.stderr
src/test/ui/suggestions/clone-on-unconstrained-borrowed-type-param.fixed [new file with mode: 0644]
src/test/ui/suggestions/clone-on-unconstrained-borrowed-type-param.rs [new file with mode: 0644]
src/test/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr [new file with mode: 0644]
src/test/ui/suggestions/derive-clone-for-eq.stderr
src/test/ui/suggestions/derive-trait-for-method-call.stderr
src/test/ui/suggestions/do-not-attempt-to-add-suggestions-with-no-changes.stderr
src/test/ui/suggestions/dont-suggest-ref/duplicate-suggestions.rs
src/test/ui/suggestions/dont-suggest-ref/duplicate-suggestions.stderr
src/test/ui/suggestions/dont-suggest-ref/move-into-closure.rs
src/test/ui/suggestions/dont-suggest-ref/move-into-closure.stderr
src/test/ui/suggestions/dont-suggest-ref/simple.rs
src/test/ui/suggestions/dont-suggest-ref/simple.stderr
src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr
src/test/ui/suggestions/for-i-in-vec.stderr
src/test/ui/suggestions/imm-ref-trait-object.stderr
src/test/ui/suggestions/import-trait-for-method-call.stderr
src/test/ui/suggestions/issue-104287.stderr
src/test/ui/suggestions/issue-62843.stderr
src/test/ui/suggestions/issue-71394-no-from-impl.stderr
src/test/ui/suggestions/issue-89064.stderr
src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr
src/test/ui/suggestions/option-content-move-from-tuple-match.stderr
src/test/ui/suggestions/option-content-move.stderr
src/test/ui/suggestions/restrict-type-not-param.stderr
src/test/ui/suggestions/sugg-else-for-closure.stderr
src/test/ui/suggestions/suggest-change-mut.stderr
src/test/ui/suggestions/suggest-tryinto-edition-change.stderr
src/test/ui/suggestions/type-ascription-instead-of-path-in-type.stderr
src/test/ui/traits/alias/generic-default-in-dyn.stderr
src/test/ui/traits/alias/object-fail.stderr
src/test/ui/traits/assoc-type-in-superbad.rs
src/test/ui/traits/assoc-type-in-superbad.stderr
src/test/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr
src/test/ui/traits/bad-sized.stderr
src/test/ui/traits/issue-77982.stderr
src/test/ui/traits/issue-85735.stderr
src/test/ui/traits/issue-97576.stderr
src/test/ui/traits/mutual-recursion-issue-75860.stderr
src/test/ui/traits/suggest-deferences/issue-39029.stderr
src/test/ui/traits/suggest-deferences/root-obligation.stderr
src/test/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.fixed [new file with mode: 0644]
src/test/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.rs [new file with mode: 0644]
src/test/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.stderr [new file with mode: 0644]
src/test/ui/traits/suggest-where-clause.stderr
src/test/ui/transmutability/issue-101739-2.stderr
src/test/ui/tuple/wrong_argument_ice-3.stderr
src/test/ui/tuple/wrong_argument_ice.stderr
src/test/ui/type-alias-impl-trait/closures_in_branches.stderr
src/test/ui/type-alias-impl-trait/issue-57961.rs
src/test/ui/type-alias-impl-trait/issue-57961.stderr
src/test/ui/type/ascription/issue-34255-1.stderr
src/test/ui/type/type-annotation-needed.stderr
src/test/ui/type/type-ascription-instead-of-initializer.stderr
src/test/ui/type/type-ascription-precedence.stderr
src/test/ui/type/type-check/issue-40294.stderr
src/test/ui/type/type-check/unknown_type_for_closure.stderr
src/test/ui/type/type-path-err-node-types.stderr
src/test/ui/type_length_limit.stderr
src/test/ui/typeck/explain_clone_autoref.stderr
src/test/ui/typeck/issue-46112.stderr
src/test/ui/typeck/issue-75883.stderr
src/test/ui/typeck/issue-83693.stderr
src/test/ui/typeck/issue-84768.stderr
src/test/ui/typeck/issue-92481.rs [new file with mode: 0644]
src/test/ui/typeck/issue-92481.stderr [new file with mode: 0644]
src/test/ui/typeck/struct-enum-wrong-args.stderr
src/test/ui/typeck/typeck-builtin-bound-type-parameters.stderr
src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr
src/test/ui/unboxed-closures/non-tupled-arg-mismatch.stderr
src/test/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.stderr
src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr
src/test/ui/union/union-borrow-move-parent-sibling.mirunsafeck.stderr
src/test/ui/union/union-borrow-move-parent-sibling.thirunsafeck.stderr
src/test/ui/union/union-derive-clone.mirunsafeck.stderr
src/test/ui/union/union-derive-clone.thirunsafeck.stderr
src/test/ui/union/union-derive-eq.mirunsafeck.stderr
src/test/ui/union/union-derive-eq.thirunsafeck.stderr
src/test/ui/unique-object-noncopyable.stderr
src/test/ui/unique-pinned-nocopy.stderr
src/test/ui/unop-move-semantics.stderr
src/test/ui/unsized-locals/borrow-after-move.stderr
src/test/ui/unsized-locals/double-move.stderr
src/test/ui/unsized/issue-71659.stderr
src/test/ui/use/use-after-move-self-based-on-type.stderr
src/test/ui/use/use-after-move-self.stderr
src/test/ui/walk-struct-literal-with.stderr
src/test/ui/wf/hir-wf-check-erase-regions.stderr
src/test/ui/wf/wf-impl-self-type.stderr
src/tools/cargo
src/tools/clippy/clippy_lints/src/dereference.rs
src/tools/clippy/clippy_lints/src/derive.rs
src/tools/clippy/clippy_lints/src/future_not_send.rs
src/tools/clippy/clippy_lints/src/len_zero.rs
src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
src/tools/clippy/clippy_utils/src/ty.rs
src/tools/compiletest/src/runtest.rs
src/tools/miri/src/machine.rs
src/tools/tidy/src/deps.rs
triagebot.toml

index 2b6e96b467e3555d0611aa845aabd522b575714c..b29b3a418038ee4407809a38b67f67b7dcf3a010 100644 (file)
@@ -301,7 +301,7 @@ jobs:
           - name: dist-x86_64-apple
             env:
               SCRIPT: "./x.py dist bootstrap --include-default-paths --host=x86_64-apple-darwin --target=x86_64-apple-darwin"
-              RUST_CONFIGURE_ARGS: "--enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false --set rust.lto=thin"
+              RUST_CONFIGURE_ARGS: "--enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false"
               RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
               MACOSX_DEPLOYMENT_TARGET: 10.7
               SELECT_XCODE: /Applications/Xcode_13.4.1.app
index 5c1990bb6c97bca9952a7bdefe4151cf24511a56..770dee7b54616dfdd0483f837d412d79a9b44ee5 100644 (file)
@@ -1,3 +1,94 @@
+Version 1.66.0 (2022-12-15)
+==========================
+
+Language
+--------
+- [Permit specifying explicit discriminants on all `repr(Int)` enums](https://github.com/rust-lang/rust/pull/95710/)
+  ```rust
+  #[repr(u8)]
+  enum Foo {
+      A(u8) = 0,
+      B(i8) = 1,
+      C(bool) = 42,
+  }
+  ```
+- [Allow transmutes between the same type differing only in lifetimes](https://github.com/rust-lang/rust/pull/101520/)
+- [Change constant evaluation errors from a deny-by-default lint to a hard error](https://github.com/rust-lang/rust/pull/102091/)
+- [Trigger `must_use` on `impl Trait` for supertraits](https://github.com/rust-lang/rust/pull/102287/)
+  This makes `impl ExactSizeIterator` respect the existing `#[must_use]` annotation on `Iterator`.
+- [Allow `..=X` in patterns](https://github.com/rust-lang/rust/pull/102275/)
+- [Uplift `clippy::for_loops_over_fallibles` lint into rustc](https://github.com/rust-lang/rust/pull/99696/)
+- [Stabilize `sym` operands in inline assembly](https://github.com/rust-lang/rust/pull/103168/)
+- [Update to Unicode 15](https://github.com/rust-lang/rust/pull/101912/)
+- [Opaque types no longer imply lifetime bounds](https://github.com/rust-lang/rust/pull/95474/)
+  This is a soundness fix which may break code that was erroneously relying on this behavior.
+
+Compiler
+--------
+- [Add armv5te-none-eabi and thumbv5te-none-eabi tier 3 targets](https://github.com/rust-lang/rust/pull/101329/)
+  - Refer to Rust's [platform support page][platform-support-doc] for more
+    information on Rust's tiered platform support.
+- [Add support for linking against macOS universal libraries](https://github.com/rust-lang/rust/pull/98736)
+
+Libraries
+---------
+- [Fix `#[derive(Default)]` on a generic `#[default]` enum adding unnecessary `Default` bounds](https://github.com/rust-lang/rust/pull/101040/)
+- [Update to Unicode 15](https://github.com/rust-lang/rust/pull/101821/)
+
+Stabilized APIs
+---------------
+
+- [`proc_macro::Span::source_text`](https://doc.rust-lang.org/stable/proc_macro/struct.Span.html#method.source_text)
+- [`uX::{checked_add_signed, overflowing_add_signed, saturating_add_signed, wrapping_add_signed}`](https://doc.rust-lang.org/stable/std/primitive.u8.html#method.checked_add_signed)
+- [`iX::{checked_add_unsigned, overflowing_add_unsigned, saturating_add_unsigned, wrapping_add_unsigned}`](https://doc.rust-lang.org/stable/std/primitive.i8.html#method.checked_add_unsigned)
+- [`iX::{checked_sub_unsigned, overflowing_sub_unsigned, saturating_sub_unsigned, wrapping_sub_unsigned}`](https://doc.rust-lang.org/stable/std/primitive.i8.html#method.checked_sub_unsigned)
+- [`BTreeSet::{first, last, pop_first, pop_last}`](https://doc.rust-lang.org/stable/std/collections/struct.BTreeSet.html#method.first)
+- [`BTreeMap::{first_key_value, last_key_value, first_entry, last_entry, pop_first, pop_last}`](https://doc.rust-lang.org/stable/std/collections/struct.BTreeMap.html#method.first_key_value)
+- [Add `AsFd` implementations for stdio lock types on WASI.](https://github.com/rust-lang/rust/pull/101768/)
+- [`impl TryFrom<Vec<T>> for Box<[T; N]>`](https://doc.rust-lang.org/stable/std/boxed/struct.Box.html#impl-TryFrom%3CVec%3CT%2C%20Global%3E%3E-for-Box%3C%5BT%3B%20N%5D%2C%20Global%3E)
+- [`core::hint::black_box`](https://doc.rust-lang.org/stable/std/hint/fn.black_box.html)
+- [`Duration::try_from_secs_{f32,f64}`](https://doc.rust-lang.org/stable/std/time/struct.Duration.html#method.try_from_secs_f32)
+- [`Option::unzip`](https://doc.rust-lang.org/stable/std/option/enum.Option.html#method.unzip)
+- [`std::os::fd`](https://doc.rust-lang.org/stable/std/os/fd/index.html)
+
+
+Rustdoc
+-------
+
+- [Add Rustdoc warning for invalid HTML tags in the documentation](https://github.com/rust-lang/rust/pull/101720/)
+
+Cargo
+-----
+
+- [Added `cargo remove` to remove dependencies from Cargo.toml](https://doc.rust-lang.org/nightly/cargo/commands/cargo-remove.html)
+- [`cargo publish` now waits for the new version to be downloadable before exiting](https://github.com/rust-lang/cargo/pull/11062)
+
+See [detailed release notes](https://github.com/rust-lang/cargo/blob/master/CHANGELOG.md#cargo-166-2022-12-15) for more.
+
+Compatibility Notes
+-------------------
+
+- [Only apply `ProceduralMasquerade` hack to older versions of `rental`](https://github.com/rust-lang/rust/pull/94063/)
+- [Don't export `__heap_base` and `__data_end` on wasm32-wasi.](https://github.com/rust-lang/rust/pull/102385/)
+- [Don't export `__wasm_init_memory` on WebAssembly.](https://github.com/rust-lang/rust/pull/102426/)
+- [Only export `__tls_*` on wasm32-unknown-unknown.](https://github.com/rust-lang/rust/pull/102440/)
+- [Don't link to `libresolv` in libstd on Darwin](https://github.com/rust-lang/rust/pull/102766/)
+- [Update libstd's libc to 0.2.135 (to make `libstd` no longer pull in `libiconv.dylib` on Darwin)](https://github.com/rust-lang/rust/pull/103277/)
+- [Opaque types no longer imply lifetime bounds](https://github.com/rust-lang/rust/pull/95474/)
+  This is a soundness fix which may break code that was erroneously relying on this behavior.
+- [Make `order_dependent_trait_objects` show up in future-breakage reports](https://github.com/rust-lang/rust/pull/102635/)
+- [Change std::process::Command spawning to default to inheriting the parent's signal mask](https://github.com/rust-lang/rust/pull/101077/)
+
+Internal Changes
+----------------
+
+These changes do not affect any public interfaces of Rust, but they represent
+significant improvements to the performance or internals of rustc and related
+tools.
+
+- [Enable BOLT for LLVM compilation](https://github.com/rust-lang/rust/pull/94381/)
+- [Enable LTO for rustc_driver.so](https://github.com/rust-lang/rust/pull/101403/)
+
 Version 1.65.0 (2022-11-03)
 ==========================
 
index 4ca59144b29902ebf2377ae220e5c9f8678f9a10..8c71332bfabb13d9f45813414978a05c1c9c2fcc 100644 (file)
@@ -802,12 +802,9 @@ pub fn fit_unsigned(x: u128) -> Integer {
     pub fn for_align<C: HasDataLayout>(cx: &C, wanted: Align) -> Option<Integer> {
         let dl = cx.data_layout();
 
-        for candidate in [I8, I16, I32, I64, I128] {
-            if wanted == candidate.align(dl).abi && wanted.bytes() == candidate.size().bytes() {
-                return Some(candidate);
-            }
-        }
-        None
+        [I8, I16, I32, I64, I128].into_iter().find(|&candidate| {
+            wanted == candidate.align(dl).abi && wanted.bytes() == candidate.size().bytes()
+        })
     }
 
     /// Find the largest integer with the given alignment or less.
index 2e86970bcfdc7d1ae84ff14adb70cd2bd9a26311..f933b9b161ca91f56bfb0db9e3f39eaae37e4d54 100644 (file)
@@ -2466,7 +2466,7 @@ pub enum ModKind {
     Unloaded,
 }
 
-#[derive(Copy, Clone, Encodable, Decodable, Debug)]
+#[derive(Copy, Clone, Encodable, Decodable, Debug, Default)]
 pub struct ModSpans {
     /// `inner_span` covers the body of the module; for a file module, its the whole file.
     /// For an inline module, its the span inside the `{ ... }`, not including the curly braces.
@@ -2474,12 +2474,6 @@ pub struct ModSpans {
     pub inject_use_span: Span,
 }
 
-impl Default for ModSpans {
-    fn default() -> ModSpans {
-        ModSpans { inner_span: Default::default(), inject_use_span: Default::default() }
-    }
-}
-
 /// Foreign module declaration.
 ///
 /// E.g., `extern { .. }` or `extern "C" { .. }`.
index c0cc4e79a3d53161b3e985c45ba1daae69ee0efc..7b8c0d79a17e8519f3fc79a3f65149db2f2537dc 100644 (file)
@@ -114,7 +114,7 @@ pub fn from_token(token: &Token) -> Option<Lit> {
                 if let NtExpr(expr) | NtLiteral(expr) = &**nt
                 && let ast::ExprKind::Lit(token_lit) = expr.kind =>
             {
-                Some(token_lit.clone())
+                Some(token_lit)
             }
             _ => None,
         }
index 3946aab646a1a5b5694b2ed82b2a3039b0dbb3f1..e86e807279d6f10157264705e42e49c8b8c872d0 100644 (file)
@@ -31,6 +31,44 @@ pub(super) fn lower_expr(&mut self, e: &Expr) -> &'hir hir::Expr<'hir> {
 
     pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'hir> {
         ensure_sufficient_stack(|| {
+            match &e.kind {
+                // Paranthesis expression does not have a HirId and is handled specially.
+                ExprKind::Paren(ex) => {
+                    let mut ex = self.lower_expr_mut(ex);
+                    // Include parens in span, but only if it is a super-span.
+                    if e.span.contains(ex.span) {
+                        ex.span = self.lower_span(e.span);
+                    }
+                    // Merge attributes into the inner expression.
+                    if !e.attrs.is_empty() {
+                        let old_attrs =
+                            self.attrs.get(&ex.hir_id.local_id).map(|la| *la).unwrap_or(&[]);
+                        self.attrs.insert(
+                            ex.hir_id.local_id,
+                            &*self.arena.alloc_from_iter(
+                                e.attrs
+                                    .iter()
+                                    .map(|a| self.lower_attr(a))
+                                    .chain(old_attrs.iter().cloned()),
+                            ),
+                        );
+                    }
+                    return ex;
+                }
+                // Desugar `ExprForLoop`
+                // from: `[opt_ident]: for <pat> in <head> <body>`
+                //
+                // This also needs special handling because the HirId of the returned `hir::Expr` will not
+                // correspond to the `e.id`, so `lower_expr_for` handles attribute lowering itself.
+                ExprKind::ForLoop(pat, head, body, opt_label) => {
+                    return self.lower_expr_for(e, pat, head, body, *opt_label);
+                }
+                _ => (),
+            }
+
+            let hir_id = self.lower_node_id(e.id);
+            self.lower_attrs(hir_id, &e.attrs);
+
             let kind = match &e.kind {
                 ExprKind::Box(inner) => hir::ExprKind::Box(self.lower_expr(inner)),
                 ExprKind::Array(exprs) => hir::ExprKind::Array(self.lower_exprs(exprs)),
@@ -48,7 +86,6 @@ pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'hir> {
                     if e.attrs.get(0).map_or(false, |a| a.has_name(sym::rustc_box)) {
                         if let [inner] = &args[..] && e.attrs.len() == 1 {
                             let kind = hir::ExprKind::Box(self.lower_expr(&inner));
-                            let hir_id = self.lower_node_id(e.id);
                             return hir::Expr { hir_id, kind, span: self.lower_span(e.span) };
                         } else {
                             self.tcx.sess.emit_err(RustcBoxAttributeError { span: e.span });
@@ -147,7 +184,7 @@ pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'hir> {
                 ),
                 ExprKind::Async(capture_clause, closure_node_id, block) => self.make_async_expr(
                     *capture_clause,
-                    None,
+                    hir_id,
                     *closure_node_id,
                     None,
                     e.span,
@@ -184,6 +221,7 @@ pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'hir> {
                             binder,
                             *capture_clause,
                             e.id,
+                            hir_id,
                             *closure_id,
                             fn_decl,
                             body,
@@ -279,39 +317,12 @@ pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'hir> {
                 ExprKind::Yield(opt_expr) => self.lower_expr_yield(e.span, opt_expr.as_deref()),
                 ExprKind::Err => hir::ExprKind::Err,
                 ExprKind::Try(sub_expr) => self.lower_expr_try(e.span, sub_expr),
-                ExprKind::Paren(ex) => {
-                    let mut ex = self.lower_expr_mut(ex);
-                    // Include parens in span, but only if it is a super-span.
-                    if e.span.contains(ex.span) {
-                        ex.span = self.lower_span(e.span);
-                    }
-                    // Merge attributes into the inner expression.
-                    if !e.attrs.is_empty() {
-                        let old_attrs =
-                            self.attrs.get(&ex.hir_id.local_id).map(|la| *la).unwrap_or(&[]);
-                        self.attrs.insert(
-                            ex.hir_id.local_id,
-                            &*self.arena.alloc_from_iter(
-                                e.attrs
-                                    .iter()
-                                    .map(|a| self.lower_attr(a))
-                                    .chain(old_attrs.iter().cloned()),
-                            ),
-                        );
-                    }
-                    return ex;
-                }
 
-                // Desugar `ExprForLoop`
-                // from: `[opt_ident]: for <pat> in <head> <body>`
-                ExprKind::ForLoop(pat, head, body, opt_label) => {
-                    return self.lower_expr_for(e, pat, head, body, *opt_label);
-                }
+                ExprKind::Paren(_) | ExprKind::ForLoop(..) => unreachable!("already handled"),
+
                 ExprKind::MacCall(_) => panic!("{:?} shouldn't exist here", e.span),
             };
 
-            let hir_id = self.lower_node_id(e.id);
-            self.lower_attrs(hir_id, &e.attrs);
             hir::Expr { hir_id, kind, span: self.lower_span(e.span) }
         })
     }
@@ -576,7 +587,7 @@ fn lower_arm(&mut self, arm: &Arm) -> hir::Arm<'hir> {
     pub(super) fn make_async_expr(
         &mut self,
         capture_clause: CaptureBy,
-        outer_hir_id: Option<hir::HirId>,
+        outer_hir_id: hir::HirId,
         closure_node_id: NodeId,
         ret_ty: Option<hir::FnRetTy<'hir>>,
         span: Span,
@@ -669,8 +680,9 @@ pub(super) fn make_async_expr(
             hir::ExprKind::Closure(c)
         };
 
-        let track_caller = outer_hir_id
-            .and_then(|id| self.attrs.get(&id.local_id))
+        let track_caller = self
+            .attrs
+            .get(&outer_hir_id.local_id)
             .map_or(false, |attrs| attrs.into_iter().any(|attr| attr.has_name(sym::track_caller)));
 
         let hir_id = self.lower_node_id(closure_node_id);
@@ -985,6 +997,7 @@ fn lower_expr_async_closure(
         binder: &ClosureBinder,
         capture_clause: CaptureBy,
         closure_id: NodeId,
+        closure_hir_id: hir::HirId,
         inner_closure_id: NodeId,
         decl: &FnDecl,
         body: &Expr,
@@ -1018,9 +1031,7 @@ fn lower_expr_async_closure(
 
                 let async_body = this.make_async_expr(
                     capture_clause,
-                    // FIXME(nbdd0121): This should also use a proper HIR id so `#[track_caller]`
-                    // can be applied on async closures as well.
-                    None,
+                    closure_hir_id,
                     inner_closure_id,
                     async_ret_ty,
                     body.span,
index d73d6d3918ea618dde2c3bbaa77e0954c73f5627..73065ab516350fe33c50fae50de39a228278340f 100644 (file)
@@ -1139,7 +1139,7 @@ fn lower_maybe_async_body(
 
             let async_expr = this.make_async_expr(
                 CaptureBy::Value,
-                Some(fn_id),
+                fn_id,
                 closure_id,
                 None,
                 body.span,
index 32f45f8b59e90a4050a7a41fb525d93ed9609ae5..039338f543cc591b19b88055b80f6888d47a9310 100644 (file)
@@ -630,7 +630,7 @@ fn check_incompatible_features(sess: &Session) {
             {
                 let spans = vec![f1_span, f2_span];
                 sess.struct_span_err(
-                    spans.clone(),
+                    spans,
                     &format!(
                         "features `{}` and `{}` are incompatible, using them at the same time \
                         is not allowed",
index 5e3745f17353af8543cc8cbdf52dcf7b1e25cfd6..72c0257756ef2f15d1adfdc8f47a2e143ced6ccc 100644 (file)
@@ -697,8 +697,8 @@ fn suggest_borrow_fn_like(
                     .map_bound(|p| p.predicates),
                 None,
             ),
-            ty::Opaque(did, substs) => {
-                find_fn_kind_from_did(tcx.bound_explicit_item_bounds(*did), Some(*substs))
+            ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
+                find_fn_kind_from_did(tcx.bound_explicit_item_bounds(*def_id), Some(*substs))
             }
             ty::Closure(_, substs) => match substs.as_closure().kind() {
                 ty::ClosureKind::Fn => Some(hir::Mutability::Not),
@@ -745,7 +745,7 @@ fn suggest_cloning(&self, err: &mut Diagnostic, ty: Ty<'tcx>, span: Span) {
             err.span_suggestion_verbose(
                 span.shrink_to_hi(),
                 "consider cloning the value if the performance cost is acceptable",
-                ".clone()".to_string(),
+                ".clone()",
                 Applicability::MachineApplicable,
             );
         }
index 4e2271a30672270a5ff8c49c1b4460ab8c11938b..cbd590052008c14a46f3ab0b099ea517ef6f7ce9 100644 (file)
@@ -1059,17 +1059,12 @@ fn explain_captures(
                     );
                     if self.fn_self_span_reported.insert(fn_span) {
                         err.span_note(
-                            // Check whether the source is accessible
-                            if self.infcx.tcx.sess.source_map().is_span_accessible(self_arg.span) {
-                                self_arg.span
-                            } else {
-                                fn_call_span
-                            },
+                            self_arg.span,
                             "calling this operator moves the left-hand side",
                         );
                     }
                 }
-                CallKind::Normal { self_arg, desugaring, is_option_or_result } => {
+                CallKind::Normal { self_arg, desugaring, method_did } => {
                     let self_arg = self_arg.unwrap();
                     if let Some((CallDesugaringKind::ForLoopIntoIter, _)) = desugaring {
                         let ty = moved_place.ty(self.body, self.infcx.tcx).ty;
@@ -1139,14 +1134,27 @@ fn explain_captures(
                             ),
                         );
                     }
+                    let tcx = self.infcx.tcx;
                     // Avoid pointing to the same function in multiple different
                     // error messages.
                     if span != DUMMY_SP && self.fn_self_span_reported.insert(self_arg.span) {
+                        let func = tcx.def_path_str(method_did);
                         err.span_note(
                             self_arg.span,
-                            &format!("this function takes ownership of the receiver `self`, which moves {}", place_name)
+                            &format!("`{func}` takes ownership of the receiver `self`, which moves {place_name}")
                         );
                     }
+                    let parent_did = tcx.parent(method_did);
+                    let parent_self_ty = (tcx.def_kind(parent_did)
+                        == rustc_hir::def::DefKind::Impl)
+                        .then_some(parent_did)
+                        .and_then(|did| match tcx.type_of(did).kind() {
+                            ty::Adt(def, ..) => Some(def.did()),
+                            _ => None,
+                        });
+                    let is_option_or_result = parent_self_ty.map_or(false, |def_id| {
+                        matches!(tcx.get_diagnostic_name(def_id), Some(sym::Option | sym::Result))
+                    });
                     if is_option_or_result && maybe_reinitialized_locations_is_empty {
                         err.span_label(
                             var_span,
index 5a47f45677ecbfd1b546f4f74f5ec83e833687cf..6db3c858ae7149b9a138dbd77c7813c3eeea298e 100644 (file)
@@ -4,7 +4,7 @@
 use rustc_mir_dataflow::move_paths::{
     IllegalMoveOrigin, IllegalMoveOriginKind, LookupResult, MoveError, MovePathIndex,
 };
-use rustc_span::Span;
+use rustc_span::{BytePos, Span};
 
 use crate::diagnostics::{DescribePlaceOpt, UseSpans};
 use crate::prefixes::PrefixSet;
@@ -148,7 +148,7 @@ fn append_binding_error(
         match_span: Span,
         statement_span: Span,
     ) {
-        debug!("append_binding_error(match_place={:?}, match_span={:?})", match_place, match_span);
+        debug!(?match_place, ?match_span, "append_binding_error");
 
         let from_simple_let = match_place.is_none();
         let match_place = match_place.unwrap_or(move_from);
@@ -160,7 +160,7 @@ fn append_binding_error(
                     if let GroupedMoveError::MovesFromPlace { span, binds_to, .. } = ge
                         && match_span == *span
                     {
-                        debug!("appending local({:?}) to list", bind_to);
+                        debug!("appending local({bind_to:?}) to list");
                         if !binds_to.is_empty() {
                             binds_to.push(bind_to);
                         }
@@ -198,7 +198,7 @@ fn append_binding_error(
                     } = ge
                     {
                         if match_span == *span && mpi == *other_mpi {
-                            debug!("appending local({:?}) to list", bind_to);
+                            debug!("appending local({bind_to:?}) to list");
                             binds_to.push(bind_to);
                             return;
                         }
@@ -410,15 +410,7 @@ fn report_cannot_move_from_borrowed_content(
     fn add_move_hints(&self, error: GroupedMoveError<'tcx>, err: &mut Diagnostic, span: Span) {
         match error {
             GroupedMoveError::MovesFromPlace { mut binds_to, move_from, .. } => {
-                if let Ok(snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(span) {
-                    err.span_suggestion(
-                        span,
-                        "consider borrowing here",
-                        format!("&{snippet}"),
-                        Applicability::Unspecified,
-                    );
-                }
-
+                self.add_borrow_suggestions(err, span);
                 if binds_to.is_empty() {
                     let place_ty = move_from.ty(self.body, self.infcx.tcx).ty;
                     let place_desc = match self.describe_place(move_from.as_ref()) {
@@ -461,39 +453,75 @@ fn add_move_hints(&self, error: GroupedMoveError<'tcx>, err: &mut Diagnostic, sp
         }
     }
 
+    fn add_borrow_suggestions(&self, err: &mut Diagnostic, span: Span) {
+        match self.infcx.tcx.sess.source_map().span_to_snippet(span) {
+            Ok(snippet) if snippet.starts_with('*') => {
+                err.span_suggestion_verbose(
+                    span.with_hi(span.lo() + BytePos(1)),
+                    "consider removing the dereference here",
+                    String::new(),
+                    Applicability::MaybeIncorrect,
+                );
+            }
+            _ => {
+                err.span_suggestion_verbose(
+                    span.shrink_to_lo(),
+                    "consider borrowing here",
+                    "&".to_string(),
+                    Applicability::MaybeIncorrect,
+                );
+            }
+        }
+    }
+
     fn add_move_error_suggestions(&self, err: &mut Diagnostic, binds_to: &[Local]) {
-        let mut suggestions: Vec<(Span, &str, String)> = Vec::new();
+        let mut suggestions: Vec<(Span, String, String)> = Vec::new();
         for local in binds_to {
             let bind_to = &self.body.local_decls[*local];
             if let Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
                 VarBindingForm { pat_span, .. },
             )))) = bind_to.local_info
             {
-                if let Ok(pat_snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(pat_span)
+                let Ok(pat_snippet) =
+                    self.infcx.tcx.sess.source_map().span_to_snippet(pat_span) else { continue; };
+                let Some(stripped) = pat_snippet.strip_prefix('&') else {
+                    suggestions.push((
+                        bind_to.source_info.span.shrink_to_lo(),
+                        "consider borrowing the pattern binding".to_string(),
+                        "ref ".to_string(),
+                    ));
+                    continue;
+                };
+                let inner_pat_snippet = stripped.trim_start();
+                let (pat_span, suggestion, to_remove) = if inner_pat_snippet.starts_with("mut")
+                    && inner_pat_snippet["mut".len()..].starts_with(rustc_lexer::is_whitespace)
                 {
-                    if let Some(stripped) = pat_snippet.strip_prefix('&') {
-                        let pat_snippet = stripped.trim_start();
-                        let (suggestion, to_remove) = if pat_snippet.starts_with("mut")
-                            && pat_snippet["mut".len()..].starts_with(rustc_lexer::is_whitespace)
-                        {
-                            (pat_snippet["mut".len()..].trim_start(), "&mut")
-                        } else {
-                            (pat_snippet, "&")
-                        };
-                        suggestions.push((pat_span, to_remove, suggestion.to_owned()));
-                    }
-                }
+                    let inner_pat_snippet = inner_pat_snippet["mut".len()..].trim_start();
+                    let pat_span = pat_span.with_hi(
+                        pat_span.lo()
+                            + BytePos((pat_snippet.len() - inner_pat_snippet.len()) as u32),
+                    );
+                    (pat_span, String::new(), "mutable borrow")
+                } else {
+                    let pat_span = pat_span.with_hi(
+                        pat_span.lo()
+                            + BytePos(
+                                (pat_snippet.len() - inner_pat_snippet.trim_start().len()) as u32,
+                            ),
+                    );
+                    (pat_span, String::new(), "borrow")
+                };
+                suggestions.push((
+                    pat_span,
+                    format!("consider removing the {to_remove}"),
+                    suggestion.to_string(),
+                ));
             }
         }
         suggestions.sort_unstable_by_key(|&(span, _, _)| span);
         suggestions.dedup_by_key(|&mut (span, _, _)| span);
-        for (span, to_remove, suggestion) in suggestions {
-            err.span_suggestion(
-                span,
-                &format!("consider removing the `{to_remove}`"),
-                suggestion,
-                Applicability::MachineApplicable,
-            );
+        for (span, msg, suggestion) in suggestions {
+            err.span_suggestion_verbose(span, &msg, suggestion, Applicability::MachineApplicable);
         }
     }
 
@@ -521,8 +549,8 @@ fn add_move_error_details(&self, err: &mut Diagnostic, binds_to: &[Local]) {
 
         if binds_to.len() > 1 {
             err.note(
-                "move occurs because these variables have types that \
-                      don't implement the `Copy` trait",
+                "move occurs because these variables have types that don't implement the `Copy` \
+                 trait",
             );
         }
     }
index 9bc2e79e29bc17c9b96a77b7ca99013312159a76..f8ec5e5e799149c888e001dd4ddc1b488847c8d2 100644 (file)
@@ -504,7 +504,7 @@ fn report_fnmut_error(
         let ErrorConstraintInfo { outlived_fr, span, .. } = errci;
 
         let mut output_ty = self.regioncx.universal_regions().unnormalized_output_ty;
-        if let ty::Opaque(def_id, _) = *output_ty.kind() {
+        if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = *output_ty.kind() {
             output_ty = self.infcx.tcx.type_of(def_id)
         };
 
index 90e2b6b698cf832ec4a2d45e266e173369a3062f..e9c98bdc514967a63f4f1dc39be0e6be7d1919ed 100644 (file)
@@ -747,27 +747,14 @@ fn apply_member_constraint(
         // Otherwise, we need to find the minimum remaining choice, if
         // any, and take that.
         debug!("choice_regions remaining are {:#?}", choice_regions);
-        let min = |r1: ty::RegionVid, r2: ty::RegionVid| -> Option<ty::RegionVid> {
-            let r1_outlives_r2 = self.universal_region_relations.outlives(r1, r2);
-            let r2_outlives_r1 = self.universal_region_relations.outlives(r2, r1);
-            match (r1_outlives_r2, r2_outlives_r1) {
-                (true, true) => Some(r1.min(r2)),
-                (true, false) => Some(r2),
-                (false, true) => Some(r1),
-                (false, false) => None,
-            }
+        let Some(&min_choice) = choice_regions.iter().find(|&r1| {
+            choice_regions.iter().all(|&r2| {
+                self.universal_region_relations.outlives(r2, *r1)
+            })
+        }) else {
+            debug!("no choice region outlived by all others");
+            return false;
         };
-        let mut min_choice = choice_regions[0];
-        for &other_option in &choice_regions[1..] {
-            debug!(?min_choice, ?other_option,);
-            match min(min_choice, other_option) {
-                Some(m) => min_choice = m,
-                None => {
-                    debug!(?min_choice, ?other_option, "incomparable; no min choice",);
-                    return false;
-                }
-            }
-        }
 
         let min_choice_scc = self.constraint_sccs.scc(min_choice);
         debug!(?min_choice, ?min_choice_scc);
index 95e38e4b053f496604f25079b22722e2fbf3dc4b..dcf500ddbd3c8d9fc576d6eb8de1261a05f129b8 100644 (file)
@@ -32,7 +32,7 @@ pub fn expand(
             (item, true, ecx.with_def_site_ctxt(fn_kind.sig.span))
         } else {
             ecx.sess.parse_sess.span_diagnostic.span_err(item.span(), "alloc_error_handler must be a function");
-            return vec![orig_item.clone()];
+            return vec![orig_item];
         };
 
     // Generate a bunch of new items using the AllocFnFactory
index 4c424ea430bdf1f0b01872db872944d88b8aea36..4f1a7d709ff8c276900c255977d478fa9a3bec81 100644 (file)
@@ -196,7 +196,7 @@ pub fn expand_concat_bytes(
         }
     }
     if !missing_literals.is_empty() {
-        let mut err = cx.struct_span_err(missing_literals.clone(), "expected a byte literal");
+        let mut err = cx.struct_span_err(missing_literals, "expected a byte literal");
         err.note("only byte literals (like `b\"foo\"`, `b's'`, and `[3, 4, 5]`) can be passed to `concat_bytes!()`");
         err.emit();
         return base::MacEager::expr(DummyResult::raw_expr(sp, true));
index 732edd66196d7de4c3d8d18e0c944e05d279906c..d627c2ee09c4ef7555f820cc2a239b73c3133269 100644 (file)
@@ -12,8 +12,6 @@ task:
     folder: target
   prepare_script:
     - . $HOME/.cargo/env
-    - git config --global user.email "user@example.com"
-    - git config --global user.name "User"
     - ./y.rs prepare
   test_script:
     - . $HOME/.cargo/env
index 5061010c86cd3451d4b8e7858b05cecf7efc8631..a6bb12a66a247d66441c390105655e9ff0910978 100644 (file)
@@ -19,6 +19,7 @@ jobs:
     - name: Rustfmt
       run: |
         cargo fmt --check
+        rustfmt --check build_system/mod.rs
 
   build:
     runs-on: ${{ matrix.os }}
@@ -28,7 +29,7 @@ jobs:
       fail-fast: false
       matrix:
         include:
-          - os: ubuntu-latest
+          - os: ubuntu-20.04 # FIXME switch to ubuntu-22.04 once #1303 is fixed
             env:
               TARGET_TRIPLE: x86_64-unknown-linux-gnu
           - os: macos-latest
@@ -41,18 +42,22 @@ jobs:
           - os: ubuntu-latest
             env:
               TARGET_TRIPLE: aarch64-unknown-linux-gnu
+          # s390x requires QEMU 6.1 or greater, we could build it from source, but ubuntu 22.04 comes with 6.2 by default
+          - os: ubuntu-latest
+            env:
+              TARGET_TRIPLE: s390x-unknown-linux-gnu
 
     steps:
     - uses: actions/checkout@v3
 
     - name: Cache cargo installed crates
-      uses: actions/cache@v2
+      uses: actions/cache@v3
       with:
         path: ~/.cargo/bin
         key: ${{ runner.os }}-cargo-installed-crates
 
     - name: Cache cargo registry and index
-      uses: actions/cache@v2
+      uses: actions/cache@v3
       with:
         path: |
             ~/.cargo/registry
@@ -60,9 +65,9 @@ jobs:
         key: ${{ runner.os }}-cargo-registry-and-index-${{ hashFiles('**/Cargo.lock') }}
 
     - name: Cache cargo target dir
-      uses: actions/cache@v2
+      uses: actions/cache@v3
       with:
-        path: target
+        path: build/cg_clif
         key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
 
     - name: Install MinGW toolchain and wine
@@ -78,11 +83,14 @@ jobs:
         sudo apt-get update
         sudo apt-get install -y gcc-aarch64-linux-gnu qemu-user
 
-    - name: Prepare dependencies
+    - name: Install s390x toolchain and qemu
+      if: matrix.env.TARGET_TRIPLE == 's390x-unknown-linux-gnu'
       run: |
-        git config --global user.email "user@example.com"
-        git config --global user.name "User"
-        ./y.rs prepare
+        sudo apt-get update
+        sudo apt-get install -y gcc-s390x-linux-gnu qemu-user
+
+    - name: Prepare dependencies
+      run: ./y.rs prepare
 
     - name: Build without unstable features
       env:
@@ -110,7 +118,7 @@ jobs:
         ./y.rs test
 
     - name: Package prebuilt cg_clif
-      run: tar cvfJ cg_clif.tar.xz build
+      run: tar cvfJ cg_clif.tar.xz dist
 
     - name: Upload prebuilt cg_clif
       if: matrix.env.TARGET_TRIPLE != 'x86_64-pc-windows-gnu'
@@ -121,7 +129,7 @@ jobs:
 
     - name: Upload prebuilt cg_clif (cross compile)
       if: matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu'
-      uses: actions/upload-artifact@v2
+      uses: actions/upload-artifact@v3
       with:
         name: cg_clif-${{ runner.os }}-cross-x86_64-mingw
         path: cg_clif.tar.xz
@@ -147,13 +155,13 @@ jobs:
     - uses: actions/checkout@v3
 
     - name: Cache cargo installed crates
-      uses: actions/cache@v2
+      uses: actions/cache@v3
       with:
         path: ~/.cargo/bin
         key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-cargo-installed-crates
 
     - name: Cache cargo registry and index
-      uses: actions/cache@v2
+      uses: actions/cache@v3
       with:
         path: |
             ~/.cargo/registry
@@ -161,9 +169,9 @@ jobs:
         key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-cargo-registry-and-index-${{ hashFiles('**/Cargo.lock') }}
 
     - name: Cache cargo target dir
-      uses: actions/cache@v2
+      uses: actions/cache@v3
       with:
-        path: target
+        path: build/cg_clif
         key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
 
     - name: Set MinGW as the default toolchain
@@ -172,8 +180,6 @@ jobs:
 
     - name: Prepare dependencies
       run: |
-        git config --global user.email "user@example.com"
-        git config --global user.name "User"
         git config --global core.autocrlf false
         rustc y.rs -o y.exe -g
         ./y.exe prepare
@@ -198,24 +204,24 @@ jobs:
 
         # Enable extra checks
         $Env:CG_CLIF_ENABLE_VERIFIER=1
-        
+
         # WIP Disable some tests
-        
+
         # This fails due to some weird argument handling by hyperfine, not an actual regression
         # more of a build system issue
         (Get-Content config.txt) -replace '(bench.simple-raytracer)', '# $1' |  Out-File config.txt
-        
-        # This fails with a different output than expected 
+
+        # This fails with a different output than expected
         (Get-Content config.txt) -replace '(test.regex-shootout-regex-dna)', '# $1' |  Out-File config.txt
 
         ./y.exe test
 
     - name: Package prebuilt cg_clif
       # don't use compression as xzip isn't supported by tar on windows and bzip2 hangs
-      run: tar cvf cg_clif.tar build
+      run: tar cvf cg_clif.tar dist
 
     - name: Upload prebuilt cg_clif
-      uses: actions/upload-artifact@v2
+      uses: actions/upload-artifact@v3
       with:
         name: cg_clif-${{ matrix.env.TARGET_TRIPLE }}
         path: cg_clif.tar
index 0a3e7ca073b45debb68785811cf0f727a7e0bde7..d0d58d2a7eacbd19a07442af167bdb0e2926274a 100644 (file)
@@ -14,7 +14,7 @@ jobs:
     - uses: actions/checkout@v3
 
     - name: Cache cargo installed crates
-      uses: actions/cache@v2
+      uses: actions/cache@v3
       with:
         path: ~/.cargo/bin
         key: ubuntu-latest-cargo-installed-crates
index b8a98b83ebe5eb1a5d292f5fa6b2b7df1168a5a9..bef806318efa836aeeb8d6df06d880b77be677fb 100644 (file)
@@ -11,13 +11,13 @@ jobs:
     - uses: actions/checkout@v3
 
     - name: Cache cargo installed crates
-      uses: actions/cache@v2
+      uses: actions/cache@v3
       with:
         path: ~/.cargo/bin
         key: ${{ runner.os }}-cargo-installed-crates
 
     - name: Cache cargo registry and index
-      uses: actions/cache@v2
+      uses: actions/cache@v3
       with:
         path: |
             ~/.cargo/registry
@@ -25,9 +25,9 @@ jobs:
         key: ${{ runner.os }}-cargo-registry-and-index-${{ hashFiles('**/Cargo.lock') }}
 
     - name: Cache cargo target dir
-      uses: actions/cache@v2
+      uses: actions/cache@v3
       with:
-        path: target
+        path: build/cg_clif
         key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
 
     - name: Prepare dependencies
@@ -49,13 +49,13 @@ jobs:
     - uses: actions/checkout@v3
 
     - name: Cache cargo installed crates
-      uses: actions/cache@v2
+      uses: actions/cache@v3
       with:
         path: ~/.cargo/bin
         key: ${{ runner.os }}-cargo-installed-crates
 
     - name: Cache cargo registry and index
-      uses: actions/cache@v2
+      uses: actions/cache@v3
       with:
         path: |
             ~/.cargo/registry
@@ -63,9 +63,9 @@ jobs:
         key: ${{ runner.os }}-cargo-registry-and-index-${{ hashFiles('**/Cargo.lock') }}
 
     - name: Cache cargo target dir
-      uses: actions/cache@v2
+      uses: actions/cache@v3
       with:
-        path: target
+        path: build/cg_clif
         key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
 
     - name: Prepare dependencies
index fae09592c6ac0dc91be2641093896c0adc9559d8..b443fd58a1b98344bec2720e26139b6467907d89 100644 (file)
@@ -14,5 +14,6 @@ perf.data.old
 /build_sysroot/sysroot_src
 /build_sysroot/compiler-builtins
 /build_sysroot/rustc_version
+/dist
 /rust
 /download
index 13301bf20a5ed7d57051c9b45fa4165a98e8b7b5..bc914e37d2b51dda8d3a0e4ef090a4cc1399fc90 100644 (file)
@@ -4,16 +4,10 @@
     "rust-analyzer.imports.granularity.enforce": true,
     "rust-analyzer.imports.granularity.group": "module",
     "rust-analyzer.imports.prefix": "crate",
-    "rust-analyzer.cargo.features": ["unstable-features"],
+    "rust-analyzer.cargo.features": ["unstable-features", "__check_build_system_using_ra"],
     "rust-analyzer.linkedProjects": [
         "./Cargo.toml",
-        //"./build_sysroot/sysroot_src/library/std/Cargo.toml",
         {
-            "roots": [
-                "./example/mini_core.rs",
-                "./example/mini_core_hello_world.rs",
-                "./example/mod_bench.rs"
-            ],
             "crates": [
                 {
                     "root_module": "./example/mini_core.rs",
             ]
         },
         {
-            "roots": ["./example/std_example.rs"],
+            "sysroot_src": "./build_sysroot/sysroot_src/library",
             "crates": [
                 {
                     "root_module": "./example/std_example.rs",
-                    "edition": "2018",
-                    "deps": [{ "crate": 1, "name": "std" }],
-                    "cfg": [],
-                },
-                {
-                    "root_module": "./build_sysroot/sysroot_src/library/std/src/lib.rs",
-                    "edition": "2018",
-                    "deps": [],
-                    "cfg": [],
-                },
-            ]
-        },
-        {
-            "roots": ["./y.rs"],
-            "crates": [
-                {
-                    "root_module": "./y.rs",
-                    "edition": "2018",
-                    "deps": [{ "crate": 1, "name": "std" }],
-                    "cfg": [],
-                },
-                {
-                    "root_module": "./build_sysroot/sysroot_src/library/std/src/lib.rs",
-                    "edition": "2018",
+                    "edition": "2015",
                     "deps": [],
                     "cfg": [],
                 },
index 3b406036c356e9e3023964f049184a2d1f0121f5..e4d3e9ca5ae0a8676863063216c420232248a554 100644 (file)
@@ -15,9 +15,9 @@ dependencies = [
 
 [[package]]
 name = "anyhow"
-version = "1.0.60"
+version = "1.0.66"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c794e162a5eff65c72ef524dfe393eb923c354e350bb78b9c7383df13f3bc142"
+checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6"
 
 [[package]]
 name = "arrayvec"
@@ -39,9 +39,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
 
 [[package]]
 name = "bumpalo"
-version = "3.11.0"
+version = "3.11.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d"
+checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba"
 
 [[package]]
 name = "byteorder"
@@ -57,24 +57,25 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
 [[package]]
 name = "cranelift-bforest"
-version = "0.88.1"
+version = "0.90.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "44409ccf2d0f663920cab563d2b79fcd6b2e9a2bcc6e929fef76c8f82ad6c17a"
+checksum = "b62c772976416112fa4484cbd688cb6fb35fd430005c1c586224fc014018abad"
 dependencies = [
  "cranelift-entity",
 ]
 
 [[package]]
 name = "cranelift-codegen"
-version = "0.88.1"
+version = "0.90.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "98de2018ad96eb97f621f7d6b900a0cc661aec8d02ea4a50e56ecb48e5a2fcaf"
+checksum = "9b40ed2dd13c2ac7e24f88a3090c68ad3414eb1d066a95f8f1f7b3b819cb4e46"
 dependencies = [
  "arrayvec",
  "bumpalo",
  "cranelift-bforest",
  "cranelift-codegen-meta",
  "cranelift-codegen-shared",
+ "cranelift-egraph",
  "cranelift-entity",
  "cranelift-isle",
  "gimli",
@@ -86,30 +87,44 @@ dependencies = [
 
 [[package]]
 name = "cranelift-codegen-meta"
-version = "0.88.1"
+version = "0.90.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5287ce36e6c4758fbaf298bd1a8697ad97a4f2375a3d1b61142ea538db4877e5"
+checksum = "bb927a8f1c27c34ee3759b6b0ffa528d2330405d5cc4511f0cab33fe2279f4b5"
 dependencies = [
  "cranelift-codegen-shared",
 ]
 
 [[package]]
 name = "cranelift-codegen-shared"
-version = "0.88.1"
+version = "0.90.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2855c24219e2f08827f3f4ffb2da92e134ae8d8ecc185b11ec8f9878cf5f588e"
+checksum = "43dfa417b884a9ab488d95fd6b93b25e959321fe7bfd7a0a960ba5d7fb7ab927"
+
+[[package]]
+name = "cranelift-egraph"
+version = "0.90.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e0a66b39785efd8513d2cca967ede56d6cc57c8d7986a595c7c47d0c78de8dce"
+dependencies = [
+ "cranelift-entity",
+ "fxhash",
+ "hashbrown",
+ "indexmap",
+ "log",
+ "smallvec",
+]
 
 [[package]]
 name = "cranelift-entity"
-version = "0.88.1"
+version = "0.90.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b65673279d75d34bf11af9660ae2dbd1c22e6d28f163f5c72f4e1dc56d56103"
+checksum = "0637ffde963cb5d759bc4d454cfa364b6509e6c74cdaa21298add0ed9276f346"
 
 [[package]]
 name = "cranelift-frontend"
-version = "0.88.1"
+version = "0.90.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ed2b3d7a4751163f6c4a349205ab1b7d9c00eecf19dcea48592ef1f7688eefc"
+checksum = "fb72b8342685e850cb037350418f62cc4fc55d6c2eb9c7ca01b82f9f1a6f3d56"
 dependencies = [
  "cranelift-codegen",
  "log",
@@ -119,15 +134,15 @@ dependencies = [
 
 [[package]]
 name = "cranelift-isle"
-version = "0.88.1"
+version = "0.90.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3be64cecea9d90105fc6a2ba2d003e98c867c1d6c4c86cc878f97ad9fb916293"
+checksum = "850579cb9e4b448f7c301f1e6e6cbad99abe3f1f1d878a4994cb66e33c6db8cd"
 
 [[package]]
 name = "cranelift-jit"
-version = "0.88.1"
+version = "0.90.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f98ed42a70a0c9c388e34ec9477f57fc7300f541b1e5136a0e2ea02b1fac6015"
+checksum = "9add822ad66dcbe152b5ab57de10240a2df4505099f2f6c27159acb711890bd4"
 dependencies = [
  "anyhow",
  "cranelift-codegen",
@@ -138,14 +153,15 @@ dependencies = [
  "log",
  "region",
  "target-lexicon",
+ "wasmtime-jit-icache-coherence",
  "windows-sys",
 ]
 
 [[package]]
 name = "cranelift-module"
-version = "0.88.1"
+version = "0.90.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d658ac7f156708bfccb647216cc8b9387469f50d352ba4ad80150541e4ae2d49"
+checksum = "406b772626fc2664864cf947f3895a23b619895c7fff635f3622e2d857f4492f"
 dependencies = [
  "anyhow",
  "cranelift-codegen",
@@ -153,9 +169,9 @@ dependencies = [
 
 [[package]]
 name = "cranelift-native"
-version = "0.88.1"
+version = "0.90.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c4a03a6ac1b063e416ca4b93f6247978c991475e8271465340caa6f92f3c16a4"
+checksum = "2d0a279e5bcba3e0466c734d8d8eb6bfc1ad29e95c37f3e4955b492b5616335e"
 dependencies = [
  "cranelift-codegen",
  "libc",
@@ -164,9 +180,9 @@ dependencies = [
 
 [[package]]
 name = "cranelift-object"
-version = "0.88.1"
+version = "0.90.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eef0b4119b645b870a43a036d76c0ada3a076b1f82e8b8487659304c8b09049b"
+checksum = "39793c550f0c1d7db96c2fc1324583670c8143befe6edbfbaf1c68aba53be983"
 dependencies = [
  "anyhow",
  "cranelift-codegen",
@@ -185,6 +201,12 @@ dependencies = [
  "cfg-if",
 ]
 
+[[package]]
+name = "fallible-iterator"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7"
+
 [[package]]
 name = "fxhash"
 version = "0.2.1"
@@ -196,9 +218,9 @@ dependencies = [
 
 [[package]]
 name = "getrandom"
-version = "0.2.7"
+version = "0.2.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6"
+checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
 dependencies = [
  "cfg-if",
  "libc",
@@ -211,7 +233,9 @@ version = "0.26.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d"
 dependencies = [
+ "fallible-iterator",
  "indexmap",
+ "stable_deref_trait",
 ]
 
 [[package]]
@@ -225,9 +249,9 @@ dependencies = [
 
 [[package]]
 name = "indexmap"
-version = "1.9.1"
+version = "1.9.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e"
+checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399"
 dependencies = [
  "autocfg",
  "hashbrown",
@@ -235,15 +259,15 @@ dependencies = [
 
 [[package]]
 name = "libc"
-version = "0.2.127"
+version = "0.2.138"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "505e71a4706fa491e9b1b55f51b95d4037d0821ee40131190475f692b35b009b"
+checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8"
 
 [[package]]
 name = "libloading"
-version = "0.7.3"
+version = "0.7.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd"
+checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f"
 dependencies = [
  "cfg-if",
  "winapi",
@@ -287,15 +311,15 @@ dependencies = [
 
 [[package]]
 name = "once_cell"
-version = "1.13.0"
+version = "1.16.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1"
+checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860"
 
 [[package]]
 name = "regalloc2"
-version = "0.3.2"
+version = "0.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d43a209257d978ef079f3d446331d0f1794f5e0fc19b306a199983857833a779"
+checksum = "91b2eab54204ea0117fe9a060537e0b07a4e72f7c7d182361ecc346cab2240e5"
 dependencies = [
  "fxhash",
  "log",
@@ -342,15 +366,21 @@ checksum = "03b634d87b960ab1a38c4fe143b508576f075e7c978bfad18217645ebfdfa2ec"
 
 [[package]]
 name = "smallvec"
-version = "1.9.0"
+version = "1.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1"
+checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
+
+[[package]]
+name = "stable_deref_trait"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
 
 [[package]]
 name = "target-lexicon"
-version = "0.12.4"
+version = "0.12.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c02424087780c9b71cc96799eaeddff35af2bc513278cda5c99fc1f5d026d3c1"
+checksum = "9410d0f6853b1d94f0e519fb95df60f29d2c1eff2d921ffdf01a4c8a3b54f12d"
 
 [[package]]
 name = "version_check"
@@ -364,6 +394,17 @@ version = "0.11.0+wasi-snapshot-preview1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
 
+[[package]]
+name = "wasmtime-jit-icache-coherence"
+version = "2.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6bbabb309c06cc238ee91b1455b748c45f0bdcab0dda2c2db85b0a1e69fcb66"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "windows-sys",
+]
+
 [[package]]
 name = "winapi"
 version = "0.3.9"
index 0fdd5de118ccb10cb4db0776c5ca9c69b19cc07f..2b216ca072f0096832412085a0eae3fda4dc79ff 100644 (file)
@@ -3,17 +3,24 @@ name = "rustc_codegen_cranelift"
 version = "0.1.0"
 edition = "2021"
 
+[[bin]]
+# This is used just to teach rust-analyzer how to check the build system. required-features is used
+# to disable it for regular builds.
+name = "y"
+path = "./y.rs"
+required-features = ["__check_build_system_using_ra"]
+
 [lib]
 crate-type = ["dylib"]
 
 [dependencies]
 # These have to be in sync with each other
-cranelift-codegen = { version = "0.88.1", features = ["unwind", "all-arch"] }
-cranelift-frontend = "0.88.1"
-cranelift-module = "0.88.1"
-cranelift-native = "0.88.1"
-cranelift-jit = { version = "0.88.1", optional = true }
-cranelift-object = "0.88.1"
+cranelift-codegen = { version = "0.90.1", features = ["unwind", "all-arch"] }
+cranelift-frontend = "0.90.1"
+cranelift-module = "0.90.1"
+cranelift-native = "0.90.1"
+cranelift-jit = { version = "0.90.1", optional = true }
+cranelift-object = "0.90.1"
 target-lexicon = "0.12.0"
 gimli = { version = "0.26.0", default-features = false, features = ["write"]}
 object = { version = "0.29.0", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] }
@@ -39,6 +46,7 @@ smallvec = "1.8.1"
 unstable-features = ["jit", "inline_asm"]
 jit = ["cranelift-jit", "libloading"]
 inline_asm = []
+__check_build_system_using_ra = []
 
 [package.metadata.rust-analyzer]
 rustc_private = true
index 1e84c7fa3657b37afeb26614a49896fab8846b40..0e9c77244d4cc85d765371e97370db5c0adebf11 100644 (file)
@@ -37,7 +37,7 @@ Assuming `$cg_clif_dir` is the directory you cloned this repo into and you follo
 In the directory with your project (where you can do the usual `cargo build`), run:
 
 ```bash
-$ $cg_clif_dir/build/cargo-clif build
+$ $cg_clif_dir/dist/cargo-clif build
 ```
 
 This will build your project with rustc_codegen_cranelift instead of the usual LLVM backend.
index f6a9cb67290c7d88d591a72b2abfafaa2df67c28..bba3210536ef7832e44ba9dbb5e46c3ee036baf6 100644 (file)
@@ -4,9 +4,9 @@ version = 3
 
 [[package]]
 name = "addr2line"
-version = "0.16.0"
+version = "0.17.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3e61f2b7f93d2c7d2b08263acaa4a363b3e276806c68af6134c44f523bf1aacd"
+checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b"
 dependencies = [
  "compiler_builtins",
  "gimli",
@@ -32,27 +32,11 @@ dependencies = [
  "core",
 ]
 
-[[package]]
-name = "autocfg"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
-
 [[package]]
 name = "cc"
-version = "1.0.73"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
-
-[[package]]
-name = "cfg-if"
-version = "0.1.10"
+version = "1.0.77"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
-dependencies = [
- "compiler_builtins",
- "rustc-std-workspace-core",
-]
+checksum = "e9f73505338f7d905b19d18738976aae232eb46b8efc15554ffc56deb5d9ebe4"
 
 [[package]]
 name = "cfg-if"
@@ -66,9 +50,9 @@ dependencies = [
 
 [[package]]
 name = "compiler_builtins"
-version = "0.1.82"
+version = "0.1.85"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "18cd7635fea7bb481ea543b392789844c1ad581299da70184c7175ce3af76603"
+checksum = "13e81c6cd7ab79f51a0c927d22858d61ad12bd0b3865f0b13ece02a4486aeabb"
 dependencies = [
  "rustc-std-workspace-core",
 ]
@@ -111,9 +95,9 @@ dependencies = [
 
 [[package]]
 name = "gimli"
-version = "0.25.0"
+version = "0.26.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0a01e0497841a3b2db4f8afa483cce65f7e96a3498bd6c541734792aeac8fe7"
+checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d"
 dependencies = [
  "compiler_builtins",
  "rustc-std-workspace-alloc",
@@ -145,9 +129,9 @@ dependencies = [
 
 [[package]]
 name = "libc"
-version = "0.2.135"
+version = "0.2.138"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "68783febc7782c6c5cb401fbda4de5a9898be1762314da0bb2c10ced61f18b0c"
+checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8"
 dependencies = [
  "rustc-std-workspace-core",
 ]
@@ -164,12 +148,11 @@ dependencies = [
 
 [[package]]
 name = "miniz_oxide"
-version = "0.4.4"
+version = "0.5.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b"
+checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34"
 dependencies = [
  "adler",
- "autocfg",
  "compiler_builtins",
  "rustc-std-workspace-alloc",
  "rustc-std-workspace-core",
@@ -177,9 +160,9 @@ dependencies = [
 
 [[package]]
 name = "object"
-version = "0.26.2"
+version = "0.29.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "39f37e50073ccad23b6d09bcb5b263f4e76d3bb6038e4a3c08e52162ffa8abc2"
+checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53"
 dependencies = [
  "compiler_builtins",
  "memchr",
@@ -192,7 +175,7 @@ name = "panic_abort"
 version = "0.0.0"
 dependencies = [
  "alloc",
- "cfg-if 0.1.10",
+ "cfg-if",
  "compiler_builtins",
  "core",
  "libc",
@@ -203,7 +186,7 @@ name = "panic_unwind"
 version = "0.0.0"
 dependencies = [
  "alloc",
- "cfg-if 0.1.10",
+ "cfg-if",
  "compiler_builtins",
  "core",
  "libc",
@@ -255,7 +238,7 @@ version = "0.0.0"
 dependencies = [
  "addr2line",
  "alloc",
- "cfg-if 1.0.0",
+ "cfg-if",
  "compiler_builtins",
  "core",
  "dlmalloc",
@@ -277,7 +260,7 @@ dependencies = [
 name = "std_detect"
 version = "0.1.5"
 dependencies = [
- "cfg-if 1.0.0",
+ "cfg-if",
  "compiler_builtins",
  "libc",
  "rustc-std-workspace-alloc",
@@ -299,7 +282,7 @@ dependencies = [
 name = "test"
 version = "0.0.0"
 dependencies = [
- "cfg-if 0.1.10",
+ "cfg-if",
  "core",
  "getopts",
  "libc",
@@ -325,7 +308,7 @@ name = "unwind"
 version = "0.0.0"
 dependencies = [
  "cc",
- "cfg-if 0.1.10",
+ "cfg-if",
  "compiler_builtins",
  "core",
  "libc",
index fae5b27163680badc511023892f92fe462ddfbaf..a081fdaa1c7e6475a727f764c033f07090b2b87e 100644 (file)
@@ -1,16 +1,21 @@
-use std::env;
 use std::path::Path;
 
 use super::build_sysroot;
 use super::config;
-use super::prepare;
-use super::utils::{cargo_command, spawn_and_wait};
+use super::path::Dirs;
+use super::prepare::GitRepo;
+use super::utils::{spawn_and_wait, CargoProject, Compiler};
 use super::SysrootKind;
 
+pub(crate) static ABI_CAFE_REPO: GitRepo =
+    GitRepo::github("Gankra", "abi-cafe", "4c6dc8c9c687e2b3a760ff2176ce236872b37212", "abi-cafe");
+
+static ABI_CAFE: CargoProject = CargoProject::new(&ABI_CAFE_REPO.source_dir(), "abi_cafe");
+
 pub(crate) fn run(
     channel: &str,
     sysroot_kind: SysrootKind,
-    target_dir: &Path,
+    dirs: &Dirs,
     cg_clif_dylib: &Path,
     host_triple: &str,
     target_triple: &str,
@@ -27,26 +32,25 @@ pub(crate) fn run(
 
     eprintln!("Building sysroot for abi-cafe");
     build_sysroot::build_sysroot(
+        dirs,
         channel,
         sysroot_kind,
-        target_dir,
         cg_clif_dylib,
         host_triple,
         target_triple,
     );
 
     eprintln!("Running abi-cafe");
-    let abi_cafe_path = prepare::ABI_CAFE.source_dir();
-    env::set_current_dir(abi_cafe_path.clone()).unwrap();
 
     let pairs = ["rustc_calls_cgclif", "cgclif_calls_rustc", "cgclif_calls_cc", "cc_calls_cgclif"];
 
-    let mut cmd = cargo_command("cargo", "run", Some(target_triple), &abi_cafe_path);
+    let mut cmd = ABI_CAFE.run(&Compiler::host(), dirs);
     cmd.arg("--");
     cmd.arg("--pairs");
     cmd.args(pairs);
     cmd.arg("--add-rustc-codegen-backend");
     cmd.arg(format!("cgclif:{}", cg_clif_dylib.display()));
+    cmd.current_dir(ABI_CAFE.source_dir(dirs));
 
     spawn_and_wait(cmd);
 }
index cda468bcfa2dfc2e0bfe494bd5a1a9414a97eed6..fde8ef424ccc5441e0198ef7b33b23c39dbe37bc 100644 (file)
@@ -1,16 +1,19 @@
 use std::env;
 use std::path::PathBuf;
 
+use super::path::{Dirs, RelPath};
 use super::rustc_info::get_file_name;
-use super::utils::{cargo_command, is_ci};
+use super::utils::{is_ci, CargoProject, Compiler};
+
+static CG_CLIF: CargoProject = CargoProject::new(&RelPath::SOURCE, "cg_clif");
 
 pub(crate) fn build_backend(
+    dirs: &Dirs,
     channel: &str,
     host_triple: &str,
     use_unstable_features: bool,
 ) -> PathBuf {
-    let source_dir = std::env::current_dir().unwrap();
-    let mut cmd = cargo_command("cargo", "build", Some(host_triple), &source_dir);
+    let mut cmd = CG_CLIF.build(&Compiler::host(), dirs);
 
     cmd.env("CARGO_BUILD_INCREMENTAL", "true"); // Force incr comp even in release mode
 
@@ -41,8 +44,8 @@ pub(crate) fn build_backend(
     eprintln!("[BUILD] rustc_codegen_cranelift");
     super::utils::spawn_and_wait(cmd);
 
-    source_dir
-        .join("target")
+    CG_CLIF
+        .target_dir(dirs)
         .join(host_triple)
         .join(channel)
         .join(get_file_name("rustc_codegen_cranelift", "dylib"))
index 856aecc49fd1c05f476c91232c9bb0b429c4c907..cbbf09b9b97b8422ab06caff3b59b34c6352dfd4 100644 (file)
@@ -1,57 +1,60 @@
 use std::fs;
-use std::path::{Path, PathBuf};
+use std::path::Path;
 use std::process::{self, Command};
 
+use super::path::{Dirs, RelPath};
 use super::rustc_info::{get_file_name, get_rustc_version, get_wrapper_file_name};
-use super::utils::{cargo_command, spawn_and_wait, try_hard_link};
+use super::utils::{spawn_and_wait, try_hard_link, CargoProject, Compiler};
 use super::SysrootKind;
 
+static DIST_DIR: RelPath = RelPath::DIST;
+static BIN_DIR: RelPath = RelPath::DIST.join("bin");
+static LIB_DIR: RelPath = RelPath::DIST.join("lib");
+static RUSTLIB_DIR: RelPath = LIB_DIR.join("rustlib");
+
 pub(crate) fn build_sysroot(
+    dirs: &Dirs,
     channel: &str,
     sysroot_kind: SysrootKind,
-    target_dir: &Path,
     cg_clif_dylib_src: &Path,
     host_triple: &str,
     target_triple: &str,
 ) {
     eprintln!("[BUILD] sysroot {:?}", sysroot_kind);
 
-    if target_dir.exists() {
-        fs::remove_dir_all(target_dir).unwrap();
-    }
-    fs::create_dir_all(target_dir.join("bin")).unwrap();
-    fs::create_dir_all(target_dir.join("lib")).unwrap();
+    DIST_DIR.ensure_fresh(dirs);
+    BIN_DIR.ensure_exists(dirs);
+    LIB_DIR.ensure_exists(dirs);
 
     // Copy the backend
-    let cg_clif_dylib_path = target_dir
-        .join(if cfg!(windows) {
-            // Windows doesn't have rpath support, so the cg_clif dylib needs to be next to the
-            // binaries.
-            "bin"
-        } else {
-            "lib"
-        })
-        .join(get_file_name("rustc_codegen_cranelift", "dylib"));
+    let cg_clif_dylib_path = if cfg!(windows) {
+        // Windows doesn't have rpath support, so the cg_clif dylib needs to be next to the
+        // binaries.
+        BIN_DIR
+    } else {
+        LIB_DIR
+    }
+    .to_path(dirs)
+    .join(get_file_name("rustc_codegen_cranelift", "dylib"));
     try_hard_link(cg_clif_dylib_src, &cg_clif_dylib_path);
 
     // Build and copy rustc and cargo wrappers
-    for wrapper in ["rustc-clif", "cargo-clif"] {
+    for wrapper in ["rustc-clif", "rustdoc-clif", "cargo-clif"] {
         let wrapper_name = get_wrapper_file_name(wrapper, "bin");
 
         let mut build_cargo_wrapper_cmd = Command::new("rustc");
         build_cargo_wrapper_cmd
-            .arg(PathBuf::from("scripts").join(format!("{wrapper}.rs")))
+            .arg(RelPath::SCRIPTS.to_path(dirs).join(&format!("{wrapper}.rs")))
             .arg("-o")
-            .arg(target_dir.join(wrapper_name))
+            .arg(DIST_DIR.to_path(dirs).join(wrapper_name))
             .arg("-g");
         spawn_and_wait(build_cargo_wrapper_cmd);
     }
 
     let default_sysroot = super::rustc_info::get_default_sysroot();
 
-    let rustlib = target_dir.join("lib").join("rustlib");
-    let host_rustlib_lib = rustlib.join(host_triple).join("lib");
-    let target_rustlib_lib = rustlib.join(target_triple).join("lib");
+    let host_rustlib_lib = RUSTLIB_DIR.to_path(dirs).join(host_triple).join("lib");
+    let target_rustlib_lib = RUSTLIB_DIR.to_path(dirs).join(target_triple).join("lib");
     fs::create_dir_all(&host_rustlib_lib).unwrap();
     fs::create_dir_all(&target_rustlib_lib).unwrap();
 
@@ -112,24 +115,18 @@ pub(crate) fn build_sysroot(
             }
         }
         SysrootKind::Clif => {
-            build_clif_sysroot_for_triple(
-                channel,
-                target_dir,
-                host_triple,
-                &cg_clif_dylib_path,
-                None,
-            );
+            build_clif_sysroot_for_triple(dirs, channel, host_triple, &cg_clif_dylib_path, None);
 
             if host_triple != target_triple {
                 // When cross-compiling it is often necessary to manually pick the right linker
-                let linker = if target_triple == "aarch64-unknown-linux-gnu" {
-                    Some("aarch64-linux-gnu-gcc")
-                } else {
-                    None
+                let linker = match target_triple {
+                    "aarch64-unknown-linux-gnu" => Some("aarch64-linux-gnu-gcc"),
+                    "s390x-unknown-linux-gnu" => Some("s390x-linux-gnu-gcc"),
+                    _ => None,
                 };
                 build_clif_sysroot_for_triple(
+                    dirs,
                     channel,
-                    target_dir,
                     target_triple,
                     &cg_clif_dylib_path,
                     linker,
@@ -142,21 +139,26 @@ pub(crate) fn build_sysroot(
                 let file = file.unwrap().path();
                 let filename = file.file_name().unwrap().to_str().unwrap();
                 if filename.contains("std-") && !filename.contains(".rlib") {
-                    try_hard_link(&file, target_dir.join("lib").join(file.file_name().unwrap()));
+                    try_hard_link(&file, LIB_DIR.to_path(dirs).join(file.file_name().unwrap()));
                 }
             }
         }
     }
 }
 
+// FIXME move to download/ or dist/
+pub(crate) static SYSROOT_RUSTC_VERSION: RelPath = RelPath::BUILD_SYSROOT.join("rustc_version");
+pub(crate) static SYSROOT_SRC: RelPath = RelPath::BUILD_SYSROOT.join("sysroot_src");
+static STANDARD_LIBRARY: CargoProject = CargoProject::new(&RelPath::BUILD_SYSROOT, "build_sysroot");
+
 fn build_clif_sysroot_for_triple(
+    dirs: &Dirs,
     channel: &str,
-    target_dir: &Path,
     triple: &str,
     cg_clif_dylib_path: &Path,
     linker: Option<&str>,
 ) {
-    match fs::read_to_string(Path::new("build_sysroot").join("rustc_version")) {
+    match fs::read_to_string(SYSROOT_RUSTC_VERSION.to_path(dirs)) {
         Err(e) => {
             eprintln!("Failed to get rustc version for patched sysroot source: {}", e);
             eprintln!("Hint: Try `./y.rs prepare` to patch the sysroot source");
@@ -174,7 +176,7 @@ fn build_clif_sysroot_for_triple(
         }
     }
 
-    let build_dir = Path::new("build_sysroot").join("target").join(triple).join(channel);
+    let build_dir = STANDARD_LIBRARY.target_dir(dirs).join(triple).join(channel);
 
     if !super::config::get_bool("keep_sysroot") {
         // Cleanup the deps dir, but keep build scripts and the incremental cache for faster
@@ -185,27 +187,27 @@ fn build_clif_sysroot_for_triple(
     }
 
     // Build sysroot
-    let mut build_cmd = cargo_command("cargo", "build", Some(triple), Path::new("build_sysroot"));
     let mut rustflags = "-Zforce-unstable-if-unmarked -Cpanic=abort".to_string();
     rustflags.push_str(&format!(" -Zcodegen-backend={}", cg_clif_dylib_path.to_str().unwrap()));
-    rustflags.push_str(&format!(" --sysroot={}", target_dir.to_str().unwrap()));
+    rustflags.push_str(&format!(" --sysroot={}", DIST_DIR.to_path(dirs).to_str().unwrap()));
     if channel == "release" {
-        build_cmd.arg("--release");
         rustflags.push_str(" -Zmir-opt-level=3");
     }
     if let Some(linker) = linker {
         use std::fmt::Write;
         write!(rustflags, " -Clinker={}", linker).unwrap();
     }
-    build_cmd.env("RUSTFLAGS", rustflags);
+    let mut compiler = Compiler::with_triple(triple.to_owned());
+    compiler.rustflags = rustflags;
+    let mut build_cmd = STANDARD_LIBRARY.build(&compiler, dirs);
+    if channel == "release" {
+        build_cmd.arg("--release");
+    }
     build_cmd.env("__CARGO_DEFAULT_LIB_METADATA", "cg_clif");
     spawn_and_wait(build_cmd);
 
     // Copy all relevant files to the sysroot
-    for entry in
-        fs::read_dir(Path::new("build_sysroot/target").join(triple).join(channel).join("deps"))
-            .unwrap()
-    {
+    for entry in fs::read_dir(build_dir.join("deps")).unwrap() {
         let entry = entry.unwrap();
         if let Some(ext) = entry.path().extension() {
             if ext == "rmeta" || ext == "d" || ext == "dSYM" || ext == "clif" {
@@ -216,7 +218,7 @@ fn build_clif_sysroot_for_triple(
         };
         try_hard_link(
             entry.path(),
-            target_dir.join("lib").join("rustlib").join(triple).join("lib").join(entry.file_name()),
+            RUSTLIB_DIR.to_path(dirs).join(triple).join("lib").join(entry.file_name()),
         );
     }
 }
index b25270d832ceb4fd483cfdbad2b6b712a4ee1a50..1afc9a55c73b5318bbc9ed006899c4f5ab3647c3 100644 (file)
@@ -8,20 +8,37 @@
 mod build_backend;
 mod build_sysroot;
 mod config;
+mod path;
 mod prepare;
 mod rustc_info;
 mod tests;
 mod utils;
 
+const USAGE: &str = r#"The build system of cg_clif.
+
+USAGE:
+    ./y.rs prepare [--out-dir DIR]
+    ./y.rs build [--debug] [--sysroot none|clif|llvm] [--out-dir DIR] [--no-unstable-features]
+    ./y.rs test [--debug] [--sysroot none|clif|llvm] [--out-dir DIR] [--no-unstable-features]
+
+OPTIONS:
+    --sysroot none|clif|llvm
+            Which sysroot libraries to use:
+            `none` will not include any standard library in the sysroot.
+            `clif` will build the standard library using Cranelift.
+            `llvm` will use the pre-compiled standard library of rustc which is compiled with LLVM.
+
+    --out-dir DIR
+            Specify the directory in which the download, build and dist directories are stored.
+            By default this is the working directory.
+
+    --no-unstable-features
+            fSome features are not yet ready for production usage. This option will disable these
+            features. This includes the JIT mode and inline assembly support.
+"#;
+
 fn usage() {
-    eprintln!("Usage:");
-    eprintln!("  ./y.rs prepare");
-    eprintln!(
-        "  ./y.rs build [--debug] [--sysroot none|clif|llvm] [--target-dir DIR] [--no-unstable-features]"
-    );
-    eprintln!(
-        "  ./y.rs test [--debug] [--sysroot none|clif|llvm] [--target-dir DIR] [--no-unstable-features]"
-    );
+    eprintln!("{USAGE}");
 }
 
 macro_rules! arg_error {
@@ -34,6 +51,7 @@ macro_rules! arg_error {
 
 #[derive(PartialEq, Debug)]
 enum Command {
+    Prepare,
     Build,
     Test,
 }
@@ -48,8 +66,6 @@ pub(crate) enum SysrootKind {
 pub fn main() {
     env::set_var("CG_CLIF_DISPLAY_CG_TIME", "1");
     env::set_var("CG_CLIF_DISABLE_INCR_CACHE", "1");
-    // The target dir is expected in the default location. Guard against the user changing it.
-    env::set_var("CARGO_TARGET_DIR", "target");
 
     if is_ci() {
         // Disabling incr comp reduces cache size and incr comp doesn't save as much on CI anyway
@@ -58,13 +74,7 @@ pub fn main() {
 
     let mut args = env::args().skip(1);
     let command = match args.next().as_deref() {
-        Some("prepare") => {
-            if args.next().is_some() {
-                arg_error!("./y.rs prepare doesn't expect arguments");
-            }
-            prepare::prepare();
-            process::exit(0);
-        }
+        Some("prepare") => Command::Prepare,
         Some("build") => Command::Build,
         Some("test") => Command::Test,
         Some(flag) if flag.starts_with('-') => arg_error!("Expected command found flag {}", flag),
@@ -75,15 +85,15 @@ pub fn main() {
         }
     };
 
-    let mut target_dir = PathBuf::from("build");
+    let mut out_dir = PathBuf::from(".");
     let mut channel = "release";
     let mut sysroot_kind = SysrootKind::Clif;
     let mut use_unstable_features = true;
     while let Some(arg) = args.next().as_deref() {
         match arg {
-            "--target-dir" => {
-                target_dir = PathBuf::from(args.next().unwrap_or_else(|| {
-                    arg_error!("--target-dir requires argument");
+            "--out-dir" => {
+                out_dir = PathBuf::from(args.next().unwrap_or_else(|| {
+                    arg_error!("--out-dir requires argument");
                 }))
             }
             "--debug" => channel = "debug",
@@ -101,7 +111,6 @@ pub fn main() {
             arg => arg_error!("Unexpected argument {}", arg),
         }
     }
-    target_dir = std::env::current_dir().unwrap().join(target_dir);
 
     let host_triple = if let Ok(host_triple) = std::env::var("HOST_TRIPLE") {
         host_triple
@@ -122,13 +131,43 @@ pub fn main() {
         host_triple.clone()
     };
 
-    let cg_clif_dylib = build_backend::build_backend(channel, &host_triple, use_unstable_features);
+    // FIXME allow changing the location of these dirs using cli arguments
+    let current_dir = std::env::current_dir().unwrap();
+    out_dir = current_dir.join(out_dir);
+    let dirs = path::Dirs {
+        source_dir: current_dir.clone(),
+        download_dir: out_dir.join("download"),
+        build_dir: out_dir.join("build"),
+        dist_dir: out_dir.join("dist"),
+    };
+
+    path::RelPath::BUILD.ensure_exists(&dirs);
+
+    {
+        // Make sure we always explicitly specify the target dir
+        let target =
+            path::RelPath::BUILD.join("target_dir_should_be_set_explicitly").to_path(&dirs);
+        env::set_var("CARGO_TARGET_DIR", &target);
+        let _ = std::fs::remove_file(&target);
+        std::fs::File::create(target).unwrap();
+    }
+
+    if command == Command::Prepare {
+        prepare::prepare(&dirs);
+        process::exit(0);
+    }
+
+    let cg_clif_dylib =
+        build_backend::build_backend(&dirs, channel, &host_triple, use_unstable_features);
     match command {
+        Command::Prepare => {
+            // Handled above
+        }
         Command::Test => {
             tests::run_tests(
+                &dirs,
                 channel,
                 sysroot_kind,
-                &target_dir,
                 &cg_clif_dylib,
                 &host_triple,
                 &target_triple,
@@ -137,7 +176,7 @@ pub fn main() {
             abi_cafe::run(
                 channel,
                 sysroot_kind,
-                &target_dir,
+                &dirs,
                 &cg_clif_dylib,
                 &host_triple,
                 &target_triple,
@@ -145,9 +184,9 @@ pub fn main() {
         }
         Command::Build => {
             build_sysroot::build_sysroot(
+                &dirs,
                 channel,
                 sysroot_kind,
-                &target_dir,
                 &cg_clif_dylib,
                 &host_triple,
                 &target_triple,
diff --git a/compiler/rustc_codegen_cranelift/build_system/path.rs b/compiler/rustc_codegen_cranelift/build_system/path.rs
new file mode 100644 (file)
index 0000000..e93981f
--- /dev/null
@@ -0,0 +1,70 @@
+use std::fs;
+use std::path::PathBuf;
+
+#[derive(Debug, Clone)]
+pub(crate) struct Dirs {
+    pub(crate) source_dir: PathBuf,
+    pub(crate) download_dir: PathBuf,
+    pub(crate) build_dir: PathBuf,
+    pub(crate) dist_dir: PathBuf,
+}
+
+#[doc(hidden)]
+#[derive(Debug, Copy, Clone)]
+pub(crate) enum PathBase {
+    Source,
+    Download,
+    Build,
+    Dist,
+}
+
+impl PathBase {
+    fn to_path(self, dirs: &Dirs) -> PathBuf {
+        match self {
+            PathBase::Source => dirs.source_dir.clone(),
+            PathBase::Download => dirs.download_dir.clone(),
+            PathBase::Build => dirs.build_dir.clone(),
+            PathBase::Dist => dirs.dist_dir.clone(),
+        }
+    }
+}
+
+#[derive(Debug, Copy, Clone)]
+pub(crate) enum RelPath {
+    Base(PathBase),
+    Join(&'static RelPath, &'static str),
+}
+
+impl RelPath {
+    pub(crate) const SOURCE: RelPath = RelPath::Base(PathBase::Source);
+    pub(crate) const DOWNLOAD: RelPath = RelPath::Base(PathBase::Download);
+    pub(crate) const BUILD: RelPath = RelPath::Base(PathBase::Build);
+    pub(crate) const DIST: RelPath = RelPath::Base(PathBase::Dist);
+
+    pub(crate) const SCRIPTS: RelPath = RelPath::SOURCE.join("scripts");
+    pub(crate) const BUILD_SYSROOT: RelPath = RelPath::SOURCE.join("build_sysroot");
+    pub(crate) const PATCHES: RelPath = RelPath::SOURCE.join("patches");
+
+    pub(crate) const fn join(&'static self, suffix: &'static str) -> RelPath {
+        RelPath::Join(self, suffix)
+    }
+
+    pub(crate) fn to_path(&self, dirs: &Dirs) -> PathBuf {
+        match self {
+            RelPath::Base(base) => base.to_path(dirs),
+            RelPath::Join(base, suffix) => base.to_path(dirs).join(suffix),
+        }
+    }
+
+    pub(crate) fn ensure_exists(&self, dirs: &Dirs) {
+        fs::create_dir_all(self.to_path(dirs)).unwrap();
+    }
+
+    pub(crate) fn ensure_fresh(&self, dirs: &Dirs) {
+        let path = self.to_path(dirs);
+        if path.exists() {
+            fs::remove_dir_all(&path).unwrap();
+        }
+        fs::create_dir_all(path).unwrap();
+    }
+}
index 3111f62f6c2156eaec0ef00a9a7213acf8950f88..8ac67e8f9422823090a97ffab654c0da5a848e12 100644 (file)
@@ -1,92 +1,75 @@
-use std::env;
 use std::ffi::OsStr;
 use std::fs;
 use std::path::{Path, PathBuf};
 use std::process::Command;
 
+use super::build_sysroot::{SYSROOT_RUSTC_VERSION, SYSROOT_SRC};
+use super::path::{Dirs, RelPath};
 use super::rustc_info::{get_file_name, get_rustc_path, get_rustc_version};
-use super::utils::{cargo_command, copy_dir_recursively, spawn_and_wait};
-
-pub(crate) const ABI_CAFE: GitRepo =
-    GitRepo::github("Gankra", "abi-cafe", "4c6dc8c9c687e2b3a760ff2176ce236872b37212", "abi-cafe");
-
-pub(crate) const RAND: GitRepo =
-    GitRepo::github("rust-random", "rand", "0f933f9c7176e53b2a3c7952ded484e1783f0bf1", "rand");
-
-pub(crate) const REGEX: GitRepo =
-    GitRepo::github("rust-lang", "regex", "341f207c1071f7290e3f228c710817c280c8dca1", "regex");
-
-pub(crate) const PORTABLE_SIMD: GitRepo = GitRepo::github(
-    "rust-lang",
-    "portable-simd",
-    "d5cd4a8112d958bd3a252327e0d069a6363249bd",
-    "portable-simd",
-);
-
-pub(crate) const SIMPLE_RAYTRACER: GitRepo = GitRepo::github(
-    "ebobby",
-    "simple-raytracer",
-    "804a7a21b9e673a482797aa289a18ed480e4d813",
-    "<none>",
-);
-
-pub(crate) fn prepare() {
-    if Path::new("download").exists() {
-        std::fs::remove_dir_all(Path::new("download")).unwrap();
+use super::utils::{copy_dir_recursively, spawn_and_wait, Compiler};
+
+pub(crate) fn prepare(dirs: &Dirs) {
+    if RelPath::DOWNLOAD.to_path(dirs).exists() {
+        std::fs::remove_dir_all(RelPath::DOWNLOAD.to_path(dirs)).unwrap();
     }
-    std::fs::create_dir_all(Path::new("download")).unwrap();
+    std::fs::create_dir_all(RelPath::DOWNLOAD.to_path(dirs)).unwrap();
 
-    prepare_sysroot();
+    prepare_sysroot(dirs);
 
     // FIXME maybe install this only locally?
     eprintln!("[INSTALL] hyperfine");
-    Command::new("cargo").arg("install").arg("hyperfine").spawn().unwrap().wait().unwrap();
+    Command::new("cargo")
+        .arg("install")
+        .arg("hyperfine")
+        .env_remove("CARGO_TARGET_DIR")
+        .spawn()
+        .unwrap()
+        .wait()
+        .unwrap();
 
-    ABI_CAFE.fetch();
-    RAND.fetch();
-    REGEX.fetch();
-    PORTABLE_SIMD.fetch();
-    SIMPLE_RAYTRACER.fetch();
+    super::abi_cafe::ABI_CAFE_REPO.fetch(dirs);
+    super::tests::RAND_REPO.fetch(dirs);
+    super::tests::REGEX_REPO.fetch(dirs);
+    super::tests::PORTABLE_SIMD_REPO.fetch(dirs);
+    super::tests::SIMPLE_RAYTRACER_REPO.fetch(dirs);
 
     eprintln!("[LLVM BUILD] simple-raytracer");
-    let build_cmd = cargo_command("cargo", "build", None, &SIMPLE_RAYTRACER.source_dir());
+    let host_compiler = Compiler::host();
+    let build_cmd = super::tests::SIMPLE_RAYTRACER.build(&host_compiler, dirs);
     spawn_and_wait(build_cmd);
     fs::copy(
-        SIMPLE_RAYTRACER
-            .source_dir()
-            .join("target")
+        super::tests::SIMPLE_RAYTRACER
+            .target_dir(dirs)
+            .join(&host_compiler.triple)
             .join("debug")
             .join(get_file_name("main", "bin")),
-        SIMPLE_RAYTRACER.source_dir().join(get_file_name("raytracer_cg_llvm", "bin")),
+        RelPath::BUILD.to_path(dirs).join(get_file_name("raytracer_cg_llvm", "bin")),
     )
     .unwrap();
 }
 
-fn prepare_sysroot() {
+fn prepare_sysroot(dirs: &Dirs) {
     let rustc_path = get_rustc_path();
     let sysroot_src_orig = rustc_path.parent().unwrap().join("../lib/rustlib/src/rust");
-    let sysroot_src = env::current_dir().unwrap().join("build_sysroot").join("sysroot_src");
+    let sysroot_src = SYSROOT_SRC;
 
     assert!(sysroot_src_orig.exists());
 
-    if sysroot_src.exists() {
-        fs::remove_dir_all(&sysroot_src).unwrap();
-    }
-    fs::create_dir_all(sysroot_src.join("library")).unwrap();
+    sysroot_src.ensure_fresh(dirs);
+    fs::create_dir_all(sysroot_src.to_path(dirs).join("library")).unwrap();
     eprintln!("[COPY] sysroot src");
-    copy_dir_recursively(&sysroot_src_orig.join("library"), &sysroot_src.join("library"));
+    copy_dir_recursively(
+        &sysroot_src_orig.join("library"),
+        &sysroot_src.to_path(dirs).join("library"),
+    );
 
     let rustc_version = get_rustc_version();
-    fs::write(Path::new("build_sysroot").join("rustc_version"), &rustc_version).unwrap();
+    fs::write(SYSROOT_RUSTC_VERSION.to_path(dirs), &rustc_version).unwrap();
 
     eprintln!("[GIT] init");
-    let mut git_init_cmd = Command::new("git");
-    git_init_cmd.arg("init").arg("-q").current_dir(&sysroot_src);
-    spawn_and_wait(git_init_cmd);
-
-    init_git_repo(&sysroot_src);
+    init_git_repo(&sysroot_src.to_path(dirs));
 
-    apply_patches("sysroot", &sysroot_src);
+    apply_patches(dirs, "sysroot", &sysroot_src.to_path(dirs));
 }
 
 pub(crate) struct GitRepo {
@@ -100,7 +83,7 @@ enum GitRepoUrl {
 }
 
 impl GitRepo {
-    const fn github(
+    pub(crate) const fn github(
         user: &'static str,
         repo: &'static str,
         rev: &'static str,
@@ -109,21 +92,25 @@ const fn github(
         GitRepo { url: GitRepoUrl::Github { user, repo }, rev, patch_name }
     }
 
-    pub(crate) fn source_dir(&self) -> PathBuf {
+    pub(crate) const fn source_dir(&self) -> RelPath {
         match self.url {
-            GitRepoUrl::Github { user: _, repo } => {
-                std::env::current_dir().unwrap().join("download").join(repo)
-            }
+            GitRepoUrl::Github { user: _, repo } => RelPath::DOWNLOAD.join(repo),
         }
     }
 
-    fn fetch(&self) {
+    fn fetch(&self, dirs: &Dirs) {
         match self.url {
             GitRepoUrl::Github { user, repo } => {
-                clone_repo_shallow_github(&self.source_dir(), user, repo, self.rev);
+                clone_repo_shallow_github(
+                    dirs,
+                    &self.source_dir().to_path(dirs),
+                    user,
+                    repo,
+                    self.rev,
+                );
             }
         }
-        apply_patches(self.patch_name, &self.source_dir());
+        apply_patches(dirs, self.patch_name, &self.source_dir().to_path(dirs));
     }
 }
 
@@ -142,18 +129,16 @@ fn clone_repo(download_dir: &Path, repo: &str, rev: &str) {
     spawn_and_wait(checkout_cmd);
 }
 
-fn clone_repo_shallow_github(download_dir: &Path, user: &str, repo: &str, rev: &str) {
+fn clone_repo_shallow_github(dirs: &Dirs, download_dir: &Path, user: &str, repo: &str, rev: &str) {
     if cfg!(windows) {
         // Older windows doesn't have tar or curl by default. Fall back to using git.
         clone_repo(download_dir, &format!("https://github.com/{}/{}.git", user, repo), rev);
         return;
     }
 
-    let downloads_dir = std::env::current_dir().unwrap().join("download");
-
     let archive_url = format!("https://github.com/{}/{}/archive/{}.tar.gz", user, repo, rev);
-    let archive_file = downloads_dir.join(format!("{}.tar.gz", rev));
-    let archive_dir = downloads_dir.join(format!("{}-{}", repo, rev));
+    let archive_file = RelPath::DOWNLOAD.to_path(dirs).join(format!("{}.tar.gz", rev));
+    let archive_dir = RelPath::DOWNLOAD.to_path(dirs).join(format!("{}-{}", repo, rev));
 
     eprintln!("[DOWNLOAD] {}/{} from {}", user, repo, archive_url);
 
@@ -169,7 +154,7 @@ fn clone_repo_shallow_github(download_dir: &Path, user: &str, repo: &str, rev: &
 
     // Unpack tar archive
     let mut unpack_cmd = Command::new("tar");
-    unpack_cmd.arg("xf").arg(&archive_file).current_dir(downloads_dir);
+    unpack_cmd.arg("xf").arg(&archive_file).current_dir(RelPath::DOWNLOAD.to_path(dirs));
     spawn_and_wait(unpack_cmd);
 
     // Rename unpacked dir to the expected name
@@ -191,12 +176,21 @@ fn init_git_repo(repo_dir: &Path) {
     spawn_and_wait(git_add_cmd);
 
     let mut git_commit_cmd = Command::new("git");
-    git_commit_cmd.arg("commit").arg("-m").arg("Initial commit").arg("-q").current_dir(repo_dir);
+    git_commit_cmd
+        .arg("-c")
+        .arg("user.name=Dummy")
+        .arg("-c")
+        .arg("user.email=dummy@example.com")
+        .arg("commit")
+        .arg("-m")
+        .arg("Initial commit")
+        .arg("-q")
+        .current_dir(repo_dir);
     spawn_and_wait(git_commit_cmd);
 }
 
-fn get_patches(source_dir: &Path, crate_name: &str) -> Vec<PathBuf> {
-    let mut patches: Vec<_> = fs::read_dir(source_dir.join("patches"))
+fn get_patches(dirs: &Dirs, crate_name: &str) -> Vec<PathBuf> {
+    let mut patches: Vec<_> = fs::read_dir(RelPath::PATCHES.to_path(dirs))
         .unwrap()
         .map(|entry| entry.unwrap().path())
         .filter(|path| path.extension() == Some(OsStr::new("patch")))
@@ -215,19 +209,27 @@ fn get_patches(source_dir: &Path, crate_name: &str) -> Vec<PathBuf> {
     patches
 }
 
-fn apply_patches(crate_name: &str, target_dir: &Path) {
+fn apply_patches(dirs: &Dirs, crate_name: &str, target_dir: &Path) {
     if crate_name == "<none>" {
         return;
     }
 
-    for patch in get_patches(&std::env::current_dir().unwrap(), crate_name) {
+    for patch in get_patches(dirs, crate_name) {
         eprintln!(
             "[PATCH] {:?} <- {:?}",
             target_dir.file_name().unwrap(),
             patch.file_name().unwrap()
         );
         let mut apply_patch_cmd = Command::new("git");
-        apply_patch_cmd.arg("am").arg(patch).arg("-q").current_dir(target_dir);
+        apply_patch_cmd
+            .arg("-c")
+            .arg("user.name=Dummy")
+            .arg("-c")
+            .arg("user.email=dummy@example.com")
+            .arg("am")
+            .arg(patch)
+            .arg("-q")
+            .current_dir(target_dir);
         spawn_and_wait(apply_patch_cmd);
     }
 }
index 3c08b6fa3894d61277a0c0b6499e23ddcdc544a9..8e5ab688e131b35325af4fb83a3387b8c6228449 100644 (file)
@@ -23,6 +23,16 @@ pub(crate) fn get_host_triple() -> String {
         .to_owned()
 }
 
+pub(crate) fn get_cargo_path() -> PathBuf {
+    let cargo_path = Command::new("rustup")
+        .stderr(Stdio::inherit())
+        .args(&["which", "cargo"])
+        .output()
+        .unwrap()
+        .stdout;
+    Path::new(String::from_utf8(cargo_path).unwrap().trim()).to_owned()
+}
+
 pub(crate) fn get_rustc_path() -> PathBuf {
     let rustc_path = Command::new("rustup")
         .stderr(Stdio::inherit())
@@ -33,6 +43,16 @@ pub(crate) fn get_rustc_path() -> PathBuf {
     Path::new(String::from_utf8(rustc_path).unwrap().trim()).to_owned()
 }
 
+pub(crate) fn get_rustdoc_path() -> PathBuf {
+    let rustc_path = Command::new("rustup")
+        .stderr(Stdio::inherit())
+        .args(&["which", "rustdoc"])
+        .output()
+        .unwrap()
+        .stdout;
+    Path::new(String::from_utf8(rustc_path).unwrap().trim()).to_owned()
+}
+
 pub(crate) fn get_default_sysroot() -> PathBuf {
     let default_sysroot = Command::new("rustc")
         .stderr(Stdio::inherit())
index a414b60f4e06b2b79dccc1ee64bc233f32ae6ba1..1c372736ed65d9121dccf04ae5bcf504d45127bc 100644 (file)
@@ -1,15 +1,20 @@
 use super::build_sysroot;
 use super::config;
-use super::prepare;
-use super::rustc_info::get_wrapper_file_name;
-use super::utils::{cargo_command, hyperfine_command, spawn_and_wait, spawn_and_wait_with_input};
-use build_system::SysrootKind;
+use super::path::{Dirs, RelPath};
+use super::prepare::GitRepo;
+use super::rustc_info::{get_cargo_path, get_wrapper_file_name};
+use super::utils::{
+    hyperfine_command, spawn_and_wait, spawn_and_wait_with_input, CargoProject, Compiler,
+};
+use super::SysrootKind;
 use std::env;
 use std::ffi::OsStr;
 use std::fs;
-use std::path::{Path, PathBuf};
+use std::path::Path;
 use std::process::Command;
 
+static BUILD_EXAMPLE_OUT_DIR: RelPath = RelPath::BUILD.join("example");
+
 struct TestCase {
     config: &'static str,
     func: &'static dyn Fn(&TestRunner),
@@ -30,7 +35,7 @@ const fn new(config: &'static str, func: &'static dyn Fn(&TestRunner)) -> Self {
             "--crate-type",
             "lib,dylib",
             "--target",
-            &runner.target_triple,
+            &runner.target_compiler.triple,
         ]);
     }),
     TestCase::new("build.example", &|runner| {
@@ -39,7 +44,7 @@ const fn new(config: &'static str, func: &'static dyn Fn(&TestRunner)) -> Self {
             "--crate-type",
             "lib",
             "--target",
-            &runner.target_triple,
+            &runner.target_compiler.triple,
         ]);
     }),
     TestCase::new("jit.mini_core_hello_world", &|runner| {
@@ -51,7 +56,7 @@ const fn new(config: &'static str, func: &'static dyn Fn(&TestRunner)) -> Self {
             "--cfg",
             "jit",
             "--target",
-            &runner.host_triple,
+            &runner.target_compiler.triple,
         ]);
         jit_cmd.env("CG_CLIF_JIT_ARGS", "abc bcd");
         spawn_and_wait(jit_cmd);
@@ -65,7 +70,7 @@ const fn new(config: &'static str, func: &'static dyn Fn(&TestRunner)) -> Self {
             "--cfg",
             "jit",
             "--target",
-            &runner.host_triple,
+            &runner.target_compiler.triple,
         ]);
         jit_cmd.env("CG_CLIF_JIT_ARGS", "abc bcd");
         spawn_and_wait(jit_cmd);
@@ -79,7 +84,7 @@ const fn new(config: &'static str, func: &'static dyn Fn(&TestRunner)) -> Self {
             "bin",
             "-g",
             "--target",
-            &runner.target_triple,
+            &runner.target_compiler.triple,
         ]);
         runner.run_out_command("mini_core_hello_world", ["abc", "bcd"]);
     }),
@@ -94,7 +99,7 @@ const fn new(config: &'static str, func: &'static dyn Fn(&TestRunner)) -> Self {
             "--crate-type",
             "bin",
             "--target",
-            &runner.target_triple,
+            &runner.target_compiler.triple,
         ]);
         runner.run_out_command("arbitrary_self_types_pointers_and_wrappers", []);
     }),
@@ -106,7 +111,7 @@ const fn new(config: &'static str, func: &'static dyn Fn(&TestRunner)) -> Self {
             "--crate-type",
             "bin",
             "--target",
-            &runner.target_triple,
+            &runner.target_compiler.triple,
         ]);
         runner.run_out_command("issue_91827_extern_types", []);
     }),
@@ -116,7 +121,7 @@ const fn new(config: &'static str, func: &'static dyn Fn(&TestRunner)) -> Self {
             "--crate-type",
             "lib",
             "--target",
-            &runner.target_triple,
+            &runner.target_compiler.triple,
         ]);
     }),
     TestCase::new("aot.alloc_example", &|runner| {
@@ -125,7 +130,7 @@ const fn new(config: &'static str, func: &'static dyn Fn(&TestRunner)) -> Self {
             "--crate-type",
             "bin",
             "--target",
-            &runner.target_triple,
+            &runner.target_compiler.triple,
         ]);
         runner.run_out_command("alloc_example", []);
     }),
@@ -136,7 +141,7 @@ const fn new(config: &'static str, func: &'static dyn Fn(&TestRunner)) -> Self {
             "-Cprefer-dynamic",
             "example/std_example.rs",
             "--target",
-            &runner.host_triple,
+            &runner.target_compiler.triple,
         ]);
 
         eprintln!("[JIT-lazy] std_example");
@@ -146,7 +151,7 @@ const fn new(config: &'static str, func: &'static dyn Fn(&TestRunner)) -> Self {
             "-Cprefer-dynamic",
             "example/std_example.rs",
             "--target",
-            &runner.host_triple,
+            &runner.target_compiler.triple,
         ]);
     }),
     TestCase::new("aot.std_example", &|runner| {
@@ -155,7 +160,7 @@ const fn new(config: &'static str, func: &'static dyn Fn(&TestRunner)) -> Self {
             "--crate-type",
             "bin",
             "--target",
-            &runner.target_triple,
+            &runner.target_compiler.triple,
         ]);
         runner.run_out_command("std_example", ["arg"]);
     }),
@@ -167,7 +172,7 @@ const fn new(config: &'static str, func: &'static dyn Fn(&TestRunner)) -> Self {
             "--crate-type",
             "bin",
             "--target",
-            &runner.target_triple,
+            &runner.target_compiler.triple,
         ]);
         runner.run_out_command("dst_field_align", []);
     }),
@@ -178,7 +183,7 @@ const fn new(config: &'static str, func: &'static dyn Fn(&TestRunner)) -> Self {
             "bin",
             "-Cpanic=abort",
             "--target",
-            &runner.target_triple,
+            &runner.target_compiler.triple,
         ]);
         runner.run_out_command("subslice-patterns-const-eval", []);
     }),
@@ -189,7 +194,7 @@ const fn new(config: &'static str, func: &'static dyn Fn(&TestRunner)) -> Self {
             "bin",
             "-Cpanic=abort",
             "--target",
-            &runner.target_triple,
+            &runner.target_compiler.triple,
         ]);
         runner.run_out_command("track-caller-attribute", []);
     }),
@@ -200,7 +205,7 @@ const fn new(config: &'static str, func: &'static dyn Fn(&TestRunner)) -> Self {
             "bin",
             "-Cpanic=abort",
             "--target",
-            &runner.target_triple,
+            &runner.target_compiler.triple,
         ]);
         runner.run_out_command("float-minmax-pass", []);
     }),
@@ -210,205 +215,252 @@ const fn new(config: &'static str, func: &'static dyn Fn(&TestRunner)) -> Self {
             "--crate-type",
             "bin",
             "--target",
-            &runner.target_triple,
+            &runner.target_compiler.triple,
         ]);
         runner.run_out_command("mod_bench", []);
     }),
+    TestCase::new("aot.issue-72793", &|runner| {
+        runner.run_rustc([
+            "example/issue-72793.rs",
+            "--crate-type",
+            "bin",
+            "--target",
+            &runner.target_compiler.triple,
+        ]);
+        runner.run_out_command("issue-72793", []);
+    }),
 ];
 
+pub(crate) static RAND_REPO: GitRepo =
+    GitRepo::github("rust-random", "rand", "0f933f9c7176e53b2a3c7952ded484e1783f0bf1", "rand");
+
+static RAND: CargoProject = CargoProject::new(&RAND_REPO.source_dir(), "rand");
+
+pub(crate) static REGEX_REPO: GitRepo =
+    GitRepo::github("rust-lang", "regex", "341f207c1071f7290e3f228c710817c280c8dca1", "regex");
+
+static REGEX: CargoProject = CargoProject::new(&REGEX_REPO.source_dir(), "regex");
+
+pub(crate) static PORTABLE_SIMD_REPO: GitRepo = GitRepo::github(
+    "rust-lang",
+    "portable-simd",
+    "d5cd4a8112d958bd3a252327e0d069a6363249bd",
+    "portable-simd",
+);
+
+static PORTABLE_SIMD: CargoProject =
+    CargoProject::new(&PORTABLE_SIMD_REPO.source_dir(), "portable_simd");
+
+pub(crate) static SIMPLE_RAYTRACER_REPO: GitRepo = GitRepo::github(
+    "ebobby",
+    "simple-raytracer",
+    "804a7a21b9e673a482797aa289a18ed480e4d813",
+    "<none>",
+);
+
+pub(crate) static SIMPLE_RAYTRACER: CargoProject =
+    CargoProject::new(&SIMPLE_RAYTRACER_REPO.source_dir(), "simple_raytracer");
+
+static LIBCORE_TESTS: CargoProject =
+    CargoProject::new(&RelPath::BUILD_SYSROOT.join("sysroot_src/library/core/tests"), "core_tests");
+
 const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[
     TestCase::new("test.rust-random/rand", &|runner| {
-        runner.in_dir(prepare::RAND.source_dir(), |runner| {
-            runner.run_cargo("clean", []);
-
-            if runner.host_triple == runner.target_triple {
-                eprintln!("[TEST] rust-random/rand");
-                runner.run_cargo("test", ["--workspace"]);
-            } else {
-                eprintln!("[AOT] rust-random/rand");
-                runner.run_cargo("build", ["--workspace", "--tests"]);
-            }
-        });
+        spawn_and_wait(RAND.clean(&runner.target_compiler.cargo, &runner.dirs));
+
+        if runner.is_native {
+            eprintln!("[TEST] rust-random/rand");
+            let mut test_cmd = RAND.test(&runner.target_compiler, &runner.dirs);
+            test_cmd.arg("--workspace");
+            spawn_and_wait(test_cmd);
+        } else {
+            eprintln!("[AOT] rust-random/rand");
+            let mut build_cmd = RAND.build(&runner.target_compiler, &runner.dirs);
+            build_cmd.arg("--workspace").arg("--tests");
+            spawn_and_wait(build_cmd);
+        }
     }),
     TestCase::new("bench.simple-raytracer", &|runner| {
-        runner.in_dir(prepare::SIMPLE_RAYTRACER.source_dir(), |runner| {
-            let run_runs = env::var("RUN_RUNS").unwrap_or("10".to_string()).parse().unwrap();
-
-            if runner.host_triple == runner.target_triple {
-                eprintln!("[BENCH COMPILE] ebobby/simple-raytracer");
-                let prepare = runner.cargo_command("clean", []);
-
-                let llvm_build_cmd = cargo_command("cargo", "build", None, Path::new("."));
-
-                let cargo_clif = runner
-                    .root_dir
-                    .clone()
-                    .join("build")
-                    .join(get_wrapper_file_name("cargo-clif", "bin"));
-                let clif_build_cmd = cargo_command(cargo_clif, "build", None, Path::new("."));
-
-                let bench_compile =
-                    hyperfine_command(1, run_runs, Some(prepare), llvm_build_cmd, clif_build_cmd);
-
-                spawn_and_wait(bench_compile);
-
-                eprintln!("[BENCH RUN] ebobby/simple-raytracer");
-                fs::copy(PathBuf::from("./target/debug/main"), PathBuf::from("raytracer_cg_clif"))
-                    .unwrap();
-
-                let bench_run = hyperfine_command(
-                    0,
-                    run_runs,
-                    None,
-                    Command::new("./raytracer_cg_llvm"),
-                    Command::new("./raytracer_cg_clif"),
-                );
-                spawn_and_wait(bench_run);
-            } else {
-                runner.run_cargo("clean", []);
-                eprintln!("[BENCH COMPILE] ebobby/simple-raytracer (skipped)");
-                eprintln!("[COMPILE] ebobby/simple-raytracer");
-                runner.run_cargo("build", []);
-                eprintln!("[BENCH RUN] ebobby/simple-raytracer (skipped)");
-            }
-        });
+        let run_runs = env::var("RUN_RUNS").unwrap_or("10".to_string()).parse().unwrap();
+
+        if runner.is_native {
+            eprintln!("[BENCH COMPILE] ebobby/simple-raytracer");
+            let cargo_clif = RelPath::DIST
+                .to_path(&runner.dirs)
+                .join(get_wrapper_file_name("cargo-clif", "bin"));
+            let manifest_path = SIMPLE_RAYTRACER.manifest_path(&runner.dirs);
+            let target_dir = SIMPLE_RAYTRACER.target_dir(&runner.dirs);
+
+            let clean_cmd = format!(
+                "cargo clean --manifest-path {manifest_path} --target-dir {target_dir}",
+                manifest_path = manifest_path.display(),
+                target_dir = target_dir.display(),
+            );
+            let llvm_build_cmd = format!(
+                "cargo build --manifest-path {manifest_path} --target-dir {target_dir}",
+                manifest_path = manifest_path.display(),
+                target_dir = target_dir.display(),
+            );
+            let clif_build_cmd = format!(
+                "{cargo_clif} build --manifest-path {manifest_path} --target-dir {target_dir}",
+                cargo_clif = cargo_clif.display(),
+                manifest_path = manifest_path.display(),
+                target_dir = target_dir.display(),
+            );
+
+            let bench_compile =
+                hyperfine_command(1, run_runs, Some(&clean_cmd), &llvm_build_cmd, &clif_build_cmd);
+
+            spawn_and_wait(bench_compile);
+
+            eprintln!("[BENCH RUN] ebobby/simple-raytracer");
+            fs::copy(
+                target_dir.join("debug").join("main"),
+                RelPath::BUILD.to_path(&runner.dirs).join("raytracer_cg_clif"),
+            )
+            .unwrap();
+
+            let mut bench_run =
+                hyperfine_command(0, run_runs, None, "./raytracer_cg_llvm", "./raytracer_cg_clif");
+            bench_run.current_dir(RelPath::BUILD.to_path(&runner.dirs));
+            spawn_and_wait(bench_run);
+        } else {
+            spawn_and_wait(SIMPLE_RAYTRACER.clean(&runner.target_compiler.cargo, &runner.dirs));
+            eprintln!("[BENCH COMPILE] ebobby/simple-raytracer (skipped)");
+            eprintln!("[COMPILE] ebobby/simple-raytracer");
+            spawn_and_wait(SIMPLE_RAYTRACER.build(&runner.target_compiler, &runner.dirs));
+            eprintln!("[BENCH RUN] ebobby/simple-raytracer (skipped)");
+        }
     }),
     TestCase::new("test.libcore", &|runner| {
-        runner.in_dir(
-            std::env::current_dir()
-                .unwrap()
-                .join("build_sysroot")
-                .join("sysroot_src")
-                .join("library")
-                .join("core")
-                .join("tests"),
-            |runner| {
-                runner.run_cargo("clean", []);
-
-                if runner.host_triple == runner.target_triple {
-                    runner.run_cargo("test", []);
-                } else {
-                    eprintln!("Cross-Compiling: Not running tests");
-                    runner.run_cargo("build", ["--tests"]);
-                }
-            },
-        );
+        spawn_and_wait(LIBCORE_TESTS.clean(&runner.host_compiler.cargo, &runner.dirs));
+
+        if runner.is_native {
+            spawn_and_wait(LIBCORE_TESTS.test(&runner.target_compiler, &runner.dirs));
+        } else {
+            eprintln!("Cross-Compiling: Not running tests");
+            let mut build_cmd = LIBCORE_TESTS.build(&runner.target_compiler, &runner.dirs);
+            build_cmd.arg("--tests");
+            spawn_and_wait(build_cmd);
+        }
     }),
     TestCase::new("test.regex-shootout-regex-dna", &|runner| {
-        runner.in_dir(prepare::REGEX.source_dir(), |runner| {
-            runner.run_cargo("clean", []);
-
-            // newer aho_corasick versions throw a deprecation warning
-            let lint_rust_flags = format!("{} --cap-lints warn", runner.rust_flags);
-
-            let mut build_cmd = runner.cargo_command("build", ["--example", "shootout-regex-dna"]);
-            build_cmd.env("RUSTFLAGS", lint_rust_flags.clone());
-            spawn_and_wait(build_cmd);
-
-            if runner.host_triple == runner.target_triple {
-                let mut run_cmd = runner.cargo_command("run", ["--example", "shootout-regex-dna"]);
-                run_cmd.env("RUSTFLAGS", lint_rust_flags);
-
-                let input =
-                    fs::read_to_string(PathBuf::from("examples/regexdna-input.txt")).unwrap();
-                let expected_path = PathBuf::from("examples/regexdna-output.txt");
-                let expected = fs::read_to_string(&expected_path).unwrap();
-
-                let output = spawn_and_wait_with_input(run_cmd, input);
-                // Make sure `[codegen mono items] start` doesn't poison the diff
-                let output = output
-                    .lines()
-                    .filter(|line| !line.contains("codegen mono items"))
-                    .chain(Some("")) // This just adds the trailing newline
-                    .collect::<Vec<&str>>()
-                    .join("\r\n");
-
-                let output_matches = expected.lines().eq(output.lines());
-                if !output_matches {
-                    let res_path = PathBuf::from("res.txt");
-                    fs::write(&res_path, &output).unwrap();
-
-                    if cfg!(windows) {
-                        println!("Output files don't match!");
-                        println!("Expected Output:\n{}", expected);
-                        println!("Actual Output:\n{}", output);
-                    } else {
-                        let mut diff = Command::new("diff");
-                        diff.arg("-u");
-                        diff.arg(res_path);
-                        diff.arg(expected_path);
-                        spawn_and_wait(diff);
-                    }
-
-                    std::process::exit(1);
+        spawn_and_wait(REGEX.clean(&runner.target_compiler.cargo, &runner.dirs));
+
+        // newer aho_corasick versions throw a deprecation warning
+        let lint_rust_flags = format!("{} --cap-lints warn", runner.target_compiler.rustflags);
+
+        let mut build_cmd = REGEX.build(&runner.target_compiler, &runner.dirs);
+        build_cmd.arg("--example").arg("shootout-regex-dna");
+        build_cmd.env("RUSTFLAGS", lint_rust_flags.clone());
+        spawn_and_wait(build_cmd);
+
+        if runner.is_native {
+            let mut run_cmd = REGEX.run(&runner.target_compiler, &runner.dirs);
+            run_cmd.arg("--example").arg("shootout-regex-dna");
+            run_cmd.env("RUSTFLAGS", lint_rust_flags);
+
+            let input = fs::read_to_string(
+                REGEX.source_dir(&runner.dirs).join("examples").join("regexdna-input.txt"),
+            )
+            .unwrap();
+            let expected_path =
+                REGEX.source_dir(&runner.dirs).join("examples").join("regexdna-output.txt");
+            let expected = fs::read_to_string(&expected_path).unwrap();
+
+            let output = spawn_and_wait_with_input(run_cmd, input);
+            // Make sure `[codegen mono items] start` doesn't poison the diff
+            let output = output
+                .lines()
+                .filter(|line| !line.contains("codegen mono items"))
+                .chain(Some("")) // This just adds the trailing newline
+                .collect::<Vec<&str>>()
+                .join("\r\n");
+
+            let output_matches = expected.lines().eq(output.lines());
+            if !output_matches {
+                let res_path = REGEX.source_dir(&runner.dirs).join("res.txt");
+                fs::write(&res_path, &output).unwrap();
+
+                if cfg!(windows) {
+                    println!("Output files don't match!");
+                    println!("Expected Output:\n{}", expected);
+                    println!("Actual Output:\n{}", output);
+                } else {
+                    let mut diff = Command::new("diff");
+                    diff.arg("-u");
+                    diff.arg(res_path);
+                    diff.arg(expected_path);
+                    spawn_and_wait(diff);
                 }
+
+                std::process::exit(1);
             }
-        });
+        }
     }),
     TestCase::new("test.regex", &|runner| {
-        runner.in_dir(prepare::REGEX.source_dir(), |runner| {
-            runner.run_cargo("clean", []);
-
-            // newer aho_corasick versions throw a deprecation warning
-            let lint_rust_flags = format!("{} --cap-lints warn", runner.rust_flags);
-
-            if runner.host_triple == runner.target_triple {
-                let mut run_cmd = runner.cargo_command(
-                    "test",
-                    [
-                        "--tests",
-                        "--",
-                        "--exclude-should-panic",
-                        "--test-threads",
-                        "1",
-                        "-Zunstable-options",
-                        "-q",
-                    ],
-                );
-                run_cmd.env("RUSTFLAGS", lint_rust_flags);
-                spawn_and_wait(run_cmd);
-            } else {
-                eprintln!("Cross-Compiling: Not running tests");
-                let mut build_cmd =
-                    runner.cargo_command("build", ["--tests", "--target", &runner.target_triple]);
-                build_cmd.env("RUSTFLAGS", lint_rust_flags.clone());
-                spawn_and_wait(build_cmd);
-            }
-        });
+        spawn_and_wait(REGEX.clean(&runner.host_compiler.cargo, &runner.dirs));
+
+        // newer aho_corasick versions throw a deprecation warning
+        let lint_rust_flags = format!("{} --cap-lints warn", runner.target_compiler.rustflags);
+
+        if runner.is_native {
+            let mut run_cmd = REGEX.test(&runner.target_compiler, &runner.dirs);
+            run_cmd.args([
+                "--tests",
+                "--",
+                "--exclude-should-panic",
+                "--test-threads",
+                "1",
+                "-Zunstable-options",
+                "-q",
+            ]);
+            run_cmd.env("RUSTFLAGS", lint_rust_flags);
+            spawn_and_wait(run_cmd);
+        } else {
+            eprintln!("Cross-Compiling: Not running tests");
+            let mut build_cmd = REGEX.build(&runner.target_compiler, &runner.dirs);
+            build_cmd.arg("--tests");
+            build_cmd.env("RUSTFLAGS", lint_rust_flags.clone());
+            spawn_and_wait(build_cmd);
+        }
     }),
     TestCase::new("test.portable-simd", &|runner| {
-        runner.in_dir(prepare::PORTABLE_SIMD.source_dir(), |runner| {
-            runner.run_cargo("clean", []);
-            runner.run_cargo("build", ["--all-targets", "--target", &runner.target_triple]);
+        spawn_and_wait(PORTABLE_SIMD.clean(&runner.host_compiler.cargo, &runner.dirs));
 
-            if runner.host_triple == runner.target_triple {
-                runner.run_cargo("test", ["-q"]);
-            }
-        });
+        let mut build_cmd = PORTABLE_SIMD.build(&runner.target_compiler, &runner.dirs);
+        build_cmd.arg("--all-targets");
+        spawn_and_wait(build_cmd);
+
+        if runner.is_native {
+            let mut test_cmd = PORTABLE_SIMD.test(&runner.target_compiler, &runner.dirs);
+            test_cmd.arg("-q");
+            spawn_and_wait(test_cmd);
+        }
     }),
 ];
 
 pub(crate) fn run_tests(
+    dirs: &Dirs,
     channel: &str,
     sysroot_kind: SysrootKind,
-    target_dir: &Path,
     cg_clif_dylib: &Path,
     host_triple: &str,
     target_triple: &str,
 ) {
-    let runner = TestRunner::new(host_triple.to_string(), target_triple.to_string());
+    let runner = TestRunner::new(dirs.clone(), host_triple.to_string(), target_triple.to_string());
 
     if config::get_bool("testsuite.no_sysroot") {
         build_sysroot::build_sysroot(
+            dirs,
             channel,
             SysrootKind::None,
-            &target_dir,
             cg_clif_dylib,
             &host_triple,
             &target_triple,
         );
 
-        let _ = fs::remove_dir_all(Path::new("target").join("out"));
+        BUILD_EXAMPLE_OUT_DIR.ensure_fresh(dirs);
         runner.run_testsuite(NO_SYSROOT_SUITE);
     } else {
         eprintln!("[SKIP] no_sysroot tests");
@@ -419,9 +471,9 @@ pub(crate) fn run_tests(
 
     if run_base_sysroot || run_extended_sysroot {
         build_sysroot::build_sysroot(
+            dirs,
             channel,
             sysroot_kind,
-            &target_dir,
             cg_clif_dylib,
             &host_triple,
             &target_triple,
@@ -442,40 +494,50 @@ pub(crate) fn run_tests(
 }
 
 struct TestRunner {
-    root_dir: PathBuf,
-    out_dir: PathBuf,
+    is_native: bool,
     jit_supported: bool,
-    rust_flags: String,
-    run_wrapper: Vec<String>,
-    host_triple: String,
-    target_triple: String,
+    dirs: Dirs,
+    host_compiler: Compiler,
+    target_compiler: Compiler,
 }
 
 impl TestRunner {
-    pub fn new(host_triple: String, target_triple: String) -> Self {
-        let root_dir = env::current_dir().unwrap();
-
-        let mut out_dir = root_dir.clone();
-        out_dir.push("target");
-        out_dir.push("out");
-
+    pub fn new(dirs: Dirs, host_triple: String, target_triple: String) -> Self {
         let is_native = host_triple == target_triple;
         let jit_supported =
             target_triple.contains("x86_64") && is_native && !host_triple.contains("windows");
 
-        let mut rust_flags = env::var("RUSTFLAGS").ok().unwrap_or("".to_string());
-        let mut run_wrapper = Vec::new();
+        let rustc_clif =
+            RelPath::DIST.to_path(&dirs).join(get_wrapper_file_name("rustc-clif", "bin"));
+        let rustdoc_clif =
+            RelPath::DIST.to_path(&dirs).join(get_wrapper_file_name("rustdoc-clif", "bin"));
+
+        let mut rustflags = env::var("RUSTFLAGS").ok().unwrap_or("".to_string());
+        let mut runner = vec![];
 
         if !is_native {
             match target_triple.as_str() {
                 "aarch64-unknown-linux-gnu" => {
                     // We are cross-compiling for aarch64. Use the correct linker and run tests in qemu.
-                    rust_flags = format!("-Clinker=aarch64-linux-gnu-gcc{}", rust_flags);
-                    run_wrapper = vec!["qemu-aarch64", "-L", "/usr/aarch64-linux-gnu"];
+                    rustflags = format!("-Clinker=aarch64-linux-gnu-gcc{}", rustflags);
+                    runner = vec![
+                        "qemu-aarch64".to_owned(),
+                        "-L".to_owned(),
+                        "/usr/aarch64-linux-gnu".to_owned(),
+                    ];
+                }
+                "s390x-unknown-linux-gnu" => {
+                    // We are cross-compiling for s390x. Use the correct linker and run tests in qemu.
+                    rustflags = format!("-Clinker=s390x-linux-gnu-gcc{}", rustflags);
+                    runner = vec![
+                        "qemu-s390x".to_owned(),
+                        "-L".to_owned(),
+                        "/usr/s390x-linux-gnu".to_owned(),
+                    ];
                 }
                 "x86_64-pc-windows-gnu" => {
                     // We are cross-compiling for Windows. Run tests in wine.
-                    run_wrapper = vec!["wine"];
+                    runner = vec!["wine".to_owned()];
                 }
                 _ => {
                     println!("Unknown non-native platform");
@@ -484,19 +546,31 @@ pub fn new(host_triple: String, target_triple: String) -> Self {
         }
 
         // FIXME fix `#[linkage = "extern_weak"]` without this
-        if host_triple.contains("darwin") {
-            rust_flags = format!("{} -Clink-arg=-undefined -Clink-arg=dynamic_lookup", rust_flags);
+        if target_triple.contains("darwin") {
+            rustflags = format!("{} -Clink-arg=-undefined -Clink-arg=dynamic_lookup", rustflags);
         }
 
-        Self {
-            root_dir,
-            out_dir,
-            jit_supported,
-            rust_flags,
-            run_wrapper: run_wrapper.iter().map(|s| s.to_string()).collect(),
-            host_triple,
-            target_triple,
-        }
+        let host_compiler = Compiler {
+            cargo: get_cargo_path(),
+            rustc: rustc_clif.clone(),
+            rustdoc: rustdoc_clif.clone(),
+            rustflags: String::new(),
+            rustdocflags: String::new(),
+            triple: host_triple,
+            runner: vec![],
+        };
+
+        let target_compiler = Compiler {
+            cargo: get_cargo_path(),
+            rustc: rustc_clif,
+            rustdoc: rustdoc_clif,
+            rustflags: rustflags.clone(),
+            rustdocflags: rustflags,
+            triple: target_triple,
+            runner,
+        };
+
+        Self { is_native, jit_supported, dirs, host_compiler, target_compiler }
     }
 
     pub fn run_testsuite(&self, tests: &[TestCase]) {
@@ -516,29 +590,18 @@ pub fn run_testsuite(&self, tests: &[TestCase]) {
         }
     }
 
-    fn in_dir(&self, new: impl AsRef<Path>, callback: impl FnOnce(&TestRunner)) {
-        let current = env::current_dir().unwrap();
-
-        env::set_current_dir(new).unwrap();
-        callback(self);
-        env::set_current_dir(current).unwrap();
-    }
-
+    #[must_use]
     fn rustc_command<I, S>(&self, args: I) -> Command
     where
         I: IntoIterator<Item = S>,
         S: AsRef<OsStr>,
     {
-        let mut rustc_clif = self.root_dir.clone();
-        rustc_clif.push("build");
-        rustc_clif.push(get_wrapper_file_name("rustc-clif", "bin"));
-
-        let mut cmd = Command::new(rustc_clif);
-        cmd.args(self.rust_flags.split_whitespace());
+        let mut cmd = Command::new(&self.target_compiler.rustc);
+        cmd.args(self.target_compiler.rustflags.split_whitespace());
         cmd.arg("-L");
-        cmd.arg(format!("crate={}", self.out_dir.display()));
+        cmd.arg(format!("crate={}", BUILD_EXAMPLE_OUT_DIR.to_path(&self.dirs).display()));
         cmd.arg("--out-dir");
-        cmd.arg(format!("{}", self.out_dir.display()));
+        cmd.arg(format!("{}", BUILD_EXAMPLE_OUT_DIR.to_path(&self.dirs).display()));
         cmd.arg("-Cdebuginfo=2");
         cmd.args(args);
         cmd
@@ -559,15 +622,13 @@ fn run_out_command<'a, I>(&self, name: &str, args: I)
         let mut full_cmd = vec![];
 
         // Prepend the RUN_WRAPPER's
-        if !self.run_wrapper.is_empty() {
-            full_cmd.extend(self.run_wrapper.iter().cloned());
+        if !self.target_compiler.runner.is_empty() {
+            full_cmd.extend(self.target_compiler.runner.iter().cloned());
         }
 
-        full_cmd.push({
-            let mut out_path = self.out_dir.clone();
-            out_path.push(name);
-            out_path.to_str().unwrap().to_string()
-        });
+        full_cmd.push(
+            BUILD_EXAMPLE_OUT_DIR.to_path(&self.dirs).join(name).to_str().unwrap().to_string(),
+        );
 
         for arg in args.into_iter() {
             full_cmd.push(arg.to_string());
@@ -581,30 +642,4 @@ fn run_out_command<'a, I>(&self, name: &str, args: I)
 
         spawn_and_wait(cmd);
     }
-
-    fn cargo_command<'a, I>(&self, subcommand: &str, args: I) -> Command
-    where
-        I: IntoIterator<Item = &'a str>,
-    {
-        let mut cargo_clif = self.root_dir.clone();
-        cargo_clif.push("build");
-        cargo_clif.push(get_wrapper_file_name("cargo-clif", "bin"));
-
-        let mut cmd = cargo_command(
-            cargo_clif,
-            subcommand,
-            if subcommand == "clean" { None } else { Some(&self.target_triple) },
-            Path::new("."),
-        );
-        cmd.args(args);
-        cmd.env("RUSTFLAGS", &self.rust_flags);
-        cmd
-    }
-
-    fn run_cargo<'a, I>(&self, subcommand: &str, args: I)
-    where
-        I: IntoIterator<Item = &'a str>,
-    {
-        spawn_and_wait(self.cargo_command(subcommand, args));
-    }
 }
index c627af4e62fe14073bc539d195cb5623afd7dabe..2be70e8e421b2961e97b53c99f38c83256940365 100644 (file)
 use std::env;
 use std::fs;
 use std::io::Write;
-use std::path::Path;
+use std::path::{Path, PathBuf};
 use std::process::{self, Command, Stdio};
 
-pub(crate) fn cargo_command(
-    cargo: impl AsRef<Path>,
-    subcommand: &str,
-    triple: Option<&str>,
-    source_dir: &Path,
-) -> Command {
-    let mut cmd = Command::new(cargo.as_ref());
-    cmd.arg(subcommand)
-        .arg("--manifest-path")
-        .arg(source_dir.join("Cargo.toml"))
-        .arg("--target-dir")
-        .arg(source_dir.join("target"));
+use super::path::{Dirs, RelPath};
+use super::rustc_info::{get_cargo_path, get_host_triple, get_rustc_path, get_rustdoc_path};
+
+pub(crate) struct Compiler {
+    pub(crate) cargo: PathBuf,
+    pub(crate) rustc: PathBuf,
+    pub(crate) rustdoc: PathBuf,
+    pub(crate) rustflags: String,
+    pub(crate) rustdocflags: String,
+    pub(crate) triple: String,
+    pub(crate) runner: Vec<String>,
+}
+
+impl Compiler {
+    pub(crate) fn host() -> Compiler {
+        Compiler {
+            cargo: get_cargo_path(),
+            rustc: get_rustc_path(),
+            rustdoc: get_rustdoc_path(),
+            rustflags: String::new(),
+            rustdocflags: String::new(),
+            triple: get_host_triple(),
+            runner: vec![],
+        }
+    }
+
+    pub(crate) fn with_triple(triple: String) -> Compiler {
+        Compiler {
+            cargo: get_cargo_path(),
+            rustc: get_rustc_path(),
+            rustdoc: get_rustdoc_path(),
+            rustflags: String::new(),
+            rustdocflags: String::new(),
+            triple,
+            runner: vec![],
+        }
+    }
+}
+
+pub(crate) struct CargoProject {
+    source: &'static RelPath,
+    target: &'static str,
+}
+
+impl CargoProject {
+    pub(crate) const fn new(path: &'static RelPath, target: &'static str) -> CargoProject {
+        CargoProject { source: path, target }
+    }
+
+    pub(crate) fn source_dir(&self, dirs: &Dirs) -> PathBuf {
+        self.source.to_path(dirs)
+    }
+
+    pub(crate) fn manifest_path(&self, dirs: &Dirs) -> PathBuf {
+        self.source_dir(dirs).join("Cargo.toml")
+    }
+
+    pub(crate) fn target_dir(&self, dirs: &Dirs) -> PathBuf {
+        RelPath::BUILD.join(self.target).to_path(dirs)
+    }
 
-    if let Some(triple) = triple {
-        cmd.arg("--target").arg(triple);
+    fn base_cmd(&self, command: &str, cargo: &Path, dirs: &Dirs) -> Command {
+        let mut cmd = Command::new(cargo);
+
+        cmd.arg(command)
+            .arg("--manifest-path")
+            .arg(self.manifest_path(dirs))
+            .arg("--target-dir")
+            .arg(self.target_dir(dirs));
+
+        cmd
+    }
+
+    fn build_cmd(&self, command: &str, compiler: &Compiler, dirs: &Dirs) -> Command {
+        let mut cmd = self.base_cmd(command, &compiler.cargo, dirs);
+
+        cmd.arg("--target").arg(&compiler.triple);
+
+        cmd.env("RUSTC", &compiler.rustc);
+        cmd.env("RUSTDOC", &compiler.rustdoc);
+        cmd.env("RUSTFLAGS", &compiler.rustflags);
+        cmd.env("RUSTDOCFLAGS", &compiler.rustdocflags);
+        if !compiler.runner.is_empty() {
+            cmd.env(
+                format!("CARGO_TARGET_{}_RUNNER", compiler.triple.to_uppercase().replace('-', "_")),
+                compiler.runner.join(" "),
+            );
+        }
+
+        cmd
     }
 
-    cmd
+    #[must_use]
+    pub(crate) fn fetch(&self, cargo: impl AsRef<Path>, dirs: &Dirs) -> Command {
+        let mut cmd = Command::new(cargo.as_ref());
+
+        cmd.arg("fetch").arg("--manifest-path").arg(self.manifest_path(dirs));
+
+        cmd
+    }
+
+    #[must_use]
+    pub(crate) fn clean(&self, cargo: &Path, dirs: &Dirs) -> Command {
+        self.base_cmd("clean", cargo, dirs)
+    }
+
+    #[must_use]
+    pub(crate) fn build(&self, compiler: &Compiler, dirs: &Dirs) -> Command {
+        self.build_cmd("build", compiler, dirs)
+    }
+
+    #[must_use]
+    pub(crate) fn test(&self, compiler: &Compiler, dirs: &Dirs) -> Command {
+        self.build_cmd("test", compiler, dirs)
+    }
+
+    #[must_use]
+    pub(crate) fn run(&self, compiler: &Compiler, dirs: &Dirs) -> Command {
+        self.build_cmd("run", compiler, dirs)
+    }
 }
 
+#[must_use]
 pub(crate) fn hyperfine_command(
     warmup: u64,
     runs: u64,
-    prepare: Option<Command>,
-    a: Command,
-    b: Command,
+    prepare: Option<&str>,
+    a: &str,
+    b: &str,
 ) -> Command {
     let mut bench = Command::new("hyperfine");
 
@@ -42,10 +145,10 @@ pub(crate) fn hyperfine_command(
     }
 
     if let Some(prepare) = prepare {
-        bench.arg("--prepare").arg(format!("{:?}", prepare));
+        bench.arg("--prepare").arg(prepare);
     }
 
-    bench.arg(format!("{:?}", a)).arg(format!("{:?}", b));
+    bench.arg(a).arg(b);
 
     bench
 }
index fedab2433aa05f66f33949f35ea62cd88ec3f4ed..1760e5836ecce00a48f7a0236748dfb94329fce0 100755 (executable)
@@ -2,7 +2,7 @@
 set -e
 
 rm -rf build_sysroot/{sysroot_src/,target/,compiler-builtins/,rustc_version}
-rm -rf target/ build/ perf.data{,.old} y.bin
+rm -rf target/ build/ dist/ perf.data{,.old} y.bin
 rm -rf download/
 
 # Kept for now in case someone updates their checkout of cg_clif before running clean_all.sh
index 0d539191b12f95936b65e6d134d460b31d96c3e6..258b67e931476850a25cab17bbc2c3300a243821 100644 (file)
@@ -40,6 +40,7 @@ aot.subslice-patterns-const-eval
 aot.track-caller-attribute
 aot.float-minmax-pass
 aot.mod_bench
+aot.issue-72793
 
 testsuite.extended_sysroot
 test.rust-random/rand
index 33f146e7ba27aec13e57e55d40ebb79e3f28e359..4c2b0fa170498812b976b67041cc62ab73ff3f81 100644 (file)
@@ -9,7 +9,7 @@ Assuming `$cg_clif_dir` is the directory you cloned this repo into and you follo
 In the directory with your project (where you can do the usual `cargo build`), run:
 
 ```bash
-$ $cg_clif_dir/build/cargo-clif build
+$ $cg_clif_dir/dist/cargo-clif build
 ```
 
 This will build your project with rustc_codegen_cranelift instead of the usual LLVM backend.
@@ -19,7 +19,7 @@ This will build your project with rustc_codegen_cranelift instead of the usual L
 > You should prefer using the Cargo method.
 
 ```bash
-$ $cg_clif_dir/build/rustc-clif my_crate.rs
+$ $cg_clif_dir/dist/rustc-clif my_crate.rs
 ```
 
 ## Jit mode
@@ -32,20 +32,20 @@ In jit mode cg_clif will immediately execute your code without creating an execu
 > The jit mode will probably need cargo integration to make this possible.
 
 ```bash
-$ $cg_clif_dir/build/cargo-clif jit
+$ $cg_clif_dir/dist/cargo-clif jit
 ```
 
 or
 
 ```bash
-$ $cg_clif_dir/build/rustc-clif -Zunstable-features -Cllvm-args=mode=jit -Cprefer-dynamic my_crate.rs
+$ $cg_clif_dir/dist/rustc-clif -Zunstable-features -Cllvm-args=mode=jit -Cprefer-dynamic my_crate.rs
 ```
 
 There is also an experimental lazy jit mode. In this mode functions are only compiled once they are
 first called.
 
 ```bash
-$ $cg_clif_dir/build/cargo-clif lazy-jit
+$ $cg_clif_dir/dist/cargo-clif lazy-jit
 ```
 
 ## Shell
@@ -54,7 +54,7 @@ These are a few functions that allow you to easily run rust code from the shell
 
 ```bash
 function jit_naked() {
-    echo "$@" | $cg_clif_dir/build/rustc-clif - -Zunstable-features -Cllvm-args=mode=jit -Cprefer-dynamic
+    echo "$@" | $cg_clif_dir/dist/rustc-clif - -Zunstable-features -Cllvm-args=mode=jit -Cprefer-dynamic
 }
 
 function jit() {
diff --git a/compiler/rustc_codegen_cranelift/example/issue-72793.rs b/compiler/rustc_codegen_cranelift/example/issue-72793.rs
new file mode 100644 (file)
index 0000000..b1bb9b8
--- /dev/null
@@ -0,0 +1,24 @@
+// Adapted from rustc ui test suite (ui/type-alias-impl-trait/issue-72793.rs)
+
+#![feature(type_alias_impl_trait)]
+
+trait T { type Item; }
+
+type Alias<'a> = impl T<Item = &'a ()>;
+
+struct S;
+impl<'a> T for &'a S {
+    type Item = &'a ();
+}
+
+fn filter_positive<'a>() -> Alias<'a> {
+    &S
+}
+
+fn with_positive(fun: impl Fn(Alias<'_>)) {
+    fun(filter_positive());
+}
+
+fn main() {
+    with_positive(|_| ());
+}
index 7f85b52f083a7c2a8de18913a937a65e711474b7..1f9db1eb2a97affce42fe9395435a0b5cd0b8341 100644 (file)
@@ -19,6 +19,9 @@ pub trait Sized {}
 #[lang = "destruct"]
 pub trait Destruct {}
 
+#[lang = "tuple_trait"]
+pub trait Tuple {}
+
 #[lang = "unsize"]
 pub trait Unsize<T: ?Sized> {}
 
@@ -443,7 +446,7 @@ pub enum Option<T> {
 
 #[lang = "fn_once"]
 #[rustc_paren_sugar]
-pub trait FnOnce<Args> {
+pub trait FnOnce<Args: Tuple> {
     #[lang = "fn_once_output"]
     type Output;
 
@@ -452,7 +455,7 @@ pub trait FnOnce<Args> {
 
 #[lang = "fn_mut"]
 #[rustc_paren_sugar]
-pub trait FnMut<Args>: FnOnce<Args> {
+pub trait FnMut<Args: Tuple>: FnOnce<Args> {
     extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
 }
 
index 215d3556a17ca8cf2b5eb7a7673b5a090612da70..c00f8a2e0cdad3229ad1362047bffeb8a4be2ad9 100644 (file)
@@ -171,8 +171,6 @@ fn main() {
 
     assert_eq!(slice_ptr as usize % 4, 0);
 
-    //return;
-
     unsafe {
         printf("Hello %s\n\0" as *const str as *const i8, "printf\0" as *const str as *const i8);
 
index ad108c34992e30efa101dc5d71fa5f832e45788f..8481d9c39a3cf672e83f85b03220fabdacf61817 100644 (file)
@@ -164,6 +164,8 @@ unsafe fn test_simd() {
     let cmp_eq = _mm_cmpeq_epi8(y, y);
     let cmp_lt = _mm_cmplt_epi8(y, y);
 
+    let (zero0, zero1) = std::mem::transmute::<_, (u64, u64)>(x);
+    assert_eq!((zero0, zero1), (0, 0));
     assert_eq!(std::mem::transmute::<_, [u16; 8]>(or), [7, 7, 7, 7, 7, 7, 7, 7]);
     assert_eq!(std::mem::transmute::<_, [u16; 8]>(cmp_eq), [0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff]);
     assert_eq!(std::mem::transmute::<_, [u16; 8]>(cmp_lt), [0, 0, 0, 0, 0, 0, 0, 0]);
index c0a2e7a7883fcb14031a9ea5a38289d564d30d4a..d8f28dbcc15c8c43d9631834b087f34ed547cebb 100644 (file)
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2022-10-23"
+channel = "nightly-2022-12-13"
 components = ["rust-src", "rustc-dev", "llvm-tools-preview"]
index 2bd8f7d1bc15d7a6690a34aad18f968f7af9bd3c..ebeca8662a5195c6408e8707a06248c189ffab99 100644 (file)
@@ -1,3 +1,5 @@
+ignore = ["y.rs"]
+
 # Matches rustfmt.toml of rustc
 version = "Two"
 use_small_heuristics = "Max"
index e6f60d1c0cb230985bf85311076b15199291a807..f782671fe36f9b45fab05a5c6f335d9880211c23 100755 (executable)
@@ -2,7 +2,7 @@
 #![forbid(unsafe_code)]/* This line is ignored by bash
 # This block is ignored by rustc
 pushd $(dirname "$0")/../
-RUSTC="$(pwd)/build/rustc-clif"
+RUSTC="$(pwd)/dist/rustc-clif"
 popd
 PROFILE=$1 OUTPUT=$2 exec $RUSTC -Zunstable-options -Cllvm-args=mode=jit -Cprefer-dynamic $0
 #*/
diff --git a/compiler/rustc_codegen_cranelift/scripts/rustdoc-clif.rs b/compiler/rustc_codegen_cranelift/scripts/rustdoc-clif.rs
new file mode 100644 (file)
index 0000000..a19d72a
--- /dev/null
@@ -0,0 +1,36 @@
+use std::env;
+use std::ffi::OsString;
+#[cfg(unix)]
+use std::os::unix::process::CommandExt;
+use std::path::PathBuf;
+use std::process::Command;
+
+fn main() {
+    let sysroot = PathBuf::from(env::current_exe().unwrap().parent().unwrap());
+
+    let cg_clif_dylib_path = sysroot.join(if cfg!(windows) { "bin" } else { "lib" }).join(
+        env::consts::DLL_PREFIX.to_string() + "rustc_codegen_cranelift" + env::consts::DLL_SUFFIX,
+    );
+
+    let mut args = std::env::args_os().skip(1).collect::<Vec<_>>();
+    args.push(OsString::from("-Cpanic=abort"));
+    args.push(OsString::from("-Zpanic-abort-tests"));
+    let mut codegen_backend_arg = OsString::from("-Zcodegen-backend=");
+    codegen_backend_arg.push(cg_clif_dylib_path);
+    args.push(codegen_backend_arg);
+    if !args.contains(&OsString::from("--sysroot")) {
+        args.push(OsString::from("--sysroot"));
+        args.push(OsString::from(sysroot.to_str().unwrap()));
+    }
+
+    // Ensure that the right toolchain is used
+    env::set_var("RUSTUP_TOOLCHAIN", env!("RUSTUP_TOOLCHAIN"));
+
+    #[cfg(unix)]
+    Command::new("rustdoc").args(args).exec();
+
+    #[cfg(not(unix))]
+    std::process::exit(
+        Command::new("rustdoc").args(args).spawn().unwrap().wait().unwrap().code().unwrap_or(1),
+    );
+}
index d6a37789599fe8d0621de8a2577fc77aa45b1be3..6c64b7de7daa10d863a903a186e0ee9c4846aeed 100644 (file)
@@ -27,24 +27,6 @@ index d95b5b7f17f..00b6f0e3635 100644
  [dev-dependencies]
  rand = "0.7"
  rand_xorshift = "0.2"
-diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
-index 8431aa7b818..a3ff7e68ce5 100644
---- a/src/tools/compiletest/src/runtest.rs
-+++ b/src/tools/compiletest/src/runtest.rs
-@@ -3489,12 +3489,7 @@ fn normalize_output(&self, output: &str, custom_rules: &[(String, String)]) -> S
-         let compiler_src_dir = base_dir.join("compiler");
-         normalize_path(&compiler_src_dir, "$(echo '$COMPILER_DIR')");
-
--        if let Some(virtual_rust_source_base_dir) =
--            option_env!("CFG_VIRTUAL_RUST_SOURCE_BASE_DIR").map(PathBuf::from)
--        {
--            normalize_path(&virtual_rust_source_base_dir.join("library"), "$(echo '$SRC_DIR')");
--            normalize_path(&virtual_rust_source_base_dir.join("compiler"), "$(echo '$COMPILER_DIR')");
--        }
-+        normalize_path(&Path::new("$(cd ../build_sysroot/sysroot_src/library; pwd)"), "$(echo '$SRC_DIR')");
-
-         // Paths into the build directory
-         let test_build_dir = &self.config.build_base;
 EOF
 
 cat > config.toml <<EOF
@@ -54,7 +36,7 @@ changelog-seen = 2
 ninja = false
 
 [build]
-rustc = "$(pwd)/../build/rustc-clif"
+rustc = "$(pwd)/../dist/rustc-clif"
 cargo = "$(rustup which cargo)"
 full-bootstrap = true
 local-rebuild = true
@@ -69,6 +51,8 @@ popd
 # FIXME remove once inline asm is fully supported
 export RUSTFLAGS="$RUSTFLAGS --cfg=rustix_use_libc"
 
+export CFG_VIRTUAL_RUST_SOURCE_BASE_DIR="$(cd build_sysroot/sysroot_src; pwd)"
+
 # Allow the testsuite to use llvm tools
 host_triple=$(rustc -vV | grep host | cut -d: -f2 | tr -d " ")
 export LLVM_BIN_DIR="$(rustc --print sysroot)/lib/rustlib/$host_triple/bin"
index 9b5db3cf81f0e3341f553398f6354c9320cf0640..04ad77ec97eac3a76d01166d875cf18bc073f76f 100755 (executable)
@@ -20,6 +20,7 @@ for test in $(rg -i --files-with-matches "//(\[\w+\])?~[^\|]*\s*ERR|// error-pat
 done
 
 git checkout -- src/test/ui/issues/auxiliary/issue-3136-a.rs # contains //~ERROR, but shouldn't be removed
+git checkout -- src/test/ui/proc-macro/pretty-print-hack/
 
 # missing features
 # ================
@@ -30,6 +31,7 @@ rm src/test/incremental/issue-80691-bad-eval-cache.rs # -Cpanic=abort causes abo
 
 # requires compiling with -Cpanic=unwind
 rm -r src/test/ui/macros/rfc-2011-nicer-assert-messages/
+rm -r src/test/run-make/test-benches
 
 # vendor intrinsics
 rm src/test/ui/sse2.rs # cpuid not supported, so sse2 not detected
@@ -64,6 +66,8 @@ rm src/test/ui/fn/dyn-fn-alignment.rs # wants a 256 byte alignment
 rm -r src/test/run-make/emit-named-files # requires full --emit support
 rm src/test/ui/abi/stack-probes.rs # stack probes not yet implemented
 rm src/test/ui/simd/intrinsic/ptr-cast.rs # simd_expose_addr intrinsic unimplemented
+rm -r src/test/run-make/repr128-dwarf # debuginfo test
+rm src/test/codegen-units/item-collection/asm-sym.rs # requires support for sym in asm!()
 
 # optimization tests
 # ==================
@@ -82,20 +86,20 @@ rm src/test/ui/abi/stack-protector.rs # requires stack protector support
 rm src/test/ui/mir/mir_misc_casts.rs # depends on deduplication of constants
 rm src/test/ui/mir/mir_raw_fat_ptr.rs # same
 rm src/test/ui/consts/issue-33537.rs # same
+rm src/test/ui/layout/valid_range_oob.rs # different ICE message
 
 # doesn't work due to the way the rustc test suite is invoked.
 # should work when using ./x.py test the way it is intended
 # ============================================================
-rm -r src/test/run-make/emit-shared-files # requires the rustdoc executable in build/bin/
+rm -r src/test/run-make/emit-shared-files # requires the rustdoc executable in dist/bin/
 rm -r src/test/run-make/unstable-flag-required # same
 rm -r src/test/run-make/rustdoc-* # same
 rm -r src/test/run-make/issue-88756-default-output # same
 rm -r src/test/run-make/remap-path-prefix-dwarf # requires llvm-dwarfdump
+rm -r src/test/ui/consts/missing_span_in_backtrace.rs # expects sysroot source to be elsewhere
 
 # genuine bugs
 # ============
-rm src/test/ui/allocator/no_std-alloc-error-handler-default.rs # missing rust_oom definition
-
 rm src/test/incremental/spike-neg1.rs # errors out for some reason
 rm src/test/incremental/spike-neg2.rs # same
 rm src/test/ui/issues/issue-74564-if-expr-stack-overflow.rs # gives a stackoverflow before the backend runs
@@ -104,6 +108,8 @@ rm src/test/ui/type-alias-impl-trait/assoc-projection-ice.rs # produces ICE
 
 rm src/test/ui/simd/intrinsic/generic-reduction-pass.rs # simd_reduce_add_unordered doesn't accept an accumulator for integer vectors
 
+rm src/test/ui/runtime/out-of-stack.rs # SIGSEGV instead of SIGABRT for some reason (#1301)
+
 # bugs in the test suite
 # ======================
 rm src/test/ui/backtrace.rs # TODO warning
@@ -111,6 +117,8 @@ rm src/test/ui/simple_global_asm.rs # TODO add needs-asm-support
 rm src/test/ui/test-attrs/test-type.rs # TODO panic message on stderr. correct stdout
 # not sure if this is actually a bug in the test suite, but the symbol list shows the function without leading _ for some reason
 rm -r src/test/run-make/native-link-modifier-bundle
+rm src/test/ui/process/nofile-limit.rs # TODO some AArch64 linking issue
+rm src/test/ui/dyn-star/dispatch-on-pin-mut.rs # TODO failed assertion in vtable::get_ptr_and_method_ref
 
 rm src/test/ui/stdio-is-blocking.rs # really slow with unoptimized libstd
 
index 98b5fb1cce28531eb856e758cde8061b8ae15426..65cc6b4376713d8c7e855c2fca1f833894a3cd09 100644 (file)
@@ -56,13 +56,13 @@ pub(crate) fn conv_to_call_conv(c: Conv, default_call_conv: CallConv) -> CallCon
 
 pub(crate) fn get_function_sig<'tcx>(
     tcx: TyCtxt<'tcx>,
-    triple: &target_lexicon::Triple,
+    default_call_conv: CallConv,
     inst: Instance<'tcx>,
 ) -> Signature {
     assert!(!inst.substs.needs_infer());
     clif_sig_from_fn_abi(
         tcx,
-        CallConv::triple_default(triple),
+        default_call_conv,
         &RevealAllLayoutCx(tcx).fn_abi_of_instance(inst, ty::List::empty()),
     )
 }
@@ -74,7 +74,7 @@ pub(crate) fn import_function<'tcx>(
     inst: Instance<'tcx>,
 ) -> FuncId {
     let name = tcx.symbol_name(inst).name;
-    let sig = get_function_sig(tcx, module.isa().triple(), inst);
+    let sig = get_function_sig(tcx, module.target_config().default_call_conv, inst);
     match module.declare_function(name, Linkage::Import, &sig) {
         Ok(func_id) => func_id,
         Err(ModuleError::IncompatibleDeclaration(_)) => tcx.sess.fatal(&format!(
@@ -341,14 +341,13 @@ pub(crate) fn codegen_terminator_call<'tcx>(
     destination: Place<'tcx>,
     target: Option<BasicBlock>,
 ) {
-    let fn_ty = fx.monomorphize(func.ty(fx.mir, fx.tcx));
-    let fn_sig =
-        fx.tcx.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), fn_ty.fn_sig(fx.tcx));
+    let func = codegen_operand(fx, func);
+    let fn_sig = func.layout().ty.fn_sig(fx.tcx);
 
     let ret_place = codegen_place(fx, destination);
 
     // Handle special calls like intrinsics and empty drop glue.
-    let instance = if let ty::FnDef(def_id, substs) = *fn_ty.kind() {
+    let instance = if let ty::FnDef(def_id, substs) = *func.layout().ty.kind() {
         let instance =
             ty::Instance::expect_resolve(fx.tcx, ty::ParamEnv::reveal_all(), def_id, substs)
                 .polymorphize(fx.tcx);
@@ -390,17 +389,17 @@ pub(crate) fn codegen_terminator_call<'tcx>(
         None
     };
 
-    let extra_args = &args[fn_sig.inputs().len()..];
+    let extra_args = &args[fn_sig.inputs().skip_binder().len()..];
     let extra_args = fx
         .tcx
         .mk_type_list(extra_args.iter().map(|op_arg| fx.monomorphize(op_arg.ty(fx.mir, fx.tcx))));
     let fn_abi = if let Some(instance) = instance {
         RevealAllLayoutCx(fx.tcx).fn_abi_of_instance(instance, extra_args)
     } else {
-        RevealAllLayoutCx(fx.tcx).fn_abi_of_fn_ptr(fn_ty.fn_sig(fx.tcx), extra_args)
+        RevealAllLayoutCx(fx.tcx).fn_abi_of_fn_ptr(fn_sig, extra_args)
     };
 
-    let is_cold = if fn_sig.abi == Abi::RustCold {
+    let is_cold = if fn_sig.abi() == Abi::RustCold {
         true
     } else {
         instance
@@ -417,7 +416,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
     }
 
     // Unpack arguments tuple for closures
-    let mut args = if fn_sig.abi == Abi::RustCall {
+    let mut args = if fn_sig.abi() == Abi::RustCall {
         assert_eq!(args.len(), 2, "rust-call abi requires two arguments");
         let self_arg = codegen_call_argument_operand(fx, &args[0]);
         let pack_arg = codegen_call_argument_operand(fx, &args[1]);
@@ -485,7 +484,7 @@ enum CallTarget {
                 fx.add_comment(nop_inst, "indirect call");
             }
 
-            let func = codegen_operand(fx, func).load_scalar(fx);
+            let func = func.load_scalar(fx);
             let sig = clif_sig_from_fn_abi(fx.tcx, fx.target_config.default_call_conv, &fn_abi);
             let sig = fx.bcx.import_signature(sig);
 
@@ -516,11 +515,11 @@ enum CallTarget {
         };
 
         // FIXME find a cleaner way to support varargs
-        if fn_sig.c_variadic {
-            if !matches!(fn_sig.abi, Abi::C { .. }) {
+        if fn_sig.c_variadic() {
+            if !matches!(fn_sig.abi(), Abi::C { .. }) {
                 fx.tcx.sess.span_fatal(
                     source_info.span,
-                    &format!("Variadic call for non-C abi {:?}", fn_sig.abi),
+                    &format!("Variadic call for non-C abi {:?}", fn_sig.abi()),
                 );
             }
             let sig_ref = fx.bcx.func.dfg.call_signature(call_inst).unwrap();
index 12bb00d346db42c42c88adfad2d5939df371c1f6..8508227179ac611fb77c350c541e5835e0313936 100644 (file)
@@ -66,7 +66,7 @@ fn codegen_inner(
         };
 
         let sig = Signature {
-            call_conv: CallConv::triple_default(module.isa().triple()),
+            call_conv: module.target_config().default_call_conv,
             params: arg_tys.iter().cloned().map(AbiParam::new).collect(),
             returns: output.into_iter().map(AbiParam::new).collect(),
         };
@@ -104,7 +104,7 @@ fn codegen_inner(
     }
 
     let sig = Signature {
-        call_conv: CallConv::triple_default(module.isa().triple()),
+        call_conv: module.target_config().default_call_conv,
         params: vec![AbiParam::new(usize_ty), AbiParam::new(usize_ty)],
         returns: vec![],
     };
index 06813d7ec953f558a44eec3eb059723167e45131..89d955e8bf2e1d84c1a40045d0b063140d325525 100644 (file)
@@ -59,7 +59,7 @@ pub(crate) fn codegen_fn<'tcx>(
 
     // Declare function
     let symbol_name = tcx.symbol_name(instance).name.to_string();
-    let sig = get_function_sig(tcx, module.isa().triple(), instance);
+    let sig = get_function_sig(tcx, module.target_config().default_call_conv, instance);
     let func_id = module.declare_function(&symbol_name, Linkage::Local, &sig).unwrap();
 
     // Make the FunctionBuilder
@@ -390,11 +390,9 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
                         _ => unreachable!("{:?}", targets),
                     };
 
-                    let discr = crate::optimize::peephole::maybe_unwrap_bint(&mut fx.bcx, discr);
                     let (discr, is_inverted) =
                         crate::optimize::peephole::maybe_unwrap_bool_not(&mut fx.bcx, discr);
                     let test_zero = if is_inverted { !test_zero } else { test_zero };
-                    let discr = crate::optimize::peephole::maybe_unwrap_bint(&mut fx.bcx, discr);
                     if let Some(taken) = crate::optimize::peephole::maybe_known_branch_taken(
                         &fx.bcx, discr, test_zero,
                     ) {
@@ -571,7 +569,7 @@ fn codegen_stmt<'tcx>(
                         UnOp::Not => match layout.ty.kind() {
                             ty::Bool => {
                                 let res = fx.bcx.ins().icmp_imm(IntCC::Equal, val, 0);
-                                CValue::by_val(fx.bcx.ins().bint(types::I8, res), layout)
+                                CValue::by_val(res, layout)
                             }
                             ty::Uint(_) | ty::Int(_) => {
                                 CValue::by_val(fx.bcx.ins().bnot(val), layout)
@@ -579,12 +577,6 @@ fn codegen_stmt<'tcx>(
                             _ => unreachable!("un op Not for {:?}", layout.ty),
                         },
                         UnOp::Neg => match layout.ty.kind() {
-                            ty::Int(IntTy::I128) => {
-                                // FIXME remove this case once ineg.i128 works
-                                let zero =
-                                    CValue::const_val(fx, layout, ty::ScalarInt::null(layout.size));
-                                crate::num::codegen_int_binop(fx, BinOp::Sub, zero, operand)
-                            }
                             ty::Int(_) => CValue::by_val(fx.bcx.ins().ineg(val), layout),
                             ty::Float(_) => CValue::by_val(fx.bcx.ins().fneg(val), layout),
                             _ => unreachable!("un op Neg for {:?}", layout.ty),
index bad5d1f08a9cf5454766b36de3f2614e5a6020a4..5091c5a9fedacbb7f4dda7b4d5ab7f086f17d1d7 100644 (file)
@@ -149,7 +149,7 @@ pub(crate) fn clif_int_or_float_cast(
         }
 
         let is_not_nan = fx.bcx.ins().fcmp(FloatCC::Equal, from, from);
-        let zero = fx.bcx.ins().iconst(to_ty, 0);
+        let zero = type_zero_value(&mut fx.bcx, to_ty);
         fx.bcx.ins().select(is_not_nan, val, zero)
     } else if from_ty.is_float() && to_ty.is_float() {
         // float -> float
index 589594465783e1611c688cd17f5c82325ae9576f..2dcd42fbd8f431833ac46b414c539e40c828f0e8 100644 (file)
@@ -162,11 +162,20 @@ pub(crate) fn codegen_icmp_imm(
             }
         }
     } else {
-        let rhs = i64::try_from(rhs).expect("codegen_icmp_imm rhs out of range for <128bit int");
+        let rhs = rhs as i64; // Truncates on purpose in case rhs is actually an unsigned value
         fx.bcx.ins().icmp_imm(intcc, lhs, rhs)
     }
 }
 
+pub(crate) fn type_zero_value(bcx: &mut FunctionBuilder<'_>, ty: Type) -> Value {
+    if ty == types::I128 {
+        let zero = bcx.ins().iconst(types::I64, 0);
+        bcx.ins().iconcat(zero, zero)
+    } else {
+        bcx.ins().iconst(ty, 0)
+    }
+}
+
 pub(crate) fn type_min_max_value(
     bcx: &mut FunctionBuilder<'_>,
     ty: Type,
index a6bde88408497ed9d12a7cd28a82966d7fc52439..dee6fb5b5130d1f27abaf1fda1581605a82973b5 100644 (file)
@@ -28,9 +28,7 @@ pub(crate) fn new() -> Self {
     }
 
     pub(crate) fn finalize(mut self, tcx: TyCtxt<'_>, module: &mut dyn Module) {
-        //println!("todo {:?}", self.todo);
         define_all_allocs(tcx, module, &mut self);
-        //println!("done {:?}", self.done);
         self.done.clear();
     }
 }
@@ -268,16 +266,7 @@ fn data_id_for_static(
     def_id: DefId,
     definition: bool,
 ) -> DataId {
-    let rlinkage = tcx.codegen_fn_attrs(def_id).linkage;
-    let linkage = if definition {
-        crate::linkage::get_static_linkage(tcx, def_id)
-    } else if rlinkage == Some(rustc_middle::mir::mono::Linkage::ExternalWeak)
-        || rlinkage == Some(rustc_middle::mir::mono::Linkage::WeakAny)
-    {
-        Linkage::Preemptible
-    } else {
-        Linkage::Import
-    };
+    let attrs = tcx.codegen_fn_attrs(def_id);
 
     let instance = Instance::mono(tcx, def_id).polymorphize(tcx);
     let symbol_name = tcx.symbol_name(instance).name;
@@ -289,22 +278,30 @@ fn data_id_for_static(
     };
     let align = tcx.layout_of(ParamEnv::reveal_all().and(ty)).unwrap().align.pref.bytes();
 
-    let attrs = tcx.codegen_fn_attrs(def_id);
+    if let Some(import_linkage) = attrs.import_linkage {
+        assert!(!definition);
 
-    let data_id = match module.declare_data(
-        &*symbol_name,
-        linkage,
-        is_mutable,
-        attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL),
-    ) {
-        Ok(data_id) => data_id,
-        Err(ModuleError::IncompatibleDeclaration(_)) => tcx.sess.fatal(&format!(
-            "attempt to declare `{symbol_name}` as static, but it was already declared as function"
-        )),
-        Err(err) => Err::<_, _>(err).unwrap(),
-    };
+        let linkage = if import_linkage == rustc_middle::mir::mono::Linkage::ExternalWeak
+            || import_linkage == rustc_middle::mir::mono::Linkage::WeakAny
+        {
+            Linkage::Preemptible
+        } else {
+            Linkage::Import
+        };
+
+        let data_id = match module.declare_data(
+            &*symbol_name,
+            linkage,
+            is_mutable,
+            attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL),
+        ) {
+            Ok(data_id) => data_id,
+            Err(ModuleError::IncompatibleDeclaration(_)) => tcx.sess.fatal(&format!(
+                "attempt to declare `{symbol_name}` as static, but it was already declared as function"
+            )),
+            Err(err) => Err::<_, _>(err).unwrap(),
+        };
 
-    if rlinkage.is_some() {
         // Comment copied from https://github.com/rust-lang/rust/blob/45060c2a66dfd667f88bd8b94261b28a58d85bd5/src/librustc_codegen_llvm/consts.rs#L141
         // Declare an internal global `extern_with_linkage_foo` which
         // is initialized with the address of `foo`.  If `foo` is
@@ -326,10 +323,34 @@ fn data_id_for_static(
             Err(ModuleError::DuplicateDefinition(_)) => {}
             res => res.unwrap(),
         }
-        ref_data_id
-    } else {
-        data_id
+
+        return ref_data_id;
     }
+
+    let linkage = if definition {
+        crate::linkage::get_static_linkage(tcx, def_id)
+    } else if attrs.linkage == Some(rustc_middle::mir::mono::Linkage::ExternalWeak)
+        || attrs.linkage == Some(rustc_middle::mir::mono::Linkage::WeakAny)
+    {
+        Linkage::Preemptible
+    } else {
+        Linkage::Import
+    };
+
+    let data_id = match module.declare_data(
+        &*symbol_name,
+        linkage,
+        is_mutable,
+        attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL),
+    ) {
+        Ok(data_id) => data_id,
+        Err(ModuleError::IncompatibleDeclaration(_)) => tcx.sess.fatal(&format!(
+            "attempt to declare `{symbol_name}` as static, but it was already declared as function"
+        )),
+        Err(err) => Err::<_, _>(err).unwrap(),
+    };
+
+    data_id
 }
 
 fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut ConstantCx) {
@@ -348,8 +369,6 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
                 (data_id, alloc, None)
             }
             TodoItem::Static(def_id) => {
-                //println!("static {:?}", def_id);
-
                 let section_name = tcx.codegen_fn_attrs(def_id).link_section;
 
                 let alloc = tcx.eval_static_initializer(def_id).unwrap();
@@ -359,7 +378,6 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
             }
         };
 
-        //("data_id {}", data_id);
         if cx.done.contains(&data_id) {
             continue;
         }
index d26392c4913b508a3ab68335d2ea771243c6b42d..493359c743f119d6bcee87920e595c943a009642 100644 (file)
@@ -39,7 +39,9 @@ pub(crate) fn new(isa: &dyn TargetIsa, pic_eh_frame: bool) -> Self {
     }
 
     pub(crate) fn add_function(&mut self, func_id: FuncId, context: &Context, isa: &dyn TargetIsa) {
-        let unwind_info = if let Some(unwind_info) = context.create_unwind_info(isa).unwrap() {
+        let unwind_info = if let Some(unwind_info) =
+            context.compiled_code().unwrap().create_unwind_info(isa).unwrap()
+        {
             unwind_info
         } else {
             return;
index 97b395bcd05186b199e59026ddec9fda4472dc77..3cbf313adf0df5a69887cdb1f0516245f2b23232 100644 (file)
@@ -1,6 +1,7 @@
 //! Handling of enum discriminants
 //!
-//! Adapted from <https://github.com/rust-lang/rust/blob/d760df5aea483aae041c9a241e7acacf48f75035/src/librustc_codegen_ssa/mir/place.rs>
+//! Adapted from <https://github.com/rust-lang/rust/blob/31c0645b9d2539f47eecb096142474b29dc542f7/compiler/rustc_codegen_ssa/src/mir/place.rs>
+//! (<https://github.com/rust-lang/rust/pull/104535>)
 
 use rustc_target::abi::{Int, TagEncoding, Variants};
 
@@ -47,13 +48,19 @@ pub(crate) fn codegen_set_discriminant<'tcx>(
         } => {
             if variant_index != untagged_variant {
                 let niche = place.place_field(fx, mir::Field::new(tag_field));
+                let niche_type = fx.clif_type(niche.layout().ty).unwrap();
                 let niche_value = variant_index.as_u32() - niche_variants.start().as_u32();
-                let niche_value = ty::ScalarInt::try_from_uint(
-                    u128::from(niche_value).wrapping_add(niche_start),
-                    niche.layout().size,
-                )
-                .unwrap();
-                let niche_llval = CValue::const_val(fx, niche.layout(), niche_value);
+                let niche_value = (niche_value as u128).wrapping_add(niche_start);
+                let niche_value = match niche_type {
+                    types::I128 => {
+                        let lsb = fx.bcx.ins().iconst(types::I64, niche_value as u64 as i64);
+                        let msb =
+                            fx.bcx.ins().iconst(types::I64, (niche_value >> 64) as u64 as i64);
+                        fx.bcx.ins().iconcat(lsb, msb)
+                    }
+                    ty => fx.bcx.ins().iconst(ty, niche_value as i64),
+                };
+                let niche_llval = CValue::by_val(niche_value, niche.layout());
                 niche.write_cvalue(fx, niche_llval);
             }
         }
@@ -96,6 +103,7 @@ pub(crate) fn codegen_get_discriminant<'tcx>(
         }
     };
 
+    let cast_to_size = dest_layout.layout.size();
     let cast_to = fx.clif_type(dest_layout.ty).unwrap();
 
     // Read the tag/niche-encoded discriminant from memory.
@@ -114,21 +122,128 @@ pub(crate) fn codegen_get_discriminant<'tcx>(
             dest.write_cvalue(fx, res);
         }
         TagEncoding::Niche { untagged_variant, ref niche_variants, niche_start } => {
-            // Rebase from niche values to discriminants, and check
-            // whether the result is in range for the niche variants.
-
-            // We first compute the "relative discriminant" (wrt `niche_variants`),
-            // that is, if `n = niche_variants.end() - niche_variants.start()`,
-            // we remap `niche_start..=niche_start + n` (which may wrap around)
-            // to (non-wrap-around) `0..=n`, to be able to check whether the
-            // discriminant corresponds to a niche variant with one comparison.
-            // We also can't go directly to the (variant index) discriminant
-            // and check that it is in the range `niche_variants`, because
-            // that might not fit in the same type, on top of needing an extra
-            // comparison (see also the comment on `let niche_discr`).
-            let relative_discr = if niche_start == 0 {
-                tag
+            let tag_size = tag_scalar.size(fx);
+            let max_unsigned = tag_size.unsigned_int_max();
+            let max_signed = tag_size.signed_int_max() as u128;
+            let min_signed = max_signed + 1;
+            let relative_max = niche_variants.end().as_u32() - niche_variants.start().as_u32();
+            let niche_end = niche_start.wrapping_add(relative_max as u128) & max_unsigned;
+            let range = tag_scalar.valid_range(fx);
+
+            let sle = |lhs: u128, rhs: u128| -> bool {
+                // Signed and unsigned comparisons give the same results,
+                // except that in signed comparisons an integer with the
+                // sign bit set is less than one with the sign bit clear.
+                // Toggle the sign bit to do a signed comparison.
+                (lhs ^ min_signed) <= (rhs ^ min_signed)
+            };
+
+            // We have a subrange `niche_start..=niche_end` inside `range`.
+            // If the value of the tag is inside this subrange, it's a
+            // "niche value", an increment of the discriminant. Otherwise it
+            // indicates the untagged variant.
+            // A general algorithm to extract the discriminant from the tag
+            // is:
+            // relative_tag = tag - niche_start
+            // is_niche = relative_tag <= (ule) relative_max
+            // discr = if is_niche {
+            //     cast(relative_tag) + niche_variants.start()
+            // } else {
+            //     untagged_variant
+            // }
+            // However, we will likely be able to emit simpler code.
+
+            // Find the least and greatest values in `range`, considered
+            // both as signed and unsigned.
+            let (low_unsigned, high_unsigned) =
+                if range.start <= range.end { (range.start, range.end) } else { (0, max_unsigned) };
+            let (low_signed, high_signed) = if sle(range.start, range.end) {
+                (range.start, range.end)
             } else {
+                (min_signed, max_signed)
+            };
+
+            let niches_ule = niche_start <= niche_end;
+            let niches_sle = sle(niche_start, niche_end);
+            let cast_smaller = cast_to_size <= tag_size;
+
+            // In the algorithm above, we can change
+            // cast(relative_tag) + niche_variants.start()
+            // into
+            // cast(tag + (niche_variants.start() - niche_start))
+            // if either the casted type is no larger than the original
+            // type, or if the niche values are contiguous (in either the
+            // signed or unsigned sense).
+            let can_incr = cast_smaller || niches_ule || niches_sle;
+
+            let data_for_boundary_niche = || -> Option<(IntCC, u128)> {
+                if !can_incr {
+                    None
+                } else if niche_start == low_unsigned {
+                    Some((IntCC::UnsignedLessThanOrEqual, niche_end))
+                } else if niche_end == high_unsigned {
+                    Some((IntCC::UnsignedGreaterThanOrEqual, niche_start))
+                } else if niche_start == low_signed {
+                    Some((IntCC::SignedLessThanOrEqual, niche_end))
+                } else if niche_end == high_signed {
+                    Some((IntCC::SignedGreaterThanOrEqual, niche_start))
+                } else {
+                    None
+                }
+            };
+
+            let (is_niche, tagged_discr, delta) = if relative_max == 0 {
+                // Best case scenario: only one tagged variant. This will
+                // likely become just a comparison and a jump.
+                // The algorithm is:
+                // is_niche = tag == niche_start
+                // discr = if is_niche {
+                //     niche_start
+                // } else {
+                //     untagged_variant
+                // }
+                let is_niche = codegen_icmp_imm(fx, IntCC::Equal, tag, niche_start as i128);
+                let tagged_discr =
+                    fx.bcx.ins().iconst(cast_to, niche_variants.start().as_u32() as i64);
+                (is_niche, tagged_discr, 0)
+            } else if let Some((predicate, constant)) = data_for_boundary_niche() {
+                // The niche values are either the lowest or the highest in
+                // `range`. We can avoid the first subtraction in the
+                // algorithm.
+                // The algorithm is now this:
+                // is_niche = tag <= niche_end
+                // discr = if is_niche {
+                //     cast(tag + (niche_variants.start() - niche_start))
+                // } else {
+                //     untagged_variant
+                // }
+                // (the first line may instead be tag >= niche_start,
+                // and may be a signed or unsigned comparison)
+                // The arithmetic must be done before the cast, so we can
+                // have the correct wrapping behavior. See issue #104519 for
+                // the consequences of getting this wrong.
+                let is_niche = codegen_icmp_imm(fx, predicate, tag, constant as i128);
+                let delta = (niche_variants.start().as_u32() as u128).wrapping_sub(niche_start);
+                let incr_tag = if delta == 0 {
+                    tag
+                } else {
+                    let delta = match fx.bcx.func.dfg.value_type(tag) {
+                        types::I128 => {
+                            let lsb = fx.bcx.ins().iconst(types::I64, delta as u64 as i64);
+                            let msb = fx.bcx.ins().iconst(types::I64, (delta >> 64) as u64 as i64);
+                            fx.bcx.ins().iconcat(lsb, msb)
+                        }
+                        ty => fx.bcx.ins().iconst(ty, delta as i64),
+                    };
+                    fx.bcx.ins().iadd(tag, delta)
+                };
+
+                let cast_tag = clif_intcast(fx, incr_tag, cast_to, !niches_ule);
+
+                (is_niche, cast_tag, 0)
+            } else {
+                // The special cases don't apply, so we'll have to go with
+                // the general algorithm.
                 let niche_start = match fx.bcx.func.dfg.value_type(tag) {
                     types::I128 => {
                         let lsb = fx.bcx.ins().iconst(types::I64, niche_start as u64 as i64);
@@ -138,40 +253,40 @@ pub(crate) fn codegen_get_discriminant<'tcx>(
                     }
                     ty => fx.bcx.ins().iconst(ty, niche_start as i64),
                 };
-                fx.bcx.ins().isub(tag, niche_start)
-            };
-            let relative_max = niche_variants.end().as_u32() - niche_variants.start().as_u32();
-            let is_niche = {
-                codegen_icmp_imm(
+                let relative_discr = fx.bcx.ins().isub(tag, niche_start);
+                let cast_tag = clif_intcast(fx, relative_discr, cast_to, false);
+                let is_niche = crate::common::codegen_icmp_imm(
                     fx,
                     IntCC::UnsignedLessThanOrEqual,
                     relative_discr,
                     i128::from(relative_max),
-                )
+                );
+                (is_niche, cast_tag, niche_variants.start().as_u32() as u128)
             };
 
-            // NOTE(eddyb) this addition needs to be performed on the final
-            // type, in case the niche itself can't represent all variant
-            // indices (e.g. `u8` niche with more than `256` variants,
-            // but enough uninhabited variants so that the remaining variants
-            // fit in the niche).
-            // In other words, `niche_variants.end - niche_variants.start`
-            // is representable in the niche, but `niche_variants.end`
-            // might not be, in extreme cases.
-            let niche_discr = {
-                let relative_discr = if relative_max == 0 {
-                    // HACK(eddyb) since we have only one niche, we know which
-                    // one it is, and we can avoid having a dynamic value here.
-                    fx.bcx.ins().iconst(cast_to, 0)
-                } else {
-                    clif_intcast(fx, relative_discr, cast_to, false)
+            let tagged_discr = if delta == 0 {
+                tagged_discr
+            } else {
+                let delta = match cast_to {
+                    types::I128 => {
+                        let lsb = fx.bcx.ins().iconst(types::I64, delta as u64 as i64);
+                        let msb = fx.bcx.ins().iconst(types::I64, (delta >> 64) as u64 as i64);
+                        fx.bcx.ins().iconcat(lsb, msb)
+                    }
+                    ty => fx.bcx.ins().iconst(ty, delta as i64),
                 };
-                fx.bcx.ins().iadd_imm(relative_discr, i64::from(niche_variants.start().as_u32()))
+                fx.bcx.ins().iadd(tagged_discr, delta)
             };
 
-            let untagged_variant =
-                fx.bcx.ins().iconst(cast_to, i64::from(untagged_variant.as_u32()));
-            let discr = fx.bcx.ins().select(is_niche, niche_discr, untagged_variant);
+            let untagged_variant = if cast_to == types::I128 {
+                let zero = fx.bcx.ins().iconst(types::I64, 0);
+                let untagged_variant =
+                    fx.bcx.ins().iconst(types::I64, i64::from(untagged_variant.as_u32()));
+                fx.bcx.ins().iconcat(untagged_variant, zero)
+            } else {
+                fx.bcx.ins().iconst(cast_to, i64::from(untagged_variant.as_u32()))
+            };
+            let discr = fx.bcx.ins().select(is_niche, tagged_discr, untagged_variant);
             let res = CValue::by_val(discr, dest_layout);
             dest.write_cvalue(fx, res);
         }
index 6a430b5215e36d11b483213b5bb7e74c75425727..be1b8c9ead3bf2e133d326818df523e19f201fda 100644 (file)
@@ -159,7 +159,7 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! {
 
     tcx.sess.abort_if_errors();
 
-    jit_module.finalize_definitions();
+    jit_module.finalize_definitions().unwrap();
     unsafe { cx.unwind_context.register_jit(&jit_module) };
 
     println!(
@@ -245,7 +245,11 @@ fn jit_fn(instance_ptr: *const Instance<'static>, trampoline_ptr: *const u8) ->
             let backend_config = lazy_jit_state.backend_config.clone();
 
             let name = tcx.symbol_name(instance).name;
-            let sig = crate::abi::get_function_sig(tcx, jit_module.isa().triple(), instance);
+            let sig = crate::abi::get_function_sig(
+                tcx,
+                jit_module.target_config().default_call_conv,
+                instance,
+            );
             let func_id = jit_module.declare_function(name, Linkage::Export, &sig).unwrap();
 
             let current_ptr = jit_module.read_got_entry(func_id);
@@ -278,7 +282,7 @@ fn jit_fn(instance_ptr: *const Instance<'static>, trampoline_ptr: *const u8) ->
             });
 
             assert!(cx.global_asm.is_empty());
-            jit_module.finalize_definitions();
+            jit_module.finalize_definitions().unwrap();
             unsafe { cx.unwind_context.register_jit(&jit_module) };
             jit_module.get_finalized_function(func_id)
         })
@@ -344,7 +348,7 @@ fn codegen_shim<'tcx>(
     let pointer_type = module.target_config().pointer_type();
 
     let name = tcx.symbol_name(inst).name;
-    let sig = crate::abi::get_function_sig(tcx, module.isa().triple(), inst);
+    let sig = crate::abi::get_function_sig(tcx, module.target_config().default_call_conv, inst);
     let func_id = module.declare_function(name, Linkage::Export, &sig).unwrap();
 
     let instance_ptr = Box::into_raw(Box::new(inst));
index 8f5714ecb417704e446edda114f65b4966facb66..6e925cea277078b68ac5d03de3cc18fae0e91e71 100644 (file)
@@ -24,7 +24,8 @@ fn predefine_mono_items<'tcx>(
                 MonoItem::Fn(instance) => {
                     let name = tcx.symbol_name(instance).name;
                     let _inst_guard = crate::PrintOnPanic(|| format!("{:?} {}", instance, name));
-                    let sig = get_function_sig(tcx, module.isa().triple(), instance);
+                    let sig =
+                        get_function_sig(tcx, module.target_config().default_call_conv, instance);
                     let linkage = crate::linkage::get_clif_linkage(
                         mono_item,
                         linkage,
index 783d426c30bcc0d14cf94bb658b854e1e4b337fb..f722e52284fe8205f269103a620fec33015ef9a4 100644 (file)
 pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
     fx: &mut FunctionCx<'_, '_, 'tcx>,
     intrinsic: &str,
-    _substs: SubstsRef<'tcx>,
+    substs: SubstsRef<'tcx>,
     args: &[mir::Operand<'tcx>],
     ret: CPlace<'tcx>,
     target: Option<BasicBlock>,
 ) {
-    match intrinsic {
-        "llvm.x86.sse2.pause" | "llvm.aarch64.isb" => {
-            // Spin loop hint
-        }
+    if intrinsic.starts_with("llvm.aarch64") {
+        return llvm_aarch64::codegen_aarch64_llvm_intrinsic_call(
+            fx, intrinsic, substs, args, ret, target,
+        );
+    }
+    if intrinsic.starts_with("llvm.x86") {
+        return llvm_x86::codegen_x86_llvm_intrinsic_call(fx, intrinsic, substs, args, ret, target);
+    }
 
-        // Used by `_mm_movemask_epi8` and `_mm256_movemask_epi8`
-        "llvm.x86.sse2.pmovmskb.128" | "llvm.x86.avx2.pmovmskb" | "llvm.x86.sse2.movmsk.pd" => {
+    match intrinsic {
+        _ if intrinsic.starts_with("llvm.ctlz.v") => {
             intrinsic_args!(fx, args => (a); intrinsic);
 
-            let (lane_count, lane_ty) = a.layout().ty.simd_size_and_type(fx.tcx);
-            let lane_ty = fx.clif_type(lane_ty).unwrap();
-            assert!(lane_count <= 32);
-
-            let mut res = fx.bcx.ins().iconst(types::I32, 0);
-
-            for lane in (0..lane_count).rev() {
-                let a_lane = a.value_lane(fx, lane).load_scalar(fx);
-
-                // cast float to int
-                let a_lane = match lane_ty {
-                    types::F32 => fx.bcx.ins().bitcast(types::I32, a_lane),
-                    types::F64 => fx.bcx.ins().bitcast(types::I64, a_lane),
-                    _ => a_lane,
-                };
-
-                // extract sign bit of an int
-                let a_lane_sign = fx.bcx.ins().ushr_imm(a_lane, i64::from(lane_ty.bits() - 1));
-
-                // shift sign bit into result
-                let a_lane_sign = clif_intcast(fx, a_lane_sign, types::I32, false);
-                res = fx.bcx.ins().ishl_imm(res, 1);
-                res = fx.bcx.ins().bor(res, a_lane_sign);
-            }
-
-            let res = CValue::by_val(res, fx.layout_of(fx.tcx.types.i32));
-            ret.write_cvalue(fx, res);
-        }
-        "llvm.x86.sse2.cmp.ps" | "llvm.x86.sse2.cmp.pd" => {
-            let (x, y, kind) = match args {
-                [x, y, kind] => (x, y, kind),
-                _ => bug!("wrong number of args for intrinsic {intrinsic}"),
-            };
-            let x = codegen_operand(fx, x);
-            let y = codegen_operand(fx, y);
-            let kind = crate::constant::mir_operand_get_const_val(fx, kind)
-                .expect("llvm.x86.sse2.cmp.* kind not const");
-
-            let flt_cc = match kind
-                .try_to_bits(Size::from_bytes(1))
-                .unwrap_or_else(|| panic!("kind not scalar: {:?}", kind))
-            {
-                0 => FloatCC::Equal,
-                1 => FloatCC::LessThan,
-                2 => FloatCC::LessThanOrEqual,
-                7 => FloatCC::Ordered,
-                3 => FloatCC::Unordered,
-                4 => FloatCC::NotEqual,
-                5 => FloatCC::UnorderedOrGreaterThanOrEqual,
-                6 => FloatCC::UnorderedOrGreaterThan,
-                kind => unreachable!("kind {:?}", kind),
-            };
-
-            simd_pair_for_each_lane(fx, x, y, ret, &|fx, lane_ty, res_lane_ty, x_lane, y_lane| {
-                let res_lane = match lane_ty.kind() {
-                    ty::Float(_) => fx.bcx.ins().fcmp(flt_cc, x_lane, y_lane),
-                    _ => unreachable!("{:?}", lane_ty),
-                };
-                bool_to_zero_or_max_uint(fx, res_lane_ty, res_lane)
+            simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| {
+                fx.bcx.ins().clz(lane)
             });
         }
-        "llvm.x86.sse2.psrli.d" => {
-            let (a, imm8) = match args {
-                [a, imm8] => (a, imm8),
-                _ => bug!("wrong number of args for intrinsic {intrinsic}"),
-            };
-            let a = codegen_operand(fx, a);
-            let imm8 = crate::constant::mir_operand_get_const_val(fx, imm8)
-                .expect("llvm.x86.sse2.psrli.d imm8 not const");
 
-            simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| match imm8
-                .try_to_bits(Size::from_bytes(4))
-                .unwrap_or_else(|| panic!("imm8 not scalar: {:?}", imm8))
-            {
-                imm8 if imm8 < 32 => fx.bcx.ins().ushr_imm(lane, i64::from(imm8 as u8)),
-                _ => fx.bcx.ins().iconst(types::I32, 0),
-            });
-        }
-        "llvm.x86.sse2.pslli.d" => {
-            let (a, imm8) = match args {
-                [a, imm8] => (a, imm8),
-                _ => bug!("wrong number of args for intrinsic {intrinsic}"),
-            };
-            let a = codegen_operand(fx, a);
-            let imm8 = crate::constant::mir_operand_get_const_val(fx, imm8)
-                .expect("llvm.x86.sse2.psrli.d imm8 not const");
+        _ if intrinsic.starts_with("llvm.ctpop.v") => {
+            intrinsic_args!(fx, args => (a); intrinsic);
 
-            simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| match imm8
-                .try_to_bits(Size::from_bytes(4))
-                .unwrap_or_else(|| panic!("imm8 not scalar: {:?}", imm8))
-            {
-                imm8 if imm8 < 32 => fx.bcx.ins().ishl_imm(lane, i64::from(imm8 as u8)),
-                _ => fx.bcx.ins().iconst(types::I32, 0),
+            simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| {
+                fx.bcx.ins().popcnt(lane)
             });
         }
-        "llvm.x86.sse2.storeu.dq" => {
-            intrinsic_args!(fx, args => (mem_addr, a); intrinsic);
-            let mem_addr = mem_addr.load_scalar(fx);
-
-            // FIXME correctly handle the unalignment
-            let dest = CPlace::for_ptr(Pointer::new(mem_addr), a.layout());
-            dest.write_cvalue(fx, a);
-        }
-        "llvm.x86.addcarry.64" => {
-            intrinsic_args!(fx, args => (c_in, a, b); intrinsic);
-            let c_in = c_in.load_scalar(fx);
-
-            llvm_add_sub(fx, BinOp::Add, ret, c_in, a, b);
-        }
-        "llvm.x86.subborrow.64" => {
-            intrinsic_args!(fx, args => (b_in, a, b); intrinsic);
-            let b_in = b_in.load_scalar(fx);
 
-            llvm_add_sub(fx, BinOp::Sub, ret, b_in, a, b);
-        }
         _ => {
             fx.tcx
                 .sess
@@ -150,47 +52,3 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
     let ret_block = fx.get_block(dest);
     fx.bcx.ins().jump(ret_block, &[]);
 }
-
-// llvm.x86.avx2.vperm2i128
-// llvm.x86.ssse3.pshuf.b.128
-// llvm.x86.avx2.pshuf.b
-// llvm.x86.avx2.psrli.w
-// llvm.x86.sse2.psrli.w
-
-fn llvm_add_sub<'tcx>(
-    fx: &mut FunctionCx<'_, '_, 'tcx>,
-    bin_op: BinOp,
-    ret: CPlace<'tcx>,
-    cb_in: Value,
-    a: CValue<'tcx>,
-    b: CValue<'tcx>,
-) {
-    assert_eq!(
-        a.layout().ty,
-        fx.tcx.types.u64,
-        "llvm.x86.addcarry.64/llvm.x86.subborrow.64 second operand must be u64"
-    );
-    assert_eq!(
-        b.layout().ty,
-        fx.tcx.types.u64,
-        "llvm.x86.addcarry.64/llvm.x86.subborrow.64 third operand must be u64"
-    );
-
-    // c + carry -> c + first intermediate carry or borrow respectively
-    let int0 = crate::num::codegen_checked_int_binop(fx, bin_op, a, b);
-    let c = int0.value_field(fx, mir::Field::new(0));
-    let cb0 = int0.value_field(fx, mir::Field::new(1)).load_scalar(fx);
-
-    // c + carry -> c + second intermediate carry or borrow respectively
-    let cb_in_as_u64 = fx.bcx.ins().uextend(types::I64, cb_in);
-    let cb_in_as_u64 = CValue::by_val(cb_in_as_u64, fx.layout_of(fx.tcx.types.u64));
-    let int1 = crate::num::codegen_checked_int_binop(fx, bin_op, c, cb_in_as_u64);
-    let (c, cb1) = int1.load_scalar_pair(fx);
-
-    // carry0 | carry1 -> carry or borrow respectively
-    let cb_out = fx.bcx.ins().bor(cb0, cb1);
-
-    let layout = fx.layout_of(fx.tcx.mk_tup([fx.tcx.types.u8, fx.tcx.types.u64].iter()));
-    let val = CValue::by_val_pair(cb_out, c, layout);
-    ret.write_cvalue(fx, val);
-}
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs
new file mode 100644 (file)
index 0000000..b431158
--- /dev/null
@@ -0,0 +1,222 @@
+//! Emulate AArch64 LLVM intrinsics
+
+use crate::intrinsics::*;
+use crate::prelude::*;
+
+use rustc_middle::ty::subst::SubstsRef;
+
+pub(crate) fn codegen_aarch64_llvm_intrinsic_call<'tcx>(
+    fx: &mut FunctionCx<'_, '_, 'tcx>,
+    intrinsic: &str,
+    _substs: SubstsRef<'tcx>,
+    args: &[mir::Operand<'tcx>],
+    ret: CPlace<'tcx>,
+    target: Option<BasicBlock>,
+) {
+    // llvm.aarch64.neon.sqshl.v*i*
+
+    match intrinsic {
+        "llvm.aarch64.isb" => {
+            fx.bcx.ins().fence();
+        }
+
+        _ if intrinsic.starts_with("llvm.aarch64.neon.abs.v") => {
+            intrinsic_args!(fx, args => (a); intrinsic);
+
+            simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| {
+                fx.bcx.ins().iabs(lane)
+            });
+        }
+
+        _ if intrinsic.starts_with("llvm.aarch64.neon.cls.v") => {
+            intrinsic_args!(fx, args => (a); intrinsic);
+
+            simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| {
+                fx.bcx.ins().cls(lane)
+            });
+        }
+
+        _ if intrinsic.starts_with("llvm.aarch64.neon.rbit.v") => {
+            intrinsic_args!(fx, args => (a); intrinsic);
+
+            simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| {
+                fx.bcx.ins().bitrev(lane)
+            });
+        }
+
+        _ if intrinsic.starts_with("llvm.aarch64.neon.sqadd.v") => {
+            intrinsic_args!(fx, args => (x, y); intrinsic);
+
+            simd_pair_for_each_lane_typed(fx, x, y, ret, &|fx, x_lane, y_lane| {
+                crate::num::codegen_saturating_int_binop(fx, BinOp::Add, x_lane, y_lane)
+            });
+        }
+
+        _ if intrinsic.starts_with("llvm.aarch64.neon.sqsub.v") => {
+            intrinsic_args!(fx, args => (x, y); intrinsic);
+
+            simd_pair_for_each_lane_typed(fx, x, y, ret, &|fx, x_lane, y_lane| {
+                crate::num::codegen_saturating_int_binop(fx, BinOp::Sub, x_lane, y_lane)
+            });
+        }
+
+        _ if intrinsic.starts_with("llvm.aarch64.neon.smax.v") => {
+            intrinsic_args!(fx, args => (x, y); intrinsic);
+
+            simd_pair_for_each_lane(
+                fx,
+                x,
+                y,
+                ret,
+                &|fx, _lane_ty, _res_lane_ty, x_lane, y_lane| {
+                    let gt = fx.bcx.ins().icmp(IntCC::SignedGreaterThan, x_lane, y_lane);
+                    fx.bcx.ins().select(gt, x_lane, y_lane)
+                },
+            );
+        }
+
+        _ if intrinsic.starts_with("llvm.aarch64.neon.umax.v") => {
+            intrinsic_args!(fx, args => (x, y); intrinsic);
+
+            simd_pair_for_each_lane(
+                fx,
+                x,
+                y,
+                ret,
+                &|fx, _lane_ty, _res_lane_ty, x_lane, y_lane| {
+                    let gt = fx.bcx.ins().icmp(IntCC::UnsignedGreaterThan, x_lane, y_lane);
+                    fx.bcx.ins().select(gt, x_lane, y_lane)
+                },
+            );
+        }
+
+        _ if intrinsic.starts_with("llvm.aarch64.neon.smaxv.i") => {
+            intrinsic_args!(fx, args => (v); intrinsic);
+
+            simd_reduce(fx, v, None, ret, &|fx, _ty, a, b| {
+                let gt = fx.bcx.ins().icmp(IntCC::SignedGreaterThan, a, b);
+                fx.bcx.ins().select(gt, a, b)
+            });
+        }
+
+        _ if intrinsic.starts_with("llvm.aarch64.neon.umaxv.i") => {
+            intrinsic_args!(fx, args => (v); intrinsic);
+
+            simd_reduce(fx, v, None, ret, &|fx, _ty, a, b| {
+                let gt = fx.bcx.ins().icmp(IntCC::UnsignedGreaterThan, a, b);
+                fx.bcx.ins().select(gt, a, b)
+            });
+        }
+
+        _ if intrinsic.starts_with("llvm.aarch64.neon.smin.v") => {
+            intrinsic_args!(fx, args => (x, y); intrinsic);
+
+            simd_pair_for_each_lane(
+                fx,
+                x,
+                y,
+                ret,
+                &|fx, _lane_ty, _res_lane_ty, x_lane, y_lane| {
+                    let gt = fx.bcx.ins().icmp(IntCC::SignedLessThan, x_lane, y_lane);
+                    fx.bcx.ins().select(gt, x_lane, y_lane)
+                },
+            );
+        }
+
+        _ if intrinsic.starts_with("llvm.aarch64.neon.umin.v") => {
+            intrinsic_args!(fx, args => (x, y); intrinsic);
+
+            simd_pair_for_each_lane(
+                fx,
+                x,
+                y,
+                ret,
+                &|fx, _lane_ty, _res_lane_ty, x_lane, y_lane| {
+                    let gt = fx.bcx.ins().icmp(IntCC::UnsignedLessThan, x_lane, y_lane);
+                    fx.bcx.ins().select(gt, x_lane, y_lane)
+                },
+            );
+        }
+
+        _ if intrinsic.starts_with("llvm.aarch64.neon.sminv.i") => {
+            intrinsic_args!(fx, args => (v); intrinsic);
+
+            simd_reduce(fx, v, None, ret, &|fx, _ty, a, b| {
+                let gt = fx.bcx.ins().icmp(IntCC::SignedLessThan, a, b);
+                fx.bcx.ins().select(gt, a, b)
+            });
+        }
+
+        _ if intrinsic.starts_with("llvm.aarch64.neon.uminv.i") => {
+            intrinsic_args!(fx, args => (v); intrinsic);
+
+            simd_reduce(fx, v, None, ret, &|fx, _ty, a, b| {
+                let gt = fx.bcx.ins().icmp(IntCC::UnsignedLessThan, a, b);
+                fx.bcx.ins().select(gt, a, b)
+            });
+        }
+
+        /*
+        _ if intrinsic.starts_with("llvm.aarch64.neon.sshl.v")
+            || intrinsic.starts_with("llvm.aarch64.neon.sqshl.v")
+            // FIXME split this one out once saturating is implemented
+            || intrinsic.starts_with("llvm.aarch64.neon.sqshlu.v") =>
+        {
+            intrinsic_args!(fx, args => (a, b); intrinsic);
+
+            simd_pair_for_each_lane(fx, a, b, ret, &|fx, _lane_ty, _res_lane_ty, a, b| {
+                // FIXME saturate?
+                fx.bcx.ins().ishl(a, b)
+            });
+        }
+
+        _ if intrinsic.starts_with("llvm.aarch64.neon.sqshrn.v") => {
+            let (a, imm32) = match args {
+                [a, imm32] => (a, imm32),
+                _ => bug!("wrong number of args for intrinsic {intrinsic}"),
+            };
+            let a = codegen_operand(fx, a);
+            let imm32 = crate::constant::mir_operand_get_const_val(fx, imm32)
+                .expect("llvm.aarch64.neon.sqshrn.v* imm32 not const");
+
+            simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| match imm32
+                .try_to_bits(Size::from_bytes(4))
+                .unwrap_or_else(|| panic!("imm32 not scalar: {:?}", imm32))
+            {
+                imm32 if imm32 < 32 => fx.bcx.ins().sshr_imm(lane, i64::from(imm32 as u8)),
+                _ => fx.bcx.ins().iconst(types::I32, 0),
+            });
+        }
+
+        _ if intrinsic.starts_with("llvm.aarch64.neon.sqshrun.v") => {
+            let (a, imm32) = match args {
+                [a, imm32] => (a, imm32),
+                _ => bug!("wrong number of args for intrinsic {intrinsic}"),
+            };
+            let a = codegen_operand(fx, a);
+            let imm32 = crate::constant::mir_operand_get_const_val(fx, imm32)
+                .expect("llvm.aarch64.neon.sqshrn.v* imm32 not const");
+
+            simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| match imm32
+                .try_to_bits(Size::from_bytes(4))
+                .unwrap_or_else(|| panic!("imm32 not scalar: {:?}", imm32))
+            {
+                imm32 if imm32 < 32 => fx.bcx.ins().ushr_imm(lane, i64::from(imm32 as u8)),
+                _ => fx.bcx.ins().iconst(types::I32, 0),
+            });
+        }
+        */
+        _ => {
+            fx.tcx.sess.warn(&format!(
+                "unsupported AArch64 llvm intrinsic {}; replacing with trap",
+                intrinsic
+            ));
+            crate::trap::trap_unimplemented(fx, intrinsic);
+            return;
+        }
+    }
+
+    let dest = target.expect("all llvm intrinsics used by stdlib should return");
+    let ret_block = fx.get_block(dest);
+    fx.bcx.ins().jump(ret_block, &[]);
+}
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs
new file mode 100644 (file)
index 0000000..7bc161f
--- /dev/null
@@ -0,0 +1,197 @@
+//! Emulate x86 LLVM intrinsics
+
+use crate::intrinsics::*;
+use crate::prelude::*;
+
+use rustc_middle::ty::subst::SubstsRef;
+
+pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
+    fx: &mut FunctionCx<'_, '_, 'tcx>,
+    intrinsic: &str,
+    _substs: SubstsRef<'tcx>,
+    args: &[mir::Operand<'tcx>],
+    ret: CPlace<'tcx>,
+    target: Option<BasicBlock>,
+) {
+    match intrinsic {
+        "llvm.x86.sse2.pause" | "llvm.aarch64.isb" => {
+            // Spin loop hint
+        }
+
+        // Used by `_mm_movemask_epi8` and `_mm256_movemask_epi8`
+        "llvm.x86.sse2.pmovmskb.128" | "llvm.x86.avx2.pmovmskb" | "llvm.x86.sse2.movmsk.pd" => {
+            intrinsic_args!(fx, args => (a); intrinsic);
+
+            let (lane_count, lane_ty) = a.layout().ty.simd_size_and_type(fx.tcx);
+            let lane_ty = fx.clif_type(lane_ty).unwrap();
+            assert!(lane_count <= 32);
+
+            let mut res = fx.bcx.ins().iconst(types::I32, 0);
+
+            for lane in (0..lane_count).rev() {
+                let a_lane = a.value_lane(fx, lane).load_scalar(fx);
+
+                // cast float to int
+                let a_lane = match lane_ty {
+                    types::F32 => fx.bcx.ins().bitcast(types::I32, a_lane),
+                    types::F64 => fx.bcx.ins().bitcast(types::I64, a_lane),
+                    _ => a_lane,
+                };
+
+                // extract sign bit of an int
+                let a_lane_sign = fx.bcx.ins().ushr_imm(a_lane, i64::from(lane_ty.bits() - 1));
+
+                // shift sign bit into result
+                let a_lane_sign = clif_intcast(fx, a_lane_sign, types::I32, false);
+                res = fx.bcx.ins().ishl_imm(res, 1);
+                res = fx.bcx.ins().bor(res, a_lane_sign);
+            }
+
+            let res = CValue::by_val(res, fx.layout_of(fx.tcx.types.i32));
+            ret.write_cvalue(fx, res);
+        }
+        "llvm.x86.sse2.cmp.ps" | "llvm.x86.sse2.cmp.pd" => {
+            let (x, y, kind) = match args {
+                [x, y, kind] => (x, y, kind),
+                _ => bug!("wrong number of args for intrinsic {intrinsic}"),
+            };
+            let x = codegen_operand(fx, x);
+            let y = codegen_operand(fx, y);
+            let kind = crate::constant::mir_operand_get_const_val(fx, kind)
+                .expect("llvm.x86.sse2.cmp.* kind not const");
+
+            let flt_cc = match kind
+                .try_to_bits(Size::from_bytes(1))
+                .unwrap_or_else(|| panic!("kind not scalar: {:?}", kind))
+            {
+                0 => FloatCC::Equal,
+                1 => FloatCC::LessThan,
+                2 => FloatCC::LessThanOrEqual,
+                7 => FloatCC::Ordered,
+                3 => FloatCC::Unordered,
+                4 => FloatCC::NotEqual,
+                5 => FloatCC::UnorderedOrGreaterThanOrEqual,
+                6 => FloatCC::UnorderedOrGreaterThan,
+                kind => unreachable!("kind {:?}", kind),
+            };
+
+            simd_pair_for_each_lane(fx, x, y, ret, &|fx, lane_ty, res_lane_ty, x_lane, y_lane| {
+                let res_lane = match lane_ty.kind() {
+                    ty::Float(_) => fx.bcx.ins().fcmp(flt_cc, x_lane, y_lane),
+                    _ => unreachable!("{:?}", lane_ty),
+                };
+                bool_to_zero_or_max_uint(fx, res_lane_ty, res_lane)
+            });
+        }
+        "llvm.x86.sse2.psrli.d" => {
+            let (a, imm8) = match args {
+                [a, imm8] => (a, imm8),
+                _ => bug!("wrong number of args for intrinsic {intrinsic}"),
+            };
+            let a = codegen_operand(fx, a);
+            let imm8 = crate::constant::mir_operand_get_const_val(fx, imm8)
+                .expect("llvm.x86.sse2.psrli.d imm8 not const");
+
+            simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| match imm8
+                .try_to_bits(Size::from_bytes(4))
+                .unwrap_or_else(|| panic!("imm8 not scalar: {:?}", imm8))
+            {
+                imm8 if imm8 < 32 => fx.bcx.ins().ushr_imm(lane, i64::from(imm8 as u8)),
+                _ => fx.bcx.ins().iconst(types::I32, 0),
+            });
+        }
+        "llvm.x86.sse2.pslli.d" => {
+            let (a, imm8) = match args {
+                [a, imm8] => (a, imm8),
+                _ => bug!("wrong number of args for intrinsic {intrinsic}"),
+            };
+            let a = codegen_operand(fx, a);
+            let imm8 = crate::constant::mir_operand_get_const_val(fx, imm8)
+                .expect("llvm.x86.sse2.psrli.d imm8 not const");
+
+            simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| match imm8
+                .try_to_bits(Size::from_bytes(4))
+                .unwrap_or_else(|| panic!("imm8 not scalar: {:?}", imm8))
+            {
+                imm8 if imm8 < 32 => fx.bcx.ins().ishl_imm(lane, i64::from(imm8 as u8)),
+                _ => fx.bcx.ins().iconst(types::I32, 0),
+            });
+        }
+        "llvm.x86.sse2.storeu.dq" => {
+            intrinsic_args!(fx, args => (mem_addr, a); intrinsic);
+            let mem_addr = mem_addr.load_scalar(fx);
+
+            // FIXME correctly handle the unalignment
+            let dest = CPlace::for_ptr(Pointer::new(mem_addr), a.layout());
+            dest.write_cvalue(fx, a);
+        }
+        "llvm.x86.addcarry.64" => {
+            intrinsic_args!(fx, args => (c_in, a, b); intrinsic);
+            let c_in = c_in.load_scalar(fx);
+
+            llvm_add_sub(fx, BinOp::Add, ret, c_in, a, b);
+        }
+        "llvm.x86.subborrow.64" => {
+            intrinsic_args!(fx, args => (b_in, a, b); intrinsic);
+            let b_in = b_in.load_scalar(fx);
+
+            llvm_add_sub(fx, BinOp::Sub, ret, b_in, a, b);
+        }
+        _ => {
+            fx.tcx.sess.warn(&format!(
+                "unsupported x86 llvm intrinsic {}; replacing with trap",
+                intrinsic
+            ));
+            crate::trap::trap_unimplemented(fx, intrinsic);
+            return;
+        }
+    }
+
+    let dest = target.expect("all llvm intrinsics used by stdlib should return");
+    let ret_block = fx.get_block(dest);
+    fx.bcx.ins().jump(ret_block, &[]);
+}
+
+// llvm.x86.avx2.vperm2i128
+// llvm.x86.ssse3.pshuf.b.128
+// llvm.x86.avx2.pshuf.b
+// llvm.x86.avx2.psrli.w
+// llvm.x86.sse2.psrli.w
+
+fn llvm_add_sub<'tcx>(
+    fx: &mut FunctionCx<'_, '_, 'tcx>,
+    bin_op: BinOp,
+    ret: CPlace<'tcx>,
+    cb_in: Value,
+    a: CValue<'tcx>,
+    b: CValue<'tcx>,
+) {
+    assert_eq!(
+        a.layout().ty,
+        fx.tcx.types.u64,
+        "llvm.x86.addcarry.64/llvm.x86.subborrow.64 second operand must be u64"
+    );
+    assert_eq!(
+        b.layout().ty,
+        fx.tcx.types.u64,
+        "llvm.x86.addcarry.64/llvm.x86.subborrow.64 third operand must be u64"
+    );
+
+    // c + carry -> c + first intermediate carry or borrow respectively
+    let int0 = crate::num::codegen_checked_int_binop(fx, bin_op, a, b);
+    let c = int0.value_field(fx, mir::Field::new(0));
+    let cb0 = int0.value_field(fx, mir::Field::new(1)).load_scalar(fx);
+
+    // c + carry -> c + second intermediate carry or borrow respectively
+    let cb_in_as_u64 = fx.bcx.ins().uextend(types::I64, cb_in);
+    let cb_in_as_u64 = CValue::by_val(cb_in_as_u64, fx.layout_of(fx.tcx.types.u64));
+    let int1 = crate::num::codegen_checked_int_binop(fx, bin_op, c, cb_in_as_u64);
+    let (c, cb1) = int1.load_scalar_pair(fx);
+
+    // carry0 | carry1 -> carry or borrow respectively
+    let cb_out = fx.bcx.ins().bor(cb0, cb1);
+
+    let layout = fx.layout_of(fx.tcx.mk_tup([fx.tcx.types.u8, fx.tcx.types.u64].iter()));
+    let val = CValue::by_val_pair(cb_out, c, layout);
+    ret.write_cvalue(fx, val);
+}
index 0302b843aa226345328a278674026baa33fda632..7a380acf798572a7606130959a7517cfecb2462b 100644 (file)
@@ -14,6 +14,8 @@ macro_rules! intrinsic_args {
 
 mod cpuid;
 mod llvm;
+mod llvm_aarch64;
+mod llvm_x86;
 mod simd;
 
 pub(crate) use cpuid::codegen_cpuid_call;
@@ -195,8 +197,7 @@ fn bool_to_zero_or_max_uint<'tcx>(
         ty => ty,
     };
 
-    let val = fx.bcx.ins().bint(int_ty, val);
-    let mut res = fx.bcx.ins().ineg(val);
+    let mut res = fx.bcx.ins().bmask(int_ty, val);
 
     if ty.is_float() {
         res = fx.bcx.ins().bitcast(ty, res);
@@ -632,85 +633,15 @@ fn codegen_regular_intrinsic_call<'tcx>(
             ret.write_cvalue(fx, res);
         }
         sym::bswap => {
-            // FIXME(CraneStation/cranelift#794) add bswap instruction to cranelift
-            fn swap(bcx: &mut FunctionBuilder<'_>, v: Value) -> Value {
-                match bcx.func.dfg.value_type(v) {
-                    types::I8 => v,
-
-                    // https://code.woboq.org/gcc/include/bits/byteswap.h.html
-                    types::I16 => {
-                        let tmp1 = bcx.ins().ishl_imm(v, 8);
-                        let n1 = bcx.ins().band_imm(tmp1, 0xFF00);
-
-                        let tmp2 = bcx.ins().ushr_imm(v, 8);
-                        let n2 = bcx.ins().band_imm(tmp2, 0x00FF);
-
-                        bcx.ins().bor(n1, n2)
-                    }
-                    types::I32 => {
-                        let tmp1 = bcx.ins().ishl_imm(v, 24);
-                        let n1 = bcx.ins().band_imm(tmp1, 0xFF00_0000);
-
-                        let tmp2 = bcx.ins().ishl_imm(v, 8);
-                        let n2 = bcx.ins().band_imm(tmp2, 0x00FF_0000);
-
-                        let tmp3 = bcx.ins().ushr_imm(v, 8);
-                        let n3 = bcx.ins().band_imm(tmp3, 0x0000_FF00);
-
-                        let tmp4 = bcx.ins().ushr_imm(v, 24);
-                        let n4 = bcx.ins().band_imm(tmp4, 0x0000_00FF);
-
-                        let or_tmp1 = bcx.ins().bor(n1, n2);
-                        let or_tmp2 = bcx.ins().bor(n3, n4);
-                        bcx.ins().bor(or_tmp1, or_tmp2)
-                    }
-                    types::I64 => {
-                        let tmp1 = bcx.ins().ishl_imm(v, 56);
-                        let n1 = bcx.ins().band_imm(tmp1, 0xFF00_0000_0000_0000u64 as i64);
-
-                        let tmp2 = bcx.ins().ishl_imm(v, 40);
-                        let n2 = bcx.ins().band_imm(tmp2, 0x00FF_0000_0000_0000u64 as i64);
-
-                        let tmp3 = bcx.ins().ishl_imm(v, 24);
-                        let n3 = bcx.ins().band_imm(tmp3, 0x0000_FF00_0000_0000u64 as i64);
-
-                        let tmp4 = bcx.ins().ishl_imm(v, 8);
-                        let n4 = bcx.ins().band_imm(tmp4, 0x0000_00FF_0000_0000u64 as i64);
-
-                        let tmp5 = bcx.ins().ushr_imm(v, 8);
-                        let n5 = bcx.ins().band_imm(tmp5, 0x0000_0000_FF00_0000u64 as i64);
-
-                        let tmp6 = bcx.ins().ushr_imm(v, 24);
-                        let n6 = bcx.ins().band_imm(tmp6, 0x0000_0000_00FF_0000u64 as i64);
-
-                        let tmp7 = bcx.ins().ushr_imm(v, 40);
-                        let n7 = bcx.ins().band_imm(tmp7, 0x0000_0000_0000_FF00u64 as i64);
-
-                        let tmp8 = bcx.ins().ushr_imm(v, 56);
-                        let n8 = bcx.ins().band_imm(tmp8, 0x0000_0000_0000_00FFu64 as i64);
-
-                        let or_tmp1 = bcx.ins().bor(n1, n2);
-                        let or_tmp2 = bcx.ins().bor(n3, n4);
-                        let or_tmp3 = bcx.ins().bor(n5, n6);
-                        let or_tmp4 = bcx.ins().bor(n7, n8);
-
-                        let or_tmp5 = bcx.ins().bor(or_tmp1, or_tmp2);
-                        let or_tmp6 = bcx.ins().bor(or_tmp3, or_tmp4);
-                        bcx.ins().bor(or_tmp5, or_tmp6)
-                    }
-                    types::I128 => {
-                        let (lo, hi) = bcx.ins().isplit(v);
-                        let lo = swap(bcx, lo);
-                        let hi = swap(bcx, hi);
-                        bcx.ins().iconcat(hi, lo)
-                    }
-                    ty => unreachable!("bswap {}", ty),
-                }
-            }
             intrinsic_args!(fx, args => (arg); intrinsic);
             let val = arg.load_scalar(fx);
 
-            let res = CValue::by_val(swap(&mut fx.bcx, val), arg.layout());
+            let res = if fx.bcx.func.dfg.value_type(val) == types::I8 {
+                val
+            } else {
+                fx.bcx.ins().bswap(val)
+            };
+            let res = CValue::by_val(res, arg.layout());
             ret.write_cvalue(fx, res);
         }
         sym::assert_inhabited | sym::assert_zero_valid | sym::assert_uninit_valid => {
@@ -936,8 +867,7 @@ fn swap(bcx: &mut FunctionBuilder<'_>, v: Value) -> Value {
             let old = fx.bcx.ins().atomic_cas(MemFlags::trusted(), ptr, test_old, new);
             let is_eq = fx.bcx.ins().icmp(IntCC::Equal, old, test_old);
 
-            let ret_val =
-                CValue::by_val_pair(old, fx.bcx.ins().bint(types::I8, is_eq), ret.layout());
+            let ret_val = CValue::by_val_pair(old, is_eq, ret.layout());
             ret.write_cvalue(fx, ret_val)
         }
 
@@ -1259,8 +1189,7 @@ fn swap(bcx: &mut FunctionBuilder<'_>, v: Value) -> Value {
                 flags.set_notrap();
                 let lhs_val = fx.bcx.ins().load(clty, flags, lhs_ref, 0);
                 let rhs_val = fx.bcx.ins().load(clty, flags, rhs_ref, 0);
-                let eq = fx.bcx.ins().icmp(IntCC::Equal, lhs_val, rhs_val);
-                fx.bcx.ins().bint(types::I8, eq)
+                fx.bcx.ins().icmp(IntCC::Equal, lhs_val, rhs_val)
             } else {
                 // Just call `memcmp` (like slices do in core) when the
                 // size is too large or it's not a power-of-two.
@@ -1270,8 +1199,7 @@ fn swap(bcx: &mut FunctionBuilder<'_>, v: Value) -> Value {
                 let returns = vec![AbiParam::new(types::I32)];
                 let args = &[lhs_ref, rhs_ref, bytes_val];
                 let cmp = fx.lib_call("memcmp", params, returns, args)[0];
-                let eq = fx.bcx.ins().icmp_imm(IntCC::Equal, cmp, 0);
-                fx.bcx.ins().bint(types::I8, eq)
+                fx.bcx.ins().icmp_imm(IntCC::Equal, cmp, 0)
             };
             ret.write_cvalue(fx, CValue::by_val(is_eq_value, ret.layout()));
         }
index 51fce8c854bdb5307149680f288fa590ed8a8b53..14f5e9187399fac76f2a64d0147f2f647a904929 100644 (file)
@@ -112,10 +112,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
                     _ => unreachable!(),
                 };
 
-                let ty = fx.clif_type(res_lane_ty).unwrap();
-
-                let res_lane = fx.bcx.ins().bint(ty, res_lane);
-                fx.bcx.ins().ineg(res_lane)
+                bool_to_zero_or_max_uint(fx, res_lane_ty, res_lane)
             });
         }
 
@@ -716,7 +713,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
 
             let res_type =
                 Type::int_with_byte_size(u16::try_from(expected_bytes).unwrap()).unwrap();
-            let mut res = fx.bcx.ins().iconst(res_type, 0);
+            let mut res = type_zero_value(&mut fx.bcx, res_type);
 
             let lanes = match fx.tcx.sess.target.endian {
                 Endian::Big => Box::new(0..lane_count) as Box<dyn Iterator<Item = u64>>,
index f7434633ea442b40fa30f4a85370135e8c134017..c10054e7f0d2c971711364aafdfe563558e3fd5d 100644 (file)
@@ -65,7 +65,7 @@ fn create_entry_fn(
             returns: vec![AbiParam::new(m.target_config().pointer_type() /*isize*/)],
             call_conv: crate::conv_to_call_conv(
                 tcx.sess.target.options.entry_abi,
-                CallConv::triple_default(m.isa().triple()),
+                m.target_config().default_call_conv,
             ),
         };
 
@@ -75,7 +75,7 @@ fn create_entry_fn(
         let instance = Instance::mono(tcx, rust_main_def_id).polymorphize(tcx);
 
         let main_name = tcx.symbol_name(instance).name;
-        let main_sig = get_function_sig(tcx, m.isa().triple(), instance);
+        let main_sig = get_function_sig(tcx, m.target_config().default_call_conv, instance);
         let main_func_id = m.declare_function(main_name, Linkage::Import, &main_sig).unwrap();
 
         let mut ctx = Context::new();
@@ -119,7 +119,7 @@ fn create_entry_fn(
                 .polymorphize(tcx);
 
                 let report_name = tcx.symbol_name(report).name;
-                let report_sig = get_function_sig(tcx, m.isa().triple(), report);
+                let report_sig = get_function_sig(tcx, m.target_config().default_call_conv, report);
                 let report_func_id =
                     m.declare_function(report_name, Linkage::Import, &report_sig).unwrap();
                 let report_func_ref = m.declare_func_in_func(report_func_id, &mut bcx.func);
index ecbab408ded972889b6cbca8840daee8c2e837f4..afacbec644582195440bcb8e3e9c58d6d99b3c74 100644 (file)
@@ -49,7 +49,6 @@ fn codegen_compare_bin_op<'tcx>(
 ) -> CValue<'tcx> {
     let intcc = crate::num::bin_op_to_intcc(bin_op, signed).unwrap();
     let val = fx.bcx.ins().icmp(intcc, lhs, rhs);
-    let val = fx.bcx.ins().bint(types::I8, val);
     CValue::by_val(val, fx.layout_of(fx.tcx.types.bool))
 }
 
@@ -290,8 +289,6 @@ pub(crate) fn codegen_checked_int_binop<'tcx>(
         _ => bug!("binop {:?} on checked int/uint lhs: {:?} rhs: {:?}", bin_op, in_lhs, in_rhs),
     };
 
-    let has_overflow = fx.bcx.ins().bint(types::I8, has_overflow);
-
     let out_layout = fx.layout_of(fx.tcx.mk_tup([in_lhs.layout().ty, fx.tcx.types.bool].iter()));
     CValue::by_val_pair(res, has_overflow, out_layout)
 }
@@ -368,7 +365,6 @@ pub(crate) fn codegen_float_binop<'tcx>(
                 _ => unreachable!(),
             };
             let val = fx.bcx.ins().fcmp(fltcc, lhs, rhs);
-            let val = fx.bcx.ins().bint(types::I8, val);
             return CValue::by_val(val, fx.layout_of(fx.tcx.types.bool));
         }
         _ => unreachable!("{:?}({:?}, {:?})", bin_op, in_lhs, in_rhs),
@@ -440,7 +436,7 @@ pub(crate) fn codegen_ptr_binop<'tcx>(
             _ => panic!("bin_op {:?} on ptr", bin_op),
         };
 
-        CValue::by_val(fx.bcx.ins().bint(types::I8, res), fx.layout_of(fx.tcx.types.bool))
+        CValue::by_val(res, fx.layout_of(fx.tcx.types.bool))
     }
 }
 
index d637b4d89293cea0a0a855ebb97378b111c3789b..7f45bbd8f28136a43b8271ba5f3e2755d19d522d 100644 (file)
@@ -3,19 +3,6 @@
 use cranelift_codegen::ir::{condcodes::IntCC, InstructionData, Opcode, Value, ValueDef};
 use cranelift_frontend::FunctionBuilder;
 
-/// If the given value was produced by a `bint` instruction, return it's input, otherwise return the
-/// given value.
-pub(crate) fn maybe_unwrap_bint(bcx: &mut FunctionBuilder<'_>, arg: Value) -> Value {
-    if let ValueDef::Result(arg_inst, 0) = bcx.func.dfg.value_def(arg) {
-        match bcx.func.dfg[arg_inst] {
-            InstructionData::Unary { opcode: Opcode::Bint, arg } => arg,
-            _ => arg,
-        }
-    } else {
-        arg
-    }
-}
-
 /// If the given value was produced by the lowering of `Rvalue::Not` return the input and true,
 /// otherwise return the given value and false.
 pub(crate) fn maybe_unwrap_bool_not(bcx: &mut FunctionBuilder<'_>, arg: Value) -> (Value, bool) {
@@ -48,13 +35,6 @@ pub(crate) fn maybe_known_branch_taken(
     };
 
     match bcx.func.dfg[arg_inst] {
-        InstructionData::UnaryBool { opcode: Opcode::Bconst, imm } => {
-            if test_zero {
-                Some(!imm)
-            } else {
-                Some(imm)
-            }
-        }
         InstructionData::UnaryImm { opcode: Opcode::Iconst, imm } => {
             if test_zero {
                 Some(imm.bits() == 0)
index 34746ff6b6645c11bdda409d0af1f627908e65a0..fe8af21ac6de567cff94a34ec13e625f8876fe4a 100644 (file)
@@ -392,7 +392,7 @@ pub(crate) fn new_var(
         local: Local,
         layout: TyAndLayout<'tcx>,
     ) -> CPlace<'tcx> {
-        let var = Variable::with_u32(fx.next_ssa_var);
+        let var = Variable::from_u32(fx.next_ssa_var);
         fx.next_ssa_var += 1;
         fx.bcx.declare_var(var, fx.clif_type(layout.ty).unwrap());
         CPlace { inner: CPlaceInner::Var(local, var), layout }
@@ -403,9 +403,9 @@ pub(crate) fn new_var_pair(
         local: Local,
         layout: TyAndLayout<'tcx>,
     ) -> CPlace<'tcx> {
-        let var1 = Variable::with_u32(fx.next_ssa_var);
+        let var1 = Variable::from_u32(fx.next_ssa_var);
         fx.next_ssa_var += 1;
-        let var2 = Variable::with_u32(fx.next_ssa_var);
+        let var2 = Variable::from_u32(fx.next_ssa_var);
         fx.next_ssa_var += 1;
 
         let (ty1, ty2) = fx.clif_pair_type(layout.ty).unwrap();
@@ -515,9 +515,7 @@ fn transmute_value<'tcx>(
                 | (types::F32, types::I32)
                 | (types::I64, types::F64)
                 | (types::F64, types::I64) => fx.bcx.ins().bitcast(dst_ty, data),
-                _ if src_ty.is_vector() && dst_ty.is_vector() => {
-                    fx.bcx.ins().raw_bitcast(dst_ty, data)
-                }
+                _ if src_ty.is_vector() && dst_ty.is_vector() => fx.bcx.ins().bitcast(dst_ty, data),
                 _ if src_ty.is_vector() || dst_ty.is_vector() => {
                     // FIXME do something more efficient for transmutes between vectors and integers.
                     let stack_slot = fx.bcx.create_sized_stack_slot(StackSlotData {
@@ -590,7 +588,10 @@ fn transmute_value<'tcx>(
                 return;
             }
             CPlaceInner::VarPair(_local, var1, var2) => {
-                let (data1, data2) = CValue(from.0, dst_layout).load_scalar_pair(fx);
+                let (ptr, meta) = from.force_stack(fx);
+                assert!(meta.is_none());
+                let (data1, data2) =
+                    CValue(CValueInner::ByRef(ptr, None), dst_layout).load_scalar_pair(fx);
                 let (dst_ty1, dst_ty2) = fx.clif_pair_type(self.layout().ty).unwrap();
                 transmute_value(fx, var1, data1, dst_ty1);
                 transmute_value(fx, var2, data2, dst_ty2);
index 3d929a1d50ce2435307a7834c1fe04c1c73b94bd..13e7784539d5a9b9cdb3c81dd7f548afcb0c418b 100755 (executable)
@@ -1,2 +1,2 @@
 #!/usr/bin/env bash
-exec ./y.rs test
+exec ./y.rs test "$@"
index f177b91c2c4876a4ac7b62dd653a3e4ea0857453..02e1e21ade1de98f4d72256adbe70755a3997a55 100755 (executable)
@@ -3,7 +3,7 @@
 # This block is ignored by rustc
 set -e
 echo "[BUILD] y.rs" 1>&2
-rustc $0 -o ${0/.rs/.bin} -Cdebuginfo=1
+rustc $0 -o ${0/.rs/.bin} -Cdebuginfo=1 --edition 2021
 exec ${0/.rs/.bin} $@
 */
 
index 0aee1a1439b9bcd2867bb2da9681092891c257d5..36aba5bb740bd6120030c0cbf0e5d6654fa0afc8 100644 (file)
@@ -15,8 +15,8 @@
 use crate::llvm::archive_ro::{ArchiveRO, Child};
 use crate::llvm::{self, ArchiveKind, LLVMMachineType, LLVMRustCOFFShortExport};
 use rustc_codegen_ssa::back::archive::{
-    get_native_object_symbols, try_extract_macho_fat_archive, ArArchiveBuilder,
-    ArchiveBuildFailure, ArchiveBuilder, ArchiveBuilderBuilder, UnknownArchiveKind,
+    get_native_object_symbols, ArArchiveBuilder, ArchiveBuildFailure, ArchiveBuilder,
+    ArchiveBuilderBuilder, UnknownArchiveKind,
 };
 
 use rustc_session::cstore::DllImport;
@@ -66,13 +66,7 @@ fn add_archive(
         archive: &Path,
         skip: Box<dyn FnMut(&str) -> bool + 'static>,
     ) -> io::Result<()> {
-        let mut archive = archive.to_path_buf();
-        if self.sess.target.llvm_target.contains("-apple-macosx") {
-            if let Some(new_archive) = try_extract_macho_fat_archive(&self.sess, &archive)? {
-                archive = new_archive
-            }
-        }
-        let archive_ro = match ArchiveRO::open(&archive) {
+        let archive_ro = match ArchiveRO::open(archive) {
             Ok(ar) => ar,
             Err(e) => return Err(io::Error::new(io::ErrorKind::Other, e)),
         };
@@ -80,7 +74,7 @@ fn add_archive(
             return Ok(());
         }
         self.additions.push(Addition::Archive {
-            path: archive,
+            path: archive.to_path_buf(),
             archive: archive_ro,
             skip: Box::new(skip),
         });
index 551663bfbbd30177707d0d72a6e901e7af4da328..e20dc906bce9a42bb3c639c27f33d7bfb8db56b2 100644 (file)
@@ -210,7 +210,7 @@ pub(crate) fn run_thin(
 }
 
 pub(crate) fn prepare_thin(module: ModuleCodegen<ModuleLlvm>) -> (String, ThinBuffer) {
-    let name = module.name.clone();
+    let name = module.name;
     let buffer = ThinBuffer::new(module.module_llvm.llmod(), true);
     (name, buffer)
 }
index 58558fb8c4ba2912b53f7fcef66c10c676c4a7aa..5266d8858d47d35dcc9c12e0e935bb9327b1d4f0 100644 (file)
@@ -14,7 +14,7 @@
 
 use std::error::Error;
 use std::fs::File;
-use std::io::{self, Write};
+use std::io;
 use std::path::{Path, PathBuf};
 
 // Re-exporting for rustc_codegen_llvm::back::archive
@@ -116,12 +116,11 @@ pub fn new(
     }
 }
 
-fn try_filter_fat_archs(
+fn try_filter_fat_archs<'a>(
     archs: object::read::Result<&[impl FatArch]>,
     target_arch: object::Architecture,
-    archive_path: &Path,
-    archive_map_data: &[u8],
-) -> io::Result<Option<PathBuf>> {
+    archive_map_data: &'a [u8],
+) -> io::Result<Option<(&'a [u8], u64)>> {
     let archs = archs.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
 
     let desired = match archs.iter().filter(|a| a.architecture() == target_arch).next() {
@@ -129,38 +128,30 @@ fn try_filter_fat_archs(
         None => return Ok(None),
     };
 
-    let (mut new_f, extracted_path) = tempfile::Builder::new()
-        .suffix(archive_path.file_name().unwrap())
-        .tempfile()?
-        .keep()
-        .unwrap();
-
-    new_f.write_all(
+    Ok(Some((
         desired.data(archive_map_data).map_err(|e| io::Error::new(io::ErrorKind::Other, e))?,
-    )?;
-
-    Ok(Some(extracted_path))
+        desired.offset().into(),
+    )))
 }
 
-pub fn try_extract_macho_fat_archive(
+pub fn try_extract_macho_fat_archive<'a>(
     sess: &Session,
-    archive_path: &Path,
-) -> io::Result<Option<PathBuf>> {
-    let archive_map = unsafe { Mmap::map(File::open(&archive_path)?)? };
+    archive_bytes: &'a [u8],
+) -> io::Result<Option<(&'a [u8], u64)>> {
     let target_arch = match sess.target.arch.as_ref() {
         "aarch64" => object::Architecture::Aarch64,
         "x86_64" => object::Architecture::X86_64,
         _ => return Ok(None),
     };
 
-    match object::macho::FatHeader::parse(&*archive_map) {
+    match object::macho::FatHeader::parse(archive_bytes) {
         Ok(h) if h.magic.get(object::endian::BigEndian) == object::macho::FAT_MAGIC => {
-            let archs = object::macho::FatHeader::parse_arch32(&*archive_map);
-            try_filter_fat_archs(archs, target_arch, archive_path, &*archive_map)
+            let archs = object::macho::FatHeader::parse_arch32(archive_bytes);
+            try_filter_fat_archs(archs, target_arch, archive_bytes)
         }
         Ok(h) if h.magic.get(object::endian::BigEndian) == object::macho::FAT_MAGIC_64 => {
-            let archs = object::macho::FatHeader::parse_arch64(&*archive_map);
-            try_filter_fat_archs(archs, target_arch, archive_path, &*archive_map)
+            let archs = object::macho::FatHeader::parse_arch64(archive_bytes);
+            try_filter_fat_archs(archs, target_arch, archive_bytes)
         }
         // Not a FatHeader at all, just return None.
         _ => Ok(None),
@@ -173,21 +164,24 @@ fn add_archive(
         archive_path: &Path,
         mut skip: Box<dyn FnMut(&str) -> bool + 'static>,
     ) -> io::Result<()> {
-        let mut archive_path = archive_path.to_path_buf();
-        if self.sess.target.llvm_target.contains("-apple-macosx") {
-            if let Some(new_archive_path) =
-                try_extract_macho_fat_archive(&self.sess, &archive_path)?
-            {
-                archive_path = new_archive_path
-            }
-        }
-
+        let archive_map = unsafe { Mmap::map(File::open(&archive_path)?)? };
         if self.src_archives.iter().any(|archive| archive.0 == archive_path) {
             return Ok(());
         }
 
-        let archive_map = unsafe { Mmap::map(File::open(&archive_path)?)? };
-        let archive = ArchiveFile::parse(&*archive_map)
+        let (archive_bytes, offset) = if self.sess.target.llvm_target.contains("-apple-macosx") {
+            if let Some((sub_archive, archive_offset)) =
+                try_extract_macho_fat_archive(&self.sess, &*archive_map)?
+            {
+                (sub_archive, Some(archive_offset))
+            } else {
+                (&*archive_map, None)
+            }
+        } else {
+            (&*archive_map, None)
+        };
+
+        let archive = ArchiveFile::parse(&*archive_bytes)
             .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
         let archive_index = self.src_archives.len();
 
@@ -196,9 +190,13 @@ fn add_archive(
             let file_name = String::from_utf8(entry.name().to_vec())
                 .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
             if !skip(&file_name) {
+                let mut range = entry.file_range();
+                if let Some(offset) = offset {
+                    range.0 += offset;
+                }
                 self.entries.push((
                     file_name.into_bytes(),
-                    ArchiveEntry::FromArchive { archive_index, file_range: entry.file_range() },
+                    ArchiveEntry::FromArchive { archive_index, file_range: range },
                 ));
             }
         }
diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
new file mode 100644 (file)
index 0000000..c7f2e19
--- /dev/null
@@ -0,0 +1,688 @@
+use rustc_ast::{ast, MetaItemKind, NestedMetaItem};
+use rustc_attr::{list_contains_name, InlineAttr, InstructionSetAttr, OptimizeAttr};
+use rustc_errors::struct_span_err;
+use rustc_hir as hir;
+use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
+use rustc_hir::{lang_items, weak_lang_items::WEAK_LANG_ITEMS, LangItem};
+use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
+use rustc_middle::mir::mono::Linkage;
+use rustc_middle::ty::query::Providers;
+use rustc_middle::ty::{self as ty, DefIdTree, TyCtxt};
+use rustc_session::{lint, parse::feature_err};
+use rustc_span::{sym, Span};
+use rustc_target::spec::{abi, SanitizerSet};
+
+use crate::target_features::from_target_feature;
+use crate::{errors::ExpectedUsedSymbol, target_features::check_target_feature_trait_unsafe};
+
+fn linkage_by_name(tcx: TyCtxt<'_>, def_id: LocalDefId, name: &str) -> Linkage {
+    use rustc_middle::mir::mono::Linkage::*;
+
+    // Use the names from src/llvm/docs/LangRef.rst here. Most types are only
+    // applicable to variable declarations and may not really make sense for
+    // Rust code in the first place but allow them anyway and trust that the
+    // user knows what they're doing. Who knows, unanticipated use cases may pop
+    // up in the future.
+    //
+    // ghost, dllimport, dllexport and linkonce_odr_autohide are not supported
+    // and don't have to be, LLVM treats them as no-ops.
+    match name {
+        "appending" => Appending,
+        "available_externally" => AvailableExternally,
+        "common" => Common,
+        "extern_weak" => ExternalWeak,
+        "external" => External,
+        "internal" => Internal,
+        "linkonce" => LinkOnceAny,
+        "linkonce_odr" => LinkOnceODR,
+        "private" => Private,
+        "weak" => WeakAny,
+        "weak_odr" => WeakODR,
+        _ => tcx.sess.span_fatal(tcx.def_span(def_id), "invalid linkage specified"),
+    }
+}
+
+fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
+    if cfg!(debug_assertions) {
+        let def_kind = tcx.def_kind(did);
+        assert!(
+            def_kind.has_codegen_attrs(),
+            "unexpected `def_kind` in `codegen_fn_attrs`: {def_kind:?}",
+        );
+    }
+
+    let did = did.expect_local();
+    let attrs = tcx.hir().attrs(tcx.hir().local_def_id_to_hir_id(did));
+    let mut codegen_fn_attrs = CodegenFnAttrs::new();
+    if tcx.should_inherit_track_caller(did) {
+        codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER;
+    }
+
+    let supported_target_features = tcx.supported_target_features(LOCAL_CRATE);
+
+    let mut inline_span = None;
+    let mut link_ordinal_span = None;
+    let mut no_sanitize_span = None;
+    for attr in attrs.iter() {
+        if attr.has_name(sym::cold) {
+            codegen_fn_attrs.flags |= CodegenFnAttrFlags::COLD;
+        } else if attr.has_name(sym::rustc_allocator) {
+            codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR;
+        } else if attr.has_name(sym::ffi_returns_twice) {
+            if tcx.is_foreign_item(did) {
+                codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_RETURNS_TWICE;
+            } else {
+                // `#[ffi_returns_twice]` is only allowed `extern fn`s.
+                struct_span_err!(
+                    tcx.sess,
+                    attr.span,
+                    E0724,
+                    "`#[ffi_returns_twice]` may only be used on foreign functions"
+                )
+                .emit();
+            }
+        } else if attr.has_name(sym::ffi_pure) {
+            if tcx.is_foreign_item(did) {
+                if attrs.iter().any(|a| a.has_name(sym::ffi_const)) {
+                    // `#[ffi_const]` functions cannot be `#[ffi_pure]`
+                    struct_span_err!(
+                        tcx.sess,
+                        attr.span,
+                        E0757,
+                        "`#[ffi_const]` function cannot be `#[ffi_pure]`"
+                    )
+                    .emit();
+                } else {
+                    codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_PURE;
+                }
+            } else {
+                // `#[ffi_pure]` is only allowed on foreign functions
+                struct_span_err!(
+                    tcx.sess,
+                    attr.span,
+                    E0755,
+                    "`#[ffi_pure]` may only be used on foreign functions"
+                )
+                .emit();
+            }
+        } else if attr.has_name(sym::ffi_const) {
+            if tcx.is_foreign_item(did) {
+                codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_CONST;
+            } else {
+                // `#[ffi_const]` is only allowed on foreign functions
+                struct_span_err!(
+                    tcx.sess,
+                    attr.span,
+                    E0756,
+                    "`#[ffi_const]` may only be used on foreign functions"
+                )
+                .emit();
+            }
+        } else if attr.has_name(sym::rustc_nounwind) {
+            codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND;
+        } else if attr.has_name(sym::rustc_reallocator) {
+            codegen_fn_attrs.flags |= CodegenFnAttrFlags::REALLOCATOR;
+        } else if attr.has_name(sym::rustc_deallocator) {
+            codegen_fn_attrs.flags |= CodegenFnAttrFlags::DEALLOCATOR;
+        } else if attr.has_name(sym::rustc_allocator_zeroed) {
+            codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR_ZEROED;
+        } else if attr.has_name(sym::naked) {
+            codegen_fn_attrs.flags |= CodegenFnAttrFlags::NAKED;
+        } else if attr.has_name(sym::no_mangle) {
+            codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE;
+        } else if attr.has_name(sym::no_coverage) {
+            codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_COVERAGE;
+        } else if attr.has_name(sym::rustc_std_internal_symbol) {
+            codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL;
+        } else if attr.has_name(sym::used) {
+            let inner = attr.meta_item_list();
+            match inner.as_deref() {
+                Some([item]) if item.has_name(sym::linker) => {
+                    if !tcx.features().used_with_arg {
+                        feature_err(
+                            &tcx.sess.parse_sess,
+                            sym::used_with_arg,
+                            attr.span,
+                            "`#[used(linker)]` is currently unstable",
+                        )
+                        .emit();
+                    }
+                    codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED_LINKER;
+                }
+                Some([item]) if item.has_name(sym::compiler) => {
+                    if !tcx.features().used_with_arg {
+                        feature_err(
+                            &tcx.sess.parse_sess,
+                            sym::used_with_arg,
+                            attr.span,
+                            "`#[used(compiler)]` is currently unstable",
+                        )
+                        .emit();
+                    }
+                    codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED;
+                }
+                Some(_) => {
+                    tcx.sess.emit_err(ExpectedUsedSymbol { span: attr.span });
+                }
+                None => {
+                    // Unfortunately, unconditionally using `llvm.used` causes
+                    // issues in handling `.init_array` with the gold linker,
+                    // but using `llvm.compiler.used` caused a nontrival amount
+                    // of unintentional ecosystem breakage -- particularly on
+                    // Mach-O targets.
+                    //
+                    // As a result, we emit `llvm.compiler.used` only on ELF
+                    // targets. This is somewhat ad-hoc, but actually follows
+                    // our pre-LLVM 13 behavior (prior to the ecosystem
+                    // breakage), and seems to match `clang`'s behavior as well
+                    // (both before and after LLVM 13), possibly because they
+                    // have similar compatibility concerns to us. See
+                    // https://github.com/rust-lang/rust/issues/47384#issuecomment-1019080146
+                    // and following comments for some discussion of this, as
+                    // well as the comments in `rustc_codegen_llvm` where these
+                    // flags are handled.
+                    //
+                    // Anyway, to be clear: this is still up in the air
+                    // somewhat, and is subject to change in the future (which
+                    // is a good thing, because this would ideally be a bit
+                    // more firmed up).
+                    let is_like_elf = !(tcx.sess.target.is_like_osx
+                        || tcx.sess.target.is_like_windows
+                        || tcx.sess.target.is_like_wasm);
+                    codegen_fn_attrs.flags |= if is_like_elf {
+                        CodegenFnAttrFlags::USED
+                    } else {
+                        CodegenFnAttrFlags::USED_LINKER
+                    };
+                }
+            }
+        } else if attr.has_name(sym::cmse_nonsecure_entry) {
+            if !matches!(tcx.fn_sig(did).abi(), abi::Abi::C { .. }) {
+                struct_span_err!(
+                    tcx.sess,
+                    attr.span,
+                    E0776,
+                    "`#[cmse_nonsecure_entry]` requires C ABI"
+                )
+                .emit();
+            }
+            if !tcx.sess.target.llvm_target.contains("thumbv8m") {
+                struct_span_err!(tcx.sess, attr.span, E0775, "`#[cmse_nonsecure_entry]` is only valid for targets with the TrustZone-M extension")
+                    .emit();
+            }
+            codegen_fn_attrs.flags |= CodegenFnAttrFlags::CMSE_NONSECURE_ENTRY;
+        } else if attr.has_name(sym::thread_local) {
+            codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL;
+        } else if attr.has_name(sym::track_caller) {
+            if !tcx.is_closure(did.to_def_id()) && tcx.fn_sig(did).abi() != abi::Abi::Rust {
+                struct_span_err!(tcx.sess, attr.span, E0737, "`#[track_caller]` requires Rust ABI")
+                    .emit();
+            }
+            if tcx.is_closure(did.to_def_id()) && !tcx.features().closure_track_caller {
+                feature_err(
+                    &tcx.sess.parse_sess,
+                    sym::closure_track_caller,
+                    attr.span,
+                    "`#[track_caller]` on closures is currently unstable",
+                )
+                .emit();
+            }
+            codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER;
+        } else if attr.has_name(sym::export_name) {
+            if let Some(s) = attr.value_str() {
+                if s.as_str().contains('\0') {
+                    // `#[export_name = ...]` will be converted to a null-terminated string,
+                    // so it may not contain any null characters.
+                    struct_span_err!(
+                        tcx.sess,
+                        attr.span,
+                        E0648,
+                        "`export_name` may not contain null characters"
+                    )
+                    .emit();
+                }
+                codegen_fn_attrs.export_name = Some(s);
+            }
+        } else if attr.has_name(sym::target_feature) {
+            if !tcx.is_closure(did.to_def_id())
+                && tcx.fn_sig(did).unsafety() == hir::Unsafety::Normal
+            {
+                if tcx.sess.target.is_like_wasm || tcx.sess.opts.actually_rustdoc {
+                    // The `#[target_feature]` attribute is allowed on
+                    // WebAssembly targets on all functions, including safe
+                    // ones. Other targets require that `#[target_feature]` is
+                    // only applied to unsafe functions (pending the
+                    // `target_feature_11` feature) because on most targets
+                    // execution of instructions that are not supported is
+                    // considered undefined behavior. For WebAssembly which is a
+                    // 100% safe target at execution time it's not possible to
+                    // execute undefined instructions, and even if a future
+                    // feature was added in some form for this it would be a
+                    // deterministic trap. There is no undefined behavior when
+                    // executing WebAssembly so `#[target_feature]` is allowed
+                    // on safe functions (but again, only for WebAssembly)
+                    //
+                    // Note that this is also allowed if `actually_rustdoc` so
+                    // if a target is documenting some wasm-specific code then
+                    // it's not spuriously denied.
+                } else if !tcx.features().target_feature_11 {
+                    let mut err = feature_err(
+                        &tcx.sess.parse_sess,
+                        sym::target_feature_11,
+                        attr.span,
+                        "`#[target_feature(..)]` can only be applied to `unsafe` functions",
+                    );
+                    err.span_label(tcx.def_span(did), "not an `unsafe` function");
+                    err.emit();
+                } else {
+                    check_target_feature_trait_unsafe(tcx, did, attr.span);
+                }
+            }
+            from_target_feature(
+                tcx,
+                attr,
+                supported_target_features,
+                &mut codegen_fn_attrs.target_features,
+            );
+        } else if attr.has_name(sym::linkage) {
+            if let Some(val) = attr.value_str() {
+                let linkage = Some(linkage_by_name(tcx, did, val.as_str()));
+                if tcx.is_foreign_item(did) {
+                    codegen_fn_attrs.import_linkage = linkage;
+                } else {
+                    codegen_fn_attrs.linkage = linkage;
+                }
+            }
+        } else if attr.has_name(sym::link_section) {
+            if let Some(val) = attr.value_str() {
+                if val.as_str().bytes().any(|b| b == 0) {
+                    let msg = format!(
+                        "illegal null byte in link_section \
+                         value: `{}`",
+                        &val
+                    );
+                    tcx.sess.span_err(attr.span, &msg);
+                } else {
+                    codegen_fn_attrs.link_section = Some(val);
+                }
+            }
+        } else if attr.has_name(sym::link_name) {
+            codegen_fn_attrs.link_name = attr.value_str();
+        } else if attr.has_name(sym::link_ordinal) {
+            link_ordinal_span = Some(attr.span);
+            if let ordinal @ Some(_) = check_link_ordinal(tcx, attr) {
+                codegen_fn_attrs.link_ordinal = ordinal;
+            }
+        } else if attr.has_name(sym::no_sanitize) {
+            no_sanitize_span = Some(attr.span);
+            if let Some(list) = attr.meta_item_list() {
+                for item in list.iter() {
+                    if item.has_name(sym::address) {
+                        codegen_fn_attrs.no_sanitize |= SanitizerSet::ADDRESS;
+                    } else if item.has_name(sym::cfi) {
+                        codegen_fn_attrs.no_sanitize |= SanitizerSet::CFI;
+                    } else if item.has_name(sym::kcfi) {
+                        codegen_fn_attrs.no_sanitize |= SanitizerSet::KCFI;
+                    } else if item.has_name(sym::memory) {
+                        codegen_fn_attrs.no_sanitize |= SanitizerSet::MEMORY;
+                    } else if item.has_name(sym::memtag) {
+                        codegen_fn_attrs.no_sanitize |= SanitizerSet::MEMTAG;
+                    } else if item.has_name(sym::shadow_call_stack) {
+                        codegen_fn_attrs.no_sanitize |= SanitizerSet::SHADOWCALLSTACK;
+                    } else if item.has_name(sym::thread) {
+                        codegen_fn_attrs.no_sanitize |= SanitizerSet::THREAD;
+                    } else if item.has_name(sym::hwaddress) {
+                        codegen_fn_attrs.no_sanitize |= SanitizerSet::HWADDRESS;
+                    } else {
+                        tcx.sess
+                            .struct_span_err(item.span(), "invalid argument for `no_sanitize`")
+                            .note("expected one of: `address`, `cfi`, `hwaddress`, `kcfi`, `memory`, `memtag`, `shadow-call-stack`, or `thread`")
+                            .emit();
+                    }
+                }
+            }
+        } else if attr.has_name(sym::instruction_set) {
+            codegen_fn_attrs.instruction_set = match attr.meta_kind() {
+                Some(MetaItemKind::List(ref items)) => match items.as_slice() {
+                    [NestedMetaItem::MetaItem(set)] => {
+                        let segments =
+                            set.path.segments.iter().map(|x| x.ident.name).collect::<Vec<_>>();
+                        match segments.as_slice() {
+                            [sym::arm, sym::a32] | [sym::arm, sym::t32] => {
+                                if !tcx.sess.target.has_thumb_interworking {
+                                    struct_span_err!(
+                                        tcx.sess.diagnostic(),
+                                        attr.span,
+                                        E0779,
+                                        "target does not support `#[instruction_set]`"
+                                    )
+                                    .emit();
+                                    None
+                                } else if segments[1] == sym::a32 {
+                                    Some(InstructionSetAttr::ArmA32)
+                                } else if segments[1] == sym::t32 {
+                                    Some(InstructionSetAttr::ArmT32)
+                                } else {
+                                    unreachable!()
+                                }
+                            }
+                            _ => {
+                                struct_span_err!(
+                                    tcx.sess.diagnostic(),
+                                    attr.span,
+                                    E0779,
+                                    "invalid instruction set specified",
+                                )
+                                .emit();
+                                None
+                            }
+                        }
+                    }
+                    [] => {
+                        struct_span_err!(
+                            tcx.sess.diagnostic(),
+                            attr.span,
+                            E0778,
+                            "`#[instruction_set]` requires an argument"
+                        )
+                        .emit();
+                        None
+                    }
+                    _ => {
+                        struct_span_err!(
+                            tcx.sess.diagnostic(),
+                            attr.span,
+                            E0779,
+                            "cannot specify more than one instruction set"
+                        )
+                        .emit();
+                        None
+                    }
+                },
+                _ => {
+                    struct_span_err!(
+                        tcx.sess.diagnostic(),
+                        attr.span,
+                        E0778,
+                        "must specify an instruction set"
+                    )
+                    .emit();
+                    None
+                }
+            };
+        } else if attr.has_name(sym::repr) {
+            codegen_fn_attrs.alignment = match attr.meta_item_list() {
+                Some(items) => match items.as_slice() {
+                    [item] => match item.name_value_literal() {
+                        Some((sym::align, literal)) => {
+                            let alignment = rustc_attr::parse_alignment(&literal.kind);
+
+                            match alignment {
+                                Ok(align) => Some(align),
+                                Err(msg) => {
+                                    struct_span_err!(
+                                        tcx.sess.diagnostic(),
+                                        attr.span,
+                                        E0589,
+                                        "invalid `repr(align)` attribute: {}",
+                                        msg
+                                    )
+                                    .emit();
+
+                                    None
+                                }
+                            }
+                        }
+                        _ => None,
+                    },
+                    [] => None,
+                    _ => None,
+                },
+                None => None,
+            };
+        }
+    }
+
+    codegen_fn_attrs.inline = attrs.iter().fold(InlineAttr::None, |ia, attr| {
+        if !attr.has_name(sym::inline) {
+            return ia;
+        }
+        match attr.meta_kind() {
+            Some(MetaItemKind::Word) => InlineAttr::Hint,
+            Some(MetaItemKind::List(ref items)) => {
+                inline_span = Some(attr.span);
+                if items.len() != 1 {
+                    struct_span_err!(
+                        tcx.sess.diagnostic(),
+                        attr.span,
+                        E0534,
+                        "expected one argument"
+                    )
+                    .emit();
+                    InlineAttr::None
+                } else if list_contains_name(&items, sym::always) {
+                    InlineAttr::Always
+                } else if list_contains_name(&items, sym::never) {
+                    InlineAttr::Never
+                } else {
+                    struct_span_err!(
+                        tcx.sess.diagnostic(),
+                        items[0].span(),
+                        E0535,
+                        "invalid argument"
+                    )
+                    .help("valid inline arguments are `always` and `never`")
+                    .emit();
+
+                    InlineAttr::None
+                }
+            }
+            Some(MetaItemKind::NameValue(_)) => ia,
+            None => ia,
+        }
+    });
+
+    codegen_fn_attrs.optimize = attrs.iter().fold(OptimizeAttr::None, |ia, attr| {
+        if !attr.has_name(sym::optimize) {
+            return ia;
+        }
+        let err = |sp, s| struct_span_err!(tcx.sess.diagnostic(), sp, E0722, "{}", s).emit();
+        match attr.meta_kind() {
+            Some(MetaItemKind::Word) => {
+                err(attr.span, "expected one argument");
+                ia
+            }
+            Some(MetaItemKind::List(ref items)) => {
+                inline_span = Some(attr.span);
+                if items.len() != 1 {
+                    err(attr.span, "expected one argument");
+                    OptimizeAttr::None
+                } else if list_contains_name(&items, sym::size) {
+                    OptimizeAttr::Size
+                } else if list_contains_name(&items, sym::speed) {
+                    OptimizeAttr::Speed
+                } else {
+                    err(items[0].span(), "invalid argument");
+                    OptimizeAttr::None
+                }
+            }
+            Some(MetaItemKind::NameValue(_)) => ia,
+            None => ia,
+        }
+    });
+
+    // #73631: closures inherit `#[target_feature]` annotations
+    if tcx.features().target_feature_11 && tcx.is_closure(did.to_def_id()) {
+        let owner_id = tcx.parent(did.to_def_id());
+        if tcx.def_kind(owner_id).has_codegen_attrs() {
+            codegen_fn_attrs
+                .target_features
+                .extend(tcx.codegen_fn_attrs(owner_id).target_features.iter().copied());
+        }
+    }
+
+    // If a function uses #[target_feature] it can't be inlined into general
+    // purpose functions as they wouldn't have the right target features
+    // enabled. For that reason we also forbid #[inline(always)] as it can't be
+    // respected.
+    if !codegen_fn_attrs.target_features.is_empty() {
+        if codegen_fn_attrs.inline == InlineAttr::Always {
+            if let Some(span) = inline_span {
+                tcx.sess.span_err(
+                    span,
+                    "cannot use `#[inline(always)]` with \
+                     `#[target_feature]`",
+                );
+            }
+        }
+    }
+
+    if !codegen_fn_attrs.no_sanitize.is_empty() {
+        if codegen_fn_attrs.inline == InlineAttr::Always {
+            if let (Some(no_sanitize_span), Some(inline_span)) = (no_sanitize_span, inline_span) {
+                let hir_id = tcx.hir().local_def_id_to_hir_id(did);
+                tcx.struct_span_lint_hir(
+                    lint::builtin::INLINE_NO_SANITIZE,
+                    hir_id,
+                    no_sanitize_span,
+                    "`no_sanitize` will have no effect after inlining",
+                    |lint| lint.span_note(inline_span, "inlining requested here"),
+                )
+            }
+        }
+    }
+
+    if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED) {
+        codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_COVERAGE;
+        codegen_fn_attrs.inline = InlineAttr::Never;
+    }
+
+    // Weak lang items have the same semantics as "std internal" symbols in the
+    // sense that they're preserved through all our LTO passes and only
+    // strippable by the linker.
+    //
+    // Additionally weak lang items have predetermined symbol names.
+    if WEAK_LANG_ITEMS.iter().any(|&l| tcx.lang_items().get(l) == Some(did.to_def_id())) {
+        codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL;
+    }
+    if let Some((name, _)) = lang_items::extract(attrs)
+        && let Some(lang_item) = LangItem::from_name(name)
+        && let Some(link_name) = lang_item.link_name()
+    {
+        codegen_fn_attrs.export_name = Some(link_name);
+        codegen_fn_attrs.link_name = Some(link_name);
+    }
+    check_link_name_xor_ordinal(tcx, &codegen_fn_attrs, link_ordinal_span);
+
+    // Internal symbols to the standard library all have no_mangle semantics in
+    // that they have defined symbol names present in the function name. This
+    // also applies to weak symbols where they all have known symbol names.
+    if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) {
+        codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE;
+    }
+
+    // Any linkage to LLVM intrinsics for now forcibly marks them all as never
+    // unwinds since LLVM sometimes can't handle codegen which `invoke`s
+    // intrinsic functions.
+    if let Some(name) = &codegen_fn_attrs.link_name {
+        if name.as_str().starts_with("llvm.") {
+            codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND;
+        }
+    }
+
+    codegen_fn_attrs
+}
+
+/// Checks if the provided DefId is a method in a trait impl for a trait which has track_caller
+/// applied to the method prototype.
+fn should_inherit_track_caller(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
+    if let Some(impl_item) = tcx.opt_associated_item(def_id)
+        && let ty::AssocItemContainer::ImplContainer = impl_item.container
+        && let Some(trait_item) = impl_item.trait_item_def_id
+    {
+        return tcx
+            .codegen_fn_attrs(trait_item)
+            .flags
+            .intersects(CodegenFnAttrFlags::TRACK_CALLER);
+    }
+
+    false
+}
+
+fn check_link_ordinal(tcx: TyCtxt<'_>, attr: &ast::Attribute) -> Option<u16> {
+    use rustc_ast::{LitIntType, LitKind, MetaItemLit};
+    if !tcx.features().raw_dylib && tcx.sess.target.arch == "x86" {
+        feature_err(
+            &tcx.sess.parse_sess,
+            sym::raw_dylib,
+            attr.span,
+            "`#[link_ordinal]` is unstable on x86",
+        )
+        .emit();
+    }
+    let meta_item_list = attr.meta_item_list();
+    let meta_item_list = meta_item_list.as_deref();
+    let sole_meta_list = match meta_item_list {
+        Some([item]) => item.lit(),
+        Some(_) => {
+            tcx.sess
+                .struct_span_err(attr.span, "incorrect number of arguments to `#[link_ordinal]`")
+                .note("the attribute requires exactly one argument")
+                .emit();
+            return None;
+        }
+        _ => None,
+    };
+    if let Some(MetaItemLit { kind: LitKind::Int(ordinal, LitIntType::Unsuffixed), .. }) =
+        sole_meta_list
+    {
+        // According to the table at https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#import-header,
+        // the ordinal must fit into 16 bits.  Similarly, the Ordinal field in COFFShortExport (defined
+        // in llvm/include/llvm/Object/COFFImportFile.h), which we use to communicate import information
+        // to LLVM for `#[link(kind = "raw-dylib"_])`, is also defined to be uint16_t.
+        //
+        // FIXME: should we allow an ordinal of 0?  The MSVC toolchain has inconsistent support for this:
+        // both LINK.EXE and LIB.EXE signal errors and abort when given a .DEF file that specifies
+        // a zero ordinal.  However, llvm-dlltool is perfectly happy to generate an import library
+        // for such a .DEF file, and MSVC's LINK.EXE is also perfectly happy to consume an import
+        // library produced by LLVM with an ordinal of 0, and it generates an .EXE.  (I don't know yet
+        // if the resulting EXE runs, as I haven't yet built the necessary DLL -- see earlier comment
+        // about LINK.EXE failing.)
+        if *ordinal <= u16::MAX as u128 {
+            Some(*ordinal as u16)
+        } else {
+            let msg = format!("ordinal value in `link_ordinal` is too large: `{}`", &ordinal);
+            tcx.sess
+                .struct_span_err(attr.span, &msg)
+                .note("the value may not exceed `u16::MAX`")
+                .emit();
+            None
+        }
+    } else {
+        tcx.sess
+            .struct_span_err(attr.span, "illegal ordinal format in `link_ordinal`")
+            .note("an unsuffixed integer value, e.g., `1`, is expected")
+            .emit();
+        None
+    }
+}
+
+fn check_link_name_xor_ordinal(
+    tcx: TyCtxt<'_>,
+    codegen_fn_attrs: &CodegenFnAttrs,
+    inline_span: Option<Span>,
+) {
+    if codegen_fn_attrs.link_name.is_none() || codegen_fn_attrs.link_ordinal.is_none() {
+        return;
+    }
+    let msg = "cannot use `#[link_name]` with `#[link_ordinal]`";
+    if let Some(span) = inline_span {
+        tcx.sess.span_err(span, msg);
+    } else {
+        tcx.sess.err(msg);
+    }
+}
+
+pub fn provide(providers: &mut Providers) {
+    *providers = Providers { codegen_fn_attrs, should_inherit_track_caller, ..*providers };
+}
index b004fbf85a97f8bcbefa345dd17da85503dd777b..819c2678d6c4d4ccead480763760400e56cae706 100644 (file)
@@ -235,7 +235,7 @@ fn push_debuginfo_type_name<'tcx>(
                 let projection_bounds: SmallVec<[_; 4]> = trait_data
                     .projection_bounds()
                     .map(|bound| {
-                        let ExistentialProjection { item_def_id, term, .. } =
+                        let ExistentialProjection { def_id: item_def_id, term, .. } =
                             tcx.erase_late_bound_regions(bound);
                         // FIXME(associated_const_equality): allow for consts here
                         (item_def_id, term.ty().unwrap())
@@ -411,9 +411,8 @@ fn push_debuginfo_type_name<'tcx>(
         ty::Error(_)
         | ty::Infer(_)
         | ty::Placeholder(..)
-        | ty::Projection(..)
+        | ty::Alias(..)
         | ty::Bound(..)
-        | ty::Opaque(..)
         | ty::GeneratorWitness(..) => {
             bug!(
                 "debuginfo: Trying to create type name for \
index e3b6fbf1bc7f0e1bf07f39e7f6d581d1d8046427..0620000201f0254f81ff6dd4200876324b02fd0a 100644 (file)
@@ -548,3 +548,10 @@ pub struct ArchiveBuildFailure {
 pub struct UnknownArchiveKind<'a> {
     pub kind: &'a str,
 }
+
+#[derive(Diagnostic)]
+#[diag(codegen_ssa_expected_used_symbol)]
+pub struct ExpectedUsedSymbol {
+    #[primary_span]
+    pub span: Span,
+}
index def6390f6a36bcbd15d9610ceaa412eef883eeda..0e6596d4ba781bfd7a859a0329105f26a7a2ef60 100644 (file)
@@ -42,6 +42,7 @@
 
 pub mod back;
 pub mod base;
+pub mod codegen_attrs;
 pub mod common;
 pub mod coverageinfo;
 pub mod debuginfo;
@@ -180,6 +181,7 @@ pub fn provide(providers: &mut Providers) {
     crate::back::symbol_export::provide(providers);
     crate::base::provide(providers);
     crate::target_features::provide(providers);
+    crate::codegen_attrs::provide(providers);
 }
 
 pub fn provide_extern(providers: &mut ExternProviders) {
index 58dfd17fb363546dfcd17a386e653a1165e52bea..3860138018bb14c2a69bdfe4a5cfc37bfc1e6da3 100644 (file)
@@ -1802,15 +1802,20 @@ fn codegen_transmute_into(
         match (src.layout.abi, dst.layout.abi) {
             (abi::Abi::Scalar(src_scalar), abi::Abi::Scalar(dst_scalar)) => {
                 // HACK(eddyb) LLVM doesn't like `bitcast`s between pointers and non-pointers.
-                if (src_scalar.primitive() == abi::Pointer)
-                    == (dst_scalar.primitive() == abi::Pointer)
-                {
+                let src_is_ptr = src_scalar.primitive() == abi::Pointer;
+                let dst_is_ptr = dst_scalar.primitive() == abi::Pointer;
+                if src_is_ptr == dst_is_ptr {
                     assert_eq!(src.layout.size, dst.layout.size);
 
                     // NOTE(eddyb) the `from_immediate` and `to_immediate_scalar`
                     // conversions allow handling `bool`s the same as `u8`s.
                     let src = bx.from_immediate(src.immediate());
-                    let src_as_dst = bx.bitcast(src, bx.backend_type(dst.layout));
+                    // LLVM also doesn't like `bitcast`s between pointers in different address spaces.
+                    let src_as_dst = if src_is_ptr {
+                        bx.pointercast(src, bx.backend_type(dst.layout))
+                    } else {
+                        bx.bitcast(src, bx.backend_type(dst.layout))
+                    };
                     Immediate(bx.to_immediate_scalar(src_as_dst, dst_scalar)).store(bx, dst);
                     return;
                 }
index 301683e8e85449370652ce4825c666715b488e8d..0dabe96b60277e032ad0214d2260277915f6a02d 100644 (file)
@@ -1,8 +1,19 @@
+use rustc_ast::ast;
+use rustc_attr::InstructionSetAttr;
+use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::fx::FxHashSet;
+use rustc_errors::Applicability;
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
+use rustc_hir::def_id::LocalDefId;
 use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_middle::ty::query::Providers;
+use rustc_middle::ty::TyCtxt;
+use rustc_session::parse::feature_err;
 use rustc_session::Session;
 use rustc_span::symbol::sym;
 use rustc_span::symbol::Symbol;
+use rustc_span::Span;
 
 /// Features that control behaviour of rustc, rather than the codegen.
 pub const RUSTC_SPECIFIC_FEATURES: &[&str] = &["crt-static"];
@@ -322,15 +333,148 @@ pub fn tied_target_features(sess: &Session) -> &'static [&'static [&'static str]
     }
 }
 
-pub(crate) fn provide(providers: &mut Providers) {
-    providers.supported_target_features = |tcx, cnum| {
-        assert_eq!(cnum, LOCAL_CRATE);
-        if tcx.sess.opts.actually_rustdoc {
-            // rustdoc needs to be able to document functions that use all the features, so
-            // whitelist them all
-            all_known_features().map(|(a, b)| (a.to_string(), b)).collect()
-        } else {
-            supported_target_features(tcx.sess).iter().map(|&(a, b)| (a.to_string(), b)).collect()
-        }
+pub fn from_target_feature(
+    tcx: TyCtxt<'_>,
+    attr: &ast::Attribute,
+    supported_target_features: &FxHashMap<String, Option<Symbol>>,
+    target_features: &mut Vec<Symbol>,
+) {
+    let Some(list) = attr.meta_item_list() else { return };
+    let bad_item = |span| {
+        let msg = "malformed `target_feature` attribute input";
+        let code = "enable = \"..\"";
+        tcx.sess
+            .struct_span_err(span, msg)
+            .span_suggestion(span, "must be of the form", code, Applicability::HasPlaceholders)
+            .emit();
     };
+    let rust_features = tcx.features();
+    for item in list {
+        // Only `enable = ...` is accepted in the meta-item list.
+        if !item.has_name(sym::enable) {
+            bad_item(item.span());
+            continue;
+        }
+
+        // Must be of the form `enable = "..."` (a string).
+        let Some(value) = item.value_str() else {
+            bad_item(item.span());
+            continue;
+        };
+
+        // We allow comma separation to enable multiple features.
+        target_features.extend(value.as_str().split(',').filter_map(|feature| {
+            let Some(feature_gate) = supported_target_features.get(feature) else {
+                let msg =
+                    format!("the feature named `{}` is not valid for this target", feature);
+                let mut err = tcx.sess.struct_span_err(item.span(), &msg);
+                err.span_label(
+                    item.span(),
+                    format!("`{}` is not valid for this target", feature),
+                );
+                if let Some(stripped) = feature.strip_prefix('+') {
+                    let valid = supported_target_features.contains_key(stripped);
+                    if valid {
+                        err.help("consider removing the leading `+` in the feature name");
+                    }
+                }
+                err.emit();
+                return None;
+            };
+
+            // Only allow features whose feature gates have been enabled.
+            let allowed = match feature_gate.as_ref().copied() {
+                Some(sym::arm_target_feature) => rust_features.arm_target_feature,
+                Some(sym::hexagon_target_feature) => rust_features.hexagon_target_feature,
+                Some(sym::powerpc_target_feature) => rust_features.powerpc_target_feature,
+                Some(sym::mips_target_feature) => rust_features.mips_target_feature,
+                Some(sym::riscv_target_feature) => rust_features.riscv_target_feature,
+                Some(sym::avx512_target_feature) => rust_features.avx512_target_feature,
+                Some(sym::sse4a_target_feature) => rust_features.sse4a_target_feature,
+                Some(sym::tbm_target_feature) => rust_features.tbm_target_feature,
+                Some(sym::wasm_target_feature) => rust_features.wasm_target_feature,
+                Some(sym::cmpxchg16b_target_feature) => rust_features.cmpxchg16b_target_feature,
+                Some(sym::movbe_target_feature) => rust_features.movbe_target_feature,
+                Some(sym::rtm_target_feature) => rust_features.rtm_target_feature,
+                Some(sym::f16c_target_feature) => rust_features.f16c_target_feature,
+                Some(sym::ermsb_target_feature) => rust_features.ermsb_target_feature,
+                Some(sym::bpf_target_feature) => rust_features.bpf_target_feature,
+                Some(sym::aarch64_ver_target_feature) => rust_features.aarch64_ver_target_feature,
+                Some(name) => bug!("unknown target feature gate {}", name),
+                None => true,
+            };
+            if !allowed {
+                feature_err(
+                    &tcx.sess.parse_sess,
+                    feature_gate.unwrap(),
+                    item.span(),
+                    &format!("the target feature `{}` is currently unstable", feature),
+                )
+                .emit();
+            }
+            Some(Symbol::intern(feature))
+        }));
+    }
+}
+
+/// Computes the set of target features used in a function for the purposes of
+/// inline assembly.
+fn asm_target_features<'tcx>(tcx: TyCtxt<'tcx>, did: DefId) -> &'tcx FxHashSet<Symbol> {
+    let mut target_features = tcx.sess.unstable_target_features.clone();
+    if tcx.def_kind(did).has_codegen_attrs() {
+        let attrs = tcx.codegen_fn_attrs(did);
+        target_features.extend(&attrs.target_features);
+        match attrs.instruction_set {
+            None => {}
+            Some(InstructionSetAttr::ArmA32) => {
+                target_features.remove(&sym::thumb_mode);
+            }
+            Some(InstructionSetAttr::ArmT32) => {
+                target_features.insert(sym::thumb_mode);
+            }
+        }
+    }
+
+    tcx.arena.alloc(target_features)
+}
+
+/// Checks the function annotated with `#[target_feature]` is not a safe
+/// trait method implementation, reporting an error if it is.
+pub fn check_target_feature_trait_unsafe(tcx: TyCtxt<'_>, id: LocalDefId, attr_span: Span) {
+    let hir_id = tcx.hir().local_def_id_to_hir_id(id);
+    let node = tcx.hir().get(hir_id);
+    if let hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }) = node {
+        let parent_id = tcx.hir().get_parent_item(hir_id);
+        let parent_item = tcx.hir().expect_item(parent_id.def_id);
+        if let hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) = parent_item.kind {
+            tcx.sess
+                .struct_span_err(
+                    attr_span,
+                    "`#[target_feature(..)]` cannot be applied to safe trait method",
+                )
+                .span_label(attr_span, "cannot be applied to safe trait method")
+                .span_label(tcx.def_span(id), "not an `unsafe` function")
+                .emit();
+        }
+    }
+}
+
+pub(crate) fn provide(providers: &mut Providers) {
+    *providers = Providers {
+        supported_target_features: |tcx, cnum| {
+            assert_eq!(cnum, LOCAL_CRATE);
+            if tcx.sess.opts.actually_rustdoc {
+                // rustdoc needs to be able to document functions that use all the features, so
+                // whitelist them all
+                all_known_features().map(|(a, b)| (a.to_string(), b)).collect()
+            } else {
+                supported_target_features(tcx.sess)
+                    .iter()
+                    .map(|&(a, b)| (a.to_string(), b))
+                    .collect()
+            }
+        },
+        asm_target_features,
+        ..*providers
+    }
 }
index c60d6e4fed9f55277ba8640f9fb8ed81d4612dfc..13472cc2bfa0a5c4b8ed7ba81baa6eb3114ac9f9 100644 (file)
@@ -86,6 +86,59 @@ pub(super) fn report(&self, tcx: TyCtxtAt<'tcx>, message: &str) -> ErrorHandled
         self.report_decorated(tcx, message, |_| {})
     }
 
+    #[instrument(level = "trace", skip(self, decorate))]
+    pub(super) fn decorate(&self, err: &mut Diagnostic, decorate: impl FnOnce(&mut Diagnostic)) {
+        trace!("reporting const eval failure at {:?}", self.span);
+        // Add some more context for select error types.
+        match self.error {
+            InterpError::Unsupported(
+                UnsupportedOpInfo::ReadPointerAsBytes
+                | UnsupportedOpInfo::PartialPointerOverwrite(_)
+                | UnsupportedOpInfo::PartialPointerCopy(_),
+            ) => {
+                err.help("this code performed an operation that depends on the underlying bytes representing a pointer");
+                err.help("the absolute address of a pointer is not known at compile-time, so such operations are not supported");
+            }
+            _ => {}
+        }
+        // Add spans for the stacktrace. Don't print a single-line backtrace though.
+        if self.stacktrace.len() > 1 {
+            // Helper closure to print duplicated lines.
+            let mut flush_last_line = |last_frame, times| {
+                if let Some((line, span)) = last_frame {
+                    err.span_note(span, &line);
+                    // Don't print [... additional calls ...] if the number of lines is small
+                    if times < 3 {
+                        for _ in 0..times {
+                            err.span_note(span, &line);
+                        }
+                    } else {
+                        err.span_note(
+                            span,
+                            format!("[... {} additional calls {} ...]", times, &line),
+                        );
+                    }
+                }
+            };
+
+            let mut last_frame = None;
+            let mut times = 0;
+            for frame_info in &self.stacktrace {
+                let frame = (frame_info.to_string(), frame_info.span);
+                if last_frame.as_ref() == Some(&frame) {
+                    times += 1;
+                } else {
+                    flush_last_line(last_frame, times);
+                    last_frame = Some(frame);
+                    times = 0;
+                }
+            }
+            flush_last_line(last_frame, times);
+        }
+        // Let the caller attach any additional information it wants.
+        decorate(err);
+    }
+
     /// Create a diagnostic for this const eval error.
     ///
     /// Sets the message passed in via `message` and adds span labels with detailed error
@@ -101,88 +154,30 @@ pub(super) fn report_decorated(
         message: &str,
         decorate: impl FnOnce(&mut Diagnostic),
     ) -> ErrorHandled {
-        let finish = |err: &mut Diagnostic, span_msg: Option<String>| {
-            trace!("reporting const eval failure at {:?}", self.span);
-            if let Some(span_msg) = span_msg {
-                err.span_label(self.span, span_msg);
-            }
-            // Add some more context for select error types.
-            match self.error {
-                InterpError::Unsupported(
-                    UnsupportedOpInfo::ReadPointerAsBytes
-                    | UnsupportedOpInfo::PartialPointerOverwrite(_)
-                    | UnsupportedOpInfo::PartialPointerCopy(_),
-                ) => {
-                    err.help("this code performed an operation that depends on the underlying bytes representing a pointer");
-                    err.help("the absolute address of a pointer is not known at compile-time, so such operations are not supported");
-                }
-                _ => {}
-            }
-            // Add spans for the stacktrace. Don't print a single-line backtrace though.
-            if self.stacktrace.len() > 1 {
-                // Helper closure to print duplicated lines.
-                let mut flush_last_line = |last_frame, times| {
-                    if let Some((line, span)) = last_frame {
-                        err.span_note(span, &line);
-                        // Don't print [... additional calls ...] if the number of lines is small
-                        if times < 3 {
-                            for _ in 0..times {
-                                err.span_note(span, &line);
-                            }
-                        } else {
-                            err.span_note(
-                                span,
-                                format!("[... {} additional calls {} ...]", times, &line),
-                            );
-                        }
-                    }
-                };
-
-                let mut last_frame = None;
-                let mut times = 0;
-                for frame_info in &self.stacktrace {
-                    let frame = (frame_info.to_string(), frame_info.span);
-                    if last_frame.as_ref() == Some(&frame) {
-                        times += 1;
-                    } else {
-                        flush_last_line(last_frame, times);
-                        last_frame = Some(frame);
-                        times = 0;
-                    }
-                }
-                flush_last_line(last_frame, times);
-            }
-            // Let the caller attach any additional information it wants.
-            decorate(err);
-        };
-
         debug!("self.error: {:?}", self.error);
         // Special handling for certain errors
         match &self.error {
             // Don't emit a new diagnostic for these errors
             err_inval!(Layout(LayoutError::Unknown(_))) | err_inval!(TooGeneric) => {
-                return ErrorHandled::TooGeneric;
-            }
-            err_inval!(AlreadyReported(error_reported)) => {
-                return ErrorHandled::Reported(*error_reported);
+                ErrorHandled::TooGeneric
             }
+            err_inval!(AlreadyReported(error_reported)) => ErrorHandled::Reported(*error_reported),
             err_inval!(Layout(LayoutError::SizeOverflow(_))) => {
                 // We must *always* hard error on these, even if the caller wants just a lint.
                 // The `message` makes little sense here, this is a more serious error than the
                 // caller thinks anyway.
                 // See <https://github.com/rust-lang/rust/pull/63152>.
                 let mut err = struct_error(tcx, &self.error.to_string());
-                finish(&mut err, None);
-                return ErrorHandled::Reported(err.emit());
+                self.decorate(&mut err, decorate);
+                ErrorHandled::Reported(err.emit())
             }
-            _ => {}
-        };
-
-        let err_msg = self.error.to_string();
-
-        // Report as hard error.
-        let mut err = struct_error(tcx, message);
-        finish(&mut err, Some(err_msg));
-        ErrorHandled::Reported(err.emit())
+            _ => {
+                // Report as hard error.
+                let mut err = struct_error(tcx, message);
+                err.span_label(self.span, self.error.to_string());
+                self.decorate(&mut err, decorate);
+                ErrorHandled::Reported(err.emit())
+            }
+        }
     }
 }
index 319f2b2c25ebf320f71c6d0fe83bca042fe3f191..18e01567ca35e44888e52e19abd6bb07edca0d0e 100644 (file)
@@ -1,3 +1,4 @@
+use crate::const_eval::CheckAlignment;
 use std::borrow::Cow;
 
 use either::{Left, Right};
@@ -76,7 +77,7 @@ fn eval_body_using_ecx<'mir, 'tcx>(
             None => InternKind::Constant,
         }
     };
-    ecx.machine.check_alignment = false; // interning doesn't need to respect alignment
+    ecx.machine.check_alignment = CheckAlignment::No; // interning doesn't need to respect alignment
     intern_const_alloc_recursive(ecx, intern_kind, &ret)?;
     // we leave alignment checks off, since this `ecx` will not be used for further evaluation anyway
 
@@ -102,11 +103,7 @@ pub(super) fn mk_eval_cx<'mir, 'tcx>(
         tcx,
         root_span,
         param_env,
-        CompileTimeInterpreter::new(
-            tcx.const_eval_limit(),
-            can_access_statics,
-            /*check_alignment:*/ false,
-        ),
+        CompileTimeInterpreter::new(tcx.const_eval_limit(), can_access_statics, CheckAlignment::No),
     )
 }
 
@@ -311,7 +308,11 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
         CompileTimeInterpreter::new(
             tcx.const_eval_limit(),
             /*can_access_statics:*/ is_static,
-            /*check_alignment:*/ tcx.sess.opts.unstable_opts.extra_const_ub_checks,
+            if tcx.sess.opts.unstable_opts.extra_const_ub_checks {
+                CheckAlignment::Error
+            } else {
+                CheckAlignment::FutureIncompat
+            },
         ),
     );
 
index 3dfded2d930a052c305859ed257536285303eda8..e006a62feeabd12bc568da7c5c42e76bdde1cc2f 100644 (file)
@@ -1,9 +1,10 @@
 use rustc_hir::def::DefKind;
-use rustc_hir::LangItem;
+use rustc_hir::{LangItem, CRATE_HIR_ID};
 use rustc_middle::mir;
 use rustc_middle::mir::interpret::PointerArithmetic;
 use rustc_middle::ty::layout::FnAbiOf;
 use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_session::lint::builtin::INVALID_ALIGNMENT;
 use std::borrow::Borrow;
 use std::hash::Hash;
 use std::ops::ControlFlow;
@@ -47,14 +48,34 @@ pub struct CompileTimeInterpreter<'mir, 'tcx> {
     pub(super) can_access_statics: bool,
 
     /// Whether to check alignment during evaluation.
-    pub(super) check_alignment: bool,
+    pub(super) check_alignment: CheckAlignment,
+}
+
+#[derive(Copy, Clone)]
+pub enum CheckAlignment {
+    /// Ignore alignment when following relocations.
+    /// This is mainly used in interning.
+    No,
+    /// Hard error when dereferencing a misaligned pointer.
+    Error,
+    /// Emit a future incompat lint when dereferencing a misaligned pointer.
+    FutureIncompat,
+}
+
+impl CheckAlignment {
+    pub fn should_check(&self) -> bool {
+        match self {
+            CheckAlignment::No => false,
+            CheckAlignment::Error | CheckAlignment::FutureIncompat => true,
+        }
+    }
 }
 
 impl<'mir, 'tcx> CompileTimeInterpreter<'mir, 'tcx> {
     pub(crate) fn new(
         const_eval_limit: Limit,
         can_access_statics: bool,
-        check_alignment: bool,
+        check_alignment: CheckAlignment,
     ) -> Self {
         CompileTimeInterpreter {
             steps_remaining: const_eval_limit.0,
@@ -309,7 +330,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
     const PANIC_ON_ALLOC_FAIL: bool = false; // will be raised as a proper error
 
     #[inline(always)]
-    fn enforce_alignment(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool {
+    fn enforce_alignment(ecx: &InterpCx<'mir, 'tcx, Self>) -> CheckAlignment {
         ecx.machine.check_alignment
     }
 
@@ -318,6 +339,36 @@ fn enforce_validity(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool {
         ecx.tcx.sess.opts.unstable_opts.extra_const_ub_checks
     }
 
+    fn alignment_check_failed(
+        ecx: &InterpCx<'mir, 'tcx, Self>,
+        has: Align,
+        required: Align,
+        check: CheckAlignment,
+    ) -> InterpResult<'tcx, ()> {
+        let err = err_ub!(AlignmentCheckFailed { has, required }).into();
+        match check {
+            CheckAlignment::Error => Err(err),
+            CheckAlignment::No => span_bug!(
+                ecx.cur_span(),
+                "`alignment_check_failed` called when no alignment check requested"
+            ),
+            CheckAlignment::FutureIncompat => {
+                let err = ConstEvalErr::new(ecx, err, None);
+                ecx.tcx.struct_span_lint_hir(
+                    INVALID_ALIGNMENT,
+                    ecx.stack().iter().find_map(|frame| frame.lint_root()).unwrap_or(CRATE_HIR_ID),
+                    err.span,
+                    err.error.to_string(),
+                    |db| {
+                        err.decorate(db, |_| {});
+                        db
+                    },
+                );
+                Ok(())
+            }
+        }
+    }
+
     fn load_mir(
         ecx: &InterpCx<'mir, 'tcx, Self>,
         instance: ty::InstanceDef<'tcx>,
index f4da11883957a73f0376d35c2202c659a2d1a8ab..498c008738793912e46e0b25afca0b8180a07d34 100644 (file)
@@ -142,12 +142,11 @@ pub(crate) fn const_to_valtree_inner<'tcx>(
         | ty::Foreign(..)
         | ty::Infer(ty::FreshIntTy(_))
         | ty::Infer(ty::FreshFloatTy(_))
-        | ty::Projection(..)
+        // FIXME(oli-obk): we could look behind opaque types
+        | ty::Alias(..)
         | ty::Param(_)
         | ty::Bound(..)
         | ty::Placeholder(..)
-        // FIXME(oli-obk): we could look behind opaque types
-        | ty::Opaque(..)
         | ty::Infer(_)
         // FIXME(oli-obk): we can probably encode closures just like structs
         | ty::Closure(..)
@@ -307,11 +306,10 @@ pub fn valtree_to_const_value<'tcx>(
         | ty::Foreign(..)
         | ty::Infer(ty::FreshIntTy(_))
         | ty::Infer(ty::FreshFloatTy(_))
-        | ty::Projection(..)
+        | ty::Alias(..)
         | ty::Param(_)
         | ty::Bound(..)
         | ty::Placeholder(..)
-        | ty::Opaque(..)
         | ty::Infer(_)
         | ty::Closure(..)
         | ty::Generator(..)
index 0b2809f1d2c285238c1a93a8bb65fc314483de87..f551b5c29114d9984fcf108ceb1b9e12628db580 100644 (file)
@@ -248,6 +248,15 @@ pub fn current_span(&self) -> Span {
             Right(span) => span,
         }
     }
+
+    pub fn lint_root(&self) -> Option<hir::HirId> {
+        self.current_source_info().and_then(|source_info| {
+            match &self.body.source_scopes[source_info.scope].local_data {
+                mir::ClearCrossCrate::Set(data) => Some(data.lint_root),
+                mir::ClearCrossCrate::Clear => None,
+            }
+        })
+    }
 }
 
 impl<'tcx> fmt::Display for FrameInfo<'tcx> {
@@ -954,12 +963,7 @@ pub fn generate_stacktrace_from_stack(
         // This deliberately does *not* honor `requires_caller_location` since it is used for much
         // more than just panics.
         for frame in stack.iter().rev() {
-            let lint_root = frame.current_source_info().and_then(|source_info| {
-                match &frame.body.source_scopes[source_info.scope].local_data {
-                    mir::ClearCrossCrate::Set(data) => Some(data.lint_root),
-                    mir::ClearCrossCrate::Clear => None,
-                }
-            });
+            let lint_root = frame.lint_root();
             let span = frame.current_span();
 
             frames.push(FrameInfo { span, instance: frame.instance, lint_root });
index b9be7fa48000be54ddef02808aa26b3a100ec2fb..9b56757eb3951a4ee201a538268f286f7b12edce 100644 (file)
@@ -82,11 +82,9 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>(
             ty::Adt(ref adt, _) => {
                 ConstValue::from_machine_usize(adt.variants().len() as u64, &tcx)
             }
-            ty::Projection(_)
-            | ty::Opaque(_, _)
-            | ty::Param(_)
-            | ty::Placeholder(_)
-            | ty::Infer(_) => throw_inval!(TooGeneric),
+            ty::Alias(..) | ty::Param(_) | ty::Placeholder(_) | ty::Infer(_) => {
+                throw_inval!(TooGeneric)
+            }
             ty::Bound(_, _) => bug!("bound ty during ctfe"),
             ty::Bool
             | ty::Char
index 0604d5ee6fa4c93e94211111da45abd2e4715f15..1d4ef20d0651f7bd11d7cb466f0290d375ff27d8 100644 (file)
 use rustc_middle::mir;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::def_id::DefId;
-use rustc_target::abi::Size;
+use rustc_target::abi::{Align, Size};
 use rustc_target::spec::abi::Abi as CallAbi;
 
+use crate::const_eval::CheckAlignment;
+
 use super::{
     AllocId, AllocRange, Allocation, ConstAllocation, Frame, ImmTy, InterpCx, InterpResult,
     MemoryKind, OpTy, Operand, PlaceTy, Pointer, Provenance, Scalar, StackPopUnwind,
@@ -122,7 +124,7 @@ pub trait Machine<'mir, 'tcx>: Sized {
     const PANIC_ON_ALLOC_FAIL: bool;
 
     /// Whether memory accesses should be alignment-checked.
-    fn enforce_alignment(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool;
+    fn enforce_alignment(ecx: &InterpCx<'mir, 'tcx, Self>) -> CheckAlignment;
 
     /// Whether, when checking alignment, we should look at the actual address and thus support
     /// custom alignment logic based on whatever the integer address happens to be.
@@ -130,6 +132,13 @@ pub trait Machine<'mir, 'tcx>: Sized {
     /// If this returns true, Provenance::OFFSET_IS_ADDR must be true.
     fn use_addr_for_alignment_check(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool;
 
+    fn alignment_check_failed(
+        ecx: &InterpCx<'mir, 'tcx, Self>,
+        has: Align,
+        required: Align,
+        check: CheckAlignment,
+    ) -> InterpResult<'tcx, ()>;
+
     /// Whether to enforce the validity invariant
     fn enforce_validity(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool;
 
index 528c1cb06c0ebadf1e2ca0cb324cc51bd8c0e794..5b1ac6b2f65e29f7bc7a726d3044a6fd5cb95654 100644 (file)
@@ -18,6 +18,8 @@
 use rustc_middle::ty::{self, Instance, ParamEnv, Ty, TyCtxt};
 use rustc_target::abi::{Align, HasDataLayout, Size};
 
+use crate::const_eval::CheckAlignment;
+
 use super::{
     alloc_range, AllocId, AllocMap, AllocRange, Allocation, CheckInAllocMsg, GlobalAlloc, InterpCx,
     InterpResult, Machine, MayLeak, Pointer, PointerArithmetic, Provenance, Scalar,
@@ -349,11 +351,11 @@ fn get_ptr_access(
         size: Size,
         align: Align,
     ) -> InterpResult<'tcx, Option<(AllocId, Size, M::ProvenanceExtra)>> {
-        let align = M::enforce_alignment(&self).then_some(align);
         self.check_and_deref_ptr(
             ptr,
             size,
             align,
+            M::enforce_alignment(self),
             CheckInAllocMsg::MemoryAccessTest,
             |alloc_id, offset, prov| {
                 let (size, align) = self.get_live_alloc_size_and_align(alloc_id)?;
@@ -373,10 +375,17 @@ pub fn check_ptr_access_align(
         align: Align,
         msg: CheckInAllocMsg,
     ) -> InterpResult<'tcx> {
-        self.check_and_deref_ptr(ptr, size, Some(align), msg, |alloc_id, _, _| {
-            let (size, align) = self.get_live_alloc_size_and_align(alloc_id)?;
-            Ok((size, align, ()))
-        })?;
+        self.check_and_deref_ptr(
+            ptr,
+            size,
+            align,
+            CheckAlignment::Error,
+            msg,
+            |alloc_id, _, _| {
+                let (size, align) = self.get_live_alloc_size_and_align(alloc_id)?;
+                Ok((size, align, ()))
+            },
+        )?;
         Ok(())
     }
 
@@ -388,7 +397,8 @@ fn check_and_deref_ptr<T>(
         &self,
         ptr: Pointer<Option<M::Provenance>>,
         size: Size,
-        align: Option<Align>,
+        align: Align,
+        check: CheckAlignment,
         msg: CheckInAllocMsg,
         alloc_size: impl FnOnce(
             AllocId,
@@ -396,19 +406,6 @@ fn check_and_deref_ptr<T>(
             M::ProvenanceExtra,
         ) -> InterpResult<'tcx, (Size, Align, T)>,
     ) -> InterpResult<'tcx, Option<T>> {
-        fn check_offset_align<'tcx>(offset: u64, align: Align) -> InterpResult<'tcx> {
-            if offset % align.bytes() == 0 {
-                Ok(())
-            } else {
-                // The biggest power of two through which `offset` is divisible.
-                let offset_pow2 = 1 << offset.trailing_zeros();
-                throw_ub!(AlignmentCheckFailed {
-                    has: Align::from_bytes(offset_pow2).unwrap(),
-                    required: align,
-                })
-            }
-        }
-
         Ok(match self.ptr_try_get_alloc_id(ptr) {
             Err(addr) => {
                 // We couldn't get a proper allocation. This is only okay if the access size is 0,
@@ -417,8 +414,8 @@ fn check_offset_align<'tcx>(offset: u64, align: Align) -> InterpResult<'tcx> {
                     throw_ub!(DanglingIntPointer(addr, msg));
                 }
                 // Must be aligned.
-                if let Some(align) = align {
-                    check_offset_align(addr, align)?;
+                if check.should_check() {
+                    self.check_offset_align(addr, align, check)?;
                 }
                 None
             }
@@ -441,16 +438,16 @@ fn check_offset_align<'tcx>(offset: u64, align: Align) -> InterpResult<'tcx> {
                 }
                 // Test align. Check this last; if both bounds and alignment are violated
                 // we want the error to be about the bounds.
-                if let Some(align) = align {
+                if check.should_check() {
                     if M::use_addr_for_alignment_check(self) {
                         // `use_addr_for_alignment_check` can only be true if `OFFSET_IS_ADDR` is true.
-                        check_offset_align(ptr.addr().bytes(), align)?;
+                        self.check_offset_align(ptr.addr().bytes(), align, check)?;
                     } else {
                         // Check allocation alignment and offset alignment.
                         if alloc_align.bytes() < align.bytes() {
-                            throw_ub!(AlignmentCheckFailed { has: alloc_align, required: align });
+                            M::alignment_check_failed(self, alloc_align, align, check)?;
                         }
-                        check_offset_align(offset.bytes(), align)?;
+                        self.check_offset_align(offset.bytes(), align, check)?;
                     }
                 }
 
@@ -460,6 +457,21 @@ fn check_offset_align<'tcx>(offset: u64, align: Align) -> InterpResult<'tcx> {
             }
         })
     }
+
+    fn check_offset_align(
+        &self,
+        offset: u64,
+        align: Align,
+        check: CheckAlignment,
+    ) -> InterpResult<'tcx> {
+        if offset % align.bytes() == 0 {
+            Ok(())
+        } else {
+            // The biggest power of two through which `offset` is divisible.
+            let offset_pow2 = 1 << offset.trailing_zeros();
+            M::alignment_check_failed(self, Align::from_bytes(offset_pow2).unwrap(), align, check)
+        }
+    }
 }
 
 /// Allocation accessors
@@ -560,11 +572,11 @@ pub fn get_ptr_alloc<'a>(
         size: Size,
         align: Align,
     ) -> InterpResult<'tcx, Option<AllocRef<'a, 'tcx, M::Provenance, M::AllocExtra>>> {
-        let align = M::enforce_alignment(self).then_some(align);
         let ptr_and_alloc = self.check_and_deref_ptr(
             ptr,
             size,
             align,
+            M::enforce_alignment(self),
             CheckInAllocMsg::MemoryAccessTest,
             |alloc_id, offset, prov| {
                 let alloc = self.get_alloc_raw(alloc_id)?;
index c47cfe8bb69fd05831734e1f42cf16e3781d7049..905eb71bb18edde28b2eeb30f7d406defedcf4ce 100644 (file)
@@ -364,13 +364,8 @@ pub fn check_mplace(&self, mplace: MPlaceTy<'tcx, M::Provenance>) -> InterpResul
             .size_and_align_of_mplace(&mplace)?
             .unwrap_or((mplace.layout.size, mplace.layout.align.abi));
         assert!(mplace.align <= align, "dynamic alignment less strict than static one?");
-        let align = M::enforce_alignment(self).then_some(align);
-        self.check_ptr_access_align(
-            mplace.ptr,
-            size,
-            align.unwrap_or(Align::ONE),
-            CheckInAllocMsg::DerefTest,
-        )?;
+        let align = if M::enforce_alignment(self).should_check() { align } else { Align::ONE };
+        self.check_ptr_access_align(mplace.ptr, size, align, CheckInAllocMsg::DerefTest)?;
         Ok(())
     }
 
index fc65306e440a9912ead726d9d4ca871cd5eae3be..f905d3fb479a0b7e343c7dd187239f94f3543705 100644 (file)
@@ -601,8 +601,7 @@ fn try_visit_primitive(
             | ty::Placeholder(..)
             | ty::Bound(..)
             | ty::Param(..)
-            | ty::Opaque(..)
-            | ty::Projection(..)
+            | ty::Alias(..)
             | ty::GeneratorWitness(..) => bug!("Encountered invalid type {:?}", ty),
         }
     }
index 64318f5f54d5d061c255726f800e9251d631933b..bb897b95b2c53cd1122663b41945764ccd354960 100644 (file)
@@ -52,7 +52,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         };
 
         let always_live_locals = always_storage_live_locals(body);
-        let storage_liveness = MaybeStorageLive::new(always_live_locals)
+        let storage_liveness = MaybeStorageLive::new(std::borrow::Cow::Owned(always_live_locals))
             .into_engine(tcx, body)
             .iterate_to_fixpoint()
             .into_results_cursor(body);
@@ -79,7 +79,7 @@ struct TypeChecker<'a, 'tcx> {
     param_env: ParamEnv<'tcx>,
     mir_phase: MirPhase,
     reachable_blocks: BitSet<BasicBlock>,
-    storage_liveness: ResultsCursor<'a, 'tcx, MaybeStorageLive>,
+    storage_liveness: ResultsCursor<'a, 'tcx, MaybeStorageLive<'static>>,
     place_cache: Vec<PlaceRef<'tcx>>,
     value_cache: Vec<u128>,
 }
@@ -241,7 +241,7 @@ fn visit_projection_elem(
                 };
 
                 let kind = match parent_ty.ty.kind() {
-                    &ty::Opaque(def_id, substs) => {
+                    &ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
                         self.tcx.bound_type_of(def_id).subst(self.tcx, substs).kind()
                     }
                     kind => kind,
@@ -652,7 +652,7 @@ fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
                     self.fail(location, "`SetDiscriminant`is not allowed until deaggregation");
                 }
                 let pty = place.ty(&self.body.local_decls, self.tcx).ty.kind();
-                if !matches!(pty, ty::Adt(..) | ty::Generator(..) | ty::Opaque(..)) {
+                if !matches!(pty, ty::Adt(..) | ty::Generator(..) | ty::Alias(ty::Opaque, ..)) {
                     self.fail(
                         location,
                         format!(
index b38a6c551388e473b7771d0e03f805f0db0b173b..38d9b044981cd723687c8962d06345fc226aa39a 100644 (file)
@@ -5,7 +5,7 @@
 use rustc_hir::def_id::DefId;
 use rustc_hir::{lang_items, LangItem};
 use rustc_middle::ty::subst::SubstsRef;
-use rustc_middle::ty::{self, AssocItemContainer, DefIdTree, Instance, ParamEnv, Ty, TyCtxt};
+use rustc_middle::ty::{AssocItemContainer, Instance, ParamEnv, Ty, TyCtxt};
 use rustc_span::symbol::Ident;
 use rustc_span::{sym, DesugaringKind, Span};
 
@@ -39,9 +39,7 @@ pub enum CallKind<'tcx> {
     Normal {
         self_arg: Option<Ident>,
         desugaring: Option<(CallDesugaringKind, Ty<'tcx>)>,
-        /// Whether the self type of the method call has an `.as_ref()` method.
-        /// Used for better diagnostics.
-        is_option_or_result: bool,
+        method_did: DefId,
     },
     /// A call to `Fn(..)::call(..)`, desugared from `my_closure(a, b, c)`
     FnCall { fn_trait_id: DefId, self_ty: Ty<'tcx> },
@@ -133,16 +131,6 @@ pub fn call_kind<'tcx>(
         } else {
             None
         };
-        let parent_did = tcx.parent(method_did);
-        let parent_self_ty = (tcx.def_kind(parent_did) == rustc_hir::def::DefKind::Impl)
-            .then_some(parent_did)
-            .and_then(|did| match tcx.type_of(did).kind() {
-                ty::Adt(def, ..) => Some(def.did()),
-                _ => None,
-            });
-        let is_option_or_result = parent_self_ty.map_or(false, |def_id| {
-            matches!(tcx.get_diagnostic_name(def_id), Some(sym::Option | sym::Result))
-        });
-        CallKind::Normal { self_arg, desugaring, is_option_or_result }
+        CallKind::Normal { self_arg, desugaring, method_did }
     })
 }
index 6ca71223391d2a5828b39b655cb113473cd0e46f..4ce107ea68d4f0f3869cebe3cce00c706a42f58d 100644 (file)
@@ -3,7 +3,7 @@
 use rustc_session::Limit;
 use rustc_target::abi::{Abi, FieldsShape, InitKind, Scalar, Variants};
 
-use crate::const_eval::CompileTimeInterpreter;
+use crate::const_eval::{CheckAlignment, CompileTimeInterpreter};
 use crate::interpret::{InterpCx, MemoryKind, OpTy};
 
 /// Determines if this type permits "raw" initialization by just transmuting some memory into an
@@ -41,7 +41,7 @@ fn might_permit_raw_init_strict<'tcx>(
     let machine = CompileTimeInterpreter::new(
         Limit::new(0),
         /*can_access_statics:*/ false,
-        /*check_alignment:*/ true,
+        CheckAlignment::Error,
     );
 
     let mut cx = InterpCx::new(tcx, rustc_span::DUMMY_SP, ParamEnv::reveal_all(), machine);
index 14c8c88028bdac0448ad5321272730a4842fcfe0..c4122f66498143a70950219d6afb696c91d58f40 100644 (file)
@@ -58,8 +58,7 @@ fn print_type(mut self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error> {
             // Types with identity (print the module path).
             ty::Adt(ty::AdtDef(Interned(&ty::AdtDefData { did: def_id, .. }, _)), substs)
             | ty::FnDef(def_id, substs)
-            | ty::Opaque(def_id, substs)
-            | ty::Projection(ty::ProjectionTy { item_def_id: def_id, substs })
+            | ty::Alias(_, ty::AliasTy { def_id, substs, .. })
             | ty::Closure(def_id, substs)
             | ty::Generator(def_id, substs, _) => self.print_def_path(def_id, substs),
             ty::Foreign(def_id) => self.print_def_path(def_id, &[]),
index 3c7bea27124096f35fd2cda702e5cb7ccc930b96..4567759c004dad7140b008d9569fc811c07fe642 100644 (file)
@@ -9,7 +9,7 @@
 pub const ALPHANUMERIC_ONLY: usize = 62;
 pub const CASE_INSENSITIVE: usize = 36;
 
-const BASE_64: &[u8; MAX_BASE as usize] =
+const BASE_64: &[u8; MAX_BASE] =
     b"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@$";
 
 #[inline]
index 03ff5e5b3751fe502d5c1c3c0265dc9c07c74aa8..05f059c89d5cd0fea01ea73e00e8d8419b4b3c9e 100644 (file)
@@ -126,13 +126,13 @@ pub fn iter(&self) -> std::slice::Iter<'_, (K, V)> {
     /// Iterate over the keys, sorted
     #[inline]
     pub fn keys(&self) -> impl Iterator<Item = &K> + ExactSizeIterator + DoubleEndedIterator {
-        self.data.iter().map(|&(ref k, _)| k)
+        self.data.iter().map(|(k, _)| k)
     }
 
     /// Iterate over values, sorted by key
     #[inline]
     pub fn values(&self) -> impl Iterator<Item = &V> + ExactSizeIterator + DoubleEndedIterator {
-        self.data.iter().map(|&(_, ref v)| v)
+        self.data.iter().map(|(_, v)| v)
     }
 
     #[inline]
@@ -222,7 +222,7 @@ fn lookup_index_for<Q>(&self, key: &Q) -> Result<usize, usize>
         K: Borrow<Q>,
         Q: Ord + ?Sized,
     {
-        self.data.binary_search_by(|&(ref x, _)| x.borrow().cmp(key))
+        self.data.binary_search_by(|(x, _)| x.borrow().cmp(key))
     }
 
     #[inline]
@@ -300,7 +300,7 @@ impl<K: Ord, V> FromIterator<(K, V)> for SortedMap<K, V> {
     fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self {
         let mut data: Vec<(K, V)> = iter.into_iter().collect();
 
-        data.sort_unstable_by(|&(ref k1, _), &(ref k2, _)| k1.cmp(k2));
+        data.sort_unstable_by(|(k1, _), (k2, _)| k1.cmp(k2));
         data.dedup_by(|&mut (ref k1, _), &mut (ref k2, _)| k1.cmp(k2) == Ordering::Equal);
 
         SortedMap { data }
index 4d1f9c1c901fc63d7fc4d877c76379baa2634e8b..db4c82b35c77822d718d16039112205dada7972c 100644 (file)
@@ -192,3 +192,5 @@ codegen_ssa_archive_build_failure =
 
 codegen_ssa_unknown_archive_kind =
     Don't know how to build archive of type: {$kind}
+
+codegen_ssa_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)`
index a9ea161b93eda2251a9c779dc1eabfad0a36baa1..26cdf8a58f3fb5e975342ef93f2237c095a2932d 100644 (file)
@@ -20,6 +20,10 @@ hir_analysis_lifetimes_or_bounds_mismatch_on_trait =
     .where_label = this `where` clause might not match the one in the trait
     .bounds_label = this bound might be missing in the impl
 
+hir_analysis_async_trait_impl_should_be_async =
+    method `{$method_name}` should be async because the method from the trait is async
+    .trait_item_label = required because the trait method is async
+
 hir_analysis_drop_impl_on_wrong_item =
     the `Drop` trait may only be implemented for local structs, enums, and unions
     .label = must be a struct, enum, or union in the current crate
@@ -101,8 +105,6 @@ hir_analysis_extern_crate_not_idiomatic =
     `extern crate` is not idiomatic in the new edition
     .suggestion = convert it to a `{$msg_code}`
 
-hir_analysis_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)`
-
 hir_analysis_const_impl_for_non_const_trait =
     const `impl` for trait `{$trait_name}` which is not marked with `#[const_trait]`
     .suggestion = mark `{$trait_name}` as const
index 48ddb54b79e795eb3c67f96b69bb5dda24e32f01..243d10bfa062150bf9bda530541b8f235d35ceae 100644 (file)
@@ -21,3 +21,6 @@ monomorphize_large_assignments =
     moving {$size} bytes
     .label = value moved from here
     .note = The current maximum size is {$limit}, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`
+
+monomorphize_couldnt_dump_mono_stats =
+    unexpected error occurred while dumping monomorphization stats: {$error}
index 114b7ec16288bb7b99f0abcb1ed89ba8559d68ad..b53550e5fd556c02e58acd21fbae26252bb2b69a 100644 (file)
@@ -362,3 +362,6 @@ parse_fn_ptr_with_generics = function pointer types may not have generic paramet
 
 parse_invalid_identifier_with_leading_number = expected identifier, found number literal
     .label = identifiers cannot start with a number
+
+parse_maybe_fn_typo_with_impl = you might have meant to write `impl` instead of `fn`
+    .suggestion = replace `fn` with `impl` here
index 06bb5edc090f48c8b6c326961982ce9730aa6957..585a54308c62e1c0bf07ab9c1478bd51ec0fca2c 100644 (file)
@@ -370,7 +370,11 @@ pub fn replace_span_with(&mut self, after: Span) -> &mut Self {
         self.set_span(after);
         for span_label in before.span_labels() {
             if let Some(label) = span_label.label {
-                self.span.push_span_label(after, label);
+                if span_label.is_primary {
+                    self.span.push_span_label(after, label);
+                } else {
+                    self.span.push_span_label(span_label.span, label);
+                }
             }
         }
         self
@@ -802,7 +806,7 @@ pub fn multipart_suggestions(
         debug_assert!(
             !(suggestions
                 .iter()
-                .flat_map(|suggs| suggs)
+                .flatten()
                 .any(|(sp, suggestion)| sp.is_empty() && suggestion.is_empty())),
             "Span must not be empty and have no suggestion"
         );
index 4df2198fb0e9bc8eaad61d0babc663efe6e6bd72..e2a0e436fd5e2677a9524066380a034907ef59b0 100644 (file)
@@ -1308,7 +1308,7 @@ fn style_or_override(style: Style, override_: Option<Style>) -> Style {
         //                see how it *looks* with
         //                very *weird* formats
         //                see?
-        for &(ref text, ref style) in msg.iter() {
+        for (text, style) in msg.iter() {
             let text = self.translate_message(text, args);
             let lines = text.split('\n').collect::<Vec<_>>();
             if lines.len() > 1 {
@@ -1370,7 +1370,7 @@ fn emit_message_default(
                 buffer.append(0, ": ", header_style);
                 label_width += 2;
             }
-            for &(ref text, _) in msg.iter() {
+            for (text, _) in msg.iter() {
                 let text = self.translate_message(text, args);
                 // Account for newlines to align output to its label.
                 for (line, text) in normalize_whitespace(&text).lines().enumerate() {
@@ -1408,49 +1408,58 @@ fn emit_message_default(
             if !sm.ensure_source_file_source_present(annotated_file.file.clone()) {
                 if !self.short_message {
                     // We'll just print an unannotated message.
-                    for (annotation_id, line) in annotated_file.lines.into_iter().enumerate() {
+                    for (annotation_id, line) in annotated_file.lines.iter().enumerate() {
                         let mut annotations = line.annotations.clone();
                         annotations.sort_by_key(|a| Reverse(a.start_col));
                         let mut line_idx = buffer.num_lines();
-                        buffer.append(
-                            line_idx,
-                            &format!(
-                                "{}:{}:{}",
-                                sm.filename_for_diagnostics(&annotated_file.file.name),
-                                sm.doctest_offset_line(&annotated_file.file.name, line.line_index),
-                                annotations[0].start_col + 1,
-                            ),
-                            Style::LineAndColumn,
-                        );
-                        if annotation_id == 0 {
-                            buffer.prepend(line_idx, "--> ", Style::LineNumber);
+
+                        let labels: Vec<_> = annotations
+                            .iter()
+                            .filter_map(|a| Some((a.label.as_ref()?, a.is_primary)))
+                            .filter(|(l, _)| !l.is_empty())
+                            .collect();
+
+                        if annotation_id == 0 || !labels.is_empty() {
+                            buffer.append(
+                                line_idx,
+                                &format!(
+                                    "{}:{}:{}",
+                                    sm.filename_for_diagnostics(&annotated_file.file.name),
+                                    sm.doctest_offset_line(
+                                        &annotated_file.file.name,
+                                        line.line_index
+                                    ),
+                                    annotations[0].start_col + 1,
+                                ),
+                                Style::LineAndColumn,
+                            );
+                            if annotation_id == 0 {
+                                buffer.prepend(line_idx, "--> ", Style::LineNumber);
+                            } else {
+                                buffer.prepend(line_idx, "::: ", Style::LineNumber);
+                            }
                             for _ in 0..max_line_num_len {
                                 buffer.prepend(line_idx, " ", Style::NoStyle);
                             }
                             line_idx += 1;
-                        };
-                        for (i, annotation) in annotations.into_iter().enumerate() {
-                            if let Some(label) = &annotation.label {
-                                let style = if annotation.is_primary {
-                                    Style::LabelPrimary
-                                } else {
-                                    Style::LabelSecondary
-                                };
-                                if annotation_id == 0 {
-                                    buffer.prepend(line_idx, " |", Style::LineNumber);
-                                    for _ in 0..max_line_num_len {
-                                        buffer.prepend(line_idx, " ", Style::NoStyle);
-                                    }
-                                    line_idx += 1;
-                                    buffer.append(line_idx + i, " = note: ", style);
-                                    for _ in 0..max_line_num_len {
-                                        buffer.prepend(line_idx, " ", Style::NoStyle);
-                                    }
-                                } else {
-                                    buffer.append(line_idx + i, ": ", style);
-                                }
-                                buffer.append(line_idx + i, label, style);
+                        }
+                        for (label, is_primary) in labels.into_iter() {
+                            let style = if is_primary {
+                                Style::LabelPrimary
+                            } else {
+                                Style::LabelSecondary
+                            };
+                            buffer.prepend(line_idx, " |", Style::LineNumber);
+                            for _ in 0..max_line_num_len {
+                                buffer.prepend(line_idx, " ", Style::NoStyle);
+                            }
+                            line_idx += 1;
+                            buffer.append(line_idx, " = note: ", style);
+                            for _ in 0..max_line_num_len {
+                                buffer.prepend(line_idx, " ", Style::NoStyle);
                             }
+                            buffer.append(line_idx, label, style);
+                            line_idx += 1;
                         }
                     }
                 }
@@ -2304,7 +2313,7 @@ fn add_annotation_to_file(
         }
 
         // Find overlapping multiline annotations, put them at different depths
-        multiline_annotations.sort_by_key(|&(_, ref ml)| (ml.line_start, usize::MAX - ml.line_end));
+        multiline_annotations.sort_by_key(|(_, ml)| (ml.line_start, usize::MAX - ml.line_end));
         for (_, ann) in multiline_annotations.clone() {
             for (_, a) in multiline_annotations.iter_mut() {
                 // Move all other multiline annotations overlapping with this one
index eb0506c459afa732b0bf07918bf8adfde11659af..518b5ec10f8906122c4ab9fb26cc19e80231bf8a 100644 (file)
@@ -324,7 +324,7 @@ fn push_trailing(
                         // Account for the difference between the width of the current code and the
                         // snippet being suggested, so that the *later* suggestions are correctly
                         // aligned on the screen.
-                        acc += len as isize - (cur_hi.col.0 - cur_lo.col.0) as isize;
+                        acc += len - (cur_hi.col.0 - cur_lo.col.0) as isize;
                     }
                     prev_hi = cur_hi;
                     prev_line = sf.get_line(prev_hi.line - 1);
index 8bc022e1e178e19b50698104254dad839b950461..91825c29258ac10bd345aedbd19fcf35faa1da72 100644 (file)
@@ -548,12 +548,7 @@ pub const fn empty() -> &'hir Generics<'hir> {
     }
 
     pub fn get_named(&self, name: Symbol) -> Option<&GenericParam<'hir>> {
-        for param in self.params {
-            if name == param.name.ident().name {
-                return Some(param);
-            }
-        }
-        None
+        self.params.iter().find(|&param| name == param.name.ident().name)
     }
 
     pub fn spans(&self) -> MultiSpan {
index 66906b331da2ece663b3b06fb9883a144b5d474a..71f26eb60c9628e880f5f5b71ca4274e4fed5598 100644 (file)
@@ -680,7 +680,7 @@ fn instantiate_poly_trait_ref_inner(
         let assoc_bindings = self.create_assoc_bindings_for_generic_args(args);
 
         let poly_trait_ref =
-            ty::Binder::bind_with_vars(ty::TraitRef::new(trait_def_id, substs), bound_vars);
+            ty::Binder::bind_with_vars(tcx.mk_trait_ref(trait_def_id, substs), bound_vars);
 
         debug!(?poly_trait_ref, ?assoc_bindings);
         bounds.trait_bounds.push((poly_trait_ref, span, constness));
@@ -813,7 +813,7 @@ fn ast_path_to_mono_trait_ref(
         if let Some(b) = trait_segment.args().bindings.first() {
             Self::prohibit_assoc_ty_binding(self.tcx(), b.span);
         }
-        ty::TraitRef::new(trait_def_id, substs)
+        self.tcx().mk_trait_ref(trait_def_id, substs)
     }
 
     #[instrument(level = "debug", skip(self, span))]
@@ -1146,10 +1146,7 @@ fn add_predicates_for_ast_type_binding(
 
             debug!(?substs_trait_ref_and_assoc_item);
 
-            ty::ProjectionTy {
-                item_def_id: assoc_item.def_id,
-                substs: substs_trait_ref_and_assoc_item,
-            }
+            self.tcx().mk_alias_ty(assoc_item.def_id, substs_trait_ref_and_assoc_item)
         });
 
         if !speculative {
@@ -1195,7 +1192,7 @@ fn add_predicates_for_ast_type_binding(
                 // the "projection predicate" for:
                 //
                 // `<T as Iterator>::Item = u32`
-                let assoc_item_def_id = projection_ty.skip_binder().item_def_id;
+                let assoc_item_def_id = projection_ty.skip_binder().def_id;
                 let def_kind = tcx.def_kind(assoc_item_def_id);
                 match (def_kind, term.unpack()) {
                     (hir::def::DefKind::AssocTy, ty::TermKind::Ty(_))
@@ -1244,7 +1241,7 @@ fn add_predicates_for_ast_type_binding(
                 //
                 // Calling `skip_binder` is okay, because `add_bounds` expects the `param_ty`
                 // parameter to have a skipped binder.
-                let param_ty = tcx.mk_ty(ty::Projection(projection_ty.skip_binder()));
+                let param_ty = tcx.mk_ty(ty::Alias(ty::Projection, projection_ty.skip_binder()));
                 self.add_bounds(param_ty, ast_bounds.iter(), bounds, candidate.bound_vars());
             }
         }
index fc0ca62090d19c62b3a1656963ef85f026d1b793..aa01feb3a1ea4d686e5b84401d4100913088ae76 100644 (file)
@@ -570,7 +570,7 @@ fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
                             assoc_item,
                             assoc_item,
                             default.span,
-                            ty::TraitRef { def_id: it.owner_id.to_def_id(), substs: trait_substs },
+                            tcx.mk_trait_ref(it.owner_id.to_def_id(), trait_substs),
                         );
                     }
                     _ => {}
@@ -1440,7 +1440,7 @@ fn opaque_type_cycle_error(tcx: TyCtxt<'_>, def_id: LocalDefId, span: Span) -> E
                 impl<'tcx> ty::visit::TypeVisitor<'tcx> for OpaqueTypeCollector {
                     fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
                         match *t.kind() {
-                            ty::Opaque(def, _) => {
+                            ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => {
                                 self.0.push(def);
                                 ControlFlow::CONTINUE
                             }
index 1d6f9b29176518a30f487dca7eab58e0610b3ccf..6b9ce9a4599e2ce45ddd8e8479ec41f32d73d6b7 100644 (file)
@@ -67,6 +67,10 @@ pub(crate) fn compare_impl_method<'tcx>(
         return;
     }
 
+    if let Err(_) = compare_asyncness(tcx, impl_m, impl_m_span, trait_m, trait_item_span) {
+        return;
+    }
+
     if let Err(_) = compare_predicate_entailment(tcx, impl_m, impl_m_span, trait_m, impl_trait_ref)
     {
         return;
@@ -323,6 +327,34 @@ fn compare_predicate_entailment<'tcx>(
     Ok(())
 }
 
+fn compare_asyncness<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    impl_m: &ty::AssocItem,
+    impl_m_span: Span,
+    trait_m: &ty::AssocItem,
+    trait_item_span: Option<Span>,
+) -> Result<(), ErrorGuaranteed> {
+    if tcx.asyncness(trait_m.def_id) == hir::IsAsync::Async {
+        match tcx.fn_sig(impl_m.def_id).skip_binder().output().kind() {
+            ty::Alias(ty::Opaque, ..) => {
+                // allow both `async fn foo()` and `fn foo() -> impl Future`
+            }
+            ty::Error(rustc_errors::ErrorGuaranteed { .. }) => {
+                // We don't know if it's ok, but at least it's already an error.
+            }
+            _ => {
+                return Err(tcx.sess.emit_err(crate::errors::AsyncTraitImplShouldBeAsync {
+                    span: impl_m_span,
+                    method_name: trait_m.name,
+                    trait_item_span,
+                }));
+            }
+        };
+    }
+
+    Ok(())
+}
+
 #[instrument(skip(tcx), level = "debug", ret)]
 pub fn collect_trait_impl_trait_tys<'tcx>(
     tcx: TyCtxt<'tcx>,
@@ -571,10 +603,10 @@ fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
     }
 
     fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
-        if let ty::Projection(proj) = ty.kind()
-            && self.tcx().def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder
+        if let ty::Alias(ty::Projection, proj) = ty.kind()
+            && self.tcx().def_kind(proj.def_id) == DefKind::ImplTraitPlaceholder
         {
-            if let Some((ty, _)) = self.types.get(&proj.item_def_id) {
+            if let Some((ty, _)) = self.types.get(&proj.def_id) {
                 return *ty;
             }
             //FIXME(RPITIT): Deny nested RPITIT in substs too
@@ -586,9 +618,9 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                 span: self.span,
                 kind: TypeVariableOriginKind::MiscVariable,
             });
-            self.types.insert(proj.item_def_id, (infer_ty, proj.substs));
+            self.types.insert(proj.def_id, (infer_ty, proj.substs));
             // Recurse into bounds
-            for (pred, pred_span) in self.tcx().bound_explicit_item_bounds(proj.item_def_id).subst_iter_copied(self.tcx(), proj.substs) {
+            for (pred, pred_span) in self.tcx().bound_explicit_item_bounds(proj.def_id).subst_iter_copied(self.tcx(), proj.substs) {
                 let pred = pred.fold_with(self);
                 let pred = self.ocx.normalize(
                     &ObligationCause::misc(self.span, self.body_id),
@@ -601,7 +633,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                     ObligationCause::new(
                         self.span,
                         self.body_id,
-                        ObligationCauseCode::BindingObligation(proj.item_def_id, pred_span),
+                        ObligationCauseCode::BindingObligation(proj.def_id, pred_span),
                     ),
                     self.param_env,
                     pred,
@@ -1734,8 +1766,8 @@ pub fn check_type_bounds<'tcx>(
     let normalize_param_env = {
         let mut predicates = param_env.caller_bounds().iter().collect::<Vec<_>>();
         match impl_ty_value.kind() {
-            ty::Projection(proj)
-                if proj.item_def_id == trait_ty.def_id && proj.substs == rebased_substs =>
+            ty::Alias(ty::Projection, proj)
+                if proj.def_id == trait_ty.def_id && proj.substs == rebased_substs =>
             {
                 // Don't include this predicate if the projected type is
                 // exactly the same as the projection. This can occur in
@@ -1746,10 +1778,7 @@ pub fn check_type_bounds<'tcx>(
             _ => predicates.push(
                 ty::Binder::bind_with_vars(
                     ty::ProjectionPredicate {
-                        projection_ty: ty::ProjectionTy {
-                            item_def_id: trait_ty.def_id,
-                            substs: rebased_substs,
-                        },
+                        projection_ty: tcx.mk_alias_ty(trait_ty.def_id, rebased_substs),
                         term: impl_ty_value.into(),
                     },
                     bound_vars,
index 29255472a2516dd0917642ff3e83886320db7fd7..57f0cae12bb312bb5afd14d971fed8bac0ad31a1 100644 (file)
@@ -352,11 +352,7 @@ fn bounds_from_generic_predicates<'tcx>(
         // insert the associated types where they correspond, but for now let's be "lazy" and
         // propose this instead of the following valid resugaring:
         // `T: Trait, Trait::Assoc = K` → `T: Trait<Assoc = K>`
-        where_clauses.push(format!(
-            "{} = {}",
-            tcx.def_path_str(p.projection_ty.item_def_id),
-            p.term,
-        ));
+        where_clauses.push(format!("{} = {}", tcx.def_path_str(p.projection_ty.def_id), p.term));
     }
     let where_clauses = if where_clauses.is_empty() {
         String::new()
index 69eb96fe8e9251871a8031c05f8278c5e2965dd3..94d333c336ef3f2768267d1ea3ce72147dd57e25 100644 (file)
@@ -759,7 +759,7 @@ impl<'tcx> TypeVisitor<'tcx> for GATSubstCollector<'tcx> {
 
     fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
         match t.kind() {
-            ty::Projection(p) if p.item_def_id == self.gat => {
+            ty::Alias(ty::Projection, p) if p.def_id == self.gat => {
                 for (idx, subst) in p.substs.iter().enumerate() {
                     match subst.unpack() {
                         GenericArgKind::Lifetime(lt) if !lt.is_late_bound() => {
@@ -1592,12 +1592,12 @@ fn check_return_position_impl_trait_in_trait_bounds<'tcx>(
     {
         for arg in fn_output.walk() {
             if let ty::GenericArgKind::Type(ty) = arg.unpack()
-                && let ty::Projection(proj) = ty.kind()
-                && tcx.def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder
-                && tcx.impl_trait_in_trait_parent(proj.item_def_id) == fn_def_id.to_def_id()
+                && let ty::Alias(ty::Projection, proj) = ty.kind()
+                && tcx.def_kind(proj.def_id) == DefKind::ImplTraitPlaceholder
+                && tcx.impl_trait_in_trait_parent(proj.def_id) == fn_def_id.to_def_id()
             {
-                let span = tcx.def_span(proj.item_def_id);
-                let bounds = wfcx.tcx().explicit_item_bounds(proj.item_def_id);
+                let span = tcx.def_span(proj.def_id);
+                let bounds = wfcx.tcx().explicit_item_bounds(proj.def_id);
                 let wf_obligations = bounds.iter().flat_map(|&(bound, bound_span)| {
                     let bound = ty::EarlyBinder(bound).subst(tcx, proj.substs);
                     let normalized_bound = wfcx.normalize(span, None, bound);
index 2890c149b3afe3f2ac1eba2ecc37a438e9824e75..6469f389bf91b313141ce01452fe74cb68b72f98 100644 (file)
@@ -223,7 +223,7 @@ fn check_item(&mut self, id: hir::ItemId) {
             | ty::Tuple(..) => {
                 self.check_primitive_impl(item.owner_id.def_id, self_ty, items, ty.span)
             }
-            ty::Projection(..) | ty::Opaque(..) | ty::Param(_) => {
+            ty::Alias(..) | ty::Param(_) => {
                 let mut err = struct_span_err!(
                     self.tcx.sess,
                     ty.span,
index 72288e5bc761f0e4ba9566e1f02c4d44d57f5420..1eeaaf55e63af0f43a8e84884140294fe0e3f846 100644 (file)
 use crate::astconv::AstConv;
 use crate::check::intrinsic::intrinsic_operation_unsafety;
 use crate::errors;
-use rustc_ast as ast;
-use rustc_ast::{MetaItemKind, NestedMetaItem};
-use rustc_attr::{list_contains_name, InlineAttr, InstructionSetAttr, OptimizeAttr};
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, StashKey};
 use rustc_hir as hir;
-use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
+use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::{self, Visitor};
-use rustc_hir::weak_lang_items::WEAK_LANG_ITEMS;
-use rustc_hir::{lang_items, GenericParamKind, LangItem, Node};
+use rustc_hir::{GenericParamKind, Node};
 use rustc_middle::hir::nested_filter;
-use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
-use rustc_middle::mir::mono::Linkage;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::util::{Discr, IntTypeExt};
-use rustc_middle::ty::{self, AdtKind, Const, DefIdTree, IsSuggestable, ToPredicate, Ty, TyCtxt};
-use rustc_session::lint;
-use rustc_session::parse::feature_err;
+use rustc_middle::ty::{self, AdtKind, Const, IsSuggestable, ToPredicate, Ty, TyCtxt};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::Span;
-use rustc_target::spec::{abi, SanitizerSet};
+use rustc_target::spec::abi;
 use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName;
 use std::iter;
 
@@ -78,10 +70,7 @@ pub fn provide(providers: &mut Providers) {
         impl_polarity,
         is_foreign_item,
         generator_kind,
-        codegen_fn_attrs,
-        asm_target_features,
         collect_mod_item_types,
-        should_inherit_track_caller,
         ..*providers
     };
 }
@@ -1455,797 +1444,3 @@ fn generator_kind(tcx: TyCtxt<'_>, def_id: DefId) -> Option<hir::GeneratorKind>
         _ => bug!("generator_kind applied to non-local def-id {:?}", def_id),
     }
 }
-
-fn from_target_feature(
-    tcx: TyCtxt<'_>,
-    attr: &ast::Attribute,
-    supported_target_features: &FxHashMap<String, Option<Symbol>>,
-    target_features: &mut Vec<Symbol>,
-) {
-    let Some(list) = attr.meta_item_list() else { return };
-    let bad_item = |span| {
-        let msg = "malformed `target_feature` attribute input";
-        let code = "enable = \"..\"";
-        tcx.sess
-            .struct_span_err(span, msg)
-            .span_suggestion(span, "must be of the form", code, Applicability::HasPlaceholders)
-            .emit();
-    };
-    let rust_features = tcx.features();
-    for item in list {
-        // Only `enable = ...` is accepted in the meta-item list.
-        if !item.has_name(sym::enable) {
-            bad_item(item.span());
-            continue;
-        }
-
-        // Must be of the form `enable = "..."` (a string).
-        let Some(value) = item.value_str() else {
-            bad_item(item.span());
-            continue;
-        };
-
-        // We allow comma separation to enable multiple features.
-        target_features.extend(value.as_str().split(',').filter_map(|feature| {
-            let Some(feature_gate) = supported_target_features.get(feature) else {
-                let msg =
-                    format!("the feature named `{}` is not valid for this target", feature);
-                let mut err = tcx.sess.struct_span_err(item.span(), &msg);
-                err.span_label(
-                    item.span(),
-                    format!("`{}` is not valid for this target", feature),
-                );
-                if let Some(stripped) = feature.strip_prefix('+') {
-                    let valid = supported_target_features.contains_key(stripped);
-                    if valid {
-                        err.help("consider removing the leading `+` in the feature name");
-                    }
-                }
-                err.emit();
-                return None;
-            };
-
-            // Only allow features whose feature gates have been enabled.
-            let allowed = match feature_gate.as_ref().copied() {
-                Some(sym::arm_target_feature) => rust_features.arm_target_feature,
-                Some(sym::hexagon_target_feature) => rust_features.hexagon_target_feature,
-                Some(sym::powerpc_target_feature) => rust_features.powerpc_target_feature,
-                Some(sym::mips_target_feature) => rust_features.mips_target_feature,
-                Some(sym::riscv_target_feature) => rust_features.riscv_target_feature,
-                Some(sym::avx512_target_feature) => rust_features.avx512_target_feature,
-                Some(sym::sse4a_target_feature) => rust_features.sse4a_target_feature,
-                Some(sym::tbm_target_feature) => rust_features.tbm_target_feature,
-                Some(sym::wasm_target_feature) => rust_features.wasm_target_feature,
-                Some(sym::cmpxchg16b_target_feature) => rust_features.cmpxchg16b_target_feature,
-                Some(sym::movbe_target_feature) => rust_features.movbe_target_feature,
-                Some(sym::rtm_target_feature) => rust_features.rtm_target_feature,
-                Some(sym::f16c_target_feature) => rust_features.f16c_target_feature,
-                Some(sym::ermsb_target_feature) => rust_features.ermsb_target_feature,
-                Some(sym::bpf_target_feature) => rust_features.bpf_target_feature,
-                Some(sym::aarch64_ver_target_feature) => rust_features.aarch64_ver_target_feature,
-                Some(name) => bug!("unknown target feature gate {}", name),
-                None => true,
-            };
-            if !allowed {
-                feature_err(
-                    &tcx.sess.parse_sess,
-                    feature_gate.unwrap(),
-                    item.span(),
-                    &format!("the target feature `{}` is currently unstable", feature),
-                )
-                .emit();
-            }
-            Some(Symbol::intern(feature))
-        }));
-    }
-}
-
-fn linkage_by_name(tcx: TyCtxt<'_>, def_id: LocalDefId, name: &str) -> Linkage {
-    use rustc_middle::mir::mono::Linkage::*;
-
-    // Use the names from src/llvm/docs/LangRef.rst here. Most types are only
-    // applicable to variable declarations and may not really make sense for
-    // Rust code in the first place but allow them anyway and trust that the
-    // user knows what they're doing. Who knows, unanticipated use cases may pop
-    // up in the future.
-    //
-    // ghost, dllimport, dllexport and linkonce_odr_autohide are not supported
-    // and don't have to be, LLVM treats them as no-ops.
-    match name {
-        "appending" => Appending,
-        "available_externally" => AvailableExternally,
-        "common" => Common,
-        "extern_weak" => ExternalWeak,
-        "external" => External,
-        "internal" => Internal,
-        "linkonce" => LinkOnceAny,
-        "linkonce_odr" => LinkOnceODR,
-        "private" => Private,
-        "weak" => WeakAny,
-        "weak_odr" => WeakODR,
-        _ => tcx.sess.span_fatal(tcx.def_span(def_id), "invalid linkage specified"),
-    }
-}
-
-fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
-    if cfg!(debug_assertions) {
-        let def_kind = tcx.def_kind(did);
-        assert!(
-            def_kind.has_codegen_attrs(),
-            "unexpected `def_kind` in `codegen_fn_attrs`: {def_kind:?}",
-        );
-    }
-
-    let did = did.expect_local();
-    let attrs = tcx.hir().attrs(tcx.hir().local_def_id_to_hir_id(did));
-    let mut codegen_fn_attrs = CodegenFnAttrs::new();
-    if tcx.should_inherit_track_caller(did) {
-        codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER;
-    }
-
-    let supported_target_features = tcx.supported_target_features(LOCAL_CRATE);
-
-    let mut inline_span = None;
-    let mut link_ordinal_span = None;
-    let mut no_sanitize_span = None;
-    for attr in attrs.iter() {
-        if attr.has_name(sym::cold) {
-            codegen_fn_attrs.flags |= CodegenFnAttrFlags::COLD;
-        } else if attr.has_name(sym::rustc_allocator) {
-            codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR;
-        } else if attr.has_name(sym::ffi_returns_twice) {
-            if tcx.is_foreign_item(did) {
-                codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_RETURNS_TWICE;
-            } else {
-                // `#[ffi_returns_twice]` is only allowed `extern fn`s.
-                struct_span_err!(
-                    tcx.sess,
-                    attr.span,
-                    E0724,
-                    "`#[ffi_returns_twice]` may only be used on foreign functions"
-                )
-                .emit();
-            }
-        } else if attr.has_name(sym::ffi_pure) {
-            if tcx.is_foreign_item(did) {
-                if attrs.iter().any(|a| a.has_name(sym::ffi_const)) {
-                    // `#[ffi_const]` functions cannot be `#[ffi_pure]`
-                    struct_span_err!(
-                        tcx.sess,
-                        attr.span,
-                        E0757,
-                        "`#[ffi_const]` function cannot be `#[ffi_pure]`"
-                    )
-                    .emit();
-                } else {
-                    codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_PURE;
-                }
-            } else {
-                // `#[ffi_pure]` is only allowed on foreign functions
-                struct_span_err!(
-                    tcx.sess,
-                    attr.span,
-                    E0755,
-                    "`#[ffi_pure]` may only be used on foreign functions"
-                )
-                .emit();
-            }
-        } else if attr.has_name(sym::ffi_const) {
-            if tcx.is_foreign_item(did) {
-                codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_CONST;
-            } else {
-                // `#[ffi_const]` is only allowed on foreign functions
-                struct_span_err!(
-                    tcx.sess,
-                    attr.span,
-                    E0756,
-                    "`#[ffi_const]` may only be used on foreign functions"
-                )
-                .emit();
-            }
-        } else if attr.has_name(sym::rustc_nounwind) {
-            codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND;
-        } else if attr.has_name(sym::rustc_reallocator) {
-            codegen_fn_attrs.flags |= CodegenFnAttrFlags::REALLOCATOR;
-        } else if attr.has_name(sym::rustc_deallocator) {
-            codegen_fn_attrs.flags |= CodegenFnAttrFlags::DEALLOCATOR;
-        } else if attr.has_name(sym::rustc_allocator_zeroed) {
-            codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR_ZEROED;
-        } else if attr.has_name(sym::naked) {
-            codegen_fn_attrs.flags |= CodegenFnAttrFlags::NAKED;
-        } else if attr.has_name(sym::no_mangle) {
-            codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE;
-        } else if attr.has_name(sym::no_coverage) {
-            codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_COVERAGE;
-        } else if attr.has_name(sym::rustc_std_internal_symbol) {
-            codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL;
-        } else if attr.has_name(sym::used) {
-            let inner = attr.meta_item_list();
-            match inner.as_deref() {
-                Some([item]) if item.has_name(sym::linker) => {
-                    if !tcx.features().used_with_arg {
-                        feature_err(
-                            &tcx.sess.parse_sess,
-                            sym::used_with_arg,
-                            attr.span,
-                            "`#[used(linker)]` is currently unstable",
-                        )
-                        .emit();
-                    }
-                    codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED_LINKER;
-                }
-                Some([item]) if item.has_name(sym::compiler) => {
-                    if !tcx.features().used_with_arg {
-                        feature_err(
-                            &tcx.sess.parse_sess,
-                            sym::used_with_arg,
-                            attr.span,
-                            "`#[used(compiler)]` is currently unstable",
-                        )
-                        .emit();
-                    }
-                    codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED;
-                }
-                Some(_) => {
-                    tcx.sess.emit_err(errors::ExpectedUsedSymbol { span: attr.span });
-                }
-                None => {
-                    // Unfortunately, unconditionally using `llvm.used` causes
-                    // issues in handling `.init_array` with the gold linker,
-                    // but using `llvm.compiler.used` caused a nontrival amount
-                    // of unintentional ecosystem breakage -- particularly on
-                    // Mach-O targets.
-                    //
-                    // As a result, we emit `llvm.compiler.used` only on ELF
-                    // targets. This is somewhat ad-hoc, but actually follows
-                    // our pre-LLVM 13 behavior (prior to the ecosystem
-                    // breakage), and seems to match `clang`'s behavior as well
-                    // (both before and after LLVM 13), possibly because they
-                    // have similar compatibility concerns to us. See
-                    // https://github.com/rust-lang/rust/issues/47384#issuecomment-1019080146
-                    // and following comments for some discussion of this, as
-                    // well as the comments in `rustc_codegen_llvm` where these
-                    // flags are handled.
-                    //
-                    // Anyway, to be clear: this is still up in the air
-                    // somewhat, and is subject to change in the future (which
-                    // is a good thing, because this would ideally be a bit
-                    // more firmed up).
-                    let is_like_elf = !(tcx.sess.target.is_like_osx
-                        || tcx.sess.target.is_like_windows
-                        || tcx.sess.target.is_like_wasm);
-                    codegen_fn_attrs.flags |= if is_like_elf {
-                        CodegenFnAttrFlags::USED
-                    } else {
-                        CodegenFnAttrFlags::USED_LINKER
-                    };
-                }
-            }
-        } else if attr.has_name(sym::cmse_nonsecure_entry) {
-            if !matches!(tcx.fn_sig(did).abi(), abi::Abi::C { .. }) {
-                struct_span_err!(
-                    tcx.sess,
-                    attr.span,
-                    E0776,
-                    "`#[cmse_nonsecure_entry]` requires C ABI"
-                )
-                .emit();
-            }
-            if !tcx.sess.target.llvm_target.contains("thumbv8m") {
-                struct_span_err!(tcx.sess, attr.span, E0775, "`#[cmse_nonsecure_entry]` is only valid for targets with the TrustZone-M extension")
-                    .emit();
-            }
-            codegen_fn_attrs.flags |= CodegenFnAttrFlags::CMSE_NONSECURE_ENTRY;
-        } else if attr.has_name(sym::thread_local) {
-            codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL;
-        } else if attr.has_name(sym::track_caller) {
-            if !tcx.is_closure(did.to_def_id()) && tcx.fn_sig(did).abi() != abi::Abi::Rust {
-                struct_span_err!(tcx.sess, attr.span, E0737, "`#[track_caller]` requires Rust ABI")
-                    .emit();
-            }
-            if tcx.is_closure(did.to_def_id()) && !tcx.features().closure_track_caller {
-                feature_err(
-                    &tcx.sess.parse_sess,
-                    sym::closure_track_caller,
-                    attr.span,
-                    "`#[track_caller]` on closures is currently unstable",
-                )
-                .emit();
-            }
-            codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER;
-        } else if attr.has_name(sym::export_name) {
-            if let Some(s) = attr.value_str() {
-                if s.as_str().contains('\0') {
-                    // `#[export_name = ...]` will be converted to a null-terminated string,
-                    // so it may not contain any null characters.
-                    struct_span_err!(
-                        tcx.sess,
-                        attr.span,
-                        E0648,
-                        "`export_name` may not contain null characters"
-                    )
-                    .emit();
-                }
-                codegen_fn_attrs.export_name = Some(s);
-            }
-        } else if attr.has_name(sym::target_feature) {
-            if !tcx.is_closure(did.to_def_id())
-                && tcx.fn_sig(did).unsafety() == hir::Unsafety::Normal
-            {
-                if tcx.sess.target.is_like_wasm || tcx.sess.opts.actually_rustdoc {
-                    // The `#[target_feature]` attribute is allowed on
-                    // WebAssembly targets on all functions, including safe
-                    // ones. Other targets require that `#[target_feature]` is
-                    // only applied to unsafe functions (pending the
-                    // `target_feature_11` feature) because on most targets
-                    // execution of instructions that are not supported is
-                    // considered undefined behavior. For WebAssembly which is a
-                    // 100% safe target at execution time it's not possible to
-                    // execute undefined instructions, and even if a future
-                    // feature was added in some form for this it would be a
-                    // deterministic trap. There is no undefined behavior when
-                    // executing WebAssembly so `#[target_feature]` is allowed
-                    // on safe functions (but again, only for WebAssembly)
-                    //
-                    // Note that this is also allowed if `actually_rustdoc` so
-                    // if a target is documenting some wasm-specific code then
-                    // it's not spuriously denied.
-                } else if !tcx.features().target_feature_11 {
-                    let mut err = feature_err(
-                        &tcx.sess.parse_sess,
-                        sym::target_feature_11,
-                        attr.span,
-                        "`#[target_feature(..)]` can only be applied to `unsafe` functions",
-                    );
-                    err.span_label(tcx.def_span(did), "not an `unsafe` function");
-                    err.emit();
-                } else {
-                    check_target_feature_trait_unsafe(tcx, did, attr.span);
-                }
-            }
-            from_target_feature(
-                tcx,
-                attr,
-                supported_target_features,
-                &mut codegen_fn_attrs.target_features,
-            );
-        } else if attr.has_name(sym::linkage) {
-            if let Some(val) = attr.value_str() {
-                let linkage = Some(linkage_by_name(tcx, did, val.as_str()));
-                if tcx.is_foreign_item(did) {
-                    codegen_fn_attrs.import_linkage = linkage;
-                } else {
-                    codegen_fn_attrs.linkage = linkage;
-                }
-            }
-        } else if attr.has_name(sym::link_section) {
-            if let Some(val) = attr.value_str() {
-                if val.as_str().bytes().any(|b| b == 0) {
-                    let msg = format!(
-                        "illegal null byte in link_section \
-                         value: `{}`",
-                        &val
-                    );
-                    tcx.sess.span_err(attr.span, &msg);
-                } else {
-                    codegen_fn_attrs.link_section = Some(val);
-                }
-            }
-        } else if attr.has_name(sym::link_name) {
-            codegen_fn_attrs.link_name = attr.value_str();
-        } else if attr.has_name(sym::link_ordinal) {
-            link_ordinal_span = Some(attr.span);
-            if let ordinal @ Some(_) = check_link_ordinal(tcx, attr) {
-                codegen_fn_attrs.link_ordinal = ordinal;
-            }
-        } else if attr.has_name(sym::no_sanitize) {
-            no_sanitize_span = Some(attr.span);
-            if let Some(list) = attr.meta_item_list() {
-                for item in list.iter() {
-                    if item.has_name(sym::address) {
-                        codegen_fn_attrs.no_sanitize |= SanitizerSet::ADDRESS;
-                    } else if item.has_name(sym::cfi) {
-                        codegen_fn_attrs.no_sanitize |= SanitizerSet::CFI;
-                    } else if item.has_name(sym::kcfi) {
-                        codegen_fn_attrs.no_sanitize |= SanitizerSet::KCFI;
-                    } else if item.has_name(sym::memory) {
-                        codegen_fn_attrs.no_sanitize |= SanitizerSet::MEMORY;
-                    } else if item.has_name(sym::memtag) {
-                        codegen_fn_attrs.no_sanitize |= SanitizerSet::MEMTAG;
-                    } else if item.has_name(sym::shadow_call_stack) {
-                        codegen_fn_attrs.no_sanitize |= SanitizerSet::SHADOWCALLSTACK;
-                    } else if item.has_name(sym::thread) {
-                        codegen_fn_attrs.no_sanitize |= SanitizerSet::THREAD;
-                    } else if item.has_name(sym::hwaddress) {
-                        codegen_fn_attrs.no_sanitize |= SanitizerSet::HWADDRESS;
-                    } else {
-                        tcx.sess
-                            .struct_span_err(item.span(), "invalid argument for `no_sanitize`")
-                            .note("expected one of: `address`, `cfi`, `hwaddress`, `kcfi`, `memory`, `memtag`, `shadow-call-stack`, or `thread`")
-                            .emit();
-                    }
-                }
-            }
-        } else if attr.has_name(sym::instruction_set) {
-            codegen_fn_attrs.instruction_set = match attr.meta_kind() {
-                Some(MetaItemKind::List(ref items)) => match items.as_slice() {
-                    [NestedMetaItem::MetaItem(set)] => {
-                        let segments =
-                            set.path.segments.iter().map(|x| x.ident.name).collect::<Vec<_>>();
-                        match segments.as_slice() {
-                            [sym::arm, sym::a32] | [sym::arm, sym::t32] => {
-                                if !tcx.sess.target.has_thumb_interworking {
-                                    struct_span_err!(
-                                        tcx.sess.diagnostic(),
-                                        attr.span,
-                                        E0779,
-                                        "target does not support `#[instruction_set]`"
-                                    )
-                                    .emit();
-                                    None
-                                } else if segments[1] == sym::a32 {
-                                    Some(InstructionSetAttr::ArmA32)
-                                } else if segments[1] == sym::t32 {
-                                    Some(InstructionSetAttr::ArmT32)
-                                } else {
-                                    unreachable!()
-                                }
-                            }
-                            _ => {
-                                struct_span_err!(
-                                    tcx.sess.diagnostic(),
-                                    attr.span,
-                                    E0779,
-                                    "invalid instruction set specified",
-                                )
-                                .emit();
-                                None
-                            }
-                        }
-                    }
-                    [] => {
-                        struct_span_err!(
-                            tcx.sess.diagnostic(),
-                            attr.span,
-                            E0778,
-                            "`#[instruction_set]` requires an argument"
-                        )
-                        .emit();
-                        None
-                    }
-                    _ => {
-                        struct_span_err!(
-                            tcx.sess.diagnostic(),
-                            attr.span,
-                            E0779,
-                            "cannot specify more than one instruction set"
-                        )
-                        .emit();
-                        None
-                    }
-                },
-                _ => {
-                    struct_span_err!(
-                        tcx.sess.diagnostic(),
-                        attr.span,
-                        E0778,
-                        "must specify an instruction set"
-                    )
-                    .emit();
-                    None
-                }
-            };
-        } else if attr.has_name(sym::repr) {
-            codegen_fn_attrs.alignment = match attr.meta_item_list() {
-                Some(items) => match items.as_slice() {
-                    [item] => match item.name_value_literal() {
-                        Some((sym::align, literal)) => {
-                            let alignment = rustc_attr::parse_alignment(&literal.kind);
-
-                            match alignment {
-                                Ok(align) => Some(align),
-                                Err(msg) => {
-                                    struct_span_err!(
-                                        tcx.sess.diagnostic(),
-                                        attr.span,
-                                        E0589,
-                                        "invalid `repr(align)` attribute: {}",
-                                        msg
-                                    )
-                                    .emit();
-
-                                    None
-                                }
-                            }
-                        }
-                        _ => None,
-                    },
-                    [] => None,
-                    _ => None,
-                },
-                None => None,
-            };
-        }
-    }
-
-    codegen_fn_attrs.inline = attrs.iter().fold(InlineAttr::None, |ia, attr| {
-        if !attr.has_name(sym::inline) {
-            return ia;
-        }
-        match attr.meta_kind() {
-            Some(MetaItemKind::Word) => InlineAttr::Hint,
-            Some(MetaItemKind::List(ref items)) => {
-                inline_span = Some(attr.span);
-                if items.len() != 1 {
-                    struct_span_err!(
-                        tcx.sess.diagnostic(),
-                        attr.span,
-                        E0534,
-                        "expected one argument"
-                    )
-                    .emit();
-                    InlineAttr::None
-                } else if list_contains_name(&items, sym::always) {
-                    InlineAttr::Always
-                } else if list_contains_name(&items, sym::never) {
-                    InlineAttr::Never
-                } else {
-                    struct_span_err!(
-                        tcx.sess.diagnostic(),
-                        items[0].span(),
-                        E0535,
-                        "invalid argument"
-                    )
-                    .help("valid inline arguments are `always` and `never`")
-                    .emit();
-
-                    InlineAttr::None
-                }
-            }
-            Some(MetaItemKind::NameValue(_)) => ia,
-            None => ia,
-        }
-    });
-
-    codegen_fn_attrs.optimize = attrs.iter().fold(OptimizeAttr::None, |ia, attr| {
-        if !attr.has_name(sym::optimize) {
-            return ia;
-        }
-        let err = |sp, s| struct_span_err!(tcx.sess.diagnostic(), sp, E0722, "{}", s).emit();
-        match attr.meta_kind() {
-            Some(MetaItemKind::Word) => {
-                err(attr.span, "expected one argument");
-                ia
-            }
-            Some(MetaItemKind::List(ref items)) => {
-                inline_span = Some(attr.span);
-                if items.len() != 1 {
-                    err(attr.span, "expected one argument");
-                    OptimizeAttr::None
-                } else if list_contains_name(&items, sym::size) {
-                    OptimizeAttr::Size
-                } else if list_contains_name(&items, sym::speed) {
-                    OptimizeAttr::Speed
-                } else {
-                    err(items[0].span(), "invalid argument");
-                    OptimizeAttr::None
-                }
-            }
-            Some(MetaItemKind::NameValue(_)) => ia,
-            None => ia,
-        }
-    });
-
-    // #73631: closures inherit `#[target_feature]` annotations
-    if tcx.features().target_feature_11 && tcx.is_closure(did.to_def_id()) {
-        let owner_id = tcx.parent(did.to_def_id());
-        if tcx.def_kind(owner_id).has_codegen_attrs() {
-            codegen_fn_attrs
-                .target_features
-                .extend(tcx.codegen_fn_attrs(owner_id).target_features.iter().copied());
-        }
-    }
-
-    // If a function uses #[target_feature] it can't be inlined into general
-    // purpose functions as they wouldn't have the right target features
-    // enabled. For that reason we also forbid #[inline(always)] as it can't be
-    // respected.
-    if !codegen_fn_attrs.target_features.is_empty() {
-        if codegen_fn_attrs.inline == InlineAttr::Always {
-            if let Some(span) = inline_span {
-                tcx.sess.span_err(
-                    span,
-                    "cannot use `#[inline(always)]` with \
-                     `#[target_feature]`",
-                );
-            }
-        }
-    }
-
-    if !codegen_fn_attrs.no_sanitize.is_empty() {
-        if codegen_fn_attrs.inline == InlineAttr::Always {
-            if let (Some(no_sanitize_span), Some(inline_span)) = (no_sanitize_span, inline_span) {
-                let hir_id = tcx.hir().local_def_id_to_hir_id(did);
-                tcx.struct_span_lint_hir(
-                    lint::builtin::INLINE_NO_SANITIZE,
-                    hir_id,
-                    no_sanitize_span,
-                    "`no_sanitize` will have no effect after inlining",
-                    |lint| lint.span_note(inline_span, "inlining requested here"),
-                )
-            }
-        }
-    }
-
-    if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED) {
-        codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_COVERAGE;
-        codegen_fn_attrs.inline = InlineAttr::Never;
-    }
-
-    // Weak lang items have the same semantics as "std internal" symbols in the
-    // sense that they're preserved through all our LTO passes and only
-    // strippable by the linker.
-    //
-    // Additionally weak lang items have predetermined symbol names.
-    if WEAK_LANG_ITEMS.iter().any(|&l| tcx.lang_items().get(l) == Some(did.to_def_id())) {
-        codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL;
-    }
-    if let Some((name, _)) = lang_items::extract(attrs)
-        && let Some(lang_item) = LangItem::from_name(name)
-        && let Some(link_name) = lang_item.link_name()
-    {
-        codegen_fn_attrs.export_name = Some(link_name);
-        codegen_fn_attrs.link_name = Some(link_name);
-    }
-    check_link_name_xor_ordinal(tcx, &codegen_fn_attrs, link_ordinal_span);
-
-    // Internal symbols to the standard library all have no_mangle semantics in
-    // that they have defined symbol names present in the function name. This
-    // also applies to weak symbols where they all have known symbol names.
-    if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) {
-        codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE;
-    }
-
-    // Any linkage to LLVM intrinsics for now forcibly marks them all as never
-    // unwinds since LLVM sometimes can't handle codegen which `invoke`s
-    // intrinsic functions.
-    if let Some(name) = &codegen_fn_attrs.link_name {
-        if name.as_str().starts_with("llvm.") {
-            codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND;
-        }
-    }
-
-    codegen_fn_attrs
-}
-
-/// Computes the set of target features used in a function for the purposes of
-/// inline assembly.
-fn asm_target_features<'tcx>(tcx: TyCtxt<'tcx>, did: DefId) -> &'tcx FxHashSet<Symbol> {
-    let mut target_features = tcx.sess.unstable_target_features.clone();
-    if tcx.def_kind(did).has_codegen_attrs() {
-        let attrs = tcx.codegen_fn_attrs(did);
-        target_features.extend(&attrs.target_features);
-        match attrs.instruction_set {
-            None => {}
-            Some(InstructionSetAttr::ArmA32) => {
-                target_features.remove(&sym::thumb_mode);
-            }
-            Some(InstructionSetAttr::ArmT32) => {
-                target_features.insert(sym::thumb_mode);
-            }
-        }
-    }
-
-    tcx.arena.alloc(target_features)
-}
-
-/// Checks if the provided DefId is a method in a trait impl for a trait which has track_caller
-/// applied to the method prototype.
-fn should_inherit_track_caller(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
-    if let Some(impl_item) = tcx.opt_associated_item(def_id)
-        && let ty::AssocItemContainer::ImplContainer = impl_item.container
-        && let Some(trait_item) = impl_item.trait_item_def_id
-    {
-        return tcx
-            .codegen_fn_attrs(trait_item)
-            .flags
-            .intersects(CodegenFnAttrFlags::TRACK_CALLER);
-    }
-
-    false
-}
-
-fn check_link_ordinal(tcx: TyCtxt<'_>, attr: &ast::Attribute) -> Option<u16> {
-    use rustc_ast::{LitIntType, LitKind, MetaItemLit};
-    if !tcx.features().raw_dylib && tcx.sess.target.arch == "x86" {
-        feature_err(
-            &tcx.sess.parse_sess,
-            sym::raw_dylib,
-            attr.span,
-            "`#[link_ordinal]` is unstable on x86",
-        )
-        .emit();
-    }
-    let meta_item_list = attr.meta_item_list();
-    let meta_item_list = meta_item_list.as_deref();
-    let sole_meta_list = match meta_item_list {
-        Some([item]) => item.lit(),
-        Some(_) => {
-            tcx.sess
-                .struct_span_err(attr.span, "incorrect number of arguments to `#[link_ordinal]`")
-                .note("the attribute requires exactly one argument")
-                .emit();
-            return None;
-        }
-        _ => None,
-    };
-    if let Some(MetaItemLit { kind: LitKind::Int(ordinal, LitIntType::Unsuffixed), .. }) =
-        sole_meta_list
-    {
-        // According to the table at https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#import-header,
-        // the ordinal must fit into 16 bits.  Similarly, the Ordinal field in COFFShortExport (defined
-        // in llvm/include/llvm/Object/COFFImportFile.h), which we use to communicate import information
-        // to LLVM for `#[link(kind = "raw-dylib"_])`, is also defined to be uint16_t.
-        //
-        // FIXME: should we allow an ordinal of 0?  The MSVC toolchain has inconsistent support for this:
-        // both LINK.EXE and LIB.EXE signal errors and abort when given a .DEF file that specifies
-        // a zero ordinal.  However, llvm-dlltool is perfectly happy to generate an import library
-        // for such a .DEF file, and MSVC's LINK.EXE is also perfectly happy to consume an import
-        // library produced by LLVM with an ordinal of 0, and it generates an .EXE.  (I don't know yet
-        // if the resulting EXE runs, as I haven't yet built the necessary DLL -- see earlier comment
-        // about LINK.EXE failing.)
-        if *ordinal <= u16::MAX as u128 {
-            Some(*ordinal as u16)
-        } else {
-            let msg = format!("ordinal value in `link_ordinal` is too large: `{}`", &ordinal);
-            tcx.sess
-                .struct_span_err(attr.span, &msg)
-                .note("the value may not exceed `u16::MAX`")
-                .emit();
-            None
-        }
-    } else {
-        tcx.sess
-            .struct_span_err(attr.span, "illegal ordinal format in `link_ordinal`")
-            .note("an unsuffixed integer value, e.g., `1`, is expected")
-            .emit();
-        None
-    }
-}
-
-fn check_link_name_xor_ordinal(
-    tcx: TyCtxt<'_>,
-    codegen_fn_attrs: &CodegenFnAttrs,
-    inline_span: Option<Span>,
-) {
-    if codegen_fn_attrs.link_name.is_none() || codegen_fn_attrs.link_ordinal.is_none() {
-        return;
-    }
-    let msg = "cannot use `#[link_name]` with `#[link_ordinal]`";
-    if let Some(span) = inline_span {
-        tcx.sess.span_err(span, msg);
-    } else {
-        tcx.sess.err(msg);
-    }
-}
-
-/// Checks the function annotated with `#[target_feature]` is not a safe
-/// trait method implementation, reporting an error if it is.
-fn check_target_feature_trait_unsafe(tcx: TyCtxt<'_>, id: LocalDefId, attr_span: Span) {
-    let hir_id = tcx.hir().local_def_id_to_hir_id(id);
-    let node = tcx.hir().get(hir_id);
-    if let Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }) = node {
-        let parent_id = tcx.hir().get_parent_item(hir_id);
-        let parent_item = tcx.hir().expect_item(parent_id.def_id);
-        if let hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) = parent_item.kind {
-            tcx.sess
-                .struct_span_err(
-                    attr_span,
-                    "`#[target_feature(..)]` cannot be applied to safe trait method",
-                )
-                .span_label(attr_span, "cannot be applied to safe trait method")
-                .span_label(tcx.def_span(id), "not an `unsafe` function")
-                .emit();
-        }
-    }
-}
index 9a7b261fffd4ded6cde9bc8bee5f84f8af042336..b4ad3467e7d87ac67cac22c7705cedb92ea5cccf 100644 (file)
@@ -1749,7 +1749,7 @@ fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<!> {
                 ty::Param(param_ty) => {
                     self.arg_is_constrained[param_ty.index as usize] = true;
                 }
-                ty::Projection(_) => return ControlFlow::Continue(()),
+                ty::Alias(ty::Projection, _) => return ControlFlow::Continue(()),
                 _ => (),
             }
             t.super_visit_with(self)
index 45e241f4e093d523cf2d6e35f380dc2a961cf464..79d75231e5d76d04024a44ebcc76621ea4449ecb 100644 (file)
@@ -75,7 +75,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
 
     const NO_GENERICS: &hir::Generics<'_> = hir::Generics::empty();
 
-    // We use an `IndexSet` to preserves order of insertion.
+    // We use an `IndexSet` to preserve order of insertion.
     // Preserving the order of insertion is important here so as not to break UI tests.
     let mut predicates: FxIndexSet<(ty::Predicate<'_>, Span)> = FxIndexSet::default();
 
@@ -97,11 +97,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
             | ItemKind::Struct(_, ref generics)
             | ItemKind::Union(_, ref generics) => *generics,
 
-            ItemKind::Trait(_, _, ref generics, ..) => {
-                is_trait = Some(ty::TraitRef::identity(tcx, def_id));
-                *generics
-            }
-            ItemKind::TraitAlias(ref generics, _) => {
+            ItemKind::Trait(_, _, ref generics, ..) | ItemKind::TraitAlias(ref generics, _) => {
                 is_trait = Some(ty::TraitRef::identity(tcx, def_id));
                 *generics
             }
@@ -406,14 +402,15 @@ pub(super) fn explicit_predicates_of<'tcx>(
             // For a predicate from a where clause to become a bound on an
             // associated type:
             // * It must use the identity substs of the item.
-            //     * Since any generic parameters on the item are not in scope,
-            //       this means that the item is not a GAT, and its identity
-            //       substs are the same as the trait's.
+            //   * We're in the scope of the trait, so we can't name any
+            //     parameters of the GAT. That means that all we need to
+            //     check are that the substs of the projection are the
+            //     identity substs of the trait.
             // * It must be an associated type for this trait (*not* a
             //   supertrait).
-            if let ty::Projection(projection) = ty.kind() {
+            if let ty::Alias(ty::Projection, projection) = ty.kind() {
                 projection.substs == trait_identity_substs
-                    && tcx.associated_item(projection.item_def_id).container_id(tcx) == def_id
+                    && tcx.associated_item(projection.def_id).container_id(tcx) == def_id
             } else {
                 false
             }
index 9bd1715ce39ffe21fe413a4bb0dee0c95b30e890..b678990f94e918ba6f9f26ad160b9771b19366b7 100644 (file)
@@ -52,7 +52,7 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
             // Using the ItemCtxt convert the HIR for the unresolved assoc type into a
             // ty which is a fully resolved projection.
             // For the code example above, this would mean converting Self::Assoc<3>
-            // into a ty::Projection(<Self as Foo>::Assoc<3>)
+            // into a ty::Alias(ty::Projection, <Self as Foo>::Assoc<3>)
             let item_hir_id = tcx
                 .hir()
                 .parent_iter(hir_id)
@@ -68,8 +68,8 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
             // the def_id that this query was called with. We filter to only type and const args here
             // as a precaution for if it's ever allowed to elide lifetimes in GAT's. It currently isn't
             // but it can't hurt to be safe ^^
-            if let ty::Projection(projection) = ty.kind() {
-                let generics = tcx.generics_of(projection.item_def_id);
+            if let ty::Alias(ty::Projection, projection) = ty.kind() {
+                let generics = tcx.generics_of(projection.def_id);
 
                 let arg_index = segment
                     .args
@@ -666,7 +666,7 @@ fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) {
 
     let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
     let scope = tcx.hir().get_defining_scope(hir_id);
-    let mut locator = ConstraintLocator { def_id: def_id, tcx, found: None, typeck_types: vec![] };
+    let mut locator = ConstraintLocator { def_id, tcx, found: None, typeck_types: vec![] };
 
     debug!(?scope);
 
@@ -803,7 +803,7 @@ fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) {
     if let Some(concrete) = concrete {
         let scope = tcx.hir().local_def_id_to_hir_id(owner_def_id);
         debug!(?scope);
-        let mut locator = ConstraintChecker { def_id: def_id, tcx, found: concrete };
+        let mut locator = ConstraintChecker { def_id, tcx, found: concrete };
 
         match tcx.hir().get(scope) {
             Node::Item(it) => intravisit::walk_item(&mut locator, it),
index b4057df7896f30fa331f932e1c838bf91a35527d..95c971c0d7845eee2d63668b8527c419b67eb4e6 100644 (file)
@@ -59,7 +59,7 @@ struct ParameterCollector {
 impl<'tcx> TypeVisitor<'tcx> for ParameterCollector {
     fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
         match *t.kind() {
-            ty::Projection(..) if !self.include_nonconstraining => {
+            ty::Alias(ty::Projection, ..) if !self.include_nonconstraining => {
                 // projections are not injective
                 return ControlFlow::CONTINUE;
             }
index c92ab749bc1f7dc4a7e44023f684401aecde76b7..d383fcacb3a9c914ce0b862daf1386e8b52c453e 100644 (file)
@@ -51,6 +51,17 @@ pub struct LifetimesOrBoundsMismatchOnTrait {
     pub ident: Ident,
 }
 
+#[derive(Diagnostic)]
+#[diag(hir_analysis_async_trait_impl_should_be_async)]
+pub struct AsyncTraitImplShouldBeAsync {
+    #[primary_span]
+    // #[label]
+    pub span: Span,
+    #[label(trait_item_label)]
+    pub trait_item_span: Option<Span>,
+    pub method_name: Symbol,
+}
+
 #[derive(Diagnostic)]
 #[diag(hir_analysis_drop_impl_on_wrong_item, code = "E0120")]
 pub struct DropImplOnWrongItem {
@@ -253,13 +264,6 @@ pub struct ExternCrateNotIdiomatic {
     pub suggestion_code: String,
 }
 
-#[derive(Diagnostic)]
-#[diag(hir_analysis_expected_used_symbol)]
-pub struct ExpectedUsedSymbol {
-    #[primary_span]
-    pub span: Span,
-}
-
 #[derive(Diagnostic)]
 #[diag(hir_analysis_const_impl_for_non_const_trait)]
 pub struct ConstImplForNonConstTrait {
index 90c6edb65e46faa6aac8214fb3587c9abd5a5723..af8d7e8515865583d84f4769944025e7d6483ded 100644 (file)
@@ -196,13 +196,13 @@ fn insert_required_predicates_to_be_wf<'tcx>(
                 }
             }
 
-            ty::Projection(obj) => {
+            ty::Alias(ty::Projection, obj) => {
                 // This corresponds to `<T as Foo<'a>>::Bar`. In this case, we should use the
                 // explicit predicates as well.
                 debug!("Projection");
                 check_explicit_predicates(
                     tcx,
-                    tcx.parent(obj.item_def_id),
+                    tcx.parent(obj.def_id),
                     obj.substs,
                     required_predicates,
                     explicit_map,
index 0409c7081dc4f5cde6e626905b82b9255e83f6f2..b51b740d08e2e7a2e87f7bb578205bbcc430237c 100644 (file)
@@ -90,7 +90,7 @@ pub(crate) fn insert_outlives_predicate<'tcx>(
                         // ```
                         //
                         // Here we want to add an explicit `where <T as Iterator>::Item: 'a`.
-                        let ty: Ty<'tcx> = tcx.mk_projection(proj_ty.item_def_id, proj_ty.substs);
+                        let ty: Ty<'tcx> = tcx.mk_projection(proj_ty.def_id, proj_ty.substs);
                         required_predicates
                             .entry(ty::OutlivesPredicate(ty.into(), outlived_region))
                             .or_insert(span);
index 6ce0c18bf45f1368730d97a460aa0716eeca2900..5e4d82b6fd5697ce31b095b0431a804f67d383f5 100644 (file)
@@ -249,14 +249,10 @@ fn add_constraints_from_ty(
                 self.add_constraints_from_substs(current, def.did(), substs, variance);
             }
 
-            ty::Projection(ref data) => {
+            ty::Alias(_, ref data) => {
                 self.add_constraints_from_invariant_substs(current, data.substs, variance);
             }
 
-            ty::Opaque(_, substs) => {
-                self.add_constraints_from_invariant_substs(current, substs, variance);
-            }
-
             ty::Dynamic(data, r, _) => {
                 // The type `Foo<T+'a>` is contravariant w/r/t `'a`:
                 let contra = self.contravariant(variance);
index 8b2719c2f8aaaef1add2f372c81751f7b6bdc8c2..24008f88814339d1f343fe38c0cf368165afe994 100644 (file)
@@ -111,11 +111,13 @@ fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
         #[instrument(level = "trace", skip(self), ret)]
         fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
             match t.kind() {
-                ty::Opaque(def_id, substs) => self.visit_opaque(*def_id, substs),
-                ty::Projection(proj)
-                    if self.tcx.def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder =>
+                ty::Alias(_, ty::AliasTy { def_id, substs, .. })
+                    if matches!(
+                        self.tcx.def_kind(*def_id),
+                        DefKind::OpaqueTy | DefKind::ImplTraitPlaceholder
+                    ) =>
                 {
-                    self.visit_opaque(proj.item_def_id, proj.substs)
+                    self.visit_opaque(*def_id, substs)
                 }
                 _ => t.super_visit_with(self),
             }
@@ -158,7 +160,7 @@ fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
         // instead of requiring an additional `+ 'a`.
         match pred.kind().skip_binder() {
             ty::PredicateKind::Clause(ty::Clause::Trait(ty::TraitPredicate {
-                trait_ref: ty::TraitRef { def_id: _, substs },
+                trait_ref: ty::TraitRef { def_id: _, substs, .. },
                 constness: _,
                 polarity: _,
             })) => {
@@ -167,7 +169,7 @@ fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
                 }
             }
             ty::PredicateKind::Clause(ty::Clause::Projection(ty::ProjectionPredicate {
-                projection_ty: ty::ProjectionTy { substs, item_def_id: _ },
+                projection_ty: ty::AliasTy { substs, .. },
                 term,
             })) => {
                 for subst in &substs[1..] {
index ef98c4ba54cbdfd1e3a6c1a0b0401beb5ab2a5e8..29a6902ccb0772591f896c431ec61e9d45ce37e1 100644 (file)
@@ -1757,7 +1757,6 @@ pub fn print_pat(&mut self, pat: &hir::Pat<'_>) {
                 self.print_qpath(qpath, true);
                 self.popen();
                 if let Some(ddpos) = ddpos.as_opt_usize() {
-                    let ddpos = ddpos as usize;
                     self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(p));
                     if ddpos != 0 {
                         self.word_space(",");
index e25a9e9036a15607e6b2000aac8c03f8281eaa63..ab12cae4e2b08a0b48fc57e8b687f841b7b59509 100644 (file)
@@ -212,7 +212,7 @@ fn suggest_removing_semicolon_for_coerce(
                 self.can_coerce(arm_ty, ret_ty)
                     && prior_arm.map_or(true, |(_, ty, _)| self.can_coerce(ty, ret_ty))
                     // The match arms need to unify for the case of `impl Trait`.
-                    && !matches!(ret_ty.kind(), ty::Opaque(..))
+                    && !matches!(ret_ty.kind(), ty::Alias(ty::Opaque, ..))
             }
             _ => false,
         };
@@ -518,7 +518,7 @@ pub(crate) fn opt_suggest_box_span(
 
                 let substs = sig.output().walk().find_map(|arg| {
                     if let ty::GenericArgKind::Type(ty) = arg.unpack()
-                        && let ty::Opaque(def_id, substs) = *ty.kind()
+                        && let ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) = *ty.kind()
                         && def_id == rpit_def_id
                     {
                         Some(substs)
@@ -542,15 +542,12 @@ pub(crate) fn opt_suggest_box_span(
                             ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) => {
                                 assert_eq!(trait_pred.trait_ref.self_ty(), opaque_ty);
                                 ty::PredicateKind::Clause(ty::Clause::Trait(
-                                    trait_pred.with_self_type(self.tcx, ty),
+                                    trait_pred.with_self_ty(self.tcx, ty),
                                 ))
                             }
                             ty::PredicateKind::Clause(ty::Clause::Projection(mut proj_pred)) => {
                                 assert_eq!(proj_pred.projection_ty.self_ty(), opaque_ty);
-                                proj_pred.projection_ty.substs = self.tcx.mk_substs_trait(
-                                    ty,
-                                    proj_pred.projection_ty.substs.iter().skip(1),
-                                );
+                                proj_pred = proj_pred.with_self_ty(self.tcx, ty);
                                 ty::PredicateKind::Clause(ty::Clause::Projection(proj_pred))
                             }
                             _ => continue,
index 890a068a7befc8c78cc14ad9d9c0d4fe96851cb7..b050ad20afbdbcca92547e224feda97a9d8af8b8 100644 (file)
@@ -38,7 +38,6 @@
 use rustc_middle::ty::adjustment::AllowTwoPhase;
 use rustc_middle::ty::cast::{CastKind, CastTy};
 use rustc_middle::ty::error::TypeError;
-use rustc_middle::ty::subst::SubstsRef;
 use rustc_middle::ty::{self, Ty, TypeAndMut, TypeVisitable, VariantDef};
 use rustc_session::lint;
 use rustc_session::Session;
@@ -75,10 +74,8 @@ enum PointerKind<'tcx> {
     VTable(Option<DefId>),
     /// Slice
     Length,
-    /// The unsize info of this projection
-    OfProjection(ty::ProjectionTy<'tcx>),
-    /// The unsize info of this opaque ty
-    OfOpaque(DefId, SubstsRef<'tcx>),
+    /// The unsize info of this projection or opaque type
+    OfAlias(ty::AliasTy<'tcx>),
     /// The unsize info of this parameter
     OfParam(ty::ParamTy),
 }
@@ -118,8 +115,7 @@ fn pointer_kind(
             // Pointers to foreign types are thin, despite being unsized
             ty::Foreign(..) => Some(PointerKind::Thin),
             // We should really try to normalize here.
-            ty::Projection(pi) => Some(PointerKind::OfProjection(pi)),
-            ty::Opaque(def_id, substs) => Some(PointerKind::OfOpaque(def_id, substs)),
+            ty::Alias(_, pi) => Some(PointerKind::OfAlias(pi)),
             ty::Param(p) => Some(PointerKind::OfParam(p)),
             // Insufficient type information.
             ty::Placeholder(..) | ty::Bound(..) | ty::Infer(_) => None,
@@ -976,11 +972,9 @@ fn check_addr_ptr_cast(
             Some(PointerKind::Thin) => Ok(CastKind::AddrPtrCast),
             Some(PointerKind::VTable(_)) => Err(CastError::IntToFatCast(Some("a vtable"))),
             Some(PointerKind::Length) => Err(CastError::IntToFatCast(Some("a length"))),
-            Some(
-                PointerKind::OfProjection(_)
-                | PointerKind::OfOpaque(_, _)
-                | PointerKind::OfParam(_),
-            ) => Err(CastError::IntToFatCast(None)),
+            Some(PointerKind::OfAlias(_) | PointerKind::OfParam(_)) => {
+                Err(CastError::IntToFatCast(None))
+            }
         }
     }
 
index 429cb60ba2b6161692c9153041a068ce638e69d5..72d8a936ab39db2adcc5b8f4970fcdc705b638ba 100644 (file)
@@ -167,9 +167,10 @@ fn deduce_expectations_from_expected_type(
         expected_ty: Ty<'tcx>,
     ) -> (Option<ExpectedSig<'tcx>>, Option<ty::ClosureKind>) {
         match *expected_ty.kind() {
-            ty::Opaque(def_id, substs) => self.deduce_signature_from_predicates(
-                self.tcx.bound_explicit_item_bounds(def_id).subst_iter_copied(self.tcx, substs),
-            ),
+            ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => self
+                .deduce_signature_from_predicates(
+                    self.tcx.bound_explicit_item_bounds(def_id).subst_iter_copied(self.tcx, substs),
+                ),
             ty::Dynamic(ref object_type, ..) => {
                 let sig = object_type.projection_bounds().find_map(|pb| {
                     let pb = pb.with_self_ty(self.tcx, self.tcx.types.trait_object_dummy_self);
@@ -677,17 +678,17 @@ fn deduce_future_output_from_obligations(
                     get_future_output(obligation.predicate, obligation.cause.span)
                 })?
             }
-            ty::Opaque(def_id, substs) => self
+            ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => self
                 .tcx
                 .bound_explicit_item_bounds(def_id)
                 .subst_iter_copied(self.tcx, substs)
                 .find_map(|(p, s)| get_future_output(p, s))?,
             ty::Error(_) => return None,
-            ty::Projection(proj)
-                if self.tcx.def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder =>
+            ty::Alias(ty::Projection, proj)
+                if self.tcx.def_kind(proj.def_id) == DefKind::ImplTraitPlaceholder =>
             {
                 self.tcx
-                    .bound_explicit_item_bounds(proj.item_def_id)
+                    .bound_explicit_item_bounds(proj.def_id)
                     .subst_iter_copied(self.tcx, proj.substs)
                     .find_map(|(p, s)| get_future_output(p, s))?
             }
@@ -743,11 +744,11 @@ fn deduce_future_output_from_projection(
         // The `Future` trait has only one associated item, `Output`,
         // so check that this is what we see.
         let output_assoc_item = self.tcx.associated_item_def_ids(future_trait)[0];
-        if output_assoc_item != predicate.projection_ty.item_def_id {
+        if output_assoc_item != predicate.projection_ty.def_id {
             span_bug!(
                 cause_span,
                 "projecting associated item `{:?}` from future, which is not Output `{:?}`",
-                predicate.projection_ty.item_def_id,
+                predicate.projection_ty.def_id,
                 output_assoc_item,
             );
         }
index f0b349f0c98dd667f349083ab9555df2aa758589..36cf4791492dd1c8c8b36d1125289dc008cb3fed 100644 (file)
@@ -1805,7 +1805,7 @@ fn add_impl_trait_explanation<'a>(
         {
             let ty = <dyn AstConv<'_>>::ast_ty_to_ty(fcx, ty);
             // Get the `impl Trait`'s `DefId`.
-            if let ty::Opaque(def_id, _) = ty.kind()
+            if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = ty.kind()
                 // Get the `impl Trait`'s `Item` so that we can get its trait bounds and
                 // get the `Trait`'s `DefId`.
                 && let hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, .. }) =
index ed87b94a040d0f87b4d665898481ea2efa3c10d9..866090260b2723dad6ef078f500805ab69b7d46c 100644 (file)
@@ -2391,7 +2391,7 @@ fn ban_nonexisting_field(
             ty::Param(param_ty) => {
                 self.point_at_param_definition(&mut err, param_ty);
             }
-            ty::Opaque(_, _) => {
+            ty::Alias(ty::Opaque, _) => {
                 self.suggest_await_on_field_access(&mut err, ident, base, base_ty.peel_refs());
             }
             _ => {}
index 952d2726259187c736488ccd827d17973b571ed7..1a4e6bf763821b05ee33737dc392ef35d145eb8a 100644 (file)
@@ -716,7 +716,7 @@ pub(in super::super) fn expected_inputs_for_expected_output(
         if formal_ret.has_infer_types() {
             for ty in ret_ty.walk() {
                 if let ty::subst::GenericArgKind::Type(ty) = ty.unpack()
-                    && let ty::Opaque(def_id, _) = *ty.kind()
+                    && let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = *ty.kind()
                     && let Some(def_id) = def_id.as_local()
                     && self.opaque_type_origin(def_id, DUMMY_SP).is_some() {
                     return None;
index 93618c61417300b5957792e262c614d14311f178..8e520e563ff630ecdeb62b0e4a1b046feb7dbe14 100644 (file)
@@ -2124,7 +2124,7 @@ fn label_fn_like(
                         }
                     }
                 }
-                ty::Opaque(new_def_id, _)
+                ty::Alias(ty::Opaque, ty::AliasTy { def_id: new_def_id, .. })
                 | ty::Closure(new_def_id, _)
                 | ty::FnDef(new_def_id, _) => {
                     def_id = new_def_id;
@@ -2132,19 +2132,15 @@ fn label_fn_like(
                 _ => {
                     // Look for a user-provided impl of a `Fn` trait, and point to it.
                     let new_def_id = self.probe(|_| {
-                        let trait_ref = ty::TraitRef::new(
+                        let trait_ref = self.tcx.mk_trait_ref(
                             call_kind.to_def_id(self.tcx),
-                            self.tcx.mk_substs(
-                                [
-                                    ty::GenericArg::from(callee_ty),
-                                    self.next_ty_var(TypeVariableOrigin {
-                                        kind: TypeVariableOriginKind::MiscVariable,
-                                        span: rustc_span::DUMMY_SP,
-                                    })
-                                    .into(),
-                                ]
-                                .into_iter(),
-                            ),
+                            [
+                                callee_ty,
+                                self.next_ty_var(TypeVariableOrigin {
+                                    kind: TypeVariableOriginKind::MiscVariable,
+                                    span: rustc_span::DUMMY_SP,
+                                }),
+                            ],
                         );
                         let obligation = traits::Obligation::new(
                             self.tcx,
@@ -2217,7 +2213,7 @@ fn find_param_in_ty<'tcx>(ty: Ty<'tcx>, param_to_point_at: ty::GenericArg<'tcx>)
         if arg == param_to_point_at {
             return true;
         } else if let ty::GenericArgKind::Type(ty) = arg.unpack()
-            && let ty::Projection(..) = ty.kind()
+            && let ty::Alias(ty::Projection, ..) = ty.kind()
         {
             // This logic may seem a bit strange, but typically when
             // we have a projection type in a function signature, the
index 4f92477b5d87ef221239c71054742025efb7bf32..407d6ac8544c211a8cce00fa74b0cfb983bddbea 100644 (file)
@@ -13,7 +13,9 @@
 use rustc_infer::infer;
 use rustc_infer::traits::{self, StatementAsExpression};
 use rustc_middle::lint::in_external_macro;
-use rustc_middle::ty::{self, Binder, DefIdTree, IsSuggestable, ToPredicate, Ty};
+use rustc_middle::ty::{
+    self, suggest_constraining_type_params, Binder, DefIdTree, IsSuggestable, ToPredicate, Ty,
+};
 use rustc_session::errors::ExprParenthesesNeeded;
 use rustc_span::symbol::sym;
 use rustc_span::Span;
@@ -174,10 +176,10 @@ pub(in super::super) fn extract_callable_info(
                     let fn_sig = substs.as_closure().sig();
                     Some((DefIdOrName::DefId(def_id), fn_sig.output(), fn_sig.inputs().map_bound(|inputs| &inputs[1..])))
                 }
-                ty::Opaque(def_id, substs) => {
+                ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
                     self.tcx.bound_item_bounds(def_id).subst(self.tcx, substs).iter().find_map(|pred| {
                         if let ty::PredicateKind::Clause(ty::Clause::Projection(proj)) = pred.kind().skip_binder()
-                        && Some(proj.projection_ty.item_def_id) == self.tcx.lang_items().fn_once_output()
+                        && Some(proj.projection_ty.def_id) == self.tcx.lang_items().fn_once_output()
                         // args tuple will always be substs[1]
                         && let ty::Tuple(args) = proj.projection_ty.substs.type_at(1).kind()
                         {
@@ -194,7 +196,7 @@ pub(in super::super) fn extract_callable_info(
                 ty::Dynamic(data, _, ty::Dyn) => {
                     data.iter().find_map(|pred| {
                         if let ty::ExistentialPredicate::Projection(proj) = pred.skip_binder()
-                        && Some(proj.item_def_id) == self.tcx.lang_items().fn_once_output()
+                        && Some(proj.def_id) == self.tcx.lang_items().fn_once_output()
                         // for existential projection, substs are shifted over by 1
                         && let ty::Tuple(args) = proj.substs.type_at(0).kind()
                         {
@@ -212,7 +214,7 @@ pub(in super::super) fn extract_callable_info(
                     let def_id = self.tcx.generics_of(self.body_id.owner).type_param(&param, self.tcx).def_id;
                     self.tcx.predicates_of(self.body_id.owner).predicates.iter().find_map(|(pred, _)| {
                         if let ty::PredicateKind::Clause(ty::Clause::Projection(proj)) = pred.kind().skip_binder()
-                        && Some(proj.projection_ty.item_def_id) == self.tcx.lang_items().fn_once_output()
+                        && Some(proj.projection_ty.def_id) == self.tcx.lang_items().fn_once_output()
                         && proj.projection_ty.self_ty() == found
                         // args tuple will always be substs[1]
                         && let ty::Tuple(args) = proj.projection_ty.substs.type_at(1).kind()
@@ -1276,18 +1278,14 @@ pub(crate) fn note_type_is_not_clone(
             && !results.expr_adjustments(callee_expr).iter().any(|adj| matches!(adj.kind, ty::adjustment::Adjust::Deref(..)))
             // Check that we're in fact trying to clone into the expected type
             && self.can_coerce(*pointee_ty, expected_ty)
+            && let trait_ref = ty::Binder::dummy(self.tcx.mk_trait_ref(clone_trait_did, [expected_ty]))
             // And the expected type doesn't implement `Clone`
-            && !self.predicate_must_hold_considering_regions(&traits::Obligation {
-                cause: traits::ObligationCause::dummy(),
-                param_env: self.param_env,
-                recursion_depth: 0,
-                predicate: ty::Binder::dummy(ty::TraitRef {
-                    def_id: clone_trait_did,
-                    substs: self.tcx.mk_substs([expected_ty.into()].iter()),
-                })
-                .without_const()
-                .to_predicate(self.tcx),
-            })
+            && !self.predicate_must_hold_considering_regions(&traits::Obligation::new(
+                self.tcx,
+                traits::ObligationCause::dummy(),
+                self.param_env,
+                trait_ref,
+            ))
         {
             diag.span_note(
                 callee_expr.span,
@@ -1295,6 +1293,19 @@ pub(crate) fn note_type_is_not_clone(
                     "`{expected_ty}` does not implement `Clone`, so `{found_ty}` was cloned instead"
                 ),
             );
+            let owner = self.tcx.hir().enclosing_body_owner(expr.hir_id);
+            if let ty::Param(param) = expected_ty.kind()
+                && let Some(generics) = self.tcx.hir().get_generics(owner)
+            {
+                suggest_constraining_type_params(
+                    self.tcx,
+                    generics,
+                    diag,
+                    vec![(param.name.as_str(), "Clone", Some(clone_trait_did))].into_iter(),
+                );
+            } else {
+                self.suggest_derive(diag, &[(trait_ref.to_predicate(self.tcx), None, None)]);
+            }
         }
     }
 
index 3b1518ff79b4e8e0859f8436615258b3587ea096..93f2ceed777b5be20bda25798be7d198ef998950 100644 (file)
@@ -563,7 +563,7 @@ fn check_must_not_suspend_ty<'tcx>(
         }
         ty::Adt(def, _) => check_must_not_suspend_def(fcx.tcx, def.did(), hir_id, data),
         // FIXME: support adding the attribute to TAITs
-        ty::Opaque(def, _) => {
+        ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => {
             let mut has_emitted = false;
             for &(predicate, _) in fcx.tcx.explicit_item_bounds(def) {
                 // We only look at the `DefId`, so it is safe to skip the binder here.
index b15c086ffad5781f2b921dd61d5c97b31d8bb470..3f3af53d199b12918512a1597a9f7b1eb34532a5 100644 (file)
@@ -209,7 +209,7 @@ pub fn lookup_method(
                     ProbeScope::TraitsInScope,
                 ) {
                     Ok(ref new_pick) if pick.differs_from(new_pick) => {
-                        needs_mut = true;
+                        needs_mut = new_pick.self_ty.ref_mutability() != self_ty.ref_mutability();
                     }
                     _ => {}
                 }
@@ -285,7 +285,7 @@ pub(super) fn obligation_for_method(
             self.var_for_def(span, param)
         });
 
-        let trait_ref = ty::TraitRef::new(trait_def_id, substs);
+        let trait_ref = self.tcx.mk_trait_ref(trait_def_id, substs);
 
         // Construct an obligation
         let poly_trait_ref = ty::Binder::dummy(trait_ref);
@@ -326,7 +326,7 @@ pub(super) fn obligation_for_op_method(
             self.var_for_def(span, param)
         });
 
-        let trait_ref = ty::TraitRef::new(trait_def_id, substs);
+        let trait_ref = self.tcx.mk_trait_ref(trait_def_id, substs);
 
         // Construct an obligation
         let poly_trait_ref = ty::Binder::dummy(trait_ref);
index 070359e71becc13381d15e12fb510b336a58c28e..b9e7830bf079214af2a29491fff1ab458fbee011 100644 (file)
@@ -920,7 +920,7 @@ fn assemble_extension_candidates_for_trait(
     ) {
         debug!("assemble_extension_candidates_for_trait(trait_def_id={:?})", trait_def_id);
         let trait_substs = self.fresh_item_substs(trait_def_id);
-        let trait_ref = ty::TraitRef::new(trait_def_id, trait_substs);
+        let trait_ref = self.tcx.mk_trait_ref(trait_def_id, trait_substs);
 
         if self.tcx.is_trait_alias(trait_def_id) {
             // For trait aliases, assume all supertraits are relevant.
index db93cfab2c0dbd6a45508b9c35607b642cfe6c51..63cec9216eb89fa70f262db6c73cb57b4eee1d6b 100644 (file)
@@ -25,7 +25,7 @@
 use rustc_middle::traits::util::supertraits;
 use rustc_middle::ty::fast_reject::DeepRejectCtxt;
 use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
-use rustc_middle::ty::print::with_crate_prefix;
+use rustc_middle::ty::print::{with_crate_prefix, with_forced_trimmed_paths};
 use rustc_middle::ty::{self, DefIdTree, GenericArgKind, Ty, TyCtxt, TypeVisitable};
 use rustc_middle::ty::{IsSuggestable, ToPolyTraitRef};
 use rustc_span::symbol::{kw, sym, Ident};
@@ -270,7 +270,7 @@ pub fn report_method_error(
                 let tcx = self.tcx;
 
                 let rcvr_ty = self.resolve_vars_if_possible(rcvr_ty);
-                let ty_str = self.ty_to_string(rcvr_ty);
+                let ty_str = with_forced_trimmed_paths!(self.ty_to_string(rcvr_ty));
                 let is_method = mode == Mode::MethodCall;
                 let item_kind = if is_method {
                     "method"
@@ -557,15 +557,16 @@ pub fn report_method_error(
                                         .chain(projection_ty.substs.iter().skip(1)),
                                 );
 
-                                let quiet_projection_ty = ty::ProjectionTy {
-                                    substs: substs_with_infer_self,
-                                    item_def_id: projection_ty.item_def_id,
-                                };
+                                let quiet_projection_ty =
+                                    tcx.mk_alias_ty(projection_ty.def_id, substs_with_infer_self);
 
                                 let term = pred.skip_binder().term;
 
                                 let obligation = format!("{} = {}", projection_ty, term);
-                                let quiet = format!("{} = {}", quiet_projection_ty, term);
+                                let quiet = with_forced_trimmed_paths!(format!(
+                                    "{} = {}",
+                                    quiet_projection_ty, term
+                                ));
 
                                 bound_span_label(projection_ty.self_ty(), &obligation, &quiet);
                                 Some((obligation, projection_ty.self_ty()))
@@ -575,7 +576,7 @@ pub fn report_method_error(
                                 let self_ty = p.self_ty();
                                 let path = p.print_only_trait_path();
                                 let obligation = format!("{}: {}", self_ty, path);
-                                let quiet = format!("_: {}", path);
+                                let quiet = with_forced_trimmed_paths!(format!("_: {}", path));
                                 bound_span_label(self_ty, &obligation, &quiet);
                                 Some((obligation, self_ty))
                             }
@@ -798,7 +799,8 @@ trait bound{s}",
                                 (None, None)
                             };
                         let primary_message = primary_message.unwrap_or_else(|| format!(
-                            "the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, but its trait bounds were not satisfied"
+                            "the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, \
+                             but its trait bounds were not satisfied"
                         ));
                         err.set_primary_message(&primary_message);
                         if let Some(label) = label {
@@ -895,7 +897,14 @@ trait bound{s}",
                             }
                         }
                     } else {
-                        err.span_label(span, format!("{item_kind} cannot be called on `{ty_str}` due to unsatisfied trait bounds"));
+                        let ty_str = if ty_str.len() > 50 {
+                            String::new()
+                        } else {
+                            format!("on `{ty_str}` ")
+                        };
+                        err.span_label(span, format!(
+                            "{item_kind} cannot be called {ty_str}due to unsatisfied trait bounds"
+                        ));
                     }
                 };
 
@@ -1843,7 +1852,7 @@ pub(crate) fn note_unmet_impls_on_type(
         self.suggest_derive(err, &preds);
     }
 
-    fn suggest_derive(
+    pub fn suggest_derive(
         &self,
         err: &mut Diagnostic,
         unsatisfied_predicates: &[(
@@ -1853,7 +1862,7 @@ fn suggest_derive(
         )],
     ) {
         let mut derives = Vec::<(String, Span, Symbol)>::new();
-        let mut traits = Vec::<Span>::new();
+        let mut traits = Vec::new();
         for (pred, _, _) in unsatisfied_predicates {
             let ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) = pred.kind().skip_binder() else { continue };
             let adt = match trait_pred.self_ty().ty_adt_def() {
@@ -1892,10 +1901,10 @@ fn suggest_derive(
                     }
                     derives.push((self_name, self_span, diagnostic_name));
                 } else {
-                    traits.push(self.tcx.def_span(trait_pred.def_id()));
+                    traits.push(trait_pred.def_id());
                 }
             } else {
-                traits.push(self.tcx.def_span(trait_pred.def_id()));
+                traits.push(trait_pred.def_id());
             }
         }
         traits.sort();
@@ -1918,10 +1927,23 @@ fn suggest_derive(
 
         let len = traits.len();
         if len > 0 {
-            let span: MultiSpan = traits.into();
+            let span =
+                MultiSpan::from_spans(traits.iter().map(|&did| self.tcx.def_span(did)).collect());
+            let mut names = format!("`{}`", self.tcx.def_path_str(traits[0]));
+            for (i, &did) in traits.iter().enumerate().skip(1) {
+                if len > 2 {
+                    names.push_str(", ");
+                }
+                if i == len - 1 {
+                    names.push_str(" and ");
+                }
+                names.push('`');
+                names.push_str(&self.tcx.def_path_str(did));
+                names.push('`');
+            }
             err.span_note(
                 span,
-                &format!("the following trait{} must be implemented", pluralize!(len),),
+                &format!("the trait{} {} must be implemented", pluralize!(len), names),
             );
         }
 
@@ -1969,7 +1991,7 @@ fn check_for_deref_method(
                         | ty::Float(_)
                         | ty::Adt(_, _)
                         | ty::Str
-                        | ty::Projection(_)
+                        | ty::Alias(ty::Projection, _)
                         | ty::Param(_) => format!("{deref_ty}"),
                         // we need to test something like  <&[_]>::len or <(&[u32])>::len
                         // and Vec::function();
@@ -2269,7 +2291,7 @@ fn suggest_traits_to_import(
                             t.def_id() == info.def_id
                         }
                         ty::PredicateKind::Clause(ty::Clause::Projection(p)) => {
-                            p.projection_ty.item_def_id == info.def_id
+                            p.projection_ty.def_id == info.def_id
                         }
                         _ => false,
                     }
index 58ced6a1d3b4ffb90308cd91e64d1012b1c245df..bb956ddc780423876eca53ec2fc209aaed365aa8 100644 (file)
@@ -546,7 +546,7 @@ struct RecursionChecker {
             impl<'tcx> ty::TypeVisitor<'tcx> for RecursionChecker {
                 type BreakTy = ();
                 fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
-                    if let ty::Opaque(def_id, _) = *t.kind() {
+                    if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = *t.kind() {
                         if def_id == self.def_id.to_def_id() {
                             return ControlFlow::Break(());
                         }
index 777112442f0104bcf7eabe5fbfb91854c5891a1a..686cb6dac496224f130d3f08a2f17d685eb30a32 100644 (file)
@@ -209,7 +209,7 @@ pub fn insert_range(&mut self, elems: impl RangeBounds<T>) {
             self.words[start_word_index] |= !(start_mask - 1);
             // And all trailing bits (i.e. from 0..=end) in the end word,
             // including the end.
-            self.words[end_word_index] |= end_mask | end_mask - 1;
+            self.words[end_word_index] |= end_mask | (end_mask - 1);
         } else {
             self.words[start_word_index] |= end_mask | (end_mask - start_mask);
         }
index 74c4c65cc1729a981db0c42c44e4c57d355cf6cd..c4f11472d55482e979acfdb41894115a7a6a4923 100644 (file)
@@ -517,6 +517,6 @@ pub struct MismatchedStaticLifetime<'a> {
     pub expl: Option<note_and_explain::RegionExplanation<'a>>,
     #[subdiagnostic]
     pub does_not_outlive_static_from_impl: DoesNotOutliveStaticFromImpl,
-    #[subdiagnostic(eager)]
+    #[subdiagnostic]
     pub implicit_static_lifetimes: Vec<ImplicitStaticLifetimeSubdiag>,
 }
index 4429e4f43629a885543c06a5ac61426e96825760..e9186540a7b7c53869366303bba18d2791432f5f 100644 (file)
@@ -411,7 +411,7 @@ fn to_trace(
     }
 }
 
-impl<'tcx> ToTrace<'tcx> for ty::ProjectionTy<'tcx> {
+impl<'tcx> ToTrace<'tcx> for ty::AliasTy<'tcx> {
     fn to_trace(
         tcx: TyCtxt<'tcx>,
         cause: &ObligationCause<'tcx>,
@@ -419,8 +419,8 @@ fn to_trace(
         a: Self,
         b: Self,
     ) -> TypeTrace<'tcx> {
-        let a_ty = tcx.mk_projection(a.item_def_id, a.substs);
-        let b_ty = tcx.mk_projection(b.item_def_id, b.substs);
+        let a_ty = tcx.mk_projection(a.def_id, a.substs);
+        let b_ty = tcx.mk_projection(b.def_id, b.substs);
         TypeTrace {
             cause: cause.clone(),
             values: Terms(ExpectedFound::new(a_is_expected, a_ty.into(), b_ty.into())),
index 3dc0d60b1eb0fab07d2358d1cf9c2c959f5c0cbd..ec5221379d2c9314f93dedab1163b409569203e6 100644 (file)
@@ -453,10 +453,9 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
             | ty::Dynamic(..)
             | ty::Never
             | ty::Tuple(..)
-            | ty::Projection(..)
+            | ty::Alias(..)
             | ty::Foreign(..)
-            | ty::Param(..)
-            | ty::Opaque(..) => {
+            | ty::Param(..) => {
                 if t.flags().intersects(self.needs_canonical_flags) {
                     t.super_fold_with(self)
                 } else {
index cf895ed0d3e598ba23eb5effcb52345e75982045..9a1c49c1aa6af24feb4625f718fc2a29acbdc2aa 100644 (file)
@@ -675,7 +675,7 @@ fn tys(&mut self, t: Ty<'tcx>, t2: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
                 // relatable.
                 Ok(t)
             }
-            ty::Opaque(def_id, substs) => {
+            ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
                 let s = self.relate(substs, substs)?;
                 Ok(if s == substs { t } else { self.infcx.tcx.mk_opaque(def_id, s) })
             }
index 8682f4d3b7aed970783395d50e8ca09a8b648d64..46e7813d99e562cd1cff9b39b0224eaa75048fb1 100644 (file)
@@ -100,11 +100,15 @@ fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
                 self.fields.instantiate(a, RelationDir::EqTo, b_id, self.a_is_expected)?;
             }
 
-            (&ty::Opaque(a_def_id, _), &ty::Opaque(b_def_id, _)) if a_def_id == b_def_id => {
+            (
+                &ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, .. }),
+                &ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }),
+            ) if a_def_id == b_def_id => {
                 self.fields.infcx.super_combine_tys(self, a, b)?;
             }
-            (&ty::Opaque(did, ..), _) | (_, &ty::Opaque(did, ..))
-                if self.fields.define_opaque_types && did.is_local() =>
+            (&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _)
+            | (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
+                if self.fields.define_opaque_types && def_id.is_local() =>
             {
                 self.fields.obligations.extend(
                     infcx
@@ -178,6 +182,11 @@ fn binders<T>(
     where
         T: Relate<'tcx>,
     {
+        // A binder is equal to itself if it's structually equal to itself
+        if a == b {
+            return Ok(a);
+        }
+
         if a.skip_binder().has_escaping_bound_vars() || b.skip_binder().has_escaping_bound_vars() {
             self.fields.higher_ranked_sub(a, b, self.a_is_expected)?;
             self.fields.higher_ranked_sub(b, a, self.a_is_expected)?;
index 987559d7e47243ead6b12e2762ae7716b0d41010..397fa43175f732b3d87e566678388b0fbcd342d8 100644 (file)
@@ -339,11 +339,13 @@ pub fn unexpected_hidden_region_diagnostic<'tcx>(
 impl<'tcx> InferCtxt<'tcx> {
     pub fn get_impl_future_output_ty(&self, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
         let (def_id, substs) = match *ty.kind() {
-            ty::Opaque(def_id, substs) => (def_id, substs),
-            ty::Projection(data)
-                if self.tcx.def_kind(data.item_def_id) == DefKind::ImplTraitPlaceholder =>
+            ty::Alias(_, ty::AliasTy { def_id, substs, .. })
+                if matches!(
+                    self.tcx.def_kind(def_id),
+                    DefKind::OpaqueTy | DefKind::ImplTraitPlaceholder
+                ) =>
             {
-                (data.item_def_id, data.substs)
+                (def_id, substs)
             }
             _ => return None,
         };
@@ -357,7 +359,7 @@ pub fn get_impl_future_output_ty(&self, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
                     .kind()
                     .map_bound(|kind| match kind {
                         ty::PredicateKind::Clause(ty::Clause::Projection(projection_predicate))
-                            if projection_predicate.projection_ty.item_def_id == item_def_id =>
+                            if projection_predicate.projection_ty.def_id == item_def_id =>
                         {
                             projection_predicate.term.ty()
                         }
@@ -1730,7 +1732,7 @@ enum Similar<'tcx> {
                     let extra = expected == found;
                     let sort_string = |ty: Ty<'tcx>, path: Option<PathBuf>| {
                         let mut s = match (extra, ty.kind()) {
-                            (true, ty::Opaque(def_id, _)) => {
+                            (true, ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. })) => {
                                 let sm = self.tcx.sess.source_map();
                                 let pos = sm.lookup_char_pos(self.tcx.def_span(*def_id).lo());
                                 format!(
@@ -1740,12 +1742,12 @@ enum Similar<'tcx> {
                                     pos.col.to_usize() + 1,
                                 )
                             }
-                            (true, ty::Projection(proj))
-                                if self.tcx.def_kind(proj.item_def_id)
+                            (true, ty::Alias(ty::Projection, proj))
+                                if self.tcx.def_kind(proj.def_id)
                                     == DefKind::ImplTraitPlaceholder =>
                             {
                                 let sm = self.tcx.sess.source_map();
-                                let pos = sm.lookup_char_pos(self.tcx.def_span(proj.item_def_id).lo());
+                                let pos = sm.lookup_char_pos(self.tcx.def_span(proj.def_id).lo());
                                 format!(
                                     " (trait associated opaque type at <{}:{}:{}>)",
                                     sm.filename_for_diagnostics(&pos.file.name),
@@ -2383,7 +2385,7 @@ enum SubOrigin<'hir> {
                         // fn get_later<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
                         // suggest:
                         // fn get_later<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
-                        ty::Closure(_, _substs) | ty::Opaque(_, _substs) if return_impl_trait => {
+                        ty::Closure(..) | ty::Alias(ty::Opaque, ..) if return_impl_trait => {
                             new_binding_suggestion(&mut err, type_param_span);
                         }
                         _ => {
@@ -2765,7 +2767,7 @@ fn descr(&self) -> &'static str {
     pub fn from_ty(tcx: TyCtxt<'_>, ty: Ty<'_>) -> Option<(Self, DefId)> {
         match *ty.kind() {
             ty::Closure(def_id, _) => Some((Self::Closure, def_id)),
-            ty::Opaque(def_id, _) => Some((Self::Opaque, def_id)),
+            ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => Some((Self::Opaque, def_id)),
             ty::Generator(def_id, ..) => {
                 Some((Self::Generator(tcx.generator_kind(def_id).unwrap()), def_id))
             }
index 8ff1639a3a24b489e1f8ffc1d039e77a298fda4f..a4c36b4c9cd59db580517b60f8d887ca2bcd40eb 100644 (file)
@@ -20,7 +20,7 @@
 use rustc_middle::ty::{self, DefIdTree, InferConst};
 use rustc_middle::ty::{GenericArg, GenericArgKind, SubstsRef};
 use rustc_middle::ty::{IsSuggestable, Ty, TyCtxt, TypeckResults};
-use rustc_span::symbol::{kw, Ident};
+use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::{BytePos, Span};
 use std::borrow::Cow;
 use std::iter;
@@ -79,7 +79,7 @@ fn can_add_more_info(&self) -> bool {
 
     fn where_x_is_kind(&self, in_type: Ty<'_>) -> &'static str {
         if in_type.is_ty_infer() {
-            "empty"
+            ""
         } else if self.name == "_" {
             // FIXME: Consider specializing this message if there is a single `_`
             // in the type.
@@ -183,13 +183,24 @@ fn fmt_printer<'a, 'tcx>(infcx: &'a InferCtxt<'tcx>, ns: Namespace) -> FmtPrinte
     printer
 }
 
-fn ty_to_string<'tcx>(infcx: &InferCtxt<'tcx>, ty: Ty<'tcx>) -> String {
+fn ty_to_string<'tcx>(
+    infcx: &InferCtxt<'tcx>,
+    ty: Ty<'tcx>,
+    called_method_def_id: Option<DefId>,
+) -> String {
     let printer = fmt_printer(infcx, Namespace::TypeNS);
     let ty = infcx.resolve_vars_if_possible(ty);
-    match ty.kind() {
+    match (ty.kind(), called_method_def_id) {
         // We don't want the regular output for `fn`s because it includes its path in
         // invalid pseudo-syntax, we want the `fn`-pointer output instead.
-        ty::FnDef(..) => ty.fn_sig(infcx.tcx).print(printer).unwrap().into_buffer(),
+        (ty::FnDef(..), _) => ty.fn_sig(infcx.tcx).print(printer).unwrap().into_buffer(),
+        (_, Some(def_id))
+            if ty.is_ty_infer()
+                && infcx.tcx.get_diagnostic_item(sym::iterator_collect_fn) == Some(def_id) =>
+        {
+            "Vec<_>".to_string()
+        }
+        _ if ty.is_ty_infer() => "/* Type */".to_string(),
         // FIXME: The same thing for closures, but this only works when the closure
         // does not capture anything.
         //
@@ -213,7 +224,7 @@ fn closure_as_fn_str<'tcx>(infcx: &InferCtxt<'tcx>, ty: Ty<'tcx>) -> String {
         .map(|args| {
             args.tuple_fields()
                 .iter()
-                .map(|arg| ty_to_string(infcx, arg))
+                .map(|arg| ty_to_string(infcx, arg, None))
                 .collect::<Vec<_>>()
                 .join(", ")
         })
@@ -221,7 +232,7 @@ fn closure_as_fn_str<'tcx>(infcx: &InferCtxt<'tcx>, ty: Ty<'tcx>) -> String {
     let ret = if fn_sig.output().skip_binder().is_unit() {
         String::new()
     } else {
-        format!(" -> {}", ty_to_string(infcx, fn_sig.output().skip_binder()))
+        format!(" -> {}", ty_to_string(infcx, fn_sig.output().skip_binder(), None))
     };
     format!("fn({}){}", args, ret)
 }
@@ -368,6 +379,7 @@ fn bad_inference_failure_err(
 }
 
 impl<'tcx> TypeErrCtxt<'_, 'tcx> {
+    #[instrument(level = "debug", skip(self, error_code))]
     pub fn emit_inference_failure_err(
         &self,
         body_id: Option<hir::BodyId>,
@@ -406,7 +418,7 @@ pub fn emit_inference_failure_err(
         let mut infer_subdiags = Vec::new();
         let mut multi_suggestions = Vec::new();
         match kind {
-            InferSourceKind::LetBinding { insert_span, pattern_name, ty } => {
+            InferSourceKind::LetBinding { insert_span, pattern_name, ty, def_id } => {
                 infer_subdiags.push(SourceKindSubdiag::LetLike {
                     span: insert_span,
                     name: pattern_name.map(|name| name.to_string()).unwrap_or_else(String::new),
@@ -415,7 +427,7 @@ pub fn emit_inference_failure_err(
                     prefix: arg_data.kind.try_get_prefix().unwrap_or_default(),
                     arg_name: arg_data.name,
                     kind: if pattern_name.is_some() { "with_pattern" } else { "other" },
-                    type_name: ty_to_string(self, ty),
+                    type_name: ty_to_string(self, ty, def_id),
                 });
             }
             InferSourceKind::ClosureArg { insert_span, ty } => {
@@ -427,7 +439,7 @@ pub fn emit_inference_failure_err(
                     prefix: arg_data.kind.try_get_prefix().unwrap_or_default(),
                     arg_name: arg_data.name,
                     kind: "closure",
-                    type_name: ty_to_string(self, ty),
+                    type_name: ty_to_string(self, ty, None),
                 });
             }
             InferSourceKind::GenericArg {
@@ -456,33 +468,39 @@ pub fn emit_inference_failure_err(
                     parent_name,
                 });
 
-                let args = fmt_printer(self, Namespace::TypeNS)
-                    .comma_sep(generic_args.iter().copied().map(|arg| {
-                        if arg.is_suggestable(self.tcx, true) {
-                            return arg;
-                        }
+                let args = if self.infcx.tcx.get_diagnostic_item(sym::iterator_collect_fn)
+                    == Some(generics_def_id)
+                {
+                    "Vec<_>".to_string()
+                } else {
+                    fmt_printer(self, Namespace::TypeNS)
+                        .comma_sep(generic_args.iter().copied().map(|arg| {
+                            if arg.is_suggestable(self.tcx, true) {
+                                return arg;
+                            }
 
-                        match arg.unpack() {
-                            GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"),
-                            GenericArgKind::Type(_) => self
-                                .next_ty_var(TypeVariableOrigin {
-                                    span: rustc_span::DUMMY_SP,
-                                    kind: TypeVariableOriginKind::MiscVariable,
-                                })
-                                .into(),
-                            GenericArgKind::Const(arg) => self
-                                .next_const_var(
-                                    arg.ty(),
-                                    ConstVariableOrigin {
+                            match arg.unpack() {
+                                GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"),
+                                GenericArgKind::Type(_) => self
+                                    .next_ty_var(TypeVariableOrigin {
                                         span: rustc_span::DUMMY_SP,
-                                        kind: ConstVariableOriginKind::MiscVariable,
-                                    },
-                                )
-                                .into(),
-                        }
-                    }))
-                    .unwrap()
-                    .into_buffer();
+                                        kind: TypeVariableOriginKind::MiscVariable,
+                                    })
+                                    .into(),
+                                GenericArgKind::Const(arg) => self
+                                    .next_const_var(
+                                        arg.ty(),
+                                        ConstVariableOrigin {
+                                            span: rustc_span::DUMMY_SP,
+                                            kind: ConstVariableOriginKind::MiscVariable,
+                                        },
+                                    )
+                                    .into(),
+                            }
+                        }))
+                        .unwrap()
+                        .into_buffer()
+                };
 
                 if !have_turbofish {
                     infer_subdiags.push(SourceKindSubdiag::GenericSuggestion {
@@ -520,7 +538,7 @@ pub fn emit_inference_failure_err(
                 ));
             }
             InferSourceKind::ClosureReturn { ty, data, should_wrap_expr } => {
-                let ty_info = ty_to_string(self, ty);
+                let ty_info = ty_to_string(self, ty, None);
                 multi_suggestions.push(SourceKindMultiSuggestion::new_closure_return(
                     ty_info,
                     data,
@@ -608,6 +626,7 @@ enum InferSourceKind<'tcx> {
         insert_span: Span,
         pattern_name: Option<Ident>,
         ty: Ty<'tcx>,
+        def_id: Option<DefId>,
     },
     ClosureArg {
         insert_span: Span,
@@ -662,7 +681,7 @@ fn ty_localized_msg(&self, infcx: &InferCtxt<'tcx>) -> (&'static str, String) {
                 if ty.is_closure() {
                     ("closure", closure_as_fn_str(infcx, ty))
                 } else if !ty.is_ty_infer() {
-                    ("normal", ty_to_string(infcx, ty))
+                    ("normal", ty_to_string(infcx, ty, None))
                 } else {
                     ("other", String::new())
                 }
@@ -788,10 +807,18 @@ fn ty_cost(self, ty: Ty<'tcx>) -> usize {
     /// Uses `fn source_cost` to determine whether this inference source is preferable to
     /// previous sources. We generally prefer earlier sources.
     #[instrument(level = "debug", skip(self))]
-    fn update_infer_source(&mut self, new_source: InferSource<'tcx>) {
+    fn update_infer_source(&mut self, mut new_source: InferSource<'tcx>) {
         let cost = self.source_cost(&new_source) + self.attempt;
         debug!(?cost);
         self.attempt += 1;
+        if let Some(InferSource { kind: InferSourceKind::GenericArg { def_id: did, ..}, .. }) = self.infer_source
+            && let InferSourceKind::LetBinding { ref ty, ref mut def_id, ..} = new_source.kind
+            && ty.is_ty_infer()
+        {
+            // Customize the output so we talk about `let x: Vec<_> = iter.collect();` instead of
+            // `let x: _ = iter.collect();`, as this is a very common case.
+            *def_id = Some(did);
+        }
         if cost < self.infer_source_cost {
             self.infer_source_cost = cost;
             self.infer_source = Some(new_source);
@@ -852,7 +879,10 @@ fn generic_arg_contains_target(&self, arg: GenericArg<'tcx>) -> bool {
             match inner.unpack() {
                 GenericArgKind::Lifetime(_) => {}
                 GenericArgKind::Type(ty) => {
-                    if matches!(ty.kind(), ty::Opaque(..) | ty::Closure(..) | ty::Generator(..)) {
+                    if matches!(
+                        ty.kind(),
+                        ty::Alias(ty::Opaque, ..) | ty::Closure(..) | ty::Generator(..)
+                    ) {
                         // Opaque types can't be named by the user right now.
                         //
                         // Both the generic arguments of closures and generators can
@@ -1089,6 +1119,7 @@ fn visit_local(&mut self, local: &'tcx Local<'tcx>) {
                                 insert_span: local.pat.span.shrink_to_hi(),
                                 pattern_name: local.pat.simple_ident(),
                                 ty,
+                                def_id: None,
                             },
                         })
                     }
index 1f554c81eff8e1941453d2f0a544ec245cd16d51..fed9fda74bfb33ec462dfadf8200f54432691762 100644 (file)
@@ -226,13 +226,11 @@ fn report_trait_placeholder_mismatch(
             false
         };
 
-        let expected_trait_ref = self.cx.resolve_vars_if_possible(ty::TraitRef {
-            def_id: trait_def_id,
-            substs: expected_substs,
-        });
-        let actual_trait_ref = self
+        let expected_trait_ref = self
             .cx
-            .resolve_vars_if_possible(ty::TraitRef { def_id: trait_def_id, substs: actual_substs });
+            .resolve_vars_if_possible(self.cx.tcx.mk_trait_ref(trait_def_id, expected_substs));
+        let actual_trait_ref =
+            self.cx.resolve_vars_if_possible(self.cx.tcx.mk_trait_ref(trait_def_id, actual_substs));
 
         // Search the expected and actual trait references to see (a)
         // whether the sub/sup placeholders appear in them (sometimes
index 09f9aa3c84220981537e7c5734dd90c0a4dbb5a8..9bd2202d2601e6f54dcb7a7bac0a5c001e2eb325 100644 (file)
@@ -330,7 +330,7 @@ pub fn suggest_new_region_bound(
                             Applicability::MaybeIncorrect,
                         );
                     }
-                    if let Some((param_span, param_ty)) = param.clone() {
+                    if let Some((param_span, ref param_ty)) = param {
                         err.span_suggestion_verbose(
                             param_span,
                             add_static_bound,
index 73b5a2cc4ad233e6ba2c5a1b1750916e3dfc55b0..30ca9f41d6e6f8d73830b5c2b98150ee61e5dd05 100644 (file)
@@ -486,12 +486,14 @@ pub fn could_remove_semicolon(
             _ if self.same_type_modulo_infer(last_expr_ty, expected_ty) => {
                 StatementAsExpression::CorrectType
             }
-            (ty::Opaque(last_def_id, _), ty::Opaque(exp_def_id, _))
-                if last_def_id == exp_def_id =>
-            {
-                StatementAsExpression::CorrectType
-            }
-            (ty::Opaque(last_def_id, last_bounds), ty::Opaque(exp_def_id, exp_bounds)) => {
+            (
+                ty::Alias(ty::Opaque, ty::AliasTy { def_id: last_def_id, .. }),
+                ty::Alias(ty::Opaque, ty::AliasTy { def_id: exp_def_id, .. }),
+            ) if last_def_id == exp_def_id => StatementAsExpression::CorrectType,
+            (
+                ty::Alias(ty::Opaque, ty::AliasTy { def_id: last_def_id, substs: last_bounds, .. }),
+                ty::Alias(ty::Opaque, ty::AliasTy { def_id: exp_def_id, substs: exp_bounds, .. }),
+            ) => {
                 debug!(
                     "both opaque, likely future {:?} {:?} {:?} {:?}",
                     last_def_id, last_bounds, exp_def_id, exp_bounds
index f6946929bd23f58dbdd62d37fbbcedb6572f3831..8f53b1ccdf45829c758721072cf55d1063f730ff 100644 (file)
@@ -205,12 +205,11 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
             | ty::Dynamic(..)
             | ty::Never
             | ty::Tuple(..)
-            | ty::Projection(..)
+            | ty::Alias(..)
             | ty::Foreign(..)
             | ty::Param(..)
             | ty::Closure(..)
-            | ty::GeneratorWitness(..)
-            | ty::Opaque(..) => t.super_fold_with(self),
+            | ty::GeneratorWitness(..) => t.super_fold_with(self),
 
             ty::Placeholder(..) | ty::Bound(..) => bug!("unexpected type {:?}", t),
         }
index 7f27b35a54e4f8808c0350a30677abd61d77bed8..21b68ce998997a6826645c6ad0036f2af522bb7d 100644 (file)
@@ -103,6 +103,11 @@ fn binders<T>(
     where
         T: Relate<'tcx>,
     {
+        // GLB of a binder and itself is just itself
+        if a == b {
+            return Ok(a);
+        }
+
         debug!("binders(a={:?}, b={:?})", a, b);
         if a.skip_binder().has_escaping_bound_vars() || b.skip_binder().has_escaping_bound_vars() {
             // When higher-ranked types are involved, computing the GLB is
index eba65361ae6b2b923ec5e8f100b41e4dc904aea1..0ebc6d55bcba952678c86e6ff3c1dba91d8a11bd 100644 (file)
@@ -105,11 +105,13 @@ pub fn super_lattice_tys<'a, 'tcx: 'a, L>(
             Ok(v)
         }
 
-        (&ty::Opaque(a_def_id, _), &ty::Opaque(b_def_id, _)) if a_def_id == b_def_id => {
-            infcx.super_combine_tys(this, a, b)
-        }
-        (&ty::Opaque(did, ..), _) | (_, &ty::Opaque(did, ..))
-            if this.define_opaque_types() && did.is_local() =>
+        (
+            &ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, .. }),
+            &ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }),
+        ) if a_def_id == b_def_id => infcx.super_combine_tys(this, a, b),
+        (&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _)
+        | (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
+            if this.define_opaque_types() && def_id.is_local() =>
         {
             this.add_obligations(
                 infcx
index 97ed4729bd0d9e67af8250645909cc3ba567950a..c07ac1d3ace92a4375b03797534a725c7b26911e 100644 (file)
@@ -103,6 +103,11 @@ fn binders<T>(
     where
         T: Relate<'tcx>,
     {
+        // LUB of a binder and itself is just itself
+        if a == b {
+            return Ok(a);
+        }
+
         debug!("binders(a={:?}, b={:?})", a, b);
         if a.skip_binder().has_escaping_bound_vars() || b.skip_binder().has_escaping_bound_vars() {
             // When higher-ranked types are involved, computing the LUB is
index 2ce7cd8beba98a5e8cf4f154161e0e325df5f484..996148a709087161775337d9945aa262c7888749 100644 (file)
@@ -2014,31 +2014,54 @@ fn replace_param_and_infer_substs_with_placeholder<'tcx>(
     tcx: TyCtxt<'tcx>,
     substs: SubstsRef<'tcx>,
 ) -> SubstsRef<'tcx> {
-    tcx.mk_substs(substs.iter().enumerate().map(|(idx, arg)| {
-        match arg.unpack() {
-            GenericArgKind::Type(_) if arg.has_non_region_param() || arg.has_non_region_infer() => {
-                tcx.mk_ty(ty::Placeholder(ty::PlaceholderType {
+    struct ReplaceParamAndInferWithPlaceholder<'tcx> {
+        tcx: TyCtxt<'tcx>,
+        idx: usize,
+    }
+
+    impl<'tcx> TypeFolder<'tcx> for ReplaceParamAndInferWithPlaceholder<'tcx> {
+        fn tcx(&self) -> TyCtxt<'tcx> {
+            self.tcx
+        }
+
+        fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
+            if let ty::Infer(_) = t.kind() {
+                self.tcx.mk_ty(ty::Placeholder(ty::PlaceholderType {
                     universe: ty::UniverseIndex::ROOT,
-                    name: ty::BoundVar::from_usize(idx),
+                    name: ty::BoundVar::from_usize({
+                        let idx = self.idx;
+                        self.idx += 1;
+                        idx
+                    }),
                 }))
-                .into()
+            } else {
+                t.super_fold_with(self)
             }
-            GenericArgKind::Const(ct) if ct.has_non_region_infer() || ct.has_non_region_param() => {
-                let ty = ct.ty();
-                // If the type references param or infer, replace that too...
+        }
+
+        fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> {
+            if let ty::ConstKind::Infer(_) = c.kind() {
+                let ty = c.ty();
+                // If the type references param or infer then ICE ICE ICE
                 if ty.has_non_region_param() || ty.has_non_region_infer() {
-                    bug!("const `{ct}`'s type should not reference params or types");
+                    bug!("const `{c}`'s type should not reference params or types");
                 }
-                tcx.mk_const(
+                self.tcx.mk_const(
                     ty::PlaceholderConst {
                         universe: ty::UniverseIndex::ROOT,
-                        name: ty::BoundVar::from_usize(idx),
+                        name: ty::BoundVar::from_usize({
+                            let idx = self.idx;
+                            self.idx += 1;
+                            idx
+                        }),
                     },
                     ty,
                 )
-                .into()
+            } else {
+                c.super_fold_with(self)
             }
-            _ => arg,
         }
-    }))
+    }
+
+    substs.fold_with(&mut ReplaceParamAndInferWithPlaceholder { tcx, idx: 0 })
 }
index f6bc4db0d59dfc5466f3927e3a6c10ce55d552c3..1f9d86a78d6e50912f7cc3dba6e0b006391a33aa 100644 (file)
@@ -275,13 +275,13 @@ fn push_outlives(
     ///   `ProjectionEq(projection = ?U)`, `ProjectionEq(other_projection = ?U)`.
     fn relate_projection_ty(
         &mut self,
-        projection_ty: ty::ProjectionTy<'tcx>,
+        projection_ty: ty::AliasTy<'tcx>,
         value_ty: Ty<'tcx>,
     ) -> Ty<'tcx> {
         use rustc_span::DUMMY_SP;
 
         match *value_ty.kind() {
-            ty::Projection(other_projection_ty) => {
+            ty::Alias(ty::Projection, other_projection_ty) => {
                 let var = self.infcx.next_ty_var(TypeVariableOrigin {
                     kind: TypeVariableOriginKind::MiscVariable,
                     span: DUMMY_SP,
@@ -335,7 +335,9 @@ fn relate_ty_var<PAIR: VidValuePair<'tcx>>(
                 return Ok(value_ty);
             }
 
-            ty::Projection(projection_ty) if D::normalization() == NormalizationStrategy::Lazy => {
+            ty::Alias(ty::Projection, projection_ty)
+                if D::normalization() == NormalizationStrategy::Lazy =>
+            {
                 return Ok(self.relate_projection_ty(projection_ty, self.infcx.tcx.mk_ty_var(vid)));
             }
 
@@ -406,8 +408,8 @@ fn relate_opaques(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<
             }
         };
         let (a, b) = match (a.kind(), b.kind()) {
-            (&ty::Opaque(..), _) => (a, generalize(b, false)?),
-            (_, &ty::Opaque(..)) => (generalize(a, true)?, b),
+            (&ty::Alias(ty::Opaque, ..), _) => (a, generalize(b, false)?),
+            (_, &ty::Alias(ty::Opaque, ..)) => (generalize(a, true)?, b),
             _ => unreachable!(),
         };
         let cause = ObligationCause::dummy_with_span(self.delegate.span());
@@ -608,26 +610,30 @@ fn tys(&mut self, a: Ty<'tcx>, mut b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>>
 
             (&ty::Infer(ty::TyVar(vid)), _) => self.relate_ty_var((vid, b)),
 
-            (&ty::Opaque(a_def_id, _), &ty::Opaque(b_def_id, _)) if a_def_id == b_def_id => {
-                infcx.super_combine_tys(self, a, b).or_else(|err| {
-                    self.tcx().sess.delay_span_bug(
-                        self.delegate.span(),
-                        "failure to relate an opaque to itself should result in an error later on",
-                    );
-                    if a_def_id.is_local() { self.relate_opaques(a, b) } else { Err(err) }
-                })
-            }
-            (&ty::Opaque(did, ..), _) | (_, &ty::Opaque(did, ..)) if did.is_local() => {
+            (
+                &ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, .. }),
+                &ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }),
+            ) if a_def_id == b_def_id => infcx.super_combine_tys(self, a, b).or_else(|err| {
+                self.tcx().sess.delay_span_bug(
+                    self.delegate.span(),
+                    "failure to relate an opaque to itself should result in an error later on",
+                );
+                if a_def_id.is_local() { self.relate_opaques(a, b) } else { Err(err) }
+            }),
+            (&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _)
+            | (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
+                if def_id.is_local() =>
+            {
                 self.relate_opaques(a, b)
             }
 
-            (&ty::Projection(projection_ty), _)
+            (&ty::Alias(ty::Projection, projection_ty), _)
                 if D::normalization() == NormalizationStrategy::Lazy =>
             {
                 Ok(self.relate_projection_ty(projection_ty, b))
             }
 
-            (_, &ty::Projection(projection_ty))
+            (_, &ty::Alias(ty::Projection, projection_ty))
                 if D::normalization() == NormalizationStrategy::Lazy =>
             {
                 Ok(self.relate_projection_ty(projection_ty, a))
index 524f7a39ebbfb8f72077340dd534b13d8aafa330..a130fde47ed5c4d7c0ccdae1536387b649f7cc1b 100644 (file)
@@ -66,7 +66,9 @@ pub fn replace_opaque_types_with_inference_vars<T: TypeFoldable<'tcx>>(
             lt_op: |lt| lt,
             ct_op: |ct| ct,
             ty_op: |ty| match *ty.kind() {
-                ty::Opaque(def_id, _substs) if replace_opaque_type(def_id) => {
+                ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. })
+                    if replace_opaque_type(def_id) =>
+                {
                     let def_span = self.tcx.def_span(def_id);
                     let span = if span.contains(def_span) { def_span } else { span };
                     let code = traits::ObligationCauseCode::OpaqueReturnType(None);
@@ -104,7 +106,7 @@ pub fn handle_opaque_type(
         }
         let (a, b) = if a_is_expected { (a, b) } else { (b, a) };
         let process = |a: Ty<'tcx>, b: Ty<'tcx>, a_is_expected| match *a.kind() {
-            ty::Opaque(def_id, substs) if def_id.is_local() => {
+            ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) if def_id.is_local() => {
                 let def_id = def_id.expect_local();
                 let origin = match self.defining_use_anchor {
                     DefiningAnchor::Bind(_) => {
@@ -147,18 +149,19 @@ pub fn handle_opaque_type(
                     DefiningAnchor::Bubble => self.opaque_ty_origin_unchecked(def_id, cause.span),
                     DefiningAnchor::Error => return None,
                 };
-                if let ty::Opaque(did2, _) = *b.kind() {
+                if let ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }) = *b.kind() {
                     // We could accept this, but there are various ways to handle this situation, and we don't
                     // want to make a decision on it right now. Likely this case is so super rare anyway, that
                     // no one encounters it in practice.
                     // It does occur however in `fn fut() -> impl Future<Output = i32> { async { 42 } }`,
                     // where it is of no concern, so we only check for TAITs.
-                    if let Some(OpaqueTyOrigin::TyAlias) =
-                        did2.as_local().and_then(|did2| self.opaque_type_origin(did2, cause.span))
+                    if let Some(OpaqueTyOrigin::TyAlias) = b_def_id
+                        .as_local()
+                        .and_then(|b_def_id| self.opaque_type_origin(b_def_id, cause.span))
                     {
                         self.tcx.sess.emit_err(OpaqueHiddenTypeDiag {
                             span: cause.span,
-                            hidden_type: self.tcx.def_span(did2),
+                            hidden_type: self.tcx.def_span(b_def_id),
                             opaque_type: self.tcx.def_span(def_id),
                         });
                     }
@@ -475,7 +478,7 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
                 substs.as_generator().resume_ty().visit_with(self);
             }
 
-            ty::Opaque(def_id, ref substs) => {
+            ty::Alias(ty::Opaque, ty::AliasTy { def_id, ref substs, .. }) => {
                 // Skip lifetime paramters that are not captures.
                 let variances = self.tcx.variances_of(*def_id);
 
@@ -486,11 +489,11 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
                 }
             }
 
-            ty::Projection(proj)
-                if self.tcx.def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder =>
+            ty::Alias(ty::Projection, proj)
+                if self.tcx.def_kind(proj.def_id) == DefKind::ImplTraitPlaceholder =>
             {
                 // Skip lifetime paramters that are not captures.
-                let variances = self.tcx.variances_of(proj.item_def_id);
+                let variances = self.tcx.variances_of(proj.def_id);
 
                 for (v, s) in std::iter::zip(variances, proj.substs.iter()) {
                     if *v != ty::Variance::Bivariant {
@@ -563,9 +566,9 @@ fn register_hidden_type(
                     // We can't normalize associated types from `rustc_infer`,
                     // but we can eagerly register inference variables for them.
                     // FIXME(RPITIT): Don't replace RPITITs with inference vars.
-                    ty::Projection(projection_ty)
+                    ty::Alias(ty::Projection, projection_ty)
                         if !projection_ty.has_escaping_bound_vars()
-                            && tcx.def_kind(projection_ty.item_def_id)
+                            && tcx.def_kind(projection_ty.def_id)
                                 != DefKind::ImplTraitPlaceholder =>
                     {
                         self.infer_projection(
@@ -578,17 +581,16 @@ fn register_hidden_type(
                     }
                     // Replace all other mentions of the same opaque type with the hidden type,
                     // as the bounds must hold on the hidden type after all.
-                    ty::Opaque(def_id2, substs2)
+                    ty::Alias(ty::Opaque, ty::AliasTy { def_id: def_id2, substs: substs2, .. })
                         if def_id.to_def_id() == def_id2 && substs == substs2 =>
                     {
                         hidden_ty
                     }
                     // FIXME(RPITIT): This can go away when we move to associated types
-                    ty::Projection(proj)
-                        if def_id.to_def_id() == proj.item_def_id && substs == proj.substs =>
-                    {
-                        hidden_ty
-                    }
+                    ty::Alias(
+                        ty::Projection,
+                        ty::AliasTy { def_id: def_id2, substs: substs2, .. },
+                    ) if def_id.to_def_id() == def_id2 && substs == substs2 => hidden_ty,
                     _ => ty,
                 },
                 lt_op: |lt| lt,
index 14ee9f05190102b8f7067bf28a1f56a7b332b9b5..aa2b5d067d266d8742c322ea147ffe5bc4905442 100644 (file)
@@ -23,7 +23,7 @@ pub enum Component<'tcx> {
     // is not in a position to judge which is the best technique, so
     // we just product the projection as a component and leave it to
     // the consumer to decide (but see `EscapingProjection` below).
-    Projection(ty::ProjectionTy<'tcx>),
+    Projection(ty::AliasTy<'tcx>),
 
     // In the case where a projection has escaping regions -- meaning
     // regions bound within the type itself -- we always use
@@ -130,7 +130,7 @@ fn compute_components<'tcx>(
             // outlives any other lifetime, which is unsound.
             // See https://github.com/rust-lang/rust/issues/84305 for
             // more details.
-            ty::Opaque(def_id, substs) => {
+            ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
                 out.push(Component::Opaque(def_id, substs));
             },
 
@@ -142,7 +142,7 @@ fn compute_components<'tcx>(
             // trait-ref. Therefore, if we see any higher-ranked regions,
             // we simply fallback to the most restrictive rule, which
             // requires that `Pi: 'a` for all `i`.
-            ty::Projection(ref data) => {
+            ty::Alias(ty::Projection, ref data) => {
                 if !data.has_escaping_bound_vars() {
                     // best case: no escaping regions, so push the
                     // projection and skip the subtree (thus generating no
index 6ca884799aa6fb3b77b5891c6ff20175f9aab922..ccae7165d80d2fac9d859c26b64031742bcbd244 100644 (file)
@@ -338,7 +338,7 @@ fn opaque_must_outlive(
             substs,
             true,
             |ty| match *ty.kind() {
-                ty::Opaque(def_id, substs) => (def_id, substs),
+                ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => (def_id, substs),
                 _ => bug!("expected only projection types from env, not {:?}", ty),
             },
         );
@@ -349,17 +349,19 @@ fn projection_must_outlive(
         &mut self,
         origin: infer::SubregionOrigin<'tcx>,
         region: ty::Region<'tcx>,
-        projection_ty: ty::ProjectionTy<'tcx>,
+        projection_ty: ty::AliasTy<'tcx>,
     ) {
         self.generic_must_outlive(
             origin,
             region,
             GenericKind::Projection(projection_ty),
-            projection_ty.item_def_id,
+            projection_ty.def_id,
             projection_ty.substs,
             false,
             |ty| match ty.kind() {
-                ty::Projection(projection_ty) => (projection_ty.item_def_id, projection_ty.substs),
+                ty::Alias(ty::Projection, projection_ty) => {
+                    (projection_ty.def_id, projection_ty.substs)
+                }
                 _ => bug!("expected only projection types from env, not {:?}", ty),
             },
         );
index f470b2eb8c1939a4acef1abd6f12e7b4c6a35b97..136da4a3cb12a110eaaffd96606370628219f855 100644 (file)
@@ -178,7 +178,7 @@ fn bound_from_single_component(
             ),
             Component::Projection(projection_ty) => self.projection_opaque_bounds(
                 GenericKind::Projection(projection_ty),
-                projection_ty.item_def_id,
+                projection_ty.def_id,
                 projection_ty.substs,
                 visited,
             ),
index eb6deee291cf7ab1b236be9e1c9283348538ee82..4667d99ff00080daacd1ad224218c596b48fb987 100644 (file)
@@ -16,12 +16,12 @@ impl<'tcx> InferCtxt<'tcx> {
     pub fn infer_projection(
         &self,
         param_env: ty::ParamEnv<'tcx>,
-        projection_ty: ty::ProjectionTy<'tcx>,
+        projection_ty: ty::AliasTy<'tcx>,
         cause: ObligationCause<'tcx>,
         recursion_depth: usize,
         obligations: &mut Vec<PredicateObligation<'tcx>>,
     ) -> Ty<'tcx> {
-        let def_id = projection_ty.item_def_id;
+        let def_id = projection_ty.def_id;
         let ty_var = self.next_ty_var(TypeVariableOrigin {
             kind: TypeVariableOriginKind::NormalizeProjectionType,
             span: self.tcx.def_span(def_id),
index 985c5d360db8e814b4a7b9b7e69924e2ae9fabcc..9a427ceacd0a7c63737805a2cb370adfa6788d7c 100644 (file)
@@ -169,7 +169,7 @@ pub struct Verify<'tcx> {
 #[derive(Copy, Clone, PartialEq, Eq, Hash, TypeFoldable, TypeVisitable)]
 pub enum GenericKind<'tcx> {
     Param(ty::ParamTy),
-    Projection(ty::ProjectionTy<'tcx>),
+    Projection(ty::AliasTy<'tcx>),
     Opaque(DefId, SubstsRef<'tcx>),
 }
 
@@ -773,7 +773,7 @@ impl<'tcx> GenericKind<'tcx> {
     pub fn to_ty(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
         match *self {
             GenericKind::Param(ref p) => p.to_ty(tcx),
-            GenericKind::Projection(ref p) => tcx.mk_projection(p.item_def_id, p.substs),
+            GenericKind::Projection(ref p) => tcx.mk_projection(p.def_id, p.substs),
             GenericKind::Opaque(def_id, substs) => tcx.mk_opaque(def_id, substs),
         }
     }
index 2c6987cc3f45670d5290b6ba8d04ecc9d3d0aae2..bd38b52ba34a7eab0fbcbae019d94d58dd0d2c40 100644 (file)
@@ -130,12 +130,16 @@ fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
                 Ok(self.tcx().ty_error_with_guaranteed(e))
             }
 
-            (&ty::Opaque(a_def_id, _), &ty::Opaque(b_def_id, _)) if a_def_id == b_def_id => {
+            (
+                &ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, .. }),
+                &ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }),
+            ) if a_def_id == b_def_id => {
                 self.fields.infcx.super_combine_tys(self, a, b)?;
                 Ok(a)
             }
-            (&ty::Opaque(did, ..), _) | (_, &ty::Opaque(did, ..))
-                if self.fields.define_opaque_types && did.is_local() =>
+            (&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _)
+            | (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
+                if self.fields.define_opaque_types && def_id.is_local() =>
             {
                 self.fields.obligations.extend(
                     infcx
@@ -213,6 +217,11 @@ fn binders<T>(
     where
         T: Relate<'tcx>,
     {
+        // A binder is always a subtype of itself if it's structually equal to itself
+        if a == b {
+            return Ok(a);
+        }
+
         self.fields.higher_ranked_sub(a, b, self.a_is_expected)?;
         Ok(a)
     }
index 5d22f9f972e10626b34adecb59283ba04905db0e..aade57be9fe6ef1f17389df22b23518193a1a243 100644 (file)
@@ -77,11 +77,11 @@ pub struct ProjectionCacheStorage<'tcx> {
 
 #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
 pub struct ProjectionCacheKey<'tcx> {
-    ty: ty::ProjectionTy<'tcx>,
+    ty: ty::AliasTy<'tcx>,
 }
 
 impl<'tcx> ProjectionCacheKey<'tcx> {
-    pub fn new(ty: ty::ProjectionTy<'tcx>) -> Self {
+    pub fn new(ty: ty::AliasTy<'tcx>) -> Self {
         Self { ty }
     }
 }
index 512e6079f43a02fa7ada619ec45164ccce254748..8f0bd3a9abe5e29ac32a3a754f3516790bd9a4c6 100644 (file)
@@ -259,8 +259,7 @@ fn elaborate(&mut self, obligation: &PredicateObligation<'tcx>) {
                             Component::Projection(projection) => {
                                 // We might end up here if we have `Foo<<Bar as Baz>::Assoc>: 'a`.
                                 // With this, we can deduce that `<Bar as Baz>::Assoc: 'a`.
-                                let ty =
-                                    tcx.mk_projection(projection.item_def_id, projection.substs);
+                                let ty = tcx.mk_projection(projection.def_id, projection.substs);
                                 Some(ty::PredicateKind::Clause(ty::Clause::TypeOutlives(
                                     ty::OutlivesPredicate(ty, r_min),
                                 )))
index e405013dcabf83047cb34a88c635e6d4d7ec8a28..87c44638a8de1918883375cd0d6357dfebd8a16b 100644 (file)
@@ -204,14 +204,13 @@ fn scan_escape(chars: &mut Chars<'_>, is_byte: bool) -> Result<char, EscapeError
                         })?;
                     }
                     Some(c) => {
-                        let digit =
+                        let digit: u32 =
                             c.to_digit(16).ok_or(EscapeError::InvalidCharInUnicodeEscape)?;
                         n_digits += 1;
                         if n_digits > 6 {
                             // Stop updating value since we're sure that it's incorrect already.
                             continue;
                         }
-                        let digit = digit as u32;
                         value = value * 16 + digit;
                     }
                 };
index 0932eee92373d764361d9a87249d6693c9c353cd..43862570e80954aa8c11dbd80e4aa4e060e66ed9 100644 (file)
@@ -3016,8 +3016,8 @@ fn structurally_same_type_impl<'tcx>(
                         | (Closure(..), Closure(..))
                         | (Generator(..), Generator(..))
                         | (GeneratorWitness(..), GeneratorWitness(..))
-                        | (Projection(..), Projection(..))
-                        | (Opaque(..), Opaque(..)) => false,
+                        | (Alias(ty::Projection, ..), Alias(ty::Projection, ..))
+                        | (Alias(ty::Opaque, ..), Alias(ty::Opaque, ..)) => false,
 
                         // These definitely should have been caught above.
                         (Bool, Bool) | (Char, Char) | (Never, Never) | (Str, Str) => unreachable!(),
index e6a0d7e60ca772b10cd67b0630dbdc50724a4907..40b2588388d66886353297cc50a5070b0bdd6069 100644 (file)
@@ -1258,7 +1258,7 @@ pub fn get_associated_type(
         tcx.associated_items(trait_id)
             .find_by_name_and_kind(tcx, Ident::from_str(name), ty::AssocKind::Type, trait_id)
             .and_then(|assoc| {
-                let proj = tcx.mk_projection(assoc.def_id, tcx.mk_substs_trait(self_ty, []));
+                let proj = tcx.mk_projection(assoc.def_id, [self_ty]);
                 tcx.try_normalize_erasing_regions(self.param_env, proj).ok()
             })
     }
index 03d6f4fd92687f192ac40cbf540209b057bdfeae..42442cfb1904d4ddfdd621d53b156e62ec1186f2 100644 (file)
@@ -82,7 +82,7 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
             let Some(proj_term) = proj.term.ty() else { continue };
 
             let proj_ty =
-                cx.tcx.mk_projection(proj.projection_ty.item_def_id, proj.projection_ty.substs);
+                cx.tcx.mk_projection(proj.projection_ty.def_id, proj.projection_ty.substs);
             // For every instance of the projection type in the bounds,
             // replace them with the term we're assigning to the associated
             // type in our opaque type.
@@ -97,7 +97,7 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
             // with `impl Send: OtherTrait`.
             for (assoc_pred, assoc_pred_span) in cx
                 .tcx
-                .bound_explicit_item_bounds(proj.projection_ty.item_def_id)
+                .bound_explicit_item_bounds(proj.projection_ty.def_id)
                 .subst_iter_copied(cx.tcx, &proj.projection_ty.substs)
             {
                 let assoc_pred = assoc_pred.fold_with(proj_replacer);
@@ -117,7 +117,7 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
                     // then we can emit a suggestion to add the bound.
                     let add_bound = match (proj_term.kind(), assoc_pred.kind().skip_binder()) {
                         (
-                            ty::Opaque(def_id, _),
+                            ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }),
                             ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)),
                         ) => Some(AddBound {
                             suggest_span: cx.tcx.def_span(*def_id).shrink_to_hi(),
index 8446da6098ee9641764fa423412368ebbbd524c4..8e27bc03c489aeedf8ab0b5d2cd15776c8cff157 100644 (file)
@@ -1139,18 +1139,20 @@ fn check_type_for_ffi(&self, cache: &mut FxHashSet<Ty<'tcx>>, ty: Ty<'tcx>) -> F
 
             // While opaque types are checked for earlier, if a projection in a struct field
             // normalizes to an opaque type, then it will reach this branch.
-            ty::Opaque(..) => {
+            ty::Alias(ty::Opaque, ..) => {
                 FfiUnsafe { ty, reason: fluent::lint_improper_ctypes_opaque, help: None }
             }
 
             // `extern "C" fn` functions can have type parameters, which may or may not be FFI-safe,
             //  so they are currently ignored for the purposes of this lint.
-            ty::Param(..) | ty::Projection(..) if matches!(self.mode, CItemKind::Definition) => {
+            ty::Param(..) | ty::Alias(ty::Projection, ..)
+                if matches!(self.mode, CItemKind::Definition) =>
+            {
                 FfiSafe
             }
 
             ty::Param(..)
-            | ty::Projection(..)
+            | ty::Alias(ty::Projection, ..)
             | ty::Infer(..)
             | ty::Bound(..)
             | ty::Error(_)
@@ -1205,7 +1207,7 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
                     return ControlFlow::CONTINUE;
                 }
 
-                if let ty::Opaque(..) = ty.kind() {
+                if let ty::Alias(ty::Opaque, ..) = ty.kind() {
                     ControlFlow::Break(ty)
                 } else {
                     ty.super_visit_with(self)
index dc352778f1d1bcdab92dea9ea4f68f698fc02f2e..d628a18dd01c5875c36e5ad8bebb8940b8f89cc6 100644 (file)
@@ -96,7 +96,7 @@ fn check_stmt(&mut self, cx: &LateContext<'_>, s: &hir::Stmt<'_>) {
 
         if let hir::ExprKind::Match(await_expr, _arms, hir::MatchSource::AwaitDesugar) = expr.kind
             && let ty = cx.typeck_results().expr_ty(&await_expr)
-            && let ty::Opaque(future_def_id, _) = ty.kind()
+            && let ty::Alias(ty::Opaque, ty::AliasTy { def_id: future_def_id, .. }) = ty.kind()
             && cx.tcx.ty_is_opaque_future(ty)
             // FIXME: This also includes non-async fns that return `impl Future`.
             && let async_fn_def_id = cx.tcx.parent(*future_def_id)
@@ -251,7 +251,7 @@ fn is_ty_must_use<'tcx>(
                         .map(|inner| MustUsePath::Boxed(Box::new(inner)))
                 }
                 ty::Adt(def, _) => is_def_must_use(cx, def.did(), span),
-                ty::Opaque(def, _) => {
+                ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => {
                     elaborate_predicates_with_span(
                         cx.tcx,
                         cx.tcx.explicit_item_bounds(def).iter().cloned(),
index df0e17dea3c051495593062c68485307b168bf01..33cb35e60ebb6cfc1edf37d68a4262b57956e19b 100644 (file)
 
 declare_lint! {
     /// The `trivial_casts` lint detects trivial casts which could be replaced
-    /// with coercion, which may require [type ascription] or a temporary
-    /// variable.
+    /// with coercion, which may require a temporary variable.
     ///
     /// ### Example
     ///
     /// with FFI interfaces or complex type aliases, where it triggers
     /// incorrectly, or in situations where it will be more difficult to
     /// clearly express the intent. It may be possible that this will become a
-    /// warning in the future, possibly with [type ascription] providing a
-    /// convenient way to work around the current issues. See [RFC 401] for
-    /// historical context.
-    ///
-    /// [type ascription]: https://github.com/rust-lang/rust/issues/23416
-    /// [RFC 401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md
+    /// warning in the future, possibly with an explicit syntax for coercions
+    /// providing a convenient way to work around the current issues.
+    /// See [RFC 401 (coercions)][rfc-401], [RFC 803 (type ascription)][rfc-803] and
+    /// [RFC 3307 (remove type ascription)][rfc-3307] for historical context.
+    ///
+    /// [rfc-401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md
+    /// [rfc-803]: https://github.com/rust-lang/rfcs/blob/master/text/0803-type-ascription.md
+    /// [rfc-3307]: https://github.com/rust-lang/rfcs/blob/master/text/3307-de-rfc-type-ascription.md
     pub TRIVIAL_CASTS,
     Allow,
     "detects trivial casts which could be removed"
     /// with FFI interfaces or complex type aliases, where it triggers
     /// incorrectly, or in situations where it will be more difficult to
     /// clearly express the intent. It may be possible that this will become a
-    /// warning in the future, possibly with [type ascription] providing a
-    /// convenient way to work around the current issues. See [RFC 401] for
-    /// historical context.
-    ///
-    /// [type ascription]: https://github.com/rust-lang/rust/issues/23416
-    /// [RFC 401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md
+    /// warning in the future, possibly with an explicit syntax for coercions
+    /// providing a convenient way to work around the current issues.
+    /// See [RFC 401 (coercions)][rfc-401], [RFC 803 (type ascription)][rfc-803] and
+    /// [RFC 3307 (remove type ascription)][rfc-3307] for historical context.
+    ///
+    /// [rfc-401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md
+    /// [rfc-803]: https://github.com/rust-lang/rfcs/blob/master/text/0803-type-ascription.md
+    /// [rfc-3307]: https://github.com/rust-lang/rfcs/blob/master/text/3307-de-rfc-type-ascription.md
     pub TRIVIAL_NUMERIC_CASTS,
     Allow,
     "detects trivial casts of numeric types which could be removed"
     };
 }
 
+declare_lint! {
+    /// The `invalid_alignment` lint detects dereferences of misaligned pointers during
+    /// constant evluation.
+    ///
+    /// ### Example
+    ///
+    /// ```rust,compile_fail
+    /// #![feature(const_ptr_read)]
+    /// const FOO: () = unsafe {
+    ///     let x = &[0_u8; 4];
+    ///     let y = x.as_ptr().cast::<u32>();
+    ///     y.read(); // the address of a `u8` array is unknown and thus we don't know if
+    ///     // it is aligned enough for reading a `u32`.
+    /// };
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// The compiler allowed dereferencing raw pointers irrespective of alignment
+    /// during const eval due to the const evaluator at the time not making it easy
+    /// or cheap to check. Now that it is both, this is not accepted anymore.
+    ///
+    /// Since it was undefined behaviour to begin with, this breakage does not violate
+    /// Rust's stability guarantees. Using undefined behaviour can cause arbitrary
+    /// behaviour, including failure to build.
+    ///
+    /// [future-incompatible]: ../index.md#future-incompatible-lints
+    pub INVALID_ALIGNMENT,
+    Deny,
+    "raw pointers must be aligned before dereferencing",
+    @future_incompatible = FutureIncompatibleInfo {
+        reference: "issue #68585 <https://github.com/rust-lang/rust/issues/104616>",
+        reason: FutureIncompatibilityReason::FutureReleaseErrorReportNow,
+    };
+}
+
 declare_lint! {
     /// The `exported_private_dependencies` lint detects private dependencies
     /// that are exposed in a public interface.
index 684835d8c5c86b88e60713d8639ab1962a4eb0da..13f06fe747349d8084b9b53d1a303c75f9b0278b 100644 (file)
@@ -192,7 +192,7 @@ fn check(slug: &syn::Path) -> Option<Mismatch> {
         let crate_name = std::env::var("CARGO_CRATE_NAME").ok()?;
 
         // If we're not in a "rustc_" crate, bail.
-        let Some(("rustc", slug_prefix)) = crate_name.split_once("_") else { return None };
+        let Some(("rustc", slug_prefix)) = crate_name.split_once('_') else { return None };
 
         let slug_name = slug.segments.first()?.ident.to_string();
         if !slug_name.starts_with(slug_prefix) {
index 9f2ac5112f1cd9d3aa4b78a9cf1deeda1c0ae799..82f6812026a7d73a185a526b7390173f4602f996 100644 (file)
@@ -372,46 +372,21 @@ fn generate_inner_field_code(
                 }
             }
             (Meta::Path(_), "subdiagnostic") => {
-                return Ok(quote! { #diag.subdiagnostic(#binding); });
+                if FieldInnerTy::from_type(&info.binding.ast().ty).will_iterate() {
+                    let DiagnosticDeriveKind::Diagnostic { handler } = &self.parent.kind else {
+                        // No eager translation for lints.
+                        return Ok(quote! { #diag.subdiagnostic(#binding); });
+                    };
+                    return Ok(quote! { #diag.eager_subdiagnostic(#handler, #binding); });
+                } else {
+                    return Ok(quote! { #diag.subdiagnostic(#binding); });
+                }
             }
-            (Meta::NameValue(_), "subdiagnostic") => {
+            (Meta::List(_), "subdiagnostic") => {
                 throw_invalid_attr!(attr, &meta, |diag| {
-                    diag.help("`eager` is the only supported nested attribute for `subdiagnostic`")
+                    diag.help("`subdiagnostic` does not support nested attributes")
                 })
             }
-            (Meta::List(MetaList { ref nested, .. }), "subdiagnostic") => {
-                if nested.len() != 1 {
-                    throw_invalid_attr!(attr, &meta, |diag| {
-                        diag.help(
-                            "`eager` is the only supported nested attribute for `subdiagnostic`",
-                        )
-                    })
-                }
-
-                let handler = match &self.parent.kind {
-                    DiagnosticDeriveKind::Diagnostic { handler } => handler,
-                    DiagnosticDeriveKind::LintDiagnostic => {
-                        throw_invalid_attr!(attr, &meta, |diag| {
-                            diag.help("eager subdiagnostics are not supported on lints")
-                        })
-                    }
-                };
-
-                let nested_attr = nested.first().expect("pop failed for single element list");
-                match nested_attr {
-                    NestedMeta::Meta(meta @ Meta::Path(_))
-                        if meta.path().segments.last().unwrap().ident.to_string().as_str()
-                            == "eager" =>
-                    {
-                        return Ok(quote! { #diag.eager_subdiagnostic(#handler, #binding); });
-                    }
-                    _ => {
-                        throw_invalid_nested_attr!(attr, nested_attr, |diag| {
-                            diag.help("`eager` is the only supported nested attribute for `subdiagnostic`")
-                        })
-                    }
-                }
-            }
             _ => (),
         }
 
index af7b0793a957413b38283188befe5def41f1e234..4370d4bd758d21f3112c664cd7a96f1456585243 100644 (file)
@@ -1527,13 +1527,15 @@ fn filter<'a>(sess: &Session, path: Option<&'a Path>) -> Option<&'a Path> {
                 if let Some(virtual_dir) = &sess.opts.unstable_opts.simulate_remapped_rust_src_base
                 {
                     if let Some(real_dir) = &sess.opts.real_rust_source_base_dir {
-                        if let rustc_span::FileName::Real(ref mut old_name) = name {
-                            if let rustc_span::RealFileName::LocalPath(local) = old_name {
-                                if let Ok(rest) = local.strip_prefix(real_dir) {
-                                    *old_name = rustc_span::RealFileName::Remapped {
-                                        local_path: None,
-                                        virtual_name: virtual_dir.join(rest),
-                                    };
+                        for subdir in ["library", "compiler"] {
+                            if let rustc_span::FileName::Real(ref mut old_name) = name {
+                                if let rustc_span::RealFileName::LocalPath(local) = old_name {
+                                    if let Ok(rest) = local.strip_prefix(real_dir.join(subdir)) {
+                                        *old_name = rustc_span::RealFileName::Remapped {
+                                            local_path: None,
+                                            virtual_name: virtual_dir.join(subdir).join(rest),
+                                        };
+                                    }
                                 }
                             }
                         }
index 29f9e82da75cc58b9b6f50b2f090dde45e50d7d2..856f5bc4645fdd34d691e7ab3a824ef603da15d1 100644 (file)
@@ -1111,8 +1111,8 @@ fn should_encode_trait_impl_trait_tys<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) ->
     // associated types.
     tcx.fn_sig(trait_item_def_id).skip_binder().output().walk().any(|arg| {
         if let ty::GenericArgKind::Type(ty) = arg.unpack()
-            && let ty::Projection(data) = ty.kind()
-            && tcx.def_kind(data.item_def_id) == DefKind::ImplTraitPlaceholder
+            && let ty::Alias(ty::Projection, data) = ty.kind()
+            && tcx.def_kind(data.def_id) == DefKind::ImplTraitPlaceholder
         {
             true
         } else {
index db4fe6f886b2549044777dd6f0e7b399fc0c3bfc..3bc331e19c1ccddb0e8ee8b7f5cb282f3ad934cc 100644 (file)
@@ -1847,7 +1847,7 @@ impl<'tcx> Operand<'tcx> {
     pub fn function_handle(
         tcx: TyCtxt<'tcx>,
         def_id: DefId,
-        substs: SubstsRef<'tcx>,
+        substs: impl IntoIterator<Item = GenericArg<'tcx>>,
         span: Span,
     ) -> Self {
         let ty = tcx.mk_fn_def(def_id, substs);
index 15a24aa4ace512f1b453902ddca2e34d2033abab..1e8d5f7eae87a8881edadb729794f43e43fc9a9e 100644 (file)
@@ -200,6 +200,15 @@ pub fn krate(&self) -> CrateNum {
             MonoItem::GlobalAsm(..) => LOCAL_CRATE,
         }
     }
+
+    /// Returns the item's `DefId`
+    pub fn def_id(&self) -> DefId {
+        match *self {
+            MonoItem::Fn(Instance { def, .. }) => def.def_id(),
+            MonoItem::Static(def_id) => def_id,
+            MonoItem::GlobalAsm(item_id) => item_id.owner_id.to_def_id(),
+        }
+    }
 }
 
 impl<'tcx> fmt::Display for MonoItem<'tcx> {
index 143435cb2a1f47bcbf11929aa4aba4a4b6e9b1da..d00b26a5a3d0b42baafca1d795332bbfc0ddbdcc 100644 (file)
@@ -250,7 +250,7 @@ pub enum ObligationCauseCode<'tcx> {
     TupleElem,
 
     /// This is the trait reference from the given projection.
-    ProjectionWf(ty::ProjectionTy<'tcx>),
+    ProjectionWf(ty::AliasTy<'tcx>),
 
     /// Must satisfy all of the where-clause predicates of the
     /// given item.
index d40d7de5f315fc3a18194348caf84fe05baeb8c4..7380c62a6693a85166a3ed26ef4184b572c6ac39 100644 (file)
@@ -76,8 +76,7 @@ pub fn new(value: T) -> Self {
     }
 }
 
-pub type CanonicalProjectionGoal<'tcx> =
-    Canonical<'tcx, ty::ParamEnvAnd<'tcx, ty::ProjectionTy<'tcx>>>;
+pub type CanonicalProjectionGoal<'tcx> = Canonical<'tcx, ty::ParamEnvAnd<'tcx, ty::AliasTy<'tcx>>>;
 
 pub type CanonicalTyGoal<'tcx> = Canonical<'tcx, ty::ParamEnvAnd<'tcx, Ty<'tcx>>>;
 
@@ -218,6 +217,6 @@ pub struct NormalizationResult<'tcx> {
 pub enum OutlivesBound<'tcx> {
     RegionSubRegion(ty::Region<'tcx>, ty::Region<'tcx>),
     RegionSubParam(ty::Region<'tcx>, ty::ParamTy),
-    RegionSubProjection(ty::Region<'tcx>, ty::ProjectionTy<'tcx>),
+    RegionSubProjection(ty::Region<'tcx>, ty::AliasTy<'tcx>),
     RegionSubOpaque(ty::Region<'tcx>, DefId, SubstsRef<'tcx>),
 }
index 7036c4a7b27d60b8da7772a1e575c33297736d4d..8ce06404de0811d64a177271ba6d4679278e007f 100644 (file)
@@ -131,7 +131,7 @@ pub fn method_call(&self, tcx: TyCtxt<'tcx>, source: Ty<'tcx>) -> Ty<'tcx> {
             .find(|m| m.kind == ty::AssocKind::Fn)
             .unwrap()
             .def_id;
-        tcx.mk_fn_def(method_def_id, tcx.mk_substs_trait(source, []))
+        tcx.mk_fn_def(method_def_id, [source])
     }
 }
 
index 7d4971d1e9e62d6fb5166ed9a5e248ea44164d2d..70ac5acb40eadd03751730e161d4f35a0e0cb508 100644 (file)
@@ -21,9 +21,8 @@
     self, AdtDef, AdtDefData, AdtKind, Binder, BindingMode, BoundVar, CanonicalPolyFnSig,
     ClosureSizeProfileData, Const, ConstS, DefIdTree, FloatTy, FloatVar, FloatVid,
     GenericParamDefKind, InferTy, IntTy, IntVar, IntVid, List, ParamConst, ParamTy,
-    PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, ProjectionTy, Region,
-    RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVar, TyVid, TypeAndMut, UintTy,
-    Visibility,
+    PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, Region, RegionKind, ReprOptions,
+    TraitObjectVisitor, Ty, TyKind, TyVar, TyVid, TypeAndMut, UintTy, Visibility,
 };
 use crate::ty::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef, UserSubsts};
 use rustc_ast as ast;
@@ -116,7 +115,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
     type ListBinderExistentialPredicate = &'tcx List<PolyExistentialPredicate<'tcx>>;
     type BinderListTy = Binder<'tcx, &'tcx List<Ty<'tcx>>>;
     type ListTy = &'tcx List<Ty<'tcx>>;
-    type ProjectionTy = ty::ProjectionTy<'tcx>;
+    type AliasTy = ty::AliasTy<'tcx>;
     type ParamTy = ParamTy;
     type BoundTy = ty::BoundTy;
     type PlaceholderType = ty::PlaceholderType;
@@ -2145,8 +2144,7 @@ fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
                     Bound,
                     Param,
                     Infer,
-                    Projection,
-                    Opaque,
+                    Alias,
                     Foreign
                 )?;
 
@@ -2323,7 +2321,7 @@ pub fn trait_may_define_assoc_type(self, trait_def_id: DefId, assoc_name: Ident)
 
     /// Given a `ty`, return whether it's an `impl Future<...>`.
     pub fn ty_is_opaque_future(self, ty: Ty<'_>) -> bool {
-        let ty::Opaque(def_id, _) = ty.kind() else { return false };
+        let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = ty.kind() else { return false };
         let future_trait = self.require_lang_item(LangItem::Future, None);
 
         self.explicit_item_bounds(def_id).iter().any(|(predicate, _)| {
@@ -2567,15 +2565,35 @@ pub fn mk_diverging_default(self) -> Ty<'tcx> {
     }
 
     #[inline]
-    pub fn mk_fn_def(self, def_id: DefId, substs: SubstsRef<'tcx>) -> Ty<'tcx> {
-        debug_assert_eq!(
-            self.generics_of(def_id).count(),
-            substs.len(),
-            "wrong number of generic parameters for {def_id:?}: {substs:?}",
-        );
+    pub fn mk_fn_def(
+        self,
+        def_id: DefId,
+        substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
+    ) -> Ty<'tcx> {
+        let substs = self.check_substs(def_id, substs);
         self.mk_ty(FnDef(def_id, substs))
     }
 
+    #[inline(always)]
+    fn check_substs(
+        self,
+        _def_id: DefId,
+        substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
+    ) -> SubstsRef<'tcx> {
+        let substs = substs.into_iter().map(Into::into);
+        #[cfg(debug_assertions)]
+        {
+            let n = self.generics_of(_def_id).count();
+            assert_eq!(
+                (n, Some(n)),
+                substs.size_hint(),
+                "wrong number of generic parameters for {_def_id:?}: {:?}",
+                substs.collect::<Vec<_>>(),
+            );
+        }
+        self.mk_substs(substs)
+    }
+
     #[inline]
     pub fn mk_fn_ptr(self, fty: PolyFnSig<'tcx>) -> Ty<'tcx> {
         self.mk_ty(FnPtr(fty))
@@ -2592,13 +2610,12 @@ pub fn mk_dynamic(
     }
 
     #[inline]
-    pub fn mk_projection(self, item_def_id: DefId, substs: SubstsRef<'tcx>) -> Ty<'tcx> {
-        debug_assert_eq!(
-            self.generics_of(item_def_id).count(),
-            substs.len(),
-            "wrong number of generic parameters for {item_def_id:?}: {substs:?}",
-        );
-        self.mk_ty(Projection(ProjectionTy { item_def_id, substs }))
+    pub fn mk_projection(
+        self,
+        item_def_id: DefId,
+        substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
+    ) -> Ty<'tcx> {
+        self.mk_ty(Alias(ty::Projection, self.mk_alias_ty(item_def_id, substs)))
     }
 
     #[inline]
@@ -2668,7 +2685,7 @@ pub fn mk_param_from_def(self, param: &ty::GenericParamDef) -> GenericArg<'tcx>
 
     #[inline]
     pub fn mk_opaque(self, def_id: DefId, substs: SubstsRef<'tcx>) -> Ty<'tcx> {
-        self.mk_ty(Opaque(def_id, substs))
+        self.mk_ty(Alias(ty::Opaque, self.mk_alias_ty(def_id, substs)))
     }
 
     pub fn mk_place_field(self, place: Place<'tcx>, f: Field, ty: Ty<'tcx>) -> Place<'tcx> {
@@ -2857,16 +2874,17 @@ pub fn mk_trait_ref(
         trait_def_id: DefId,
         substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
     ) -> ty::TraitRef<'tcx> {
-        let substs = substs.into_iter().map(Into::into);
-        let n = self.generics_of(trait_def_id).count();
-        debug_assert_eq!(
-            (n, Some(n)),
-            substs.size_hint(),
-            "wrong number of generic parameters for {trait_def_id:?}: {:?} \nDid you accidentally include the self-type in the params list?",
-            substs.collect::<Vec<_>>(),
-        );
-        let substs = self.mk_substs(substs);
-        ty::TraitRef::new(trait_def_id, substs)
+        let substs = self.check_substs(trait_def_id, substs);
+        ty::TraitRef { def_id: trait_def_id, substs, _use_mk_trait_ref_instead: () }
+    }
+
+    pub fn mk_alias_ty(
+        self,
+        def_id: DefId,
+        substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
+    ) -> ty::AliasTy<'tcx> {
+        let substs = self.check_substs(def_id, substs);
+        ty::AliasTy { def_id, substs, _use_mk_alias_ty_instead: () }
     }
 
     pub fn mk_bound_variable_kinds<
index 511d51cd670fb94ff8bf013f3512e545f9ea881e..8c22df7395f1052669ad14f2e36cc7e187bf4b23 100644 (file)
@@ -3,7 +3,7 @@
 use std::ops::ControlFlow;
 
 use crate::ty::{
-    visit::TypeVisitable, Const, ConstKind, DefIdTree, ExistentialPredicate, InferConst, InferTy,
+    visit::TypeVisitable, AliasTy, Const, ConstKind, DefIdTree, InferConst, InferTy, Opaque,
     PolyTraitPredicate, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor,
 };
 
@@ -457,11 +457,11 @@ fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
                 return ControlFlow::Break(());
             }
 
-            Opaque(did, _) => {
-                let parent = self.tcx.parent(*did);
+            Alias(Opaque, AliasTy { def_id, .. }) => {
+                let parent = self.tcx.parent(*def_id);
                 if let hir::def::DefKind::TyAlias | hir::def::DefKind::AssocTy = self.tcx.def_kind(parent)
-                    && let Opaque(parent_did, _) = self.tcx.type_of(parent).kind()
-                    && parent_did == did
+                    && let Alias(Opaque, AliasTy { def_id: parent_opaque_def_id, .. }) = self.tcx.type_of(parent).kind()
+                    && parent_opaque_def_id == def_id
                 {
                     // Okay
                 } else {
@@ -469,17 +469,6 @@ fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
                 }
             }
 
-            Dynamic(dty, _, _) => {
-                for pred in *dty {
-                    match pred.skip_binder() {
-                        ExistentialPredicate::Trait(_) | ExistentialPredicate::Projection(_) => {
-                            // Okay
-                        }
-                        _ => return ControlFlow::Break(()),
-                    }
-                }
-            }
-
             Param(param) => {
                 // FIXME: It would be nice to make this not use string manipulation,
                 // but it's pretty hard to do this, since `ty::ParamTy` is missing
index 4e113d72469c81d34eb10e25e952742ff9876174..14d07608a780e6c5b33b6dbae204401251b39088 100644 (file)
@@ -337,9 +337,9 @@ pub fn sort_string(self, tcx: TyCtxt<'_>) -> Cow<'static, str> {
             ty::Infer(ty::FreshTy(_)) => "fresh type".into(),
             ty::Infer(ty::FreshIntTy(_)) => "fresh integral type".into(),
             ty::Infer(ty::FreshFloatTy(_)) => "fresh floating-point type".into(),
-            ty::Projection(_) => "associated type".into(),
+            ty::Alias(ty::Projection, _) => "associated type".into(),
             ty::Param(p) => format!("type parameter `{}`", p).into(),
-            ty::Opaque(..) => "opaque type".into(),
+            ty::Alias(ty::Opaque, ..) => "opaque type".into(),
             ty::Error(_) => "type error".into(),
         }
     }
@@ -375,9 +375,9 @@ pub fn prefix_string(self, tcx: TyCtxt<'_>) -> Cow<'static, str> {
             ty::Tuple(..) => "tuple".into(),
             ty::Placeholder(..) => "higher-ranked type".into(),
             ty::Bound(..) => "bound type variable".into(),
-            ty::Projection(_) => "associated type".into(),
+            ty::Alias(ty::Projection, _) => "associated type".into(),
             ty::Param(_) => "type parameter".into(),
-            ty::Opaque(..) => "opaque type".into(),
+            ty::Alias(ty::Opaque, ..) => "opaque type".into(),
         }
     }
 }
@@ -400,7 +400,7 @@ pub fn note_and_explain_type_err(
                         diag.note("no two closures, even if identical, have the same type");
                         diag.help("consider boxing your closure and/or using it as a trait object");
                     }
-                    (ty::Opaque(..), ty::Opaque(..)) => {
+                    (ty::Alias(ty::Opaque, ..), ty::Alias(ty::Opaque, ..)) => {
                         // Issue #63167
                         diag.note("distinct uses of `impl Trait` result in different opaque types");
                     }
@@ -439,11 +439,11 @@ pub fn note_and_explain_type_err(
                              #traits-as-parameters",
                         );
                     }
-                    (ty::Projection(_), ty::Projection(_)) => {
+                    (ty::Alias(ty::Projection, _), ty::Alias(ty::Projection, _)) => {
                         diag.note("an associated type was expected, but a different one was found");
                     }
-                    (ty::Param(p), ty::Projection(proj)) | (ty::Projection(proj), ty::Param(p))
-                        if self.def_kind(proj.item_def_id) != DefKind::ImplTraitPlaceholder =>
+                    (ty::Param(p), ty::Alias(ty::Projection, proj)) | (ty::Alias(ty::Projection, proj), ty::Param(p))
+                        if self.def_kind(proj.def_id) != DefKind::ImplTraitPlaceholder =>
                     {
                         let generics = self.generics_of(body_owner_def_id);
                         let p_span = self.def_span(generics.type_param(p, self).def_id);
@@ -466,7 +466,7 @@ pub fn note_and_explain_type_err(
                             let (trait_ref, assoc_substs) = proj.trait_ref_and_own_substs(self);
                             let path =
                                 self.def_path_str_with_substs(trait_ref.def_id, trait_ref.substs);
-                            let item_name = self.item_name(proj.item_def_id);
+                            let item_name = self.item_name(proj.def_id);
                             let item_args = self.format_generic_args(assoc_substs);
 
                             let path = if path.ends_with('>') {
@@ -493,8 +493,8 @@ pub fn note_and_explain_type_err(
                             diag.note("you might be missing a type parameter or trait bound");
                         }
                     }
-                    (ty::Param(p), ty::Dynamic(..) | ty::Opaque(..))
-                    | (ty::Dynamic(..) | ty::Opaque(..), ty::Param(p)) => {
+                    (ty::Param(p), ty::Dynamic(..) | ty::Alias(ty::Opaque, ..))
+                    | (ty::Dynamic(..) | ty::Alias(ty::Opaque, ..), ty::Param(p)) => {
                         let generics = self.generics_of(body_owner_def_id);
                         let p_span = self.def_span(generics.type_param(p, self).def_id);
                         if !sp.contains(p_span) {
@@ -553,7 +553,7 @@ fn foo(&self, x: T) -> T { x }
                             diag.span_label(p_span, "this type parameter");
                         }
                     }
-                    (ty::Projection(proj_ty), _) if self.def_kind(proj_ty.item_def_id) != DefKind::ImplTraitPlaceholder => {
+                    (ty::Alias(ty::Projection, proj_ty), _) if self.def_kind(proj_ty.def_id) != DefKind::ImplTraitPlaceholder => {
                         self.expected_projection(
                             diag,
                             proj_ty,
@@ -562,7 +562,7 @@ fn foo(&self, x: T) -> T { x }
                             cause.code(),
                         );
                     }
-                    (_, ty::Projection(proj_ty)) if self.def_kind(proj_ty.item_def_id) != DefKind::ImplTraitPlaceholder => {
+                    (_, ty::Alias(ty::Projection, proj_ty)) if self.def_kind(proj_ty.def_id) != DefKind::ImplTraitPlaceholder => {
                         let msg = format!(
                             "consider constraining the associated type `{}` to `{}`",
                             values.found, values.expected,
@@ -624,10 +624,10 @@ fn suggest_constraint(
         diag: &mut Diagnostic,
         msg: &str,
         body_owner_def_id: DefId,
-        proj_ty: &ty::ProjectionTy<'tcx>,
+        proj_ty: &ty::AliasTy<'tcx>,
         ty: Ty<'tcx>,
     ) -> bool {
-        let assoc = self.associated_item(proj_ty.item_def_id);
+        let assoc = self.associated_item(proj_ty.def_id);
         let (trait_ref, assoc_substs) = proj_ty.trait_ref_and_own_substs(self);
         if let Some(item) = self.hir().get_if_local(body_owner_def_id) {
             if let Some(hir_generics) = item.generics() {
@@ -680,7 +680,7 @@ fn suggest_constraint(
     fn expected_projection(
         self,
         diag: &mut Diagnostic,
-        proj_ty: &ty::ProjectionTy<'tcx>,
+        proj_ty: &ty::AliasTy<'tcx>,
         values: ExpectedFound<Ty<'tcx>>,
         body_owner_def_id: DefId,
         cause_code: &ObligationCauseCode<'_>,
@@ -703,7 +703,7 @@ fn expected_projection(
         );
         let impl_comparison =
             matches!(cause_code, ObligationCauseCode::CompareImplItemObligation { .. });
-        let assoc = self.associated_item(proj_ty.item_def_id);
+        let assoc = self.associated_item(proj_ty.def_id);
         if !callable_scope || impl_comparison {
             // We do not want to suggest calling functions when the reason of the
             // type error is a comparison of an `impl` with its `trait` or when the
@@ -716,7 +716,7 @@ fn expected_projection(
                 diag,
                 assoc.container_id(self),
                 current_method_ident,
-                proj_ty.item_def_id,
+                proj_ty.def_id,
                 values.expected,
             );
             // Possibly suggest constraining the associated type to conform to the
@@ -775,11 +775,11 @@ fn suggest_constraining_opaque_associated_type(
         self,
         diag: &mut Diagnostic,
         msg: &str,
-        proj_ty: &ty::ProjectionTy<'tcx>,
+        proj_ty: &ty::AliasTy<'tcx>,
         ty: Ty<'tcx>,
     ) -> bool {
-        let assoc = self.associated_item(proj_ty.item_def_id);
-        if let ty::Opaque(def_id, _) = *proj_ty.self_ty().kind() {
+        let assoc = self.associated_item(proj_ty.def_id);
+        if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = *proj_ty.self_ty().kind() {
             let opaque_local_def_id = def_id.as_local();
             let opaque_hir_ty = if let Some(opaque_local_def_id) = opaque_local_def_id {
                 match &self.hir().expect_item(opaque_local_def_id).kind {
@@ -828,7 +828,7 @@ fn point_at_methods_that_satisfy_associated_type(
             .filter_map(|(_, item)| {
                 let method = self.fn_sig(item.def_id);
                 match *method.output().skip_binder().kind() {
-                    ty::Projection(ty::ProjectionTy { item_def_id, .. })
+                    ty::Alias(ty::Projection, ty::AliasTy { def_id: item_def_id, .. })
                         if item_def_id == proj_ty_item_def_id =>
                     {
                         Some((
@@ -1010,7 +1010,7 @@ pub fn short_ty_string(self, ty: Ty<'tcx>) -> (String, Option<PathBuf>) {
         }
         let mut short;
         loop {
-            // Look for the longest properly trimmed path that still fits in lenght_limit.
+            // Look for the longest properly trimmed path that still fits in length_limit.
             short = with_forced_trimmed_paths!(
                 FmtPrinter::new_with_limit(
                     self,
index c9c09c93a3e1c470a9e94b68d6e8d2c7086f575c..44650827810abf11095901cb7907f433098996b6 100644 (file)
@@ -126,7 +126,7 @@ pub fn simplify_type<'tcx>(
             TreatParams::AsPlaceholder => Some(PlaceholderSimplifiedType),
             TreatParams::AsInfer => None,
         },
-        ty::Opaque(..) | ty::Projection(_) => match treat_params {
+        ty::Alias(..) => match treat_params {
             // When treating `ty::Param` as a placeholder, projections also
             // don't unify with anything else as long as they are fully normalized.
             //
@@ -225,7 +225,7 @@ pub fn types_may_unify<'tcx>(self, obligation_ty: Ty<'tcx>, impl_ty: Ty<'tcx>) -
         match impl_ty.kind() {
             // Start by checking whether the type in the impl may unify with
             // pretty much everything. Just return `true` in that case.
-            ty::Param(_) | ty::Projection(_) | ty::Error(_) | ty::Opaque(..) => return true,
+            ty::Param(_) | ty::Error(_) | ty::Alias(..) => return true,
             // These types only unify with inference variables or their own
             // variant.
             ty::Bool
@@ -323,8 +323,6 @@ pub fn types_may_unify<'tcx>(self, obligation_ty: Ty<'tcx>, impl_ty: Ty<'tcx>) -
                 _ => false,
             },
 
-            ty::Opaque(..) => true,
-
             // Impls cannot contain these types as these cannot be named directly.
             ty::FnDef(..) | ty::Closure(..) | ty::Generator(..) => false,
 
@@ -344,7 +342,7 @@ pub fn types_may_unify<'tcx>(self, obligation_ty: Ty<'tcx>, impl_ty: Ty<'tcx>) -
             // projections can unify with other stuff.
             //
             // Looking forward to lazy normalization this is the safer strategy anyways.
-            ty::Projection(_) => true,
+            ty::Alias(..) => true,
 
             ty::Error(_) => true,
 
index 046a2660a1f6dd51b45d23616ef786ee69767ca8..d283ccc3ad8a29435035c2c6bc4fc1fe9b0b3454 100644 (file)
@@ -155,12 +155,12 @@ fn add_kind(&mut self, kind: &ty::TyKind<'_>) {
                 self.add_substs(substs);
             }
 
-            &ty::Projection(data) => {
+            &ty::Alias(ty::Projection, data) => {
                 self.add_flags(TypeFlags::HAS_TY_PROJECTION);
                 self.add_projection_ty(data);
             }
 
-            &ty::Opaque(_, substs) => {
+            &ty::Alias(ty::Opaque, ty::AliasTy { substs, .. }) => {
                 self.add_flags(TypeFlags::HAS_TY_OPAQUE);
                 self.add_substs(substs);
             }
@@ -345,7 +345,7 @@ fn add_existential_projection(&mut self, projection: &ty::ExistentialProjection<
         }
     }
 
-    fn add_projection_ty(&mut self, projection_ty: ty::ProjectionTy<'_>) {
+    fn add_projection_ty(&mut self, projection_ty: ty::AliasTy<'_>) {
         self.add_substs(projection_ty.substs);
     }
 
index ace81bc4f8352e155330d5178968f369eed30054..5d5089cec82a696d105c196e45d16808e20569c5 100644 (file)
@@ -112,7 +112,7 @@ pub fn inhabited_predicate(self, tcx: TyCtxt<'tcx>) -> InhabitedPredicate<'tcx>
                 InhabitedPredicate::True
             }
             Never => InhabitedPredicate::False,
-            Param(_) | Projection(_) => InhabitedPredicate::GenericType(self),
+            Param(_) | Alias(ty::Projection, _) => InhabitedPredicate::GenericType(self),
             Tuple(tys) if tys.is_empty() => InhabitedPredicate::True,
             // use a query for more complex cases
             Adt(..) | Array(..) | Tuple(_) => tcx.inhabited_predicate_type(self),
index 488fd567846a3a850f973c7a7f3328ae21f28694..7f66b993646a32058461edd9b1063ea46a892475 100644 (file)
@@ -271,7 +271,7 @@ pub fn compute(
                 let non_zero = !ty.is_unsafe_ptr();
                 let tail = tcx.struct_tail_erasing_lifetimes(pointee, param_env);
                 match tail.kind() {
-                    ty::Param(_) | ty::Projection(_) => {
+                    ty::Param(_) | ty::Alias(ty::Projection, _) => {
                         debug_assert!(tail.has_non_region_param());
                         Ok(SizeSkeleton::Pointer { non_zero, tail: tcx.erase_regions(tail) })
                     }
@@ -349,7 +349,7 @@ pub fn compute(
                 }
             }
 
-            ty::Projection(_) | ty::Opaque(..) => {
+            ty::Alias(..) => {
                 let normalized = tcx.normalize_erasing_regions(param_env, ty);
                 if ty == normalized {
                     Err(err)
@@ -757,10 +757,9 @@ fn field_ty_or_layout<'tcx>(
                     }
                 }
 
-                ty::Projection(_)
+                ty::Alias(..)
                 | ty::Bound(..)
                 | ty::Placeholder(..)
-                | ty::Opaque(..)
                 | ty::Param(_)
                 | ty::Infer(_)
                 | ty::Error(_) => bug!("TyAndLayout::field: unexpected type `{}`", this.ty),
index 659d99f025da03a469729b0f070448ac23cfc240..5232c1e1cc0f83d7333baa4c066c1fd4bcd3a75d 100644 (file)
@@ -64,6 +64,7 @@
 use std::{fmt, str};
 
 pub use crate::ty::diagnostics::*;
+pub use rustc_type_ir::AliasKind::*;
 pub use rustc_type_ir::DynKind::*;
 pub use rustc_type_ir::InferTy::*;
 pub use rustc_type_ir::RegionKind::*;
 pub use self::rvalue_scopes::RvalueScopes;
 pub use self::sty::BoundRegionKind::*;
 pub use self::sty::{
-    Article, Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar,
+    AliasTy, Article, Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar,
     BoundVariableKind, CanonicalPolyFnSig, ClosureSubsts, ClosureSubstsParts, ConstVid,
     EarlyBoundRegion, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FnSig,
     FreeRegion, GenSig, GeneratorSubsts, GeneratorSubstsParts, InlineConstSubsts,
     InlineConstSubstsParts, ParamConst, ParamTy, PolyExistentialPredicate,
     PolyExistentialProjection, PolyExistentialTraitRef, PolyFnSig, PolyGenSig, PolyTraitRef,
-    ProjectionTy, Region, RegionKind, RegionVid, TraitRef, TyKind, TypeAndMut, UpvarSubsts,
-    VarianceDiagInfo,
+    Region, RegionKind, RegionVid, TraitRef, TyKind, TypeAndMut, UpvarSubsts, VarianceDiagInfo,
 };
 pub use self::trait_def::TraitDef;
 
@@ -235,7 +235,7 @@ pub struct ImplHeader<'tcx> {
     pub predicates: Vec<Predicate<'tcx>>,
 }
 
-#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable)]
+#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable)]
 pub enum ImplSubject<'tcx> {
     Trait(TraitRef<'tcx>),
     Inherent(Ty<'tcx>),
@@ -781,8 +781,8 @@ pub fn remap_constness_diag(&mut self, param_env: ParamEnv<'tcx>) {
         }
     }
 
-    pub fn with_self_type(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
-        Self { trait_ref: self.trait_ref.with_self_type(tcx, self_ty), ..self }
+    pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
+        Self { trait_ref: self.trait_ref.with_self_ty(tcx, self_ty), ..self }
     }
 
     pub fn def_id(self) -> DefId {
@@ -1010,7 +1010,7 @@ fn pack(self) -> Term<'tcx> {
 #[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
 #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
 pub struct ProjectionPredicate<'tcx> {
-    pub projection_ty: ProjectionTy<'tcx>,
+    pub projection_ty: AliasTy<'tcx>,
     pub term: Term<'tcx>,
 }
 
@@ -1046,7 +1046,19 @@ pub fn term(&self) -> Binder<'tcx, Term<'tcx>> {
     /// associated type, which is in `tcx.associated_item(projection_def_id()).container`.
     pub fn projection_def_id(&self) -> DefId {
         // Ok to skip binder since trait `DefId` does not care about regions.
-        self.skip_binder().projection_ty.item_def_id
+        self.skip_binder().projection_ty.def_id
+    }
+}
+
+impl<'tcx> ProjectionPredicate<'tcx> {
+    pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
+        Self {
+            projection_ty: tcx.mk_alias_ty(
+                self.projection_ty.def_id,
+                [self_ty.into()].into_iter().chain(self.projection_ty.substs.iter().skip(1)),
+            ),
+            ..self
+        }
     }
 }
 
index 667298b9b5b1316ff2738e5c08b1ceab2502be75..29bad33e4bc0f36aa5ef8f955e1ec30da54ef19a 100644 (file)
@@ -169,10 +169,8 @@ fn default_print_def_path(
                 self.path_append(
                     |cx: Self| {
                         if trait_qualify_parent {
-                            let trait_ref = ty::TraitRef::new(
-                                parent_def_id,
-                                cx.tcx().intern_substs(parent_substs),
-                            );
+                            let trait_ref =
+                                cx.tcx().mk_trait_ref(parent_def_id, parent_substs.iter().copied());
                             cx.path_qualified(trait_ref.self_ty(), Some(trait_ref))
                         } else {
                             cx.print_def_path(parent_def_id, parent_substs)
@@ -275,10 +273,9 @@ fn characteristic_def_id_of_type_cached<'a>(
         | ty::Uint(_)
         | ty::Str
         | ty::FnPtr(_)
-        | ty::Projection(_)
+        | ty::Alias(..)
         | ty::Placeholder(..)
         | ty::Param(_)
-        | ty::Opaque(..)
         | ty::Infer(_)
         | ty::Bound(..)
         | ty::Error(_)
index 6bf42f81f131e6e447537bd290a3263fb054f715..a1d53506707c9a2938749623d087c314bad761a6 100644 (file)
@@ -16,6 +16,7 @@
 use rustc_session::cstore::{ExternCrate, ExternCrateSource};
 use rustc_session::Limit;
 use rustc_span::symbol::{kw, Ident, Symbol};
+use rustc_span::FileNameDisplayPreference;
 use rustc_target::abi::Size;
 use rustc_target::spec::abi::Abi;
 use smallvec::SmallVec;
@@ -718,17 +719,17 @@ fn pretty_print_type(mut self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error>
             ty::Foreign(def_id) => {
                 p!(print_def_path(def_id, &[]));
             }
-            ty::Projection(ref data) => {
+            ty::Alias(ty::Projection, ref data) => {
                 if !(self.should_print_verbose() || NO_QUERIES.with(|q| q.get()))
-                    && self.tcx().def_kind(data.item_def_id) == DefKind::ImplTraitPlaceholder
+                    && self.tcx().def_kind(data.def_id) == DefKind::ImplTraitPlaceholder
                 {
-                    return self.pretty_print_opaque_impl_type(data.item_def_id, data.substs);
+                    return self.pretty_print_opaque_impl_type(data.def_id, data.substs);
                 } else {
                     p!(print(data))
                 }
             }
             ty::Placeholder(placeholder) => p!(write("Placeholder({:?})", placeholder)),
-            ty::Opaque(def_id, substs) => {
+            ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
                 // FIXME(eddyb) print this with `print_def_path`.
                 // We use verbose printing in 'NO_QUERIES' mode, to
                 // avoid needing to call `predicates_of`. This should
@@ -743,7 +744,9 @@ fn pretty_print_type(mut self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error>
                 let parent = self.tcx().parent(def_id);
                 match self.tcx().def_kind(parent) {
                     DefKind::TyAlias | DefKind::AssocTy => {
-                        if let ty::Opaque(d, _) = *self.tcx().type_of(parent).kind() {
+                        if let ty::Alias(ty::Opaque, ty::AliasTy { def_id: d, .. }) =
+                            *self.tcx().type_of(parent).kind()
+                        {
                             if d == def_id {
                                 // If the type alias directly starts with the `impl` of the
                                 // opaque type we're printing, then skip the `::{opaque#1}`.
@@ -816,11 +819,16 @@ fn pretty_print_type(mut self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error>
                             p!("@", print_def_path(did.to_def_id(), substs));
                         } else {
                             let span = self.tcx().def_span(did);
+                            let preference = if FORCE_TRIMMED_PATH.with(|flag| flag.get()) {
+                                FileNameDisplayPreference::Short
+                            } else {
+                                FileNameDisplayPreference::Remapped
+                            };
                             p!(write(
                                 "@{}",
                                 // This may end up in stderr diagnostics but it may also be emitted
                                 // into MIR. Hence we use the remapped path if available
-                                self.tcx().sess.source_map().span_to_embeddable_string(span)
+                                self.tcx().sess.source_map().span_to_string(span, preference)
                             ));
                         }
                     } else {
@@ -1019,8 +1027,8 @@ fn pretty_print_opaque_impl_type(
                         // Skip printing `<[generator@] as Generator<_>>::Return` from async blocks,
                         // unless we can find out what generator return type it comes from.
                         let term = if let Some(ty) = term.skip_binder().ty()
-                            && let ty::Projection(proj) = ty.kind()
-                            && let Some(assoc) = tcx.opt_associated_item(proj.item_def_id)
+                            && let ty::Alias(ty::Projection, proj) = ty.kind()
+                            && let Some(assoc) = tcx.opt_associated_item(proj.def_id)
                             && assoc.trait_container(tcx) == tcx.lang_items().gen_trait()
                             && assoc.name == rustc_span::sym::Return
                         {
@@ -2653,7 +2661,7 @@ pub struct PrintClosureAsImpl<'tcx> {
     }
 
     ty::ExistentialProjection<'tcx> {
-        let name = cx.tcx().associated_item(self.item_def_id).name;
+        let name = cx.tcx().associated_item(self.def_id).name;
         p!(write("{} = ", name), print(self.term))
     }
 
@@ -2740,8 +2748,8 @@ pub struct PrintClosureAsImpl<'tcx> {
       }
     }
 
-    ty::ProjectionTy<'tcx> {
-        p!(print_def_path(self.item_def_id, self.substs));
+    ty::AliasTy<'tcx> {
+        p!(print_def_path(self.def_id, self.substs));
     }
 
     ty::ClosureKind {
index c759fb6d5e4f4c50c05a7972032f83e6218f10b1..c4116558bd27b262b6aebdc3ccdb0ee587213d0c 100644 (file)
@@ -106,7 +106,7 @@ fn binders<T>(
         T: Relate<'tcx>;
 }
 
-pub trait Relate<'tcx>: TypeFoldable<'tcx> + Copy {
+pub trait Relate<'tcx>: TypeFoldable<'tcx> + PartialEq + Copy {
     fn relate<R: TypeRelation<'tcx>>(
         relation: &mut R,
         a: Self,
@@ -270,21 +270,17 @@ fn relate<R: TypeRelation<'tcx>>(
     }
 }
 
-impl<'tcx> Relate<'tcx> for ty::ProjectionTy<'tcx> {
+impl<'tcx> Relate<'tcx> for ty::AliasTy<'tcx> {
     fn relate<R: TypeRelation<'tcx>>(
         relation: &mut R,
-        a: ty::ProjectionTy<'tcx>,
-        b: ty::ProjectionTy<'tcx>,
-    ) -> RelateResult<'tcx, ty::ProjectionTy<'tcx>> {
-        if a.item_def_id != b.item_def_id {
-            Err(TypeError::ProjectionMismatched(expected_found(
-                relation,
-                a.item_def_id,
-                b.item_def_id,
-            )))
+        a: ty::AliasTy<'tcx>,
+        b: ty::AliasTy<'tcx>,
+    ) -> RelateResult<'tcx, ty::AliasTy<'tcx>> {
+        if a.def_id != b.def_id {
+            Err(TypeError::ProjectionMismatched(expected_found(relation, a.def_id, b.def_id)))
         } else {
             let substs = relation.relate(a.substs, b.substs)?;
-            Ok(ty::ProjectionTy { item_def_id: a.item_def_id, substs: &substs })
+            Ok(relation.tcx().mk_alias_ty(a.def_id, substs))
         }
     }
 }
@@ -295,12 +291,8 @@ fn relate<R: TypeRelation<'tcx>>(
         a: ty::ExistentialProjection<'tcx>,
         b: ty::ExistentialProjection<'tcx>,
     ) -> RelateResult<'tcx, ty::ExistentialProjection<'tcx>> {
-        if a.item_def_id != b.item_def_id {
-            Err(TypeError::ProjectionMismatched(expected_found(
-                relation,
-                a.item_def_id,
-                b.item_def_id,
-            )))
+        if a.def_id != b.def_id {
+            Err(TypeError::ProjectionMismatched(expected_found(relation, a.def_id, b.def_id)))
         } else {
             let term = relation.relate_with_variance(
                 ty::Invariant,
@@ -314,7 +306,7 @@ fn relate<R: TypeRelation<'tcx>>(
                 a.substs,
                 b.substs,
             )?;
-            Ok(ty::ExistentialProjection { item_def_id: a.item_def_id, substs, term })
+            Ok(ty::ExistentialProjection { def_id: a.def_id, substs, term })
         }
     }
 }
@@ -330,7 +322,7 @@ fn relate<R: TypeRelation<'tcx>>(
             Err(TypeError::Traits(expected_found(relation, a.def_id, b.def_id)))
         } else {
             let substs = relate_substs(relation, a.substs, b.substs)?;
-            Ok(ty::TraitRef { def_id: a.def_id, substs })
+            Ok(relation.tcx().mk_trait_ref(a.def_id, substs))
         }
     }
 }
@@ -351,7 +343,7 @@ fn relate<R: TypeRelation<'tcx>>(
     }
 }
 
-#[derive(Copy, Debug, Clone, TypeFoldable, TypeVisitable)]
+#[derive(PartialEq, Copy, Debug, Clone, TypeFoldable, TypeVisitable)]
 struct GeneratorWitness<'tcx>(&'tcx ty::List<Ty<'tcx>>);
 
 impl<'tcx> Relate<'tcx> for GeneratorWitness<'tcx> {
@@ -559,14 +551,15 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>(
         }
 
         // these two are already handled downstream in case of lazy normalization
-        (&ty::Projection(a_data), &ty::Projection(b_data)) => {
+        (&ty::Alias(ty::Projection, a_data), &ty::Alias(ty::Projection, b_data)) => {
             let projection_ty = relation.relate(a_data, b_data)?;
-            Ok(tcx.mk_projection(projection_ty.item_def_id, projection_ty.substs))
+            Ok(tcx.mk_projection(projection_ty.def_id, projection_ty.substs))
         }
 
-        (&ty::Opaque(a_def_id, a_substs), &ty::Opaque(b_def_id, b_substs))
-            if a_def_id == b_def_id =>
-        {
+        (
+            &ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, substs: a_substs, .. }),
+            &ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, substs: b_substs, .. }),
+        ) if a_def_id == b_def_id => {
             if relation.intercrate() {
                 // During coherence, opaque types should be treated as equal to each other, even if their generic params
                 // differ, as they could resolve to the same hidden type, even for different generic params.
index 9f70b4f1ffd25291592894531cab301143c473bb..3c6800cf293dee25e44b9b807a7c14550330f8cf 100644 (file)
@@ -651,8 +651,7 @@ fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
             }
             ty::GeneratorWitness(types) => ty::GeneratorWitness(types.try_fold_with(folder)?),
             ty::Closure(did, substs) => ty::Closure(did, substs.try_fold_with(folder)?),
-            ty::Projection(data) => ty::Projection(data.try_fold_with(folder)?),
-            ty::Opaque(did, substs) => ty::Opaque(did, substs.try_fold_with(folder)?),
+            ty::Alias(kind, data) => ty::Alias(kind, data.try_fold_with(folder)?),
 
             ty::Bool
             | ty::Char
@@ -697,8 +696,7 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow
             ty::Generator(_did, ref substs, _) => substs.visit_with(visitor),
             ty::GeneratorWitness(ref types) => types.visit_with(visitor),
             ty::Closure(_did, ref substs) => substs.visit_with(visitor),
-            ty::Projection(ref data) => data.visit_with(visitor),
-            ty::Opaque(_, ref substs) => substs.visit_with(visitor),
+            ty::Alias(_, ref data) => data.visit_with(visitor),
 
             ty::Bool
             | ty::Char
index 9cbda95a4df7a7f1e582dadbcf021829f45791a4..66aeebab88ba017d24bfd90895e1d1f7b58d4d94 100644 (file)
@@ -217,7 +217,7 @@ fn article(&self) -> &'static str {
 /// * `GR`: The "return type", which is the type of value returned upon
 ///   completion of the generator.
 /// * `GW`: The "generator witness".
-#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, Lift)]
+#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable, Lift)]
 pub struct ClosureSubsts<'tcx> {
     /// Lifetime and type parameters from the enclosing function,
     /// concatenated with a tuple containing the types of the upvars.
@@ -348,7 +348,7 @@ pub fn print_as_impl_trait(self) -> ty::print::PrintClosureAsImpl<'tcx> {
 }
 
 /// Similar to `ClosureSubsts`; see the above documentation for more.
-#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, Lift)]
+#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable, Lift)]
 pub struct GeneratorSubsts<'tcx> {
     pub substs: SubstsRef<'tcx>,
 }
@@ -693,7 +693,7 @@ pub fn stable_cmp(&self, tcx: TyCtxt<'tcx>, other: &Self) -> Ordering {
         match (*self, *other) {
             (Trait(_), Trait(_)) => Ordering::Equal,
             (Projection(ref a), Projection(ref b)) => {
-                tcx.def_path_hash(a.item_def_id).cmp(&tcx.def_path_hash(b.item_def_id))
+                tcx.def_path_hash(a.def_id).cmp(&tcx.def_path_hash(b.def_id))
             }
             (AutoTrait(ref a), AutoTrait(ref b)) => {
                 tcx.def_path_hash(*a).cmp(&tcx.def_path_hash(*b))
@@ -816,14 +816,13 @@ pub fn auto_traits<'a>(&'a self) -> impl Iterator<Item = DefId> + Captures<'tcx>
 pub struct TraitRef<'tcx> {
     pub def_id: DefId,
     pub substs: SubstsRef<'tcx>,
+    /// This field exists to prevent the creation of `TraitRef` without
+    /// calling [TyCtxt::mk_trait_ref].
+    pub(super) _use_mk_trait_ref_instead: (),
 }
 
 impl<'tcx> TraitRef<'tcx> {
-    pub fn new(def_id: DefId, substs: SubstsRef<'tcx>) -> TraitRef<'tcx> {
-        TraitRef { def_id, substs }
-    }
-
-    pub fn with_self_type(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
+    pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
         tcx.mk_trait_ref(
             self.def_id,
             [self_ty.into()].into_iter().chain(self.substs.iter().skip(1)),
@@ -833,10 +832,7 @@ pub fn with_self_type(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
     /// Returns a `TraitRef` of the form `P0: Foo<P1..Pn>` where `Pi`
     /// are the parameters defined on trait.
     pub fn identity(tcx: TyCtxt<'tcx>, def_id: DefId) -> Binder<'tcx, TraitRef<'tcx>> {
-        ty::Binder::dummy(TraitRef {
-            def_id,
-            substs: InternalSubsts::identity_for_item(tcx, def_id),
-        })
+        ty::Binder::dummy(tcx.mk_trait_ref(def_id, InternalSubsts::identity_for_item(tcx, def_id)))
     }
 
     #[inline]
@@ -850,7 +846,7 @@ pub fn from_method(
         substs: SubstsRef<'tcx>,
     ) -> ty::TraitRef<'tcx> {
         let defs = tcx.generics_of(trait_id);
-        ty::TraitRef { def_id: trait_id, substs: tcx.intern_substs(&substs[..defs.params.len()]) }
+        tcx.mk_trait_ref(trait_id, tcx.intern_substs(&substs[..defs.params.len()]))
     }
 }
 
@@ -980,8 +976,12 @@ impl<'tcx, T> Binder<'tcx, T>
     /// contain any bound vars that would be bound by the
     /// binder. This is commonly used to 'inject' a value T into a
     /// different binding level.
+    #[track_caller]
     pub fn dummy(value: T) -> Binder<'tcx, T> {
-        assert!(!value.has_escaping_bound_vars());
+        assert!(
+            !value.has_escaping_bound_vars(),
+            "`{value:?}` has escaping bound vars, so it cannot be wrapped in a dummy binder."
+        );
         Binder(value, ty::List::empty())
     }
 
@@ -1128,28 +1128,52 @@ pub fn transpose(self) -> Option<Binder<'tcx, T>> {
     }
 }
 
-/// Represents the projection of an associated type. In explicit UFCS
-/// form this would be written `<T as Trait<..>>::N`.
+impl<'tcx, T: IntoIterator> Binder<'tcx, T> {
+    pub fn iter(self) -> impl Iterator<Item = ty::Binder<'tcx, T::Item>> {
+        let bound_vars = self.1;
+        self.0.into_iter().map(|v| Binder(v, bound_vars))
+    }
+}
+
+/// Represents the projection of an associated type.
+///
+/// For a projection, this would be `<Ty as Trait<...>>::N`.
+///
+/// For an opaque type, there is no explicit syntax.
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
 #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
-pub struct ProjectionTy<'tcx> {
-    /// The parameters of the associated item.
+pub struct AliasTy<'tcx> {
+    /// The parameters of the associated or opaque item.
+    ///
+    /// For a projection, these are the substitutions for the trait and the
+    /// GAT substitutions, if there are any.
+    ///
+    /// For RPIT the substitutions are for the generics of the function,
+    /// while for TAIT it is used for the generic parameters of the alias.
     pub substs: SubstsRef<'tcx>,
 
-    /// The `DefId` of the `TraitItem` for the associated type `N`.
+    /// The `DefId` of the `TraitItem` for the associated type `N` if this is a projection,
+    /// or the `OpaqueType` item if this is an opaque.
     ///
-    /// Note that this is not the `DefId` of the `TraitRef` containing this
-    /// associated type, which is in `tcx.associated_item(item_def_id).container`,
-    /// aka. `tcx.parent(item_def_id).unwrap()`.
-    pub item_def_id: DefId,
+    /// During codegen, `tcx.type_of(def_id)` can be used to get the type of the
+    /// underlying type if the type is an opaque.
+    ///
+    /// Note that if this is an associated type, this is not the `DefId` of the
+    /// `TraitRef` containing this associated type, which is in `tcx.associated_item(def_id).container`,
+    /// aka. `tcx.parent(def_id)`.
+    pub def_id: DefId,
+
+    /// This field exists to prevent the creation of `ProjectionTy` without using
+    /// [TyCtxt::mk_alias_ty].
+    pub(super) _use_mk_alias_ty_instead: (),
 }
 
-impl<'tcx> ProjectionTy<'tcx> {
+impl<'tcx> AliasTy<'tcx> {
     pub fn trait_def_id(&self, tcx: TyCtxt<'tcx>) -> DefId {
-        match tcx.def_kind(self.item_def_id) {
-            DefKind::AssocTy | DefKind::AssocConst => tcx.parent(self.item_def_id),
+        match tcx.def_kind(self.def_id) {
+            DefKind::AssocTy | DefKind::AssocConst => tcx.parent(self.def_id),
             DefKind::ImplTraitPlaceholder => {
-                tcx.parent(tcx.impl_trait_in_trait_parent(self.item_def_id))
+                tcx.parent(tcx.impl_trait_in_trait_parent(self.def_id))
             }
             kind => bug!("unexpected DefKind in ProjectionTy: {kind:?}"),
         }
@@ -1162,11 +1186,11 @@ pub fn trait_ref_and_own_substs(
         &self,
         tcx: TyCtxt<'tcx>,
     ) -> (ty::TraitRef<'tcx>, &'tcx [ty::GenericArg<'tcx>]) {
-        let def_id = tcx.parent(self.item_def_id);
-        assert_eq!(tcx.def_kind(def_id), DefKind::Trait);
-        let trait_generics = tcx.generics_of(def_id);
+        debug_assert!(matches!(tcx.def_kind(self.def_id), DefKind::AssocTy | DefKind::AssocConst));
+        let trait_def_id = self.trait_def_id(tcx);
+        let trait_generics = tcx.generics_of(trait_def_id);
         (
-            ty::TraitRef { def_id, substs: self.substs.truncate_to(tcx, trait_generics) },
+            tcx.mk_trait_ref(trait_def_id, self.substs.truncate_to(tcx, trait_generics)),
             &self.substs[trait_generics.count()..],
         )
     }
@@ -1180,7 +1204,7 @@ pub fn trait_ref_and_own_substs(
     /// as well.
     pub fn trait_ref(&self, tcx: TyCtxt<'tcx>) -> ty::TraitRef<'tcx> {
         let def_id = self.trait_def_id(tcx);
-        ty::TraitRef { def_id, substs: self.substs.truncate_to(tcx, tcx.generics_of(def_id)) }
+        tcx.mk_trait_ref(def_id, self.substs.truncate_to(tcx, tcx.generics_of(def_id)))
     }
 
     pub fn self_ty(&self) -> Ty<'tcx> {
@@ -1394,7 +1418,7 @@ fn from(var: BoundVar) -> Self {
 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
 #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
 pub struct ExistentialProjection<'tcx> {
-    pub item_def_id: DefId,
+    pub def_id: DefId,
     pub substs: SubstsRef<'tcx>,
     pub term: Term<'tcx>,
 }
@@ -1407,7 +1431,7 @@ impl<'tcx> ExistentialProjection<'tcx> {
     /// then this function would return an `exists T. T: Iterator` existential trait
     /// reference.
     pub fn trait_ref(&self, tcx: TyCtxt<'tcx>) -> ty::ExistentialTraitRef<'tcx> {
-        let def_id = tcx.parent(self.item_def_id);
+        let def_id = tcx.parent(self.def_id);
         let subst_count = tcx.generics_of(def_id).count() - 1;
         let substs = tcx.intern_substs(&self.substs[..subst_count]);
         ty::ExistentialTraitRef { def_id, substs }
@@ -1422,10 +1446,8 @@ pub fn with_self_ty(
         debug_assert!(!self_ty.has_escaping_bound_vars());
 
         ty::ProjectionPredicate {
-            projection_ty: ty::ProjectionTy {
-                item_def_id: self.item_def_id,
-                substs: tcx.mk_substs_trait(self_ty, self.substs),
-            },
+            projection_ty: tcx
+                .mk_alias_ty(self.def_id, [self_ty.into()].into_iter().chain(self.substs)),
             term: self.term,
         }
     }
@@ -1438,7 +1460,7 @@ pub fn erase_self_ty(
         projection_predicate.projection_ty.substs.type_at(0);
 
         Self {
-            item_def_id: projection_predicate.projection_ty.item_def_id,
+            def_id: projection_predicate.projection_ty.def_id,
             substs: tcx.intern_substs(&projection_predicate.projection_ty.substs[1..]),
             term: projection_predicate.term,
         }
@@ -1455,7 +1477,7 @@ pub fn with_self_ty(
     }
 
     pub fn item_def_id(&self) -> DefId {
-        self.skip_binder().item_def_id
+        self.skip_binder().def_id
     }
 }
 
@@ -1962,7 +1984,7 @@ pub fn is_fn_ptr(self) -> bool {
 
     #[inline]
     pub fn is_impl_trait(self) -> bool {
-        matches!(self.kind(), Opaque(..))
+        matches!(self.kind(), Alias(ty::Opaque, ..))
     }
 
     #[inline]
@@ -2029,7 +2051,7 @@ pub fn discriminant_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
             ty::Adt(adt, _) if adt.is_enum() => adt.repr().discr_type().to_ty(tcx),
             ty::Generator(_, substs, _) => substs.as_generator().discr_ty(tcx),
 
-            ty::Param(_) | ty::Projection(_) | ty::Opaque(..) | ty::Infer(ty::TyVar(_)) => {
+            ty::Param(_) | ty::Alias(..) | ty::Infer(ty::TyVar(_)) => {
                 let assoc_items = tcx.associated_item_def_ids(
                     tcx.require_lang_item(hir::LangItem::DiscriminantKind, None),
                 );
@@ -2109,7 +2131,7 @@ pub fn ptr_metadata_ty(
 
             // type parameters only have unit metadata if they're sized, so return true
             // to make sure we double check this during confirmation
-            ty::Param(_) |  ty::Projection(_) | ty::Opaque(..) => (tcx.types.unit, true),
+            ty::Param(_) |  ty::Alias(..) => (tcx.types.unit, true),
 
             ty::Infer(ty::TyVar(_))
             | ty::Bound(..)
@@ -2185,7 +2207,7 @@ pub fn is_trivially_sized(self, tcx: TyCtxt<'tcx>) -> bool {
 
             ty::Adt(def, _substs) => def.sized_constraint(tcx).0.is_empty(),
 
-            ty::Projection(_) | ty::Param(_) | ty::Opaque(..) => false,
+            ty::Alias(..) | ty::Param(_) => false,
 
             ty::Infer(ty::TyVar(_)) => false,
 
@@ -2241,9 +2263,12 @@ pub fn is_trivially_pure_clone_copy(self) -> bool {
             ty::Generator(..) | ty::GeneratorWitness(..) => false,
 
             // Might be, but not "trivial" so just giving the safe answer.
-            ty::Adt(..) | ty::Closure(..) | ty::Opaque(..) => false,
+            ty::Adt(..) | ty::Closure(..) => false,
+
+            // Needs normalization or revealing to determine, so no is the safe answer.
+            ty::Alias(..) => false,
 
-            ty::Projection(..) | ty::Param(..) | ty::Infer(..) | ty::Error(..) => false,
+            ty::Param(..) | ty::Infer(..) | ty::Error(..) => false,
 
             ty::Bound(..) | ty::Placeholder(..) => {
                 bug!("`is_trivially_pure_clone_copy` applied to unexpected type: {:?}", self);
index a1b084a5e891eca1bb2bf780597bae2fb06cbb40..f8385c4701605bcc07841ef86b7bb6d6a36c8122 100644 (file)
@@ -252,7 +252,7 @@ fn decode(d: &mut D) -> GenericArg<'tcx> {
     }
 }
 
-/// A substitution mapping generic parameters to new values.
+/// List of generic arguments that are gonna be used to substitute generic parameters.
 pub type InternalSubsts<'tcx> = List<GenericArg<'tcx>>;
 
 pub type SubstsRef<'tcx> = &'tcx InternalSubsts<'tcx>;
index 9ea8dc6e69fdde0b172103282cd1c384bd3fb5b2..857f52c8a245612ddc9d164207681e8c15a7f4aa 100644 (file)
@@ -259,7 +259,7 @@ pub fn struct_tail_with_normalize(
 
                 ty::Tuple(_) => break,
 
-                ty::Projection(_) | ty::Opaque(..) => {
+                ty::Alias(..) => {
                     let normalized = normalize(ty);
                     if ty == normalized {
                         return ty;
@@ -332,8 +332,7 @@ pub fn struct_lockstep_tails_with_normalize(
                         break;
                     }
                 }
-                (ty::Projection(_) | ty::Opaque(..), _)
-                | (_, ty::Projection(_) | ty::Opaque(..)) => {
+                (ty::Alias(..), _) | (_, ty::Alias(..)) => {
                     // If either side is a projection, attempt to
                     // progress via normalization. (Should be safe to
                     // apply to both sides as normalization is
@@ -826,7 +825,7 @@ fn tcx(&self) -> TyCtxt<'tcx> {
     }
 
     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
-        if let ty::Opaque(def_id, substs) = *t.kind() {
+        if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) = *t.kind() {
             self.expand_opaque_ty(def_id, substs).unwrap_or(t)
         } else if t.has_opaque_types() {
             t.super_fold_with(self)
@@ -938,10 +937,9 @@ fn is_trivially_freeze(self) -> bool {
             | ty::Generator(..)
             | ty::GeneratorWitness(_)
             | ty::Infer(_)
-            | ty::Opaque(..)
+            | ty::Alias(..)
             | ty::Param(_)
-            | ty::Placeholder(_)
-            | ty::Projection(_) => false,
+            | ty::Placeholder(_) => false,
         }
     }
 
@@ -978,10 +976,9 @@ fn is_trivially_unpin(self) -> bool {
             | ty::Generator(..)
             | ty::GeneratorWitness(_)
             | ty::Infer(_)
-            | ty::Opaque(..)
+            | ty::Alias(..)
             | ty::Param(_)
-            | ty::Placeholder(_)
-            | ty::Projection(_) => false,
+            | ty::Placeholder(_) => false,
         }
     }
 
@@ -1101,12 +1098,9 @@ pub fn is_structural_eq_shallow(self, tcx: TyCtxt<'tcx>) -> bool {
             //
             // FIXME(ecstaticmorse): Maybe we should `bug` here? This should probably only be
             // called for known, fully-monomorphized types.
-            ty::Projection(_)
-            | ty::Opaque(..)
-            | ty::Param(_)
-            | ty::Bound(..)
-            | ty::Placeholder(_)
-            | ty::Infer(_) => false,
+            ty::Alias(..) | ty::Param(_) | ty::Bound(..) | ty::Placeholder(_) | ty::Infer(_) => {
+                false
+            }
 
             ty::Foreign(_) | ty::GeneratorWitness(..) | ty::Error(_) => false,
         }
@@ -1237,11 +1231,10 @@ pub fn needs_drop_components<'tcx>(
 
         // These require checking for `Copy` bounds or `Adt` destructors.
         ty::Adt(..)
-        | ty::Projection(..)
+        | ty::Alias(..)
         | ty::Param(_)
         | ty::Bound(..)
         | ty::Placeholder(..)
-        | ty::Opaque(..)
         | ty::Infer(_)
         | ty::Closure(..)
         | ty::Generator(..) => Ok(smallvec![ty]),
@@ -1265,13 +1258,12 @@ pub fn is_trivially_const_drop<'tcx>(ty: Ty<'tcx>) -> bool {
         | ty::Never
         | ty::Foreign(_) => true,
 
-        ty::Opaque(..)
+        ty::Alias(..)
         | ty::Dynamic(..)
         | ty::Error(_)
         | ty::Bound(..)
         | ty::Param(_)
         | ty::Placeholder(_)
-        | ty::Projection(_)
         | ty::Infer(_) => false,
 
         // Not trivial because they have components, and instead of looking inside,
index 4cdfd9e594042ba3550aa038094c7c707ad836b2..b302572f3cabdf3db89d88a04f8d3ba38e065f2b 100644 (file)
@@ -654,7 +654,7 @@ fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
         // ignore the inputs to a projection, as they may not appear
         // in the normalized form
         if self.just_constrained {
-            if let ty::Projection(..) | ty::Opaque(..) = t.kind() {
+            if let ty::Alias(..) = t.kind() {
                 return ControlFlow::CONTINUE;
             }
         }
index 4fab5abe909d40c39042aee829a86bff88e51f7b..34dbb6e9f68ea1cf6fe295448322edf3f532cea9 100644 (file)
@@ -165,7 +165,7 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>)
                 stack.push(ty.into());
                 stack.push(lt.into());
             }
-            ty::Projection(data) => {
+            ty::Alias(_, data) => {
                 stack.extend(data.substs.iter().rev());
             }
             ty::Dynamic(obj, lt, _) => {
@@ -188,7 +188,6 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>)
                 }));
             }
             ty::Adt(_, substs)
-            | ty::Opaque(_, substs)
             | ty::Closure(_, substs)
             | ty::Generator(_, substs, _)
             | ty::FnDef(_, substs) => {
index 49d7136a2f1ffd26faff815c99bfbf1467149acd..2643d33cee00abde2688faf2b4f25186ff8ccf6b 100644 (file)
@@ -231,7 +231,7 @@ fn ast_block_stmts(
                                         remainder_span,
                                         pattern,
                                         None,
-                                        Some((None, initializer_span)),
+                                        Some((Some(&destination), initializer_span)),
                                     );
                                     this.visit_primary_bindings(
                                         pattern,
@@ -373,7 +373,9 @@ fn ast_block_stmts(
             // the case of `!`, no return value is required, as the block will never return.
             // Opaque types of empty bodies also need this unit assignment, in order to infer that their
             // type is actually unit. Otherwise there will be no defining use found in the MIR.
-            if destination_ty.is_unit() || matches!(destination_ty.kind(), ty::Opaque(..)) {
+            if destination_ty.is_unit()
+                || matches!(destination_ty.kind(), ty::Alias(ty::Opaque, ..))
+            {
                 // We only want to assign an implicit `()` as the return value of the block if the
                 // block does not diverge. (Otherwise, we may try to assign a unit to a `!`-type.)
                 this.cfg.push_assign_unit(block, source_info, destination, this.tcx);
index eb021f477573c165847eb5159def1aff24535c7c..1fd2e40c187e0487eb761156caa852a091d45b98 100644 (file)
@@ -20,6 +20,7 @@
 use rustc_ast::Attribute;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::def_id::DefId;
+use rustc_hir::HirId;
 use rustc_index::vec::IndexVec;
 use rustc_middle::{
     mir::*,
@@ -33,6 +34,7 @@
 pub(super) fn build_custom_mir<'tcx>(
     tcx: TyCtxt<'tcx>,
     did: DefId,
+    hir_id: HirId,
     thir: &Thir<'tcx>,
     expr: ExprId,
     params: &IndexVec<ParamId, Param<'tcx>>,
@@ -67,7 +69,10 @@ pub(super) fn build_custom_mir<'tcx>(
         parent_scope: None,
         inlined: None,
         inlined_parent_scope: None,
-        local_data: ClearCrossCrate::Clear,
+        local_data: ClearCrossCrate::Set(SourceScopeLocalData {
+            lint_root: hir_id,
+            safety: Safety::Safe,
+        }),
     });
     body.injection_phase = Some(parse_attribute(attr));
 
index 0814793f27790159dd3aa6400fe3a6e28b6b3b4f..c7b3eb44dc5fb52318b716a2d1c53ce3ae483b10 100644 (file)
@@ -142,7 +142,7 @@ pub(crate) fn as_rvalue(
                 let exchange_malloc = Operand::function_handle(
                     tcx,
                     tcx.require_lang_item(LangItem::ExchangeMalloc, Some(expr_span)),
-                    ty::List::empty(),
+                    [],
                     expr_span,
                 );
                 let storage = this.temp(tcx.mk_mut_ptr(tcx.types.u8), expr_span);
index 00dbcaeb0c96f98866bdfc7a466d90785340d5df..e9f327978aab1f0ac0617bafe6f3d85af4b31251 100644 (file)
@@ -6,10 +6,8 @@
 
 impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// Builds a block of MIR statements to evaluate the THIR `expr`.
-    /// If the original expression was an AST statement,
-    /// (e.g., `some().code(&here());`) then `opt_stmt_span` is the
-    /// span of that statement (including its semicolon, if any).
-    /// The scope is used if a statement temporary must be dropped.
+    ///
+    /// The `statement_scope` is used if a statement temporary must be dropped.
     pub(crate) fn stmt_expr(
         &mut self,
         mut block: BasicBlock,
index 6d5a98342d2936730549754f62fcacdadd06bcae..de6a48f7cc411c4c7afb830f729c5bcb95227dfe 100644 (file)
@@ -838,8 +838,6 @@ fn trait_method<'tcx>(
     method_name: Symbol,
     substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
 ) -> ConstantKind<'tcx> {
-    let substs = tcx.mk_substs(substs.into_iter().map(Into::into));
-
     // The unhygienic comparison here is acceptable because this is only
     // used on known traits.
     let item = tcx
index 007f3b55ec8bb156b6c53c338fdfbbfacd3641f8..7af89dd472f88e9be4ccf03111f2ad525d870d7c 100644 (file)
@@ -487,6 +487,7 @@ fn construct_fn<'tcx>(
         return custom::build_custom_mir(
             tcx,
             fn_def.did.to_def_id(),
+            fn_id,
             thir,
             expr,
             arguments,
index fb1ea9ed300ad4f8c87a02d6c32718c614ceca21..3bb1f51650abd5c846acad632a7e649099f4559f 100644 (file)
@@ -132,6 +132,18 @@ fn warn_unused_unsafe(
     fn unsafe_op_in_unsafe_fn_allowed(&self) -> bool {
         self.tcx.lint_level_at_node(UNSAFE_OP_IN_UNSAFE_FN, self.hir_context).0 == Level::Allow
     }
+
+    /// Handle closures/generators/inline-consts, which is unsafecked with their parent body.
+    fn visit_inner_body(&mut self, def: ty::WithOptConstParam<LocalDefId>) {
+        if let Ok((inner_thir, expr)) = self.tcx.thir_body(def) {
+            let inner_thir = &inner_thir.borrow();
+            let hir_context = self.tcx.hir().local_def_id_to_hir_id(def.did);
+            let mut inner_visitor = UnsafetyVisitor { thir: inner_thir, hir_context, ..*self };
+            inner_visitor.visit_expr(&inner_thir[expr]);
+            // Unsafe blocks can be used in the inner body, make sure to take it into account
+            self.safety_context = inner_visitor.safety_context;
+        }
+    }
 }
 
 // Searches for accesses to layout constrained fields.
@@ -408,16 +420,11 @@ fn visit_expr(&mut self, expr: &Expr<'tcx>) {
                 } else {
                     ty::WithOptConstParam::unknown(closure_id)
                 };
-                let (closure_thir, expr) = self.tcx.thir_body(closure_def).unwrap_or_else(|_| {
-                    (self.tcx.alloc_steal_thir(Thir::new()), ExprId::from_u32(0))
-                });
-                let closure_thir = &closure_thir.borrow();
-                let hir_context = self.tcx.hir().local_def_id_to_hir_id(closure_id);
-                let mut closure_visitor =
-                    UnsafetyVisitor { thir: closure_thir, hir_context, ..*self };
-                closure_visitor.visit_expr(&closure_thir[expr]);
-                // Unsafe blocks can be used in closures, make sure to take it into account
-                self.safety_context = closure_visitor.safety_context;
+                self.visit_inner_body(closure_def);
+            }
+            ExprKind::ConstBlock { did, substs: _ } => {
+                let def_id = did.expect_local();
+                self.visit_inner_body(ty::WithOptConstParam::unknown(def_id));
             }
             ExprKind::Field { lhs, .. } => {
                 let lhs = &self.thir[lhs];
@@ -612,11 +619,8 @@ pub fn check_unsafety<'tcx>(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam<LocalD
         return;
     }
 
-    // Closures are handled by their owner, if it has a body
-    if tcx.is_closure(def.did.to_def_id()) {
-        let hir = tcx.hir();
-        let owner = hir.enclosing_body_owner(hir.local_def_id_to_hir_id(def.did));
-        tcx.ensure().thir_check_unsafety(owner);
+    // Closures and inline consts are handled by their owner, if it has a body
+    if tcx.is_typeck_child(def.did.to_def_id()) {
         return;
     }
 
index a21f6cd39f01442aa6b45b1d86c528571dd1d113..7e1f708b0d6a1685f01257e69c479cb20097bbc9 100644 (file)
@@ -121,7 +121,7 @@ fn search_for_structural_match_violation(&self, ty: Ty<'tcx>) -> Option<String>
                 ty::Dynamic(..) => {
                     "trait objects cannot be used in patterns".to_string()
                 }
-                ty::Opaque(..) => {
+                ty::Alias(ty::Opaque, ..) => {
                     "opaque types cannot be used in patterns".to_string()
                 }
                 ty::Closure(..) => {
index 3e370a053766574d110cefebb855cfed25ff81fc..8f80cb95e58e70ff3512a5c95c93977c3e3490af 100644 (file)
@@ -845,7 +845,7 @@ fn is_useful<'p, 'tcx>(
 
         // Opaque types can't get destructured/split, but the patterns can
         // actually hint at hidden types, so we use the patterns' types instead.
-        if let ty::Opaque(..) = ty.kind() {
+        if let ty::Alias(ty::Opaque, ..) = ty.kind() {
             if let Some(row) = rows.first() {
                 ty = row.head().ty();
             }
index f102872cd2d064abeda1d758bde420d5b25d6c38..3224e13f7af4bfe9da8c9fd3b045edadee2b5496 100644 (file)
@@ -29,56 +29,6 @@ pub fn move_path_children_matching<'tcx, F>(
     None
 }
 
-/// When enumerating the child fragments of a path, don't recurse into
-/// paths (1.) past arrays, slices, and pointers, nor (2.) into a type
-/// that implements `Drop`.
-///
-/// Places behind references or arrays are not tracked by elaboration
-/// and are always assumed to be initialized when accessible. As
-/// references and indexes can be reseated, trying to track them can
-/// only lead to trouble.
-///
-/// Places behind ADT's with a Drop impl are not tracked by
-/// elaboration since they can never have a drop-flag state that
-/// differs from that of the parent with the Drop impl.
-///
-/// In both cases, the contents can only be accessed if and only if
-/// their parents are initialized. This implies for example that there
-/// is no need to maintain separate drop flags to track such state.
-//
-// FIXME: we have to do something for moving slice patterns.
-fn place_contents_drop_state_cannot_differ<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    body: &Body<'tcx>,
-    place: mir::Place<'tcx>,
-) -> bool {
-    let ty = place.ty(body, tcx).ty;
-    match ty.kind() {
-        ty::Array(..) => {
-            debug!(
-                "place_contents_drop_state_cannot_differ place: {:?} ty: {:?} => false",
-                place, ty
-            );
-            false
-        }
-        ty::Slice(..) | ty::Ref(..) | ty::RawPtr(..) => {
-            debug!(
-                "place_contents_drop_state_cannot_differ place: {:?} ty: {:?} refd => true",
-                place, ty
-            );
-            true
-        }
-        ty::Adt(def, _) if (def.has_dtor(tcx) && !def.is_box()) || def.is_union() => {
-            debug!(
-                "place_contents_drop_state_cannot_differ place: {:?} ty: {:?} Drop => true",
-                place, ty
-            );
-            true
-        }
-        _ => false,
-    }
-}
-
 pub fn on_lookup_result_bits<'tcx, F>(
     tcx: TyCtxt<'tcx>,
     body: &Body<'tcx>,
@@ -105,13 +55,58 @@ pub fn on_all_children_bits<'tcx, F>(
 ) where
     F: FnMut(MovePathIndex),
 {
+    #[inline]
     fn is_terminal_path<'tcx>(
         tcx: TyCtxt<'tcx>,
         body: &Body<'tcx>,
         move_data: &MoveData<'tcx>,
         path: MovePathIndex,
     ) -> bool {
-        place_contents_drop_state_cannot_differ(tcx, body, move_data.move_paths[path].place)
+        let place = move_data.move_paths[path].place;
+
+        // When enumerating the child fragments of a path, don't recurse into
+        // paths (1.) past arrays, slices, and pointers, nor (2.) into a type
+        // that implements `Drop`.
+        //
+        // Places behind references or arrays are not tracked by elaboration
+        // and are always assumed to be initialized when accessible. As
+        // references and indexes can be reseated, trying to track them can
+        // only lead to trouble.
+        //
+        // Places behind ADT's with a Drop impl are not tracked by
+        // elaboration since they can never have a drop-flag state that
+        // differs from that of the parent with the Drop impl.
+        //
+        // In both cases, the contents can only be accessed if and only if
+        // their parents are initialized. This implies for example that there
+        // is no need to maintain separate drop flags to track such state.
+        //
+        // FIXME: we have to do something for moving slice patterns.
+        let ty = place.ty(body, tcx).ty;
+        match ty.kind() {
+            ty::Adt(def, _) if (def.has_dtor(tcx) && !def.is_box()) || def.is_union() => {
+                debug!(
+                    "place_contents_drop_state_cannot_differ place: {:?} ty: {:?} Drop => true",
+                    place, ty
+                );
+                true
+            }
+            ty::Array(..) => {
+                debug!(
+                    "place_contents_drop_state_cannot_differ place: {:?} ty: {:?} => false",
+                    place, ty
+                );
+                false
+            }
+            ty::Slice(..) | ty::Ref(..) | ty::RawPtr(..) => {
+                debug!(
+                    "place_contents_drop_state_cannot_differ place: {:?} ty: {:?} refd => true",
+                    place, ty
+                );
+                true
+            }
+            _ => false,
+        }
     }
 
     fn on_all_children_bits<'tcx, F>(
index 8610792c0eb5d24be0eced169c40d1d141ec3a4e..7836ae2e7b76f9959107eceb12875c9da02fdd63 100644 (file)
@@ -614,7 +614,6 @@ fn destructor_call_block(&mut self, (succ, unwind): (BasicBlock, Unwind)) -> Bas
         let drop_trait = tcx.require_lang_item(LangItem::Drop, None);
         let drop_fn = tcx.associated_item_def_ids(drop_trait)[0];
         let ty = self.place_ty(self.place);
-        let substs = tcx.mk_substs_trait(ty, []);
 
         let ref_ty =
             tcx.mk_ref(tcx.lifetimes.re_erased, ty::TypeAndMut { ty, mutbl: hir::Mutability::Mut });
@@ -632,7 +631,12 @@ fn destructor_call_block(&mut self, (succ, unwind): (BasicBlock, Unwind)) -> Bas
             )],
             terminator: Some(Terminator {
                 kind: TerminatorKind::Call {
-                    func: Operand::function_handle(tcx, drop_fn, substs, self.source_info.span),
+                    func: Operand::function_handle(
+                        tcx,
+                        drop_fn,
+                        [ty.into()],
+                        self.source_info.span,
+                    ),
                     args: vec![Operand::Move(Place::from(ref_place))],
                     destination: unit_temp,
                     target: Some(succ),
index 18760b6c6fa543328b69ec269cc9c3c4a265afd2..8d379b90a86db28194b2946df68bc564b8e84961 100644 (file)
@@ -3,20 +3,21 @@
 use crate::{CallReturnPlaces, GenKill, Results, ResultsRefCursor};
 use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::*;
+use std::borrow::Cow;
 use std::cell::RefCell;
 
 #[derive(Clone)]
-pub struct MaybeStorageLive {
-    always_live_locals: BitSet<Local>,
+pub struct MaybeStorageLive<'a> {
+    always_live_locals: Cow<'a, BitSet<Local>>,
 }
 
-impl MaybeStorageLive {
-    pub fn new(always_live_locals: BitSet<Local>) -> Self {
+impl<'a> MaybeStorageLive<'a> {
+    pub fn new(always_live_locals: Cow<'a, BitSet<Local>>) -> Self {
         MaybeStorageLive { always_live_locals }
     }
 }
 
-impl<'tcx> crate::AnalysisDomain<'tcx> for MaybeStorageLive {
+impl<'tcx, 'a> crate::AnalysisDomain<'tcx> for MaybeStorageLive<'a> {
     type Domain = BitSet<Local>;
 
     const NAME: &'static str = "maybe_storage_live";
@@ -38,7 +39,7 @@ fn initialize_start_block(&self, body: &mir::Body<'tcx>, on_entry: &mut Self::Do
     }
 }
 
-impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeStorageLive {
+impl<'tcx, 'a> crate::GenKillAnalysis<'tcx> for MaybeStorageLive<'a> {
     type Idx = Local;
 
     fn statement_effect(
index e783d189137749cabfc28a12872bf7ff4ad64006..782abd7804d5d0f66ed7175a141d42fe41bb6e2d 100644 (file)
@@ -1,6 +1,7 @@
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
+use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::hir_id::HirId;
 use rustc_hir::intravisit;
@@ -134,6 +135,28 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
         self.super_rvalue(rvalue, location);
     }
 
+    fn visit_operand(&mut self, op: &Operand<'tcx>, location: Location) {
+        if let Operand::Constant(constant) = op {
+            let maybe_uneval = match constant.literal {
+                ConstantKind::Val(..) | ConstantKind::Ty(_) => None,
+                ConstantKind::Unevaluated(uv, _) => Some(uv),
+            };
+
+            if let Some(uv) = maybe_uneval {
+                if uv.promoted.is_none() {
+                    let def_id = uv.def.def_id_for_type_of();
+                    if self.tcx.def_kind(def_id) == DefKind::InlineConst {
+                        let local_def_id = def_id.expect_local();
+                        let UnsafetyCheckResult { violations, used_unsafe_blocks, .. } =
+                            self.tcx.unsafety_check_result(local_def_id);
+                        self.register_violations(violations, used_unsafe_blocks.iter().copied());
+                    }
+                }
+            }
+        }
+        self.super_operand(op, location);
+    }
+
     fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location: Location) {
         // On types with `scalar_valid_range`, prevent
         // * `&mut x.field`
@@ -410,6 +433,12 @@ fn visit_block(&mut self, block: &'tcx hir::Block<'tcx>) {
         intravisit::walk_block(self, block);
     }
 
+    fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) {
+        if matches!(self.tcx.def_kind(c.def_id), DefKind::InlineConst) {
+            self.visit_body(self.tcx.hir().body(c.body))
+        }
+    }
+
     fn visit_fn(
         &mut self,
         fk: intravisit::FnKind<'tcx>,
@@ -484,7 +513,7 @@ fn unsafety_check_result<'tcx>(
     let mut checker = UnsafetyChecker::new(body, def.did, tcx, param_env);
     checker.visit_body(&body);
 
-    let unused_unsafes = (!tcx.is_closure(def.did.to_def_id()))
+    let unused_unsafes = (!tcx.is_typeck_child(def.did.to_def_id()))
         .then(|| check_unused_unsafe(tcx, def.did, &checker.used_unsafe_blocks));
 
     tcx.arena.alloc(UnsafetyCheckResult {
@@ -516,8 +545,8 @@ fn report_unused_unsafe(tcx: TyCtxt<'_>, kind: UnusedUnsafe, id: HirId) {
 pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) {
     debug!("check_unsafety({:?})", def_id);
 
-    // closures are handled by their parent fn.
-    if tcx.is_closure(def_id.to_def_id()) {
+    // closures and inline consts are handled by their parent fn.
+    if tcx.is_typeck_child(def_id.to_def_id()) {
         return;
     }
 
index b0514e033566c9a65ebe8f5484a41d74ddb39898..044b7ce65bd71cd65ed54597d246e1e4efc01cac 100644 (file)
@@ -6,6 +6,7 @@
 use either::Right;
 
 use rustc_ast::Mutability;
+use rustc_const_eval::const_eval::CheckAlignment;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::def::DefKind;
 use rustc_index::bit_set::BitSet;
@@ -22,7 +23,7 @@
 use rustc_middle::ty::InternalSubsts;
 use rustc_middle::ty::{self, ConstKind, Instance, ParamEnv, Ty, TyCtxt, TypeVisitable};
 use rustc_span::{def_id::DefId, Span};
-use rustc_target::abi::{self, HasDataLayout, Size, TargetDataLayout};
+use rustc_target::abi::{self, Align, HasDataLayout, Size, TargetDataLayout};
 use rustc_target::spec::abi::Abi as CallAbi;
 use rustc_trait_selection::traits;
 
@@ -186,16 +187,27 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx>
     type MemoryKind = !;
 
     #[inline(always)]
-    fn enforce_alignment(_ecx: &InterpCx<'mir, 'tcx, Self>) -> bool {
+    fn enforce_alignment(_ecx: &InterpCx<'mir, 'tcx, Self>) -> CheckAlignment {
         // We do not check for alignment to avoid having to carry an `Align`
         // in `ConstValue::ByRef`.
-        false
+        CheckAlignment::No
     }
 
     #[inline(always)]
     fn enforce_validity(_ecx: &InterpCx<'mir, 'tcx, Self>) -> bool {
         false // for now, we don't enforce validity
     }
+    fn alignment_check_failed(
+        ecx: &InterpCx<'mir, 'tcx, Self>,
+        _has: Align,
+        _required: Align,
+        _check: CheckAlignment,
+    ) -> InterpResult<'tcx, ()> {
+        span_bug!(
+            ecx.cur_span(),
+            "`alignment_check_failed` called when no alignment check requested"
+        )
+    }
 
     fn load_mir(
         _ecx: &InterpCx<'mir, 'tcx, Self>,
index e9027387413cfe1e97425a7992e74e33384fbfb3..c75fe2327de3eb0b52e35f0cbebfe02fc9282838 100644 (file)
@@ -2,6 +2,7 @@
 //!
 //! Currently, this pass only propagates scalar values.
 
+use rustc_const_eval::const_eval::CheckAlignment;
 use rustc_const_eval::interpret::{ConstValue, ImmTy, Immediate, InterpCx, Scalar};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_middle::mir::visit::{MutVisitor, Visitor};
@@ -10,6 +11,7 @@
 use rustc_mir_dataflow::value_analysis::{Map, State, TrackElem, ValueAnalysis, ValueOrPlace};
 use rustc_mir_dataflow::{lattice::FlatSet, Analysis, ResultsVisitor, SwitchIntEdgeEffects};
 use rustc_span::DUMMY_SP;
+use rustc_target::abi::Align;
 
 use crate::MirPass;
 
@@ -448,13 +450,21 @@ impl<'mir, 'tcx> rustc_const_eval::interpret::Machine<'mir, 'tcx> for DummyMachi
     type MemoryKind = !;
     const PANIC_ON_ALLOC_FAIL: bool = true;
 
-    fn enforce_alignment(_ecx: &InterpCx<'mir, 'tcx, Self>) -> bool {
+    fn enforce_alignment(_ecx: &InterpCx<'mir, 'tcx, Self>) -> CheckAlignment {
         unimplemented!()
     }
 
     fn enforce_validity(_ecx: &InterpCx<'mir, 'tcx, Self>) -> bool {
         unimplemented!()
     }
+    fn alignment_check_failed(
+        _ecx: &InterpCx<'mir, 'tcx, Self>,
+        _has: Align,
+        _required: Align,
+        _check: CheckAlignment,
+    ) -> interpret::InterpResult<'tcx, ()> {
+        unimplemented!()
+    }
 
     fn find_mir_or_eval_fn(
         _ecx: &mut InterpCx<'mir, 'tcx, Self>,
index 97485c4f57b12ea872de807daf68c6ca9fe7ec8a..3e45319431cec0e9de6816ed78310c892d09d461 100644 (file)
 use crate::MirPass;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_index::bit_set::BitSet;
+use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor};
 use rustc_middle::mir::{dump_mir, PassWhere};
 use rustc_middle::mir::{
     traversal, BasicBlock, Body, InlineAsmOperand, Local, LocalKind, Location, Operand, Place,
     Rvalue, Statement, StatementKind, TerminatorKind,
 };
-use rustc_middle::mir::{
-    visit::{MutVisitor, PlaceContext, Visitor},
-    ProjectionElem,
-};
 use rustc_middle::ty::TyCtxt;
 use rustc_mir_dataflow::impls::MaybeLiveLocals;
 use rustc_mir_dataflow::{Analysis, ResultsCursor};
@@ -359,40 +356,45 @@ struct FilterInformation<'a, 'body, 'alloc, 'tcx> {
 // through these methods, and not directly.
 impl<'alloc> Candidates<'alloc> {
     /// Just `Vec::retain`, but the condition is inverted and we add debugging output
-    fn vec_remove_debug(
+    fn vec_filter_candidates(
         src: Local,
         v: &mut Vec<Local>,
-        mut f: impl FnMut(Local) -> bool,
+        mut f: impl FnMut(Local) -> CandidateFilter,
         at: Location,
     ) {
         v.retain(|dest| {
             let remove = f(*dest);
-            if remove {
+            if remove == CandidateFilter::Remove {
                 trace!("eliminating {:?} => {:?} due to conflict at {:?}", src, dest, at);
             }
-            !remove
+            remove == CandidateFilter::Keep
         });
     }
 
-    /// `vec_remove_debug` but for an `Entry`
-    fn entry_remove(
+    /// `vec_filter_candidates` but for an `Entry`
+    fn entry_filter_candidates(
         mut entry: OccupiedEntry<'_, Local, Vec<Local>>,
         p: Local,
-        f: impl FnMut(Local) -> bool,
+        f: impl FnMut(Local) -> CandidateFilter,
         at: Location,
     ) {
         let candidates = entry.get_mut();
-        Self::vec_remove_debug(p, candidates, f, at);
+        Self::vec_filter_candidates(p, candidates, f, at);
         if candidates.len() == 0 {
             entry.remove();
         }
     }
 
-    /// Removes all candidates `(p, q)` or `(q, p)` where `p` is the indicated local and `f(q)` is true.
-    fn remove_candidates_if(&mut self, p: Local, mut f: impl FnMut(Local) -> bool, at: Location) {
+    /// For all candidates `(p, q)` or `(q, p)` removes the candidate if `f(q)` says to do so
+    fn filter_candidates_by(
+        &mut self,
+        p: Local,
+        mut f: impl FnMut(Local) -> CandidateFilter,
+        at: Location,
+    ) {
         // Cover the cases where `p` appears as a `src`
         if let Entry::Occupied(entry) = self.c.entry(p) {
-            Self::entry_remove(entry, p, &mut f, at);
+            Self::entry_filter_candidates(entry, p, &mut f, at);
         }
         // And the cases where `p` appears as a `dest`
         let Some(srcs) = self.reverse.get_mut(&p) else {
@@ -401,18 +403,31 @@ fn remove_candidates_if(&mut self, p: Local, mut f: impl FnMut(Local) -> bool, a
         // We use `retain` here to remove the elements from the reverse set if we've removed the
         // matching candidate in the forward set.
         srcs.retain(|src| {
-            if !f(*src) {
+            if f(*src) == CandidateFilter::Keep {
                 return true;
             }
             let Entry::Occupied(entry) = self.c.entry(*src) else {
                 return false;
             };
-            Self::entry_remove(entry, *src, |dest| dest == p, at);
+            Self::entry_filter_candidates(
+                entry,
+                *src,
+                |dest| {
+                    if dest == p { CandidateFilter::Remove } else { CandidateFilter::Keep }
+                },
+                at,
+            );
             false
         });
     }
 }
 
+#[derive(Copy, Clone, PartialEq, Eq)]
+enum CandidateFilter {
+    Keep,
+    Remove,
+}
+
 impl<'a, 'body, 'alloc, 'tcx> FilterInformation<'a, 'body, 'alloc, 'tcx> {
     /// Filters the set of candidates to remove those that conflict.
     ///
@@ -460,7 +475,7 @@ fn internal_filter_liveness(&mut self) {
             for (i, statement) in data.statements.iter().enumerate().rev() {
                 self.at = Location { block, statement_index: i };
                 self.live.seek_after_primary_effect(self.at);
-                self.get_statement_write_info(&statement.kind);
+                self.write_info.for_statement(&statement.kind, self.body);
                 self.apply_conflicts();
             }
         }
@@ -469,80 +484,59 @@ fn internal_filter_liveness(&mut self) {
     fn apply_conflicts(&mut self) {
         let writes = &self.write_info.writes;
         for p in writes {
-            self.candidates.remove_candidates_if(
+            let other_skip = self.write_info.skip_pair.and_then(|(a, b)| {
+                if a == *p {
+                    Some(b)
+                } else if b == *p {
+                    Some(a)
+                } else {
+                    None
+                }
+            });
+            self.candidates.filter_candidates_by(
                 *p,
-                // It is possible that a local may be live for less than the
-                // duration of a statement This happens in the case of function
-                // calls or inline asm. Because of this, we also mark locals as
-                // conflicting when both of them are written to in the same
-                // statement.
-                |q| self.live.contains(q) || writes.contains(&q),
+                |q| {
+                    if Some(q) == other_skip {
+                        return CandidateFilter::Keep;
+                    }
+                    // It is possible that a local may be live for less than the
+                    // duration of a statement This happens in the case of function
+                    // calls or inline asm. Because of this, we also mark locals as
+                    // conflicting when both of them are written to in the same
+                    // statement.
+                    if self.live.contains(q) || writes.contains(&q) {
+                        CandidateFilter::Remove
+                    } else {
+                        CandidateFilter::Keep
+                    }
+                },
                 self.at,
             );
         }
     }
-
-    /// Gets the write info for the `statement`.
-    fn get_statement_write_info(&mut self, statement: &StatementKind<'tcx>) {
-        self.write_info.writes.clear();
-        match statement {
-            StatementKind::Assign(box (lhs, rhs)) => match rhs {
-                Rvalue::Use(op) => {
-                    if !lhs.is_indirect() {
-                        self.get_assign_use_write_info(*lhs, op);
-                        return;
-                    }
-                }
-                _ => (),
-            },
-            _ => (),
-        }
-
-        self.write_info.for_statement(statement);
-    }
-
-    fn get_assign_use_write_info(&mut self, lhs: Place<'tcx>, rhs: &Operand<'tcx>) {
-        // We register the writes for the operand unconditionally
-        self.write_info.add_operand(rhs);
-        // However, we cannot do the same thing for the `lhs` as that would always block the
-        // optimization. Instead, we consider removing candidates manually.
-        let Some(rhs) = rhs.place() else {
-            self.write_info.add_place(lhs);
-            return;
-        };
-        // Find out which candidate pair we should skip, if any
-        let Some((src, dest)) = places_to_candidate_pair(lhs, rhs, self.body) else {
-            self.write_info.add_place(lhs);
-            return;
-        };
-        self.candidates.remove_candidates_if(
-            lhs.local,
-            |other| {
-                // Check if this is the candidate pair that should not be removed
-                if (lhs.local == src && other == dest) || (lhs.local == dest && other == src) {
-                    return false;
-                }
-                // Otherwise, do the "standard" thing
-                self.live.contains(other)
-            },
-            self.at,
-        )
-    }
 }
 
 /// Describes where a statement/terminator writes to
 #[derive(Default, Debug)]
 struct WriteInfo {
     writes: Vec<Local>,
+    /// If this pair of locals is a candidate pair, completely skip processing it during this
+    /// statement. All other candidates are unaffected.
+    skip_pair: Option<(Local, Local)>,
 }
 
 impl WriteInfo {
-    fn for_statement<'tcx>(&mut self, statement: &StatementKind<'tcx>) {
+    fn for_statement<'tcx>(&mut self, statement: &StatementKind<'tcx>, body: &Body<'tcx>) {
+        self.reset();
         match statement {
             StatementKind::Assign(box (lhs, rhs)) => {
                 self.add_place(*lhs);
                 match rhs {
-                    Rvalue::Use(op) | Rvalue::Repeat(op, _) => {
+                    Rvalue::Use(op) => {
+                        self.add_operand(op);
+                        self.consider_skipping_for_assign_use(*lhs, op, body);
+                    }
+                    Rvalue::Repeat(op, _) => {
                         self.add_operand(op);
                     }
                     Rvalue::Cast(_, op, _)
@@ -586,8 +580,22 @@ fn for_statement<'tcx>(&mut self, statement: &StatementKind<'tcx>) {
         }
     }
 
+    fn consider_skipping_for_assign_use<'tcx>(
+        &mut self,
+        lhs: Place<'tcx>,
+        rhs: &Operand<'tcx>,
+        body: &Body<'tcx>,
+    ) {
+        let Some(rhs) = rhs.place() else {
+            return
+        };
+        if let Some(pair) = places_to_candidate_pair(lhs, rhs, body) {
+            self.skip_pair = Some(pair);
+        }
+    }
+
     fn for_terminator<'tcx>(&mut self, terminator: &TerminatorKind<'tcx>) {
-        self.writes.clear();
+        self.reset();
         match terminator {
             TerminatorKind::SwitchInt { discr: op, .. }
             | TerminatorKind::Assert { cond: op, .. } => {
@@ -657,15 +665,16 @@ fn add_operand<'tcx>(&mut self, op: &Operand<'tcx>) {
             Operand::Copy(_) | Operand::Constant(_) => (),
         }
     }
+
+    fn reset(&mut self) {
+        self.writes.clear();
+        self.skip_pair = None;
+    }
 }
 
 /////////////////////////////////////////////////////
 // Candidate accumulation
 
-fn is_constant<'tcx>(place: Place<'tcx>) -> bool {
-    place.projection.iter().all(|p| !matches!(p, ProjectionElem::Deref | ProjectionElem::Index(_)))
-}
-
 /// If the pair of places is being considered for merging, returns the candidate which would be
 /// merged in order to accomplish this.
 ///
@@ -741,10 +750,6 @@ fn visit_statement(&mut self, statement: &Statement<'tcx>, _: Location) {
             Rvalue::Use(Operand::Copy(rhs) | Operand::Move(rhs)),
         )) = &statement.kind
         {
-            if !is_constant(*lhs) || !is_constant(*rhs) {
-                return;
-            }
-
             let Some((src, dest)) = places_to_candidate_pair(*lhs, *rhs, self.body) else {
                 return;
             };
index c08593afe9d88ff900b6c116ffcd8183cc0b89d4..c097af6161159a7fcec85b6b0bb69a3605fcb8e9 100644 (file)
@@ -490,7 +490,7 @@ fn locals_live_across_suspend_points<'tcx>(
 
     // Calculate when MIR locals have live storage. This gives us an upper bound of their
     // lifetimes.
-    let mut storage_live = MaybeStorageLive::new(always_live_locals.clone())
+    let mut storage_live = MaybeStorageLive::new(std::borrow::Cow::Borrowed(always_live_locals))
         .into_engine(tcx, body_ref)
         .iterate_to_fixpoint()
         .into_results_cursor(body_ref);
index 220cf7df9c6c7e99cd35d103fa959988f9b1db34..9d560f5c837e2d75e75f6899d65199bdef8fe710 100644 (file)
@@ -849,7 +849,7 @@ fn visit_projection_elem(
             };
 
             let kind = match parent_ty.ty.kind() {
-                &ty::Opaque(def_id, substs) => {
+                &ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
                     self.tcx.bound_type_of(def_id).subst(self.tcx, substs).kind()
                 }
                 kind => kind,
index 569e783fee847b17a561293e001783627773ab9e..6cabef92d8c2190e7f31514eb319eee727dcc9c2 100644 (file)
@@ -52,7 +52,11 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
 fn maybe_zst(ty: Ty<'_>) -> bool {
     match ty.kind() {
         // maybe ZST (could be more precise)
-        ty::Adt(..) | ty::Array(..) | ty::Closure(..) | ty::Tuple(..) | ty::Opaque(..) => true,
+        ty::Adt(..)
+        | ty::Array(..)
+        | ty::Closure(..)
+        | ty::Tuple(..)
+        | ty::Alias(ty::Opaque, ..) => true,
         // definitely ZST
         ty::FnDef(..) | ty::Never => true,
         // unreachable or can't be ZST
index f92a0e826dcdfb6dcf55e264235d07e360a5137f..f8b55c862875e06796968c7cc1bbc0d9de190570 100644 (file)
@@ -336,8 +336,7 @@ fn new(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -> Self {
         // we must subst the self_ty because it's
         // otherwise going to be TySelf and we can't index
         // or access fields of a Place of type TySelf.
-        let substs = tcx.mk_substs_trait(self_ty, []);
-        let sig = tcx.bound_fn_sig(def_id).subst(tcx, substs);
+        let sig = tcx.bound_fn_sig(def_id).subst(tcx, &[self_ty.into()]);
         let sig = tcx.erase_late_bound_regions(sig);
         let span = tcx.def_span(def_id);
 
@@ -417,10 +416,8 @@ fn make_clone_call(
     ) {
         let tcx = self.tcx;
 
-        let substs = tcx.mk_substs_trait(ty, []);
-
         // `func == Clone::clone(&ty) -> ty`
-        let func_ty = tcx.mk_fn_def(self.def_id, substs);
+        let func_ty = tcx.mk_fn_def(self.def_id, [ty]);
         let func = Operand::Constant(Box::new(Constant {
             span: self.span,
             user_ty: None,
@@ -575,9 +572,8 @@ fn build_call_shim<'tcx>(
 
         // Create substitutions for the `Self` and `Args` generic parameters of the shim body.
         let arg_tup = tcx.mk_tup(untuple_args.iter());
-        let sig_substs = tcx.mk_substs_trait(ty, [ty::subst::GenericArg::from(arg_tup)]);
 
-        (Some(sig_substs), Some(untuple_args))
+        (Some([ty.into(), arg_tup.into()]), Some(untuple_args))
     } else {
         (None, None)
     };
@@ -588,7 +584,7 @@ fn build_call_shim<'tcx>(
 
     assert_eq!(sig_substs.is_some(), !instance.has_polymorphic_mir_body());
     let mut sig =
-        if let Some(sig_substs) = sig_substs { sig.subst(tcx, sig_substs) } else { sig.0 };
+        if let Some(sig_substs) = sig_substs { sig.subst(tcx, &sig_substs) } else { sig.0 };
 
     if let CallKind::Indirect(fnty) = call_kind {
         // `sig` determines our local decls, and thus the callee type in the `Call` terminator. This
index f1ca72de8dbe47d934cc8b8c197c5ed4b4d11ff7..f15cf54718e2b7221bbb70fb9261f36af32fd525 100644 (file)
@@ -77,3 +77,9 @@ pub struct SymbolAlreadyDefined {
     pub span: Option<Span>,
     pub symbol: String,
 }
+
+#[derive(Diagnostic)]
+#[diag(monomorphize_couldnt_dump_mono_stats)]
+pub struct CouldntDumpMonoStats {
+    pub error: String,
+}
index 932edc6675f5900cb6dd04d9678d7847345f0f9b..38e1d98e44e13f0d72af80666004b666fb21835c 100644 (file)
 mod default;
 mod merging;
 
+use std::cmp;
+use std::fs::{self, File};
+use std::io::{BufWriter, Write};
+use std::path::{Path, PathBuf};
+
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::sync;
 use rustc_hir::def_id::DefIdSet;
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::TyCtxt;
+use rustc_session::config::SwitchWithOptPath;
 use rustc_span::symbol::Symbol;
 
 use crate::collector::InliningMap;
 use crate::collector::{self, MonoItemCollectionMode};
-use crate::errors::{SymbolAlreadyDefined, UnknownPartitionStrategy};
+use crate::errors::{CouldntDumpMonoStats, SymbolAlreadyDefined, UnknownPartitionStrategy};
 
 pub struct PartitioningCx<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
@@ -411,6 +417,15 @@ fn collect_and_partition_mono_items<'tcx>(
         })
         .collect();
 
+    // Output monomorphization stats per def_id
+    if let SwitchWithOptPath::Enabled(ref path) = tcx.sess.opts.unstable_opts.dump_mono_stats {
+        if let Err(err) =
+            dump_mono_items_stats(tcx, &codegen_units, path, tcx.sess.opts.crate_name.as_deref())
+        {
+            tcx.sess.emit_fatal(CouldntDumpMonoStats { error: err.to_string() });
+        }
+    }
+
     if tcx.sess.opts.unstable_opts.print_mono_items.is_some() {
         let mut item_to_cgus: FxHashMap<_, Vec<_>> = Default::default();
 
@@ -465,6 +480,67 @@ fn collect_and_partition_mono_items<'tcx>(
     (tcx.arena.alloc(mono_items), codegen_units)
 }
 
+/// Outputs stats about instantation counts and estimated size, per `MonoItem`'s
+/// def, to a file in the given output directory.
+fn dump_mono_items_stats<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    codegen_units: &[CodegenUnit<'tcx>],
+    output_directory: &Option<PathBuf>,
+    crate_name: Option<&str>,
+) -> Result<(), Box<dyn std::error::Error>> {
+    let output_directory = if let Some(ref directory) = output_directory {
+        fs::create_dir_all(directory)?;
+        directory
+    } else {
+        Path::new(".")
+    };
+
+    let filename = format!("{}.mono_items.md", crate_name.unwrap_or("unknown-crate"));
+    let output_path = output_directory.join(&filename);
+    let file = File::create(output_path)?;
+    let mut file = BufWriter::new(file);
+
+    // Gather instantiated mono items grouped by def_id
+    let mut items_per_def_id: FxHashMap<_, Vec<_>> = Default::default();
+    for cgu in codegen_units {
+        for (&mono_item, _) in cgu.items() {
+            // Avoid variable-sized compiler-generated shims
+            if mono_item.is_user_defined() {
+                items_per_def_id.entry(mono_item.def_id()).or_default().push(mono_item);
+            }
+        }
+    }
+
+    // Output stats sorted by total instantiated size, from heaviest to lightest
+    let mut stats: Vec<_> = items_per_def_id
+        .into_iter()
+        .map(|(def_id, items)| {
+            let instantiation_count = items.len();
+            let size_estimate = items[0].size_estimate(tcx);
+            let total_estimate = instantiation_count * size_estimate;
+            (def_id, instantiation_count, size_estimate, total_estimate)
+        })
+        .collect();
+    stats.sort_unstable_by_key(|(_, _, _, total_estimate)| cmp::Reverse(*total_estimate));
+
+    if !stats.is_empty() {
+        writeln!(
+            file,
+            "| Item | Instantiation count | Estimated Cost Per Instantiation | Total Estimated Cost |"
+        )?;
+        writeln!(file, "| --- | ---: | ---: | ---: |")?;
+        for (def_id, instantiation_count, size_estimate, total_estimate) in stats {
+            let item = with_no_trimmed_paths!(tcx.def_path_str(def_id));
+            writeln!(
+                file,
+                "| {item} | {instantiation_count} | {size_estimate} | {total_estimate} |"
+            )?;
+        }
+    }
+
+    Ok(())
+}
+
 fn codegened_and_inlined_items<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> &'tcx DefIdSet {
     let (items, cgus) = tcx.collect_and_partition_mono_items(());
     let mut visited = DefIdSet::default();
index 9875cde4a05ebe9354ef1ed5b83b6ba59e29aa5d..18a0bee9c2e5ee83ba98e4543fdc54b2befb3d8d 100644 (file)
@@ -1221,3 +1221,11 @@ pub(crate) struct UnexpectedIfWithIf(
     #[suggestion(applicability = "machine-applicable", code = " ", style = "verbose")]
     pub Span,
 );
+
+#[derive(Diagnostic)]
+#[diag(parse_maybe_fn_typo_with_impl)]
+pub(crate) struct FnTypoWithImpl {
+    #[primary_span]
+    #[suggestion(applicability = "maybe-incorrect", code = "impl", style = "verbose")]
+    pub fn_span: Span,
+}
index c316a4dd6b41ad346527e1ff0b31512d06434a0f..0191ab730c812e89e55099c5896dc4be68284e38 100644 (file)
@@ -159,8 +159,6 @@ enum IsStandalone {
     Standalone,
     /// It's a subexpression, i.e., *not* standalone.
     Subexpr,
-    /// It's maybe standalone; we're not sure.
-    Maybe,
 }
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
@@ -213,14 +211,8 @@ fn emit(self, err: &mut Diagnostic) {
         err.multipart_suggestion(&self.msg, self.patches, self.applicability);
     }
 
-    /// Overrides individual messages and applicabilities.
-    fn emit_many(
-        err: &mut Diagnostic,
-        msg: &str,
-        applicability: Applicability,
-        suggestions: impl Iterator<Item = Self>,
-    ) {
-        err.multipart_suggestions(msg, suggestions.map(|s| s.patches), applicability);
+    fn emit_verbose(self, err: &mut Diagnostic) {
+        err.multipart_suggestion_verbose(&self.msg, self.patches, self.applicability);
     }
 }
 
@@ -1267,12 +1259,10 @@ pub(super) fn recover_from_prefix_increment(
         &mut self,
         operand_expr: P<Expr>,
         op_span: Span,
-        prev_is_semi: bool,
+        start_stmt: bool,
     ) -> PResult<'a, P<Expr>> {
-        let standalone =
-            if prev_is_semi { IsStandalone::Standalone } else { IsStandalone::Subexpr };
+        let standalone = if start_stmt { IsStandalone::Standalone } else { IsStandalone::Subexpr };
         let kind = IncDecRecovery { standalone, op: IncOrDec::Inc, fixity: UnaryFixity::Pre };
-
         self.recover_from_inc_dec(operand_expr, kind, op_span)
     }
 
@@ -1280,13 +1270,13 @@ pub(super) fn recover_from_postfix_increment(
         &mut self,
         operand_expr: P<Expr>,
         op_span: Span,
+        start_stmt: bool,
     ) -> PResult<'a, P<Expr>> {
         let kind = IncDecRecovery {
-            standalone: IsStandalone::Maybe,
+            standalone: if start_stmt { IsStandalone::Standalone } else { IsStandalone::Subexpr },
             op: IncOrDec::Inc,
             fixity: UnaryFixity::Post,
         };
-
         self.recover_from_inc_dec(operand_expr, kind, op_span)
     }
 
@@ -1315,34 +1305,25 @@ fn recover_from_inc_dec(
         };
 
         match kind.standalone {
-            IsStandalone::Standalone => self.inc_dec_standalone_suggest(kind, spans).emit(&mut err),
+            IsStandalone::Standalone => {
+                self.inc_dec_standalone_suggest(kind, spans).emit_verbose(&mut err)
+            }
             IsStandalone::Subexpr => {
                 let Ok(base_src) = self.span_to_snippet(base.span)
-                    else { return help_base_case(err, base) };
+                else { return help_base_case(err, base) };
                 match kind.fixity {
                     UnaryFixity::Pre => {
                         self.prefix_inc_dec_suggest(base_src, kind, spans).emit(&mut err)
                     }
                     UnaryFixity::Post => {
-                        self.postfix_inc_dec_suggest(base_src, kind, spans).emit(&mut err)
+                        // won't suggest since we can not handle the precedences
+                        // for example: `a + b++` has been parsed (a + b)++ and we can not suggest here
+                        if !matches!(base.kind, ExprKind::Binary(_, _, _)) {
+                            self.postfix_inc_dec_suggest(base_src, kind, spans).emit(&mut err)
+                        }
                     }
                 }
             }
-            IsStandalone::Maybe => {
-                let Ok(base_src) = self.span_to_snippet(base.span)
-                    else { return help_base_case(err, base) };
-                let sugg1 = match kind.fixity {
-                    UnaryFixity::Pre => self.prefix_inc_dec_suggest(base_src, kind, spans),
-                    UnaryFixity::Post => self.postfix_inc_dec_suggest(base_src, kind, spans),
-                };
-                let sugg2 = self.inc_dec_standalone_suggest(kind, spans);
-                MultiSugg::emit_many(
-                    &mut err,
-                    "use `+= 1` instead",
-                    Applicability::Unspecified,
-                    [sugg1, sugg2].into_iter(),
-                )
-            }
         }
         Err(err)
     }
@@ -1392,7 +1373,6 @@ fn inc_dec_standalone_suggest(
         }
 
         patches.push((post_span, format!(" {}= 1", kind.op.chr())));
-
         MultiSugg {
             msg: format!("use `{}= 1` instead", kind.op.chr()),
             patches,
index 8a3545eb3be3ab5d874b9c11acc48761774706f1..c0ed450b98508e07beed81f05c23030695d232c5 100644 (file)
@@ -83,7 +83,7 @@ macro_rules! maybe_whole_expr {
 pub(super) enum LhsExpr {
     NotYetParsed,
     AttributesParsed(AttrWrapper),
-    AlreadyParsed(P<Expr>),
+    AlreadyParsed(P<Expr>, bool), // (expr, starts_statement)
 }
 
 impl From<Option<AttrWrapper>> for LhsExpr {
@@ -101,7 +101,7 @@ impl From<P<Expr>> for LhsExpr {
     ///
     /// This conversion does not allocate.
     fn from(expr: P<Expr>) -> Self {
-        LhsExpr::AlreadyParsed(expr)
+        LhsExpr::AlreadyParsed(expr, false)
     }
 }
 
@@ -173,7 +173,9 @@ pub(super) fn parse_assoc_expr_with(
         min_prec: usize,
         lhs: LhsExpr,
     ) -> PResult<'a, P<Expr>> {
-        let mut lhs = if let LhsExpr::AlreadyParsed(expr) = lhs {
+        let mut starts_stmt = false;
+        let mut lhs = if let LhsExpr::AlreadyParsed(expr, starts_statement) = lhs {
+            starts_stmt = starts_statement;
             expr
         } else {
             let attrs = match lhs {
@@ -292,7 +294,7 @@ pub(super) fn parse_assoc_expr_with(
                 let op_span = self.prev_token.span.to(self.token.span);
                 // Eat the second `+`
                 self.bump();
-                lhs = self.recover_from_postfix_increment(lhs, op_span)?;
+                lhs = self.recover_from_postfix_increment(lhs, op_span, starts_stmt)?;
                 continue;
             }
 
@@ -590,14 +592,15 @@ macro_rules! make_it {
             token::BinOp(token::Plus)
                 if this.look_ahead(1, |t| *t == token::BinOp(token::Plus)) =>
             {
-                let prev_is_semi = this.prev_token == token::Semi;
+                let starts_stmt = this.prev_token == token::Semi
+                    || this.prev_token == token::CloseDelim(Delimiter::Brace);
                 let pre_span = this.token.span.to(this.look_ahead(1, |t| t.span));
                 // Eat both `+`s.
                 this.bump();
                 this.bump();
 
                 let operand_expr = this.parse_dot_or_call_expr(Default::default())?;
-                this.recover_from_prefix_increment(operand_expr, pre_span, prev_is_semi)
+                this.recover_from_prefix_increment(operand_expr, pre_span, starts_stmt)
             }
             token::Ident(..) if this.token.is_keyword(kw::Box) => {
                 make_it!(this, attrs, |this, _| this.parse_box_expr(lo))
index beb9d55d454162d11da7442a650989fe9a72895a..7c2d01509de417b100c281abf1a6863106d05ee0 100644 (file)
@@ -3,6 +3,7 @@
 use super::diagnostics::{dummy_arg, ConsumeClosingDelim};
 use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
 use super::{AttrWrapper, FollowedByType, ForceCollect, Parser, PathStyle, TrailingToken};
+use crate::errors::FnTypoWithImpl;
 use rustc_ast::ast::*;
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Delimiter, TokenKind};
@@ -2131,11 +2132,26 @@ fn parse_fn(
         vis: &Visibility,
         case: Case,
     ) -> PResult<'a, (Ident, FnSig, Generics, Option<P<Block>>)> {
+        let fn_span = self.token.span;
         let header = self.parse_fn_front_matter(vis, case)?; // `const ... fn`
         let ident = self.parse_ident()?; // `foo`
         let mut generics = self.parse_generics()?; // `<'a, T, ...>`
-        let decl =
-            self.parse_fn_decl(fn_parse_mode.req_name, AllowPlus::Yes, RecoverReturnSign::Yes)?; // `(p: u8, ...)`
+        let decl = match self.parse_fn_decl(
+            fn_parse_mode.req_name,
+            AllowPlus::Yes,
+            RecoverReturnSign::Yes,
+        ) {
+            Ok(decl) => decl,
+            Err(old_err) => {
+                // If we see `for Ty ...` then user probably meant `impl` item.
+                if self.token.is_keyword(kw::For) {
+                    old_err.cancel();
+                    return Err(self.sess.create_err(FnTypoWithImpl { fn_span }));
+                } else {
+                    return Err(old_err);
+                }
+            }
+        };
         generics.where_clause = self.parse_where_clause()?; // `where T: Ord`
 
         let mut sig_hi = self.prev_token.span;
index 42197e6379749a264c325dbb332a41926754b515..bae7f2670cb11689866e837b411160d0cebe7552 100644 (file)
@@ -164,7 +164,7 @@ fn parse_stmt_path_start(&mut self, lo: Span, attrs: AttrWrapper) -> PResult<'a,
             // Perform this outside of the `collect_tokens_trailing_token` closure,
             // since our outer attributes do not apply to this part of the expression
             let expr = self.with_res(Restrictions::STMT_EXPR, |this| {
-                this.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(expr))
+                this.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(expr, true))
             })?;
             Ok(self.mk_stmt(lo.to(self.prev_token.span), StmtKind::Expr(expr)))
         } else {
@@ -198,7 +198,7 @@ fn parse_stmt_mac(&mut self, lo: Span, attrs: AttrVec, path: ast::Path) -> PResu
             let e = self.mk_expr(lo.to(hi), ExprKind::MacCall(mac));
             let e = self.maybe_recover_from_bad_qpath(e)?;
             let e = self.parse_dot_or_call_expr_with(e, lo, attrs)?;
-            let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e))?;
+            let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e, false))?;
             StmtKind::Expr(e)
         };
         Ok(self.mk_stmt(lo.to(hi), kind))
index a254c892478cf19815f2ccf79e670f3db96f08dd..72d38aeac7a0c0647f176fe451143d3cc1611354 100644 (file)
@@ -88,10 +88,7 @@ fn visit(&mut self, ty_fragment: impl TypeVisitable<'tcx>) -> ControlFlow<Self::
     fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> ControlFlow<Self::BreakTy> {
         self.skeleton().visit_trait(trait_ref)
     }
-    fn visit_projection_ty(
-        &mut self,
-        projection: ty::ProjectionTy<'tcx>,
-    ) -> ControlFlow<Self::BreakTy> {
+    fn visit_projection_ty(&mut self, projection: ty::AliasTy<'tcx>) -> ControlFlow<Self::BreakTy> {
         self.skeleton().visit_projection_ty(projection)
     }
     fn visit_predicates(
@@ -113,29 +110,25 @@ impl<'tcx, V> DefIdVisitorSkeleton<'_, 'tcx, V>
     V: DefIdVisitor<'tcx> + ?Sized,
 {
     fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> ControlFlow<V::BreakTy> {
-        let TraitRef { def_id, substs } = trait_ref;
+        let TraitRef { def_id, substs, .. } = trait_ref;
         self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref.print_only_trait_path())?;
         if self.def_id_visitor.shallow() { ControlFlow::CONTINUE } else { substs.visit_with(self) }
     }
 
-    fn visit_projection_ty(
-        &mut self,
-        projection: ty::ProjectionTy<'tcx>,
-    ) -> ControlFlow<V::BreakTy> {
+    fn visit_projection_ty(&mut self, projection: ty::AliasTy<'tcx>) -> ControlFlow<V::BreakTy> {
         let tcx = self.def_id_visitor.tcx();
-        let (trait_ref, assoc_substs) = if tcx.def_kind(projection.item_def_id)
-            != DefKind::ImplTraitPlaceholder
-        {
-            projection.trait_ref_and_own_substs(tcx)
-        } else {
-            // HACK(RPITIT): Remove this when RPITITs are lowered to regular assoc tys
-            let def_id = tcx.impl_trait_in_trait_parent(projection.item_def_id);
-            let trait_generics = tcx.generics_of(def_id);
-            (
-                ty::TraitRef { def_id, substs: projection.substs.truncate_to(tcx, trait_generics) },
-                &projection.substs[trait_generics.count()..],
-            )
-        };
+        let (trait_ref, assoc_substs) =
+            if tcx.def_kind(projection.def_id) != DefKind::ImplTraitPlaceholder {
+                projection.trait_ref_and_own_substs(tcx)
+            } else {
+                // HACK(RPITIT): Remove this when RPITITs are lowered to regular assoc tys
+                let def_id = tcx.impl_trait_in_trait_parent(projection.def_id);
+                let trait_generics = tcx.generics_of(def_id);
+                (
+                    tcx.mk_trait_ref(def_id, projection.substs.truncate_to(tcx, trait_generics)),
+                    &projection.substs[trait_generics.count()..],
+                )
+            };
         self.visit_trait(trait_ref)?;
         if self.def_id_visitor.shallow() {
             ControlFlow::CONTINUE
@@ -214,7 +207,7 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<V::BreakTy> {
                     }
                 }
             }
-            ty::Projection(proj) => {
+            ty::Alias(ty::Projection, proj) => {
                 if self.def_id_visitor.skip_assoc_tys() {
                     // Visitors searching for minimal visibility/reachability want to
                     // conservatively approximate associated types like `<Type as Trait>::Alias`
@@ -241,7 +234,7 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<V::BreakTy> {
                     self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref)?;
                 }
             }
-            ty::Opaque(def_id, ..) => {
+            ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => {
                 // Skip repeated `Opaque`s to avoid infinite recursion.
                 if self.visited_opaque_tys.insert(def_id) {
                     // The intent is to treat `impl Trait1 + Trait2` identically to
@@ -1308,15 +1301,15 @@ fn visit_qpath(&mut self, qpath: &'tcx hir::QPath<'tcx>, id: hir::HirId, span: S
             let is_local_static =
                 if let DefKind::Static(_) = kind { def_id.is_local() } else { false };
             if !self.item_is_accessible(def_id) && !is_local_static {
-                let sess = self.tcx.sess;
-                let sm = sess.source_map();
-                let name = match qpath {
-                    hir::QPath::Resolved(..) | hir::QPath::LangItem(..) => {
-                        sm.span_to_snippet(qpath.span()).ok()
+                let name = match *qpath {
+                    hir::QPath::LangItem(it, ..) => {
+                        self.tcx.lang_items().get(it).map(|did| self.tcx.def_path_str(did))
                     }
+                    hir::QPath::Resolved(_, path) => Some(self.tcx.def_path_str(path.res.def_id())),
                     hir::QPath::TypeRelative(_, segment) => Some(segment.ident.to_string()),
                 };
                 let kind = kind.descr(def_id);
+                let sess = self.tcx.sess;
                 let _ = match name {
                     Some(name) => {
                         sess.emit_err(ItemIsPrivate { span, kind, descr: (&name).into() })
index 7a20eaceba0247682a7ae74451ddcbf3eeeb7772..cf2f04c7486b846c0609109998fc8daedc75b8db 100644 (file)
@@ -49,7 +49,7 @@ pub struct Cycle {
     #[primary_span]
     pub span: Span,
     pub stack_bottom: String,
-    #[subdiagnostic(eager)]
+    #[subdiagnostic]
     pub cycle_stack: Vec<CycleStack>,
     #[subdiagnostic]
     pub stack_count: StackCount,
index cf3e5946053fe514f5b9195784e93e37d63e053f..5b7a00101e9b75b53cd635ec29c1d90da6a9a5be 100644 (file)
@@ -566,6 +566,9 @@ struct LateResolutionVisitor<'a, 'b, 'ast> {
     /// FIXME #4948: Reuse ribs to avoid allocation.
     ribs: PerNS<Vec<Rib<'a>>>,
 
+    /// Previous poped `rib`, only used for diagnostic.
+    last_block_rib: Option<Rib<'a>>,
+
     /// The current set of local scopes, for labels.
     label_ribs: Vec<Rib<'a, NodeId>>,
 
@@ -873,6 +876,8 @@ fn visit_fn(&mut self, fn_kind: FnKind<'ast>, sp: Span, fn_id: NodeId) {
                             // Ignore errors in function bodies if this is rustdoc
                             // Be sure not to set this until the function signature has been resolved.
                             let previous_state = replace(&mut this.in_func_body, true);
+                            // We only care block in the same function
+                            this.last_block_rib = None;
                             // Resolve the function body, potentially inside the body of an async closure
                             this.with_lifetime_rib(
                                 LifetimeRibKind::Elided(LifetimeRes::Infer),
@@ -1168,6 +1173,7 @@ fn new(resolver: &'b mut Resolver<'a>) -> LateResolutionVisitor<'a, 'b, 'ast> {
                 type_ns: vec![Rib::new(start_rib_kind)],
                 macro_ns: vec![Rib::new(start_rib_kind)],
             },
+            last_block_rib: None,
             label_ribs: Vec::new(),
             lifetime_ribs: Vec::new(),
             lifetime_elision_candidates: None,
@@ -3769,7 +3775,7 @@ fn resolve_block(&mut self, block: &'ast Block) {
             self.ribs[ValueNS].pop();
             self.label_ribs.pop();
         }
-        self.ribs[ValueNS].pop();
+        self.last_block_rib = self.ribs[ValueNS].pop();
         if anonymous_module.is_some() {
             self.ribs[TypeNS].pop();
         }
index d43983ea8150faf15db202c7b8a242a770c81c97..49bbe37ee4328ad5dadd9ae79c87a7ded364dcd0 100644 (file)
@@ -623,6 +623,22 @@ fn try_lookup_name_relaxed(
                 return (true, candidates);
             }
         }
+
+        // Try to find in last block rib
+        if let Some(rib) = &self.last_block_rib && let RibKind::NormalRibKind = rib.kind {
+            for (ident, &res) in &rib.bindings {
+                if let Res::Local(_) = res && path.len() == 1 &&
+                    ident.span.eq_ctxt(path[0].ident.span) &&
+                    ident.name == path[0].ident.name {
+                    err.span_help(
+                        ident.span,
+                        &format!("the binding `{}` is available in a different scope in the same function", path_str),
+                    );
+                    return (true, candidates);
+                }
+            }
+        }
+
         return (false, candidates);
     }
 
index 6de564a3a069225ebee1f06be5418c9de0e1cac1..3bafd3730bd79d2db4cb31d95bda50d7e756a492 100644 (file)
@@ -875,18 +875,12 @@ pub struct PacRet {
     pub key: PAuthKey,
 }
 
-#[derive(Clone, Copy, Hash, Debug, PartialEq)]
+#[derive(Clone, Copy, Hash, Debug, PartialEq, Default)]
 pub struct BranchProtection {
     pub bti: bool,
     pub pac_ret: Option<PacRet>,
 }
 
-impl Default for BranchProtection {
-    fn default() -> Self {
-        BranchProtection { bti: false, pac_ret: None }
-    }
-}
-
 pub const fn default_lib_output() -> CrateType {
     CrateType::Rlib
 }
@@ -1875,7 +1869,7 @@ fn parse_opt_level(
         .into_iter()
         .flat_map(|(i, s)| {
             // NB: This can match a string without `=`.
-            if let Some("opt-level") = s.splitn(2, '=').next() { Some(i) } else { None }
+            if let Some("opt-level") = s.split('=').next() { Some(i) } else { None }
         })
         .max();
     if max_o > max_c {
@@ -1912,7 +1906,7 @@ fn select_debuginfo(
         .into_iter()
         .flat_map(|(i, s)| {
             // NB: This can match a string without `=`.
-            if let Some("debuginfo") = s.splitn(2, '=').next() { Some(i) } else { None }
+            if let Some("debuginfo") = s.split('=').next() { Some(i) } else { None }
         })
         .max();
     if max_g > max_c {
index ee492f802a70c08d21fcd119dc81755cb307aa4e..25d84506efaf0df5477c34bbab0392fc5b9fa20a 100644 (file)
@@ -176,7 +176,7 @@ pub fn surrounding(s: Span) -> Self {
 #[derive(Diagnostic)]
 #[diag(session_skipping_const_checks)]
 pub struct SkippingConstChecks {
-    #[subdiagnostic(eager)]
+    #[subdiagnostic]
     pub unleashed_features: Vec<UnleashedFeatureHelp>,
 }
 
@@ -291,20 +291,33 @@ fn looks_like_width_suffix(first_chars: &[char], s: &str) -> bool {
         s.len() > 1 && s.starts_with(first_chars) && s[1..].chars().all(|c| c.is_ascii_digit())
     }
 
-    // Try to lowercase the prefix if it's a valid base prefix.
-    fn fix_base_capitalisation(s: &str) -> Option<String> {
-        if let Some(stripped) = s.strip_prefix('B') {
-            Some(format!("0b{stripped}"))
-        } else if let Some(stripped) = s.strip_prefix('O') {
-            Some(format!("0o{stripped}"))
-        } else if let Some(stripped) = s.strip_prefix('X') {
-            Some(format!("0x{stripped}"))
+    // Try to lowercase the prefix if the prefix and suffix are valid.
+    fn fix_base_capitalisation(prefix: &str, suffix: &str) -> Option<String> {
+        let mut chars = suffix.chars();
+
+        let base_char = chars.next().unwrap();
+        let base = match base_char {
+            'B' => 2,
+            'O' => 8,
+            'X' => 16,
+            _ => return None,
+        };
+
+        // check that the suffix contains only base-appropriate characters
+        let valid = prefix == "0"
+            && chars
+                .filter(|c| *c != '_')
+                .take_while(|c| *c != 'i' && *c != 'u')
+                .all(|c| c.to_digit(base).is_some());
+
+        if valid {
+            Some(format!("0{}{}", base_char.to_ascii_lowercase(), &suffix[1..]))
         } else {
             None
         }
     }
 
-    let token::Lit { kind, suffix, .. } = lit;
+    let token::Lit { kind, symbol, suffix, .. } = lit;
     match err {
         // `LexerError` is an error, but it was already reported
         // by lexer, so here we don't report it the second time.
@@ -320,7 +333,7 @@ fn fix_base_capitalisation(s: &str) -> Option<String> {
             if looks_like_width_suffix(&['i', 'u'], suf) {
                 // If it looks like a width, try to be helpful.
                 sess.emit_err(InvalidIntLiteralWidth { span, width: suf[1..].into() });
-            } else if let Some(fixed) = fix_base_capitalisation(suf) {
+            } else if let Some(fixed) = fix_base_capitalisation(symbol.as_str(), suf) {
                 sess.emit_err(InvalidNumLiteralBasePrefix { span, fixed });
             } else {
                 sess.emit_err(InvalidNumLiteralSuffix { span, suffix: suf.to_string() });
index dab9c736d14d59d496f8bbed8b2e2d52f57a5980..9e130287104f9b1edd38a3d47e3dc11701c14e7f 100644 (file)
@@ -1294,6 +1294,9 @@ pub(crate) fn parse_proc_macro_execution_strategy(
         computed `block` spans (one span encompassing a block's terminator and \
         all statements). If `-Z instrument-coverage` is also enabled, create \
         an additional `.html` file showing the computed coverage spans."),
+    dump_mono_stats: SwitchWithOptPath = (SwitchWithOptPath::Disabled,
+        parse_switch_with_opt_path, [UNTRACKED],
+        "output statistics about monomorphization collection (format: markdown)"),
     dwarf_version: Option<u32> = (None, parse_opt_number, [TRACKED],
         "version of DWARF debug information to emit (default: 2 or 4, depending on platform)"),
     dylib_lto: bool = (false, parse_bool, [UNTRACKED],
index d3c2c5113bcdec663f1b00fb9d873d316d7bccae..26cd54210d0bbb9c33134c7876269f4f7a336006 100644 (file)
@@ -175,7 +175,7 @@ unsafe fn analyze_source_file_sse2(src: &str,
             // There might still be a tail left to analyze
             let tail_start = chunk_count * CHUNK_SIZE + intra_chunk_offset;
             if tail_start < src.len() {
-                analyze_source_file_generic(&src[tail_start as usize ..],
+                analyze_source_file_generic(&src[tail_start ..],
                                         src.len() - tail_start,
                                         output_offset + BytePos::from_usize(tail_start),
                                         lines,
@@ -219,7 +219,7 @@ fn analyze_source_file_generic(
     while i < scan_len {
         let byte = unsafe {
             // We verified that i < scan_len <= src.len()
-            *src_bytes.get_unchecked(i as usize)
+            *src_bytes.get_unchecked(i)
         };
 
         // How much to advance in order to get to the next UTF-8 char in the
index 335bfc3302f27c34bd0dada4f2e93840574a55f0..2181c090027b535819aec1eb8afeb1851c0f4841 100644 (file)
@@ -259,6 +259,10 @@ pub fn to_string_lossy(&self, display_pref: FileNameDisplayPreference) -> Cow<'_
             FileNameDisplayPreference::Remapped => {
                 self.remapped_path_if_available().to_string_lossy()
             }
+            FileNameDisplayPreference::Short => self
+                .local_path_if_available()
+                .file_name()
+                .map_or_else(|| "".into(), |f| f.to_string_lossy()),
         }
     }
 }
@@ -302,6 +306,9 @@ pub enum FileNameDisplayPreference {
     /// Display the path before the application of rewrite rules provided via `--remap-path-prefix`.
     /// This is appropriate for use in user-facing output (such as diagnostics).
     Local,
+    /// Display only the filename, as a way to reduce the verbosity of the output.
+    /// This is appropriate for use in user-facing output (such as diagnostics).
+    Short,
 }
 
 pub struct FileNameDisplay<'a> {
@@ -1381,7 +1388,7 @@ fn encode(&self, s: &mut S) {
                     4 => {
                         raw_diffs = Vec::with_capacity(bytes_per_diff * num_diffs);
                         for diff in diff_iter {
-                            raw_diffs.extend_from_slice(&(diff.0 as u32).to_le_bytes());
+                            raw_diffs.extend_from_slice(&(diff.0).to_le_bytes());
                         }
                     }
                     _ => unreachable!(),
index 43a3172270733ffebdc86005de630265f1b206a3..d9c87ac0ba82bfb6ecb0c9b3991dc6dee752ea44 100644 (file)
@@ -438,7 +438,11 @@ pub fn lookup_line(&self, pos: BytePos) -> Result<SourceFileAndLine, Lrc<SourceF
         }
     }
 
-    fn span_to_string(&self, sp: Span, filename_display_pref: FileNameDisplayPreference) -> String {
+    pub fn span_to_string(
+        &self,
+        sp: Span,
+        filename_display_pref: FileNameDisplayPreference,
+    ) -> String {
         if self.files.borrow().source_files.is_empty() || sp.is_dummy() {
             return "no-location".to_string();
         }
@@ -446,12 +450,15 @@ fn span_to_string(&self, sp: Span, filename_display_pref: FileNameDisplayPrefere
         let lo = self.lookup_char_pos(sp.lo());
         let hi = self.lookup_char_pos(sp.hi());
         format!(
-            "{}:{}:{}: {}:{}",
+            "{}:{}:{}{}",
             lo.file.name.display(filename_display_pref),
             lo.line,
             lo.col.to_usize() + 1,
-            hi.line,
-            hi.col.to_usize() + 1,
+            if let FileNameDisplayPreference::Short = filename_display_pref {
+                String::new()
+            } else {
+                format!(": {}:{}", hi.line, hi.col.to_usize() + 1)
+            }
         )
     }
 
@@ -941,7 +948,7 @@ pub fn next_point(&self, sp: Span) -> Span {
     /// Otherwise, the span reached to limit is returned.
     pub fn span_look_ahead(&self, span: Span, expect: Option<&str>, limit: Option<usize>) -> Span {
         let mut sp = span;
-        for _ in 0..limit.unwrap_or(100 as usize) {
+        for _ in 0..limit.unwrap_or(100_usize) {
             sp = self.next_point(sp);
             if let Ok(ref snippet) = self.span_to_snippet(sp) {
                 if expect.map_or(false, |es| snippet == es) {
@@ -1150,7 +1157,7 @@ fn remap_path_prefix(mapping: &[(PathBuf, PathBuf)], path: PathBuf) -> (PathBuf,
             // NOTE: We are iterating over the mapping entries from last to first
             //       because entries specified later on the command line should
             //       take precedence.
-            for &(ref from, ref to) in mapping.iter().rev() {
+            for (from, to) in mapping.iter().rev() {
                 debug!("Trying to apply {from:?} => {to:?}");
 
                 if let Ok(rest) = path.strip_prefix(from) {
index 85d416c43f95a8512c66c4f2b0c8a99f282bee80..ace095736c92fd8a1a2e2b39c91b4c08b1ed6115 100644 (file)
         item_like_imports,
         iter,
         iter_repeat,
+        iterator_collect_fn,
         kcfi,
         keyword,
         kind,
index c60a2f4671d6c4d841565f9aaba8bb6f67279fa7..a59c9011ab21a4116e4452b206392781e0ab0e25 100644 (file)
@@ -216,8 +216,7 @@ fn print_type(mut self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error> {
         match *ty.kind() {
             // Print all nominal types as paths (unlike `pretty_print_type`).
             ty::FnDef(def_id, substs)
-            | ty::Opaque(def_id, substs)
-            | ty::Projection(ty::ProjectionTy { item_def_id: def_id, substs })
+            | ty::Alias(_, ty::AliasTy { def_id, substs, .. })
             | ty::Closure(def_id, substs)
             | ty::Generator(def_id, substs, _) => self.print_def_path(def_id, substs),
 
@@ -287,11 +286,7 @@ fn path_qualified(
         // Similar to `pretty_path_qualified`, but for the other
         // types that are printed as paths (see `print_type` above).
         match self_ty.kind() {
-            ty::FnDef(..)
-            | ty::Opaque(..)
-            | ty::Projection(_)
-            | ty::Closure(..)
-            | ty::Generator(..)
+            ty::FnDef(..) | ty::Alias(..) | ty::Closure(..) | ty::Generator(..)
                 if trait_ref.is_none() =>
             {
                 self.print_type(self_ty)
index 87128e0f893a263edb6a8b9a6877f697338d1da7..c9ddb084d63a12d2f5198bae6c2f19ec3493a12b 100644 (file)
@@ -240,7 +240,7 @@ fn encode_predicate<'tcx>(
             s.push_str(&encode_substs(tcx, trait_ref.substs, dict, options));
         }
         ty::ExistentialPredicate::Projection(projection) => {
-            let name = encode_ty_name(tcx, projection.item_def_id);
+            let name = encode_ty_name(tcx, projection.def_id);
             let _ = write!(s, "u{}{}", name.len(), &name);
             s.push_str(&encode_substs(tcx, projection.substs, dict, options));
             match projection.term.unpack() {
@@ -646,10 +646,9 @@ fn encode_ty<'tcx>(
         | ty::Error(..)
         | ty::GeneratorWitness(..)
         | ty::Infer(..)
-        | ty::Opaque(..)
+        | ty::Alias(..)
         | ty::Param(..)
-        | ty::Placeholder(..)
-        | ty::Projection(..) => {
+        | ty::Placeholder(..) => {
             bug!("encode_ty: unexpected `{:?}`", ty.kind());
         }
     };
@@ -799,10 +798,9 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio
         | ty::Error(..)
         | ty::GeneratorWitness(..)
         | ty::Infer(..)
-        | ty::Opaque(..)
+        | ty::Alias(..)
         | ty::Param(..)
-        | ty::Placeholder(..)
-        | ty::Projection(..) => {
+        | ty::Placeholder(..) => {
             bug!("transform_ty: unexpected `{:?}`", ty.kind());
         }
     }
index 2cca480f271c73331046c25302e291f9e26e58ad..4285aa62cb96307991169be15b067839e36c2686 100644 (file)
@@ -439,8 +439,7 @@ fn print_type(mut self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error> {
             // Mangle all nominal types as paths.
             ty::Adt(ty::AdtDef(Interned(&ty::AdtDefData { did: def_id, .. }, _)), substs)
             | ty::FnDef(def_id, substs)
-            | ty::Opaque(def_id, substs)
-            | ty::Projection(ty::ProjectionTy { item_def_id: def_id, substs })
+            | ty::Alias(_, ty::AliasTy { def_id, substs, .. })
             | ty::Closure(def_id, substs)
             | ty::Generator(def_id, substs, _) => {
                 self = self.print_def_path(def_id, substs)?;
@@ -544,7 +543,7 @@ fn print_dyn_existential(
                         cx = cx.print_def_path(trait_ref.def_id, trait_ref.substs)?;
                     }
                     ty::ExistentialPredicate::Projection(projection) => {
-                        let name = cx.tcx.associated_item(projection.item_def_id).name;
+                        let name = cx.tcx.associated_item(projection.def_id).name;
                         cx.push("p");
                         cx.push_ident(name.as_str());
                         cx = match projection.term.unpack() {
index fc6a2edabb763c89de1dad368dfecf7b17154b2a..44644c4733e8726b33c886394631744352af4a04 100644 (file)
@@ -81,7 +81,7 @@ fn pre_link_args(os: &'static str, arch: Arch, abi: &'static str) -> LinkArgs {
         _ => os.into(),
     };
 
-    let platform_version: StaticCow<str> = match os.as_ref() {
+    let platform_version: StaticCow<str> = match os {
         "ios" => ios_lld_platform_version(),
         "tvos" => tvos_lld_platform_version(),
         "watchos" => watchos_lld_platform_version(),
index e3eb9bccd5ed78d5001471c83cec143a3586d02c..34934379c7e84a468abfe4995612c6bbb80aa579 100644 (file)
@@ -5,12 +5,7 @@ pub fn target() -> Target {
     base.max_atomic_width = Some(64);
     base.add_pre_link_args(
         LinkerFlavor::Unix(Cc::No),
-        &[
-            "-b64".into(),
-            "-bpT:0x100000000".into(),
-            "-bpD:0x110000000".into(),
-            "-bcdtors:all:0:s".into(),
-        ],
+        &["-b64", "-bpT:0x100000000", "-bpD:0x110000000", "-bcdtors:all:0:s"],
     );
 
     Target {
index 8e04da4f9be2479aa584270611a9607279b495d8..aef2f8ff9911cc90b565bf27c02d946d0ffcd766 100644 (file)
@@ -579,14 +579,14 @@ fn is_param_no_infer(&self, substs: SubstsRef<'_>) -> bool {
     pub fn is_of_param(&self, ty: Ty<'_>) -> bool {
         match ty.kind() {
             ty::Param(_) => true,
-            ty::Projection(p) => self.is_of_param(p.self_ty()),
+            ty::Alias(ty::Projection, p) => self.is_of_param(p.self_ty()),
             _ => false,
         }
     }
 
     fn is_self_referential_projection(&self, p: ty::PolyProjectionPredicate<'_>) -> bool {
         if let Some(ty) = p.term().skip_binder().ty() {
-            matches!(ty.kind(), ty::Projection(proj) if proj == &p.skip_binder().projection_ty)
+            matches!(ty.kind(), ty::Alias(ty::Projection, proj) if proj == &p.skip_binder().projection_ty)
         } else {
             false
         }
index 899e30275a05296eb2de1958b29b41286f3f51d0..7c569621cfeb85ab3b64cd2c2bc05c3b045180f5 100644 (file)
@@ -659,7 +659,7 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
             | ty::RawPtr(..)
             | ty::Never
             | ty::Tuple(..)
-            | ty::Projection(..) => self.found_non_local_ty(ty),
+            | ty::Alias(ty::Projection, ..) => self.found_non_local_ty(ty),
 
             ty::Param(..) => self.found_param_ty(ty),
 
@@ -704,7 +704,7 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
                 );
                 ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty))
             }
-            ty::Opaque(..) => {
+            ty::Alias(ty::Opaque, ..) => {
                 // This merits some explanation.
                 // Normally, opaque types are not involved when performing
                 // coherence checking, since it is illegal to directly
index 752b53fbc3f9a2011c5cfa90afc2e32d2fbfb8b0..0c1717cff332c40e79bede7a633994be3c054155 100644 (file)
 use rustc_hir::def_id::DefId;
-use rustc_infer::infer::InferCtxt;
+use rustc_infer::infer::{InferCtxt, LateBoundRegionConversionTime};
+use rustc_infer::traits::util::elaborate_predicates_with_span;
 use rustc_infer::traits::{Obligation, ObligationCause, TraitObligation};
-use rustc_span::DUMMY_SP;
+use rustc_middle::ty;
+use rustc_span::{Span, DUMMY_SP};
 
 use crate::traits::ObligationCtxt;
 
+pub enum Ambiguity {
+    DefId(DefId),
+    ParamEnv(Span),
+}
+
 pub fn recompute_applicable_impls<'tcx>(
     infcx: &InferCtxt<'tcx>,
     obligation: &TraitObligation<'tcx>,
-) -> Vec<DefId> {
+) -> Vec<Ambiguity> {
     let tcx = infcx.tcx;
     let param_env = obligation.param_env;
-    let dummy_cause = ObligationCause::dummy();
+
     let impl_may_apply = |impl_def_id| {
         let ocx = ObligationCtxt::new_in_snapshot(infcx);
         let placeholder_obligation =
             infcx.replace_bound_vars_with_placeholders(obligation.predicate);
         let obligation_trait_ref =
-            ocx.normalize(&dummy_cause, param_env, placeholder_obligation.trait_ref);
+            ocx.normalize(&ObligationCause::dummy(), param_env, placeholder_obligation.trait_ref);
 
         let impl_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id);
         let impl_trait_ref = tcx.bound_impl_trait_ref(impl_def_id).unwrap().subst(tcx, impl_substs);
         let impl_trait_ref = ocx.normalize(&ObligationCause::dummy(), param_env, impl_trait_ref);
 
-        if let Err(_) = ocx.eq(&dummy_cause, param_env, obligation_trait_ref, impl_trait_ref) {
+        if let Err(_) =
+            ocx.eq(&ObligationCause::dummy(), param_env, obligation_trait_ref, impl_trait_ref)
+        {
             return false;
         }
 
         let impl_predicates = tcx.predicates_of(impl_def_id).instantiate(tcx, impl_substs);
-        ocx.register_obligations(
-            impl_predicates
-                .predicates
-                .iter()
-                .map(|&predicate| Obligation::new(tcx, dummy_cause.clone(), param_env, predicate)),
+        ocx.register_obligations(impl_predicates.predicates.iter().map(|&predicate| {
+            Obligation::new(tcx, ObligationCause::dummy(), param_env, predicate)
+        }));
+
+        ocx.select_where_possible().is_empty()
+    };
+
+    let param_env_candidate_may_apply = |poly_trait_predicate: ty::PolyTraitPredicate<'tcx>| {
+        let ocx = ObligationCtxt::new_in_snapshot(infcx);
+        let placeholder_obligation =
+            infcx.replace_bound_vars_with_placeholders(obligation.predicate);
+        let obligation_trait_ref =
+            ocx.normalize(&ObligationCause::dummy(), param_env, placeholder_obligation.trait_ref);
+
+        let param_env_predicate = infcx.replace_bound_vars_with_fresh_vars(
+            DUMMY_SP,
+            LateBoundRegionConversionTime::HigherRankedType,
+            poly_trait_predicate,
         );
+        let param_env_trait_ref =
+            ocx.normalize(&ObligationCause::dummy(), param_env, param_env_predicate.trait_ref);
+
+        if let Err(_) =
+            ocx.eq(&ObligationCause::dummy(), param_env, obligation_trait_ref, param_env_trait_ref)
+        {
+            return false;
+        }
 
         ocx.select_where_possible().is_empty()
     };
 
-    let mut impls = Vec::new();
+    let mut ambiguities = Vec::new();
+
     tcx.for_each_relevant_impl(
         obligation.predicate.def_id(),
         obligation.predicate.skip_binder().trait_ref.self_ty(),
         |impl_def_id| {
-            if infcx.probe(move |_snapshot| impl_may_apply(impl_def_id)) {
-                impls.push(impl_def_id)
+            if infcx.probe(|_| impl_may_apply(impl_def_id)) {
+                ambiguities.push(Ambiguity::DefId(impl_def_id))
             }
         },
     );
-    impls
+
+    let predicates =
+        tcx.predicates_of(obligation.cause.body_id.owner.to_def_id()).instantiate_identity(tcx);
+    for obligation in
+        elaborate_predicates_with_span(tcx, std::iter::zip(predicates.predicates, predicates.spans))
+    {
+        let kind = obligation.predicate.kind();
+        if let ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) = kind.skip_binder()
+            && param_env_candidate_may_apply(kind.rebind(trait_pred))
+        {
+            if kind.rebind(trait_pred.trait_ref) == ty::TraitRef::identity(tcx, trait_pred.def_id()) {
+                ambiguities.push(Ambiguity::ParamEnv(tcx.def_span(trait_pred.def_id())))
+            } else {
+                ambiguities.push(Ambiguity::ParamEnv(obligation.cause.span))
+            }
+        }
+    }
+
+    ambiguities
 }
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/method_chain.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/method_chain.rs
new file mode 100644 (file)
index 0000000..cb373d6
--- /dev/null
@@ -0,0 +1,74 @@
+use crate::infer::InferCtxt;
+
+use rustc_middle::ty::error::TypeError;
+use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
+use rustc_middle::ty::{self, Ty, TyCtxt};
+
+pub struct CollectAllMismatches<'a, 'tcx> {
+    pub infcx: &'a InferCtxt<'tcx>,
+    pub param_env: ty::ParamEnv<'tcx>,
+    pub errors: Vec<TypeError<'tcx>>,
+}
+
+impl<'a, 'tcx> TypeRelation<'tcx> for CollectAllMismatches<'a, 'tcx> {
+    fn tag(&self) -> &'static str {
+        "CollectAllMismatches"
+    }
+    fn tcx(&self) -> TyCtxt<'tcx> {
+        self.infcx.tcx
+    }
+    fn intercrate(&self) -> bool {
+        false
+    }
+    fn param_env(&self) -> ty::ParamEnv<'tcx> {
+        self.param_env
+    }
+    fn a_is_expected(&self) -> bool {
+        true
+    } // irrelevant
+    fn mark_ambiguous(&mut self) {
+        bug!()
+    }
+    fn relate_with_variance<T: Relate<'tcx>>(
+        &mut self,
+        _: ty::Variance,
+        _: ty::VarianceDiagInfo<'tcx>,
+        a: T,
+        b: T,
+    ) -> RelateResult<'tcx, T> {
+        self.relate(a, b)
+    }
+    fn regions(
+        &mut self,
+        a: ty::Region<'tcx>,
+        _b: ty::Region<'tcx>,
+    ) -> RelateResult<'tcx, ty::Region<'tcx>> {
+        Ok(a)
+    }
+    fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
+        if a == b || matches!(a.kind(), ty::Infer(_)) || matches!(b.kind(), ty::Infer(_)) {
+            return Ok(a);
+        }
+        relate::super_relate_tys(self, a, b).or_else(|e| {
+            self.errors.push(e);
+            Ok(a)
+        })
+    }
+    fn consts(
+        &mut self,
+        a: ty::Const<'tcx>,
+        b: ty::Const<'tcx>,
+    ) -> RelateResult<'tcx, ty::Const<'tcx>> {
+        if a == b {
+            return Ok(a);
+        }
+        relate::super_relate_consts(self, a, b) // could do something similar here for constants!
+    }
+    fn binders<T: Relate<'tcx>>(
+        &mut self,
+        a: ty::Binder<'tcx, T>,
+        b: ty::Binder<'tcx, T>,
+    ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> {
+        Ok(a.rebind(self.relate(a.skip_binder(), b.skip_binder())?))
+    }
+}
index 82449a36b1d54115320fbc52c17d5f7ebdcdf5de..181316427609e58aa9cd6dddc96b1c459453a3b2 100644 (file)
@@ -1,4 +1,5 @@
 mod ambiguity;
+pub mod method_chain;
 pub mod on_unimplemented;
 pub mod suggestions;
 
 use rustc_middle::ty::abstract_const::NotConstEvaluatable;
 use rustc_middle::ty::error::ExpectedFound;
 use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable};
-use rustc_middle::ty::print::{FmtPrinter, Print};
+use rustc_middle::ty::print::{with_forced_trimmed_paths, FmtPrinter, Print};
 use rustc_middle::ty::{
     self, SubtypePredicate, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TyCtxt, TypeFoldable,
     TypeVisitable,
 };
 use rustc_session::Limit;
 use rustc_span::def_id::LOCAL_CRATE;
-use rustc_span::symbol::{kw, sym};
+use rustc_span::symbol::sym;
 use rustc_span::{ExpnKind, Span, DUMMY_SP};
 use std::fmt;
 use std::iter;
@@ -536,7 +537,7 @@ fn report_overflow_obligation<T>(
             |err| {
                 self.note_obligation_cause_code(
                     err,
-                    &predicate,
+                    predicate,
                     obligation.param_env,
                     obligation.cause.code(),
                     &mut vec![],
@@ -979,6 +980,7 @@ fn report_selection_error(
                                 trait_ref,
                                 obligation.cause.body_id,
                                 &mut err,
+                                true,
                             ) {
                                 // This is *almost* equivalent to
                                 // `obligation.cause.code().peel_derives()`, but it gives us the
@@ -1014,6 +1016,7 @@ fn report_selection_error(
                                         trait_ref,
                                         obligation.cause.body_id,
                                         &mut err,
+                                        true,
                                     );
                                 }
                             }
@@ -1033,7 +1036,7 @@ fn report_selection_error(
                             && self.fallback_has_occurred
                         {
                             let predicate = trait_predicate.map_bound(|trait_pred| {
-                                trait_pred.with_self_type(self.tcx, self.tcx.mk_unit())
+                                trait_pred.with_self_ty(self.tcx, self.tcx.mk_unit())
                             });
                             let unit_obligation = obligation.with(tcx, predicate);
                             if self.predicate_may_hold(&unit_obligation) {
@@ -1233,6 +1236,7 @@ fn report_selection_error(
                     _ => None,
                 };
 
+                let found_node = found_did.and_then(|did| self.tcx.hir().get_if_local(did));
                 let found_span = found_did.and_then(|did| self.tcx.hir().span_if_local(did));
 
                 if self.reported_closure_mismatch.borrow().contains(&(span, found_span)) {
@@ -1286,6 +1290,7 @@ fn report_selection_error(
                         found_trait_ref,
                         expected_trait_ref,
                         obligation.cause.code(),
+                        found_node,
                     )
                 } else {
                     let (closure_span, closure_arg_span, found) = found_did
@@ -1431,6 +1436,7 @@ fn report_similar_impl_candidates(
         trait_ref: ty::PolyTraitRef<'tcx>,
         body_id: hir::HirId,
         err: &mut Diagnostic,
+        other: bool,
     ) -> bool;
 
     /// Gets the parent trait chain start
@@ -1481,7 +1487,7 @@ fn suggest_unsized_bound_if_applicable(
     fn annotate_source_of_ambiguity(
         &self,
         err: &mut Diagnostic,
-        impls: &[DefId],
+        impls: &[ambiguity::Ambiguity],
         predicate: ty::Predicate<'tcx>,
     );
 
@@ -1587,7 +1593,7 @@ fn report_fulfillment_error(
                 {
                     self.note_obligation_cause_code(
                         &mut diag,
-                        &error.obligation.predicate,
+                        error.obligation.predicate,
                         error.obligation.param_env,
                         code,
                         &mut vec![],
@@ -1630,18 +1636,30 @@ fn report_projection_error(
                     infer::LateBoundRegionConversionTime::HigherRankedType,
                     bound_predicate.rebind(data),
                 );
-                let normalized_ty = ocx.normalize(
-                    &obligation.cause,
-                    obligation.param_env,
-                    self.tcx
-                        .mk_projection(data.projection_ty.item_def_id, data.projection_ty.substs),
-                );
+                let unnormalized_term = match data.term.unpack() {
+                    ty::TermKind::Ty(_) => self
+                        .tcx
+                        .mk_projection(data.projection_ty.def_id, data.projection_ty.substs)
+                        .into(),
+                    ty::TermKind::Const(ct) => self
+                        .tcx
+                        .mk_const(
+                            ty::UnevaluatedConst {
+                                def: ty::WithOptConstParam::unknown(data.projection_ty.def_id),
+                                substs: data.projection_ty.substs,
+                            },
+                            ct.ty(),
+                        )
+                        .into(),
+                };
+                let normalized_term =
+                    ocx.normalize(&obligation.cause, obligation.param_env, unnormalized_term);
 
                 debug!(?obligation.cause, ?obligation.param_env);
 
-                debug!(?normalized_ty, data.ty = ?data.term);
+                debug!(?normalized_term, data.ty = ?data.term);
 
-                let is_normalized_ty_expected = !matches!(
+                let is_normalized_term_expected = !matches!(
                     obligation.cause.code().peel_derives(),
                     ObligationCauseCode::ItemObligation(_)
                         | ObligationCauseCode::BindingObligation(_, _)
@@ -1650,7 +1668,6 @@ fn report_projection_error(
                         | ObligationCauseCode::ObjectCastObligation(..)
                         | ObligationCauseCode::OpaqueType
                 );
-                let expected_ty = data.term.ty().unwrap_or_else(|| self.tcx.ty_error());
 
                 // constrain inference variables a bit more to nested obligations from normalize so
                 // we can have more helpful errors.
@@ -1659,11 +1676,11 @@ fn report_projection_error(
                 if let Err(new_err) = ocx.eq_exp(
                     &obligation.cause,
                     obligation.param_env,
-                    is_normalized_ty_expected,
-                    normalized_ty,
-                    expected_ty,
+                    is_normalized_term_expected,
+                    normalized_term,
+                    data.term,
                 ) {
-                    (Some((data, is_normalized_ty_expected, normalized_ty, expected_ty)), new_err)
+                    (Some((data, is_normalized_term_expected, normalized_term, data.term)), new_err)
                 } else {
                     (None, error.err)
                 }
@@ -1672,12 +1689,8 @@ fn report_projection_error(
             };
 
             let msg = values
-                .and_then(|(predicate, _, normalized_ty, expected_ty)| {
-                    self.maybe_detailed_projection_msg(
-                        predicate,
-                        normalized_ty.into(),
-                        expected_ty.into(),
-                    )
+                .and_then(|(predicate, _, normalized_term, expected_term)| {
+                    self.maybe_detailed_projection_msg(predicate, normalized_term, expected_term)
                 })
                 .unwrap_or_else(|| format!("type mismatch resolving `{}`", predicate));
             let mut diag = struct_span_err!(self.tcx.sess, obligation.cause.span, E0271, "{msg}");
@@ -1685,10 +1698,10 @@ fn report_projection_error(
             let secondary_span = match predicate.kind().skip_binder() {
                 ty::PredicateKind::Clause(ty::Clause::Projection(proj)) => self
                     .tcx
-                    .opt_associated_item(proj.projection_ty.item_def_id)
+                    .opt_associated_item(proj.projection_ty.def_id)
                     .and_then(|trait_assoc_item| {
                         self.tcx
-                            .trait_of_item(proj.projection_ty.item_def_id)
+                            .trait_of_item(proj.projection_ty.def_id)
                             .map(|id| (trait_assoc_item, id))
                     })
                     .and_then(|(trait_assoc_item, id)| {
@@ -1744,21 +1757,26 @@ fn maybe_detailed_projection_msg(
         let trait_def_id = pred.projection_ty.trait_def_id(self.tcx);
         let self_ty = pred.projection_ty.self_ty();
 
-        if Some(pred.projection_ty.item_def_id) == self.tcx.lang_items().fn_once_output() {
-            Some(format!(
-                "expected `{self_ty}` to be a {fn_kind} that returns `{expected_ty}`, but it returns `{normalized_ty}`",
-                fn_kind = self_ty.prefix_string(self.tcx)
-            ))
-        } else if Some(trait_def_id) == self.tcx.lang_items().future_trait() {
-            Some(format!(
-                "expected `{self_ty}` to be a future that resolves to `{expected_ty}`, but it resolves to `{normalized_ty}`"
-            ))
-        } else if Some(trait_def_id) == self.tcx.get_diagnostic_item(sym::Iterator) {
-            Some(format!(
-                "expected `{self_ty}` to be an iterator that yields `{expected_ty}`, but it yields `{normalized_ty}`"
-            ))
-        } else {
-            None
+        with_forced_trimmed_paths! {
+            if Some(pred.projection_ty.def_id) == self.tcx.lang_items().fn_once_output() {
+                Some(format!(
+                    "expected `{self_ty}` to be a {fn_kind} that returns `{expected_ty}`, but it \
+                     returns `{normalized_ty}`",
+                    fn_kind = self_ty.prefix_string(self.tcx)
+                ))
+            } else if Some(trait_def_id) == self.tcx.lang_items().future_trait() {
+                Some(format!(
+                    "expected `{self_ty}` to be a future that resolves to `{expected_ty}`, but it \
+                     resolves to `{normalized_ty}`"
+                ))
+            } else if Some(trait_def_id) == self.tcx.get_diagnostic_item(sym::Iterator) {
+                Some(format!(
+                    "expected `{self_ty}` to be an iterator that yields `{expected_ty}`, but it \
+                     yields `{normalized_ty}`"
+                ))
+            } else {
+                None
+            }
         }
     }
 
@@ -1787,8 +1805,8 @@ fn type_category(tcx: TyCtxt<'_>, t: Ty<'_>) -> Option<u32> {
                 ty::Closure(..) => Some(9),
                 ty::Tuple(..) => Some(10),
                 ty::Param(..) => Some(11),
-                ty::Projection(..) => Some(12),
-                ty::Opaque(..) => Some(13),
+                ty::Alias(ty::Projection, ..) => Some(12),
+                ty::Alias(ty::Opaque, ..) => Some(13),
                 ty::Never => Some(14),
                 ty::Adt(..) => Some(15),
                 ty::Generator(..) => Some(16),
@@ -1886,7 +1904,9 @@ fn report_similar_impl_candidates(
         trait_ref: ty::PolyTraitRef<'tcx>,
         body_id: hir::HirId,
         err: &mut Diagnostic,
+        other: bool,
     ) -> bool {
+        let other = if other { "other " } else { "" };
         let report = |mut candidates: Vec<TraitRef<'tcx>>, err: &mut Diagnostic| {
             candidates.sort();
             candidates.dedup();
@@ -1937,7 +1957,7 @@ fn report_similar_impl_candidates(
             candidates.dedup();
             let end = if candidates.len() <= 9 { candidates.len() } else { 8 };
             err.help(&format!(
-                "the following other types implement trait `{}`:{}{}",
+                "the following {other}types implement trait `{}`:{}{}",
                 trait_ref.print_only_trait_path(),
                 candidates[..end].join(""),
                 if len > 9 { format!("\nand {} others", len - 8) } else { String::new() }
@@ -2078,8 +2098,8 @@ fn mk_trait_obligation_with_new_self_ty(
         param_env: ty::ParamEnv<'tcx>,
         trait_ref_and_ty: ty::Binder<'tcx, (ty::TraitPredicate<'tcx>, Ty<'tcx>)>,
     ) -> PredicateObligation<'tcx> {
-        let trait_pred = trait_ref_and_ty
-            .map_bound(|(tr, new_self_ty)| tr.with_self_type(self.tcx, new_self_ty));
+        let trait_pred =
+            trait_ref_and_ty.map_bound(|(tr, new_self_ty)| tr.with_self_ty(self.tcx, new_self_ty));
 
         Obligation::new(self.tcx, ObligationCause::dummy(), param_env, trait_pred)
     }
@@ -2173,19 +2193,40 @@ fn maybe_report_ambiguity(
                 let mut selcx = SelectionContext::new(&self);
                 match selcx.select_from_obligation(&obligation) {
                     Ok(None) => {
-                        let impls = ambiguity::recompute_applicable_impls(self.infcx, &obligation);
+                        let ambiguities =
+                            ambiguity::recompute_applicable_impls(self.infcx, &obligation);
                         let has_non_region_infer =
                             trait_ref.skip_binder().substs.types().any(|t| !t.is_ty_infer());
                         // It doesn't make sense to talk about applicable impls if there are more
                         // than a handful of them.
-                        if impls.len() > 1 && impls.len() < 5 && has_non_region_infer {
-                            self.annotate_source_of_ambiguity(&mut err, &impls, predicate);
+                        if ambiguities.len() > 1 && ambiguities.len() < 10 && has_non_region_infer {
+                            if self.tainted_by_errors().is_some() && subst.is_none() {
+                                // If `subst.is_none()`, then this is probably two param-env
+                                // candidates or impl candidates that are equal modulo lifetimes.
+                                // Therefore, if we've already emitted an error, just skip this
+                                // one, since it's not particularly actionable.
+                                err.cancel();
+                                return;
+                            }
+                            self.annotate_source_of_ambiguity(&mut err, &ambiguities, predicate);
                         } else {
                             if self.tainted_by_errors().is_some() {
                                 err.cancel();
                                 return;
                             }
                             err.note(&format!("cannot satisfy `{}`", predicate));
+                            let impl_candidates = self.find_similar_impl_candidates(
+                                predicate.to_opt_poly_trait_pred().unwrap(),
+                            );
+                            if impl_candidates.len() < 10 {
+                                self.report_similar_impl_candidates(
+                                    impl_candidates,
+                                    trait_ref,
+                                    body_id.map(|id| id.hir_id).unwrap_or(obligation.cause.body_id),
+                                    &mut err,
+                                    false,
+                                );
+                            }
                         }
                     }
                     _ => {
@@ -2197,60 +2238,10 @@ fn maybe_report_ambiguity(
                     }
                 }
 
-                if let ObligationCauseCode::ItemObligation(def_id) | ObligationCauseCode::ExprItemObligation(def_id, ..) = *obligation.cause.code() {
-                    self.suggest_fully_qualified_path(&mut err, def_id, span, trait_ref.def_id());
-                } else if let Ok(snippet) = &self.tcx.sess.source_map().span_to_snippet(span)
-                    && let ObligationCauseCode::BindingObligation(def_id, _) | ObligationCauseCode::ExprBindingObligation(def_id, ..)
-                        = *obligation.cause.code()
+                if let ObligationCauseCode::ItemObligation(def_id)
+                | ObligationCauseCode::ExprItemObligation(def_id, ..) = *obligation.cause.code()
                 {
-                    let generics = self.tcx.generics_of(def_id);
-                    if generics.params.iter().any(|p| p.name != kw::SelfUpper)
-                        && !snippet.ends_with('>')
-                        && !generics.has_impl_trait()
-                        && !self.tcx.is_fn_trait(def_id)
-                    {
-                        // FIXME: To avoid spurious suggestions in functions where type arguments
-                        // where already supplied, we check the snippet to make sure it doesn't
-                        // end with a turbofish. Ideally we would have access to a `PathSegment`
-                        // instead. Otherwise we would produce the following output:
-                        //
-                        // error[E0283]: type annotations needed
-                        //   --> $DIR/issue-54954.rs:3:24
-                        //    |
-                        // LL | const ARR_LEN: usize = Tt::const_val::<[i8; 123]>();
-                        //    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^
-                        //    |                        |
-                        //    |                        cannot infer type
-                        //    |                        help: consider specifying the type argument
-                        //    |                        in the function call:
-                        //    |                        `Tt::const_val::<[i8; 123]>::<T>`
-                        // ...
-                        // LL |     const fn const_val<T: Sized>() -> usize {
-                        //    |                        - required by this bound in `Tt::const_val`
-                        //    |
-                        //    = note: cannot satisfy `_: Tt`
-
-                        // Clear any more general suggestions in favor of our specific one
-                        err.clear_suggestions();
-
-                        err.span_suggestion_verbose(
-                            span.shrink_to_hi(),
-                            &format!(
-                                "consider specifying the type argument{} in the function call",
-                                pluralize!(generics.params.len()),
-                            ),
-                            format!(
-                                "::<{}>",
-                                generics
-                                    .params
-                                    .iter()
-                                    .map(|p| p.name.to_string())
-                                    .collect::<Vec<String>>()
-                                    .join(", ")
-                            ),
-                            Applicability::HasPlaceholders,
-                        );
-                    }
+                    self.suggest_fully_qualified_path(&mut err, def_id, span, trait_ref.def_id());
                 }
 
                 if let (Some(body_id), Some(ty::subst::GenericArgKind::Type(_))) =
@@ -2465,21 +2456,30 @@ fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
     fn annotate_source_of_ambiguity(
         &self,
         err: &mut Diagnostic,
-        impls: &[DefId],
+        ambiguities: &[ambiguity::Ambiguity],
         predicate: ty::Predicate<'tcx>,
     ) {
         let mut spans = vec![];
         let mut crates = vec![];
         let mut post = vec![];
-        for def_id in impls {
-            match self.tcx.span_of_impl(*def_id) {
-                Ok(span) => spans.push(span),
-                Err(name) => {
-                    crates.push(name);
-                    if let Some(header) = to_pretty_impl_header(self.tcx, *def_id) {
-                        post.push(header);
+        let mut has_param_env = false;
+        for ambiguity in ambiguities {
+            match ambiguity {
+                ambiguity::Ambiguity::DefId(impl_def_id) => {
+                    match self.tcx.span_of_impl(*impl_def_id) {
+                        Ok(span) => spans.push(span),
+                        Err(name) => {
+                            crates.push(name);
+                            if let Some(header) = to_pretty_impl_header(self.tcx, *impl_def_id) {
+                                post.push(header);
+                            }
+                        }
                     }
                 }
+                ambiguity::Ambiguity::ParamEnv(span) => {
+                    has_param_env = true;
+                    spans.push(*span);
+                }
             }
         }
         let mut crate_names: Vec<_> = crates.iter().map(|n| format!("`{}`", n)).collect();
@@ -2503,7 +2503,11 @@ fn annotate_source_of_ambiguity(
             return;
         }
 
-        let msg = format!("multiple `impl`s satisfying `{}` found", predicate);
+        let msg = format!(
+            "multiple `impl`s{} satisfying `{}` found",
+            if has_param_env { " or `where` clauses" } else { "" },
+            predicate
+        );
         let post = if post.len() > 1 || (post.len() == 1 && post[0].contains('\n')) {
             format!(":\n{}", post.iter().map(|p| format!("- {}", p)).collect::<Vec<_>>().join("\n"),)
         } else if post.len() == 1 {
@@ -2602,7 +2606,7 @@ fn note_obligation_cause(&self, err: &mut Diagnostic, obligation: &PredicateObli
         if !self.maybe_note_obligation_cause_for_async_await(err, obligation) {
             self.note_obligation_cause_code(
                 err,
-                &obligation.predicate,
+                obligation.predicate,
                 obligation.param_env,
                 obligation.cause.code(),
                 &mut vec![],
index 9f5814a6bda738c7e275c6f2a7d935c0e87a5d9e..e77b9da08f51a7040c2df44069861afc815315f4 100644 (file)
@@ -1,8 +1,10 @@
+// ignore-tidy-filelength
+
 use super::{DefIdOrName, Obligation, ObligationCause, ObligationCauseCode, PredicateObligation};
 
 use crate::autoderef::Autoderef;
 use crate::infer::InferCtxt;
-use crate::traits::NormalizeExt;
+use crate::traits::{NormalizeExt, ObligationCtxt};
 
 use hir::def::CtorOf;
 use hir::HirId;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_infer::infer::{InferOk, LateBoundRegionConversionTime};
 use rustc_middle::hir::map;
+use rustc_middle::ty::error::TypeError::{self, Sorts};
+use rustc_middle::ty::relate::TypeRelation;
 use rustc_middle::ty::{
     self, suggest_arbitrary_trait_bound, suggest_constraining_type_param, AdtKind, DefIdTree,
-    GeneratorDiagnosticData, GeneratorInteriorTypeCause, Infer, InferTy, IsSuggestable,
-    ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable,
+    GeneratorDiagnosticData, GeneratorInteriorTypeCause, Infer, InferTy, InternalSubsts,
+    IsSuggestable, ToPredicate, Ty, TyCtxt, TypeAndMut, TypeFoldable, TypeFolder,
+    TypeSuperFoldable, TypeVisitable, TypeckResults,
 };
-use rustc_middle::ty::{TypeAndMut, TypeckResults};
 use rustc_span::symbol::{sym, Ident, Symbol};
 use rustc_span::{BytePos, DesugaringKind, ExpnKind, Span, DUMMY_SP};
 use rustc_target::spec::abi;
-use std::fmt;
+use std::ops::Deref;
 
+use super::method_chain::CollectAllMismatches;
 use super::InferCtxtPrivExt;
 use crate::infer::InferCtxtExt as _;
 use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
@@ -254,6 +259,7 @@ fn report_closure_arg_mismatch(
         found: ty::PolyTraitRef<'tcx>,
         expected: ty::PolyTraitRef<'tcx>,
         cause: &ObligationCauseCode<'tcx>,
+        found_node: Option<Node<'_>>,
     ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>;
 
     fn note_conflicting_closure_bounds(
@@ -292,13 +298,13 @@ fn note_obligation_cause_for_async_await(
     fn note_obligation_cause_code<T>(
         &self,
         err: &mut Diagnostic,
-        predicate: &T,
+        predicate: T,
         param_env: ty::ParamEnv<'tcx>,
         cause_code: &ObligationCauseCode<'tcx>,
         obligated_types: &mut Vec<Ty<'tcx>>,
         seen_requirements: &mut FxHashSet<DefId>,
     ) where
-        T: fmt::Display + ToPredicate<'tcx>;
+        T: ToPredicate<'tcx>;
 
     /// Suggest to await before try: future? => future.await?
     fn suggest_await_before_try(
@@ -329,6 +335,31 @@ fn suggest_dereferencing_index(
         err: &mut Diagnostic,
         trait_pred: ty::PolyTraitPredicate<'tcx>,
     );
+    fn function_argument_obligation(
+        &self,
+        arg_hir_id: HirId,
+        err: &mut Diagnostic,
+        parent_code: &ObligationCauseCode<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+        predicate: ty::Predicate<'tcx>,
+        call_hir_id: HirId,
+    );
+    fn point_at_chain(
+        &self,
+        expr: &hir::Expr<'_>,
+        typeck_results: &TypeckResults<'tcx>,
+        type_diffs: Vec<TypeError<'tcx>>,
+        param_env: ty::ParamEnv<'tcx>,
+        err: &mut Diagnostic,
+    );
+    fn probe_assoc_types_at_expr(
+        &self,
+        type_diffs: &[TypeError<'tcx>],
+        span: Span,
+        prev_ty: Ty<'tcx>,
+        body_id: hir::HirId,
+        param_env: ty::ParamEnv<'tcx>,
+    ) -> Vec<Option<(Span, (DefId, Ty<'tcx>))>>;
 }
 
 fn predicate_constraint(generics: &hir::Generics<'_>, pred: ty::Predicate<'_>) -> (Span, String) {
@@ -348,7 +379,7 @@ fn suggest_restriction<'tcx>(
     msg: &str,
     err: &mut Diagnostic,
     fn_sig: Option<&hir::FnSig<'_>>,
-    projection: Option<&ty::ProjectionTy<'_>>,
+    projection: Option<&ty::AliasTy<'_>>,
     trait_pred: ty::PolyTraitPredicate<'tcx>,
     // When we are dealing with a trait, `super_traits` will be `Some`:
     // Given `trait T: A + B + C {}`
@@ -474,7 +505,7 @@ fn suggest_restricting_param_bound(
         let self_ty = trait_pred.skip_binder().self_ty();
         let (param_ty, projection) = match self_ty.kind() {
             ty::Param(_) => (true, None),
-            ty::Projection(projection) => (false, Some(projection)),
+            ty::Alias(ty::Projection, projection) => (false, Some(projection)),
             _ => (false, None),
         };
 
@@ -673,7 +704,7 @@ fn suggest_dereferences(
         trait_pred: ty::PolyTraitPredicate<'tcx>,
     ) -> bool {
         // It only make sense when suggesting dereferences for arguments
-        let ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, .. } = obligation.cause.code()
+        let ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, call_hir_id, .. } = obligation.cause.code()
             else { return false; };
         let Some(typeck_results) = &self.typeck_results
             else { return false; };
@@ -752,12 +783,33 @@ fn suggest_dereferences(
                         real_trait_pred_and_base_ty,
                     );
                     if self.predicate_may_hold(&obligation) {
-                        err.span_suggestion_verbose(
-                            span.shrink_to_lo(),
-                            "consider dereferencing here",
-                            "*",
-                            Applicability::MachineApplicable,
+                        let call_node = self.tcx.hir().get(*call_hir_id);
+                        let msg = "consider dereferencing here";
+                        let is_receiver = matches!(
+                            call_node,
+                            Node::Expr(hir::Expr {
+                                kind: hir::ExprKind::MethodCall(_, receiver_expr, ..),
+                                ..
+                            })
+                            if receiver_expr.hir_id == *arg_hir_id
                         );
+                        if is_receiver {
+                            err.multipart_suggestion_verbose(
+                                msg,
+                                vec![
+                                    (span.shrink_to_lo(), "(*".to_string()),
+                                    (span.shrink_to_hi(), ")".to_string()),
+                                ],
+                                Applicability::MachineApplicable,
+                            )
+                        } else {
+                            err.span_suggestion_verbose(
+                                span.shrink_to_lo(),
+                                msg,
+                                '*',
+                                Applicability::MachineApplicable,
+                            )
+                        };
                         return true;
                     }
                 }
@@ -834,10 +886,10 @@ fn suggest_fn_call(
                     fn_sig.inputs().map_bound(|inputs| &inputs[1..]),
                 ))
             }
-            ty::Opaque(def_id, substs) => {
+            ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
                 self.tcx.bound_item_bounds(def_id).subst(self.tcx, substs).iter().find_map(|pred| {
                     if let ty::PredicateKind::Clause(ty::Clause::Projection(proj)) = pred.kind().skip_binder()
-                    && Some(proj.projection_ty.item_def_id) == self.tcx.lang_items().fn_once_output()
+                    && Some(proj.projection_ty.def_id) == self.tcx.lang_items().fn_once_output()
                     // args tuple will always be substs[1]
                     && let ty::Tuple(args) = proj.projection_ty.substs.type_at(1).kind()
                     {
@@ -854,7 +906,7 @@ fn suggest_fn_call(
             ty::Dynamic(data, _, ty::Dyn) => {
                 data.iter().find_map(|pred| {
                     if let ty::ExistentialPredicate::Projection(proj) = pred.skip_binder()
-                    && Some(proj.item_def_id) == self.tcx.lang_items().fn_once_output()
+                    && Some(proj.def_id) == self.tcx.lang_items().fn_once_output()
                     // for existential projection, substs are shifted over by 1
                     && let ty::Tuple(args) = proj.substs.type_at(0).kind()
                     {
@@ -871,7 +923,7 @@ fn suggest_fn_call(
             ty::Param(_) => {
                 obligation.param_env.caller_bounds().iter().find_map(|pred| {
                     if let ty::PredicateKind::Clause(ty::Clause::Projection(proj)) = pred.kind().skip_binder()
-                    && Some(proj.projection_ty.item_def_id) == self.tcx.lang_items().fn_once_output()
+                    && Some(proj.projection_ty.def_id) == self.tcx.lang_items().fn_once_output()
                     && proj.projection_ty.self_ty() == found
                     // args tuple will always be substs[1]
                     && let ty::Tuple(args) = proj.projection_ty.substs.type_at(1).kind()
@@ -1674,6 +1726,7 @@ fn report_closure_arg_mismatch(
         found: ty::PolyTraitRef<'tcx>,
         expected: ty::PolyTraitRef<'tcx>,
         cause: &ObligationCauseCode<'tcx>,
+        found_node: Option<Node<'_>>,
     ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
         pub(crate) fn build_fn_sig_ty<'tcx>(
             infcx: &InferCtxt<'tcx>,
@@ -1735,6 +1788,10 @@ pub(crate) fn build_fn_sig_ty<'tcx>(
 
         self.note_conflicting_closure_bounds(cause, &mut err);
 
+        if let Some(found_node) = found_node {
+            hint_missing_borrow(span, found_span, found, expected, found_node, &mut err);
+        }
+
         err
     }
 
@@ -2158,15 +2215,15 @@ fn note_obligation_cause_for_async_await(
             format!("does not implement `{}`", trait_pred.print_modifiers_and_trait_path())
         };
 
-        let mut explain_yield = |interior_span: Span,
-                                 yield_span: Span,
-                                 scope_span: Option<Span>| {
-            let mut span = MultiSpan::from_span(yield_span);
-            if let Ok(snippet) = source_map.span_to_snippet(interior_span) {
-                // #70935: If snippet contains newlines, display "the value" instead
-                // so that we do not emit complex diagnostics.
-                let snippet = &format!("`{}`", snippet);
-                let snippet = if snippet.contains('\n') { "the value" } else { snippet };
+        let mut explain_yield =
+            |interior_span: Span, yield_span: Span, scope_span: Option<Span>| {
+                let mut span = MultiSpan::from_span(yield_span);
+                let snippet = match source_map.span_to_snippet(interior_span) {
+                    // #70935: If snippet contains newlines, display "the value" instead
+                    // so that we do not emit complex diagnostics.
+                    Ok(snippet) if !snippet.contains('\n') => format!("`{}`", snippet),
+                    _ => "the value".to_string(),
+                };
                 // note: future is not `Send` as this value is used across an await
                 //   --> $DIR/issue-70935-complex-spans.rs:13:9
                 //    |
@@ -2191,17 +2248,11 @@ fn note_obligation_cause_for_async_await(
                     interior_span,
                     format!("has type `{}` which {}", target_ty, trait_explanation),
                 );
-                // If available, use the scope span to annotate the drop location.
-                let mut scope_note = None;
                 if let Some(scope_span) = scope_span {
                     let scope_span = source_map.end_point(scope_span);
 
                     let msg = format!("{} is later dropped here", snippet);
-                    if source_map.is_multiline(yield_span.between(scope_span)) {
-                        span.push_span_label(scope_span, msg);
-                    } else {
-                        scope_note = Some((scope_span, msg));
-                    }
+                    span.push_span_label(scope_span, msg);
                 }
                 err.span_note(
                     span,
@@ -2210,11 +2261,7 @@ fn note_obligation_cause_for_async_await(
                         future_or_generator, trait_explanation, an_await_or_yield
                     ),
                 );
-                if let Some((span, msg)) = scope_note {
-                    err.span_note(span, &msg);
-                }
-            }
-        };
+            };
         match interior_or_upvar_span {
             GeneratorInteriorOrUpvar::Interior(interior_span, interior_extra_info) => {
                 if let Some((scope_span, yield_span, expr, from_awaited_ty)) = interior_extra_info {
@@ -2336,7 +2383,7 @@ fn note_obligation_cause_for_async_await(
         debug!(?next_code);
         self.note_obligation_cause_code(
             err,
-            &obligation.predicate,
+            obligation.predicate,
             obligation.param_env,
             next_code.unwrap(),
             &mut Vec::new(),
@@ -2347,15 +2394,16 @@ fn note_obligation_cause_for_async_await(
     fn note_obligation_cause_code<T>(
         &self,
         err: &mut Diagnostic,
-        predicate: &T,
+        predicate: T,
         param_env: ty::ParamEnv<'tcx>,
         cause_code: &ObligationCauseCode<'tcx>,
         obligated_types: &mut Vec<Ty<'tcx>>,
         seen_requirements: &mut FxHashSet<DefId>,
     ) where
-        T: fmt::Display + ToPredicate<'tcx>,
+        T: ToPredicate<'tcx>,
     {
         let tcx = self.tcx;
+        let predicate = predicate.to_predicate(tcx);
         match *cause_code {
             ObligationCauseCode::ExprAssignable
             | ObligationCauseCode::MatchExpressionArm { .. }
@@ -2390,12 +2438,11 @@ fn note_obligation_cause_code<T>(
                 err.note("only the last element of a tuple may have a dynamically sized type");
             }
             ObligationCauseCode::ProjectionWf(data) => {
-                err.note(&format!("required so that the projection `{}` is well-formed", data,));
+                err.note(&format!("required so that the projection `{data}` is well-formed"));
             }
             ObligationCauseCode::ReferenceOutlivesReferent(ref_ty) => {
                 err.note(&format!(
-                    "required so that reference `{}` does not outlive its referent",
-                    ref_ty,
+                    "required so that reference `{ref_ty}` does not outlive its referent"
                 ));
             }
             ObligationCauseCode::ObjectTypeBound(object_ty, region) => {
@@ -2623,7 +2670,7 @@ fn note_obligation_cause_code<T>(
                                 Some(ident) => err.span_note(ident.span, &msg),
                                 None => err.note(&msg),
                             },
-                            ty::Opaque(def_id, _) => {
+                            ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => {
                                 // Avoid printing the future from `core::future::identity_future`, it's not helpful
                                 if tcx.parent(*def_id) == identity_future {
                                     break 'print;
@@ -2689,7 +2736,7 @@ fn note_obligation_cause_code<T>(
                     ensure_sufficient_stack(|| {
                         self.note_obligation_cause_code(
                             err,
-                            &parent_predicate,
+                            parent_predicate,
                             param_env,
                             &data.parent_code,
                             obligated_types,
@@ -2700,7 +2747,7 @@ fn note_obligation_cause_code<T>(
                     ensure_sufficient_stack(|| {
                         self.note_obligation_cause_code(
                             err,
-                            &parent_predicate,
+                            parent_predicate,
                             param_env,
                             cause_code.peel_derives(),
                             obligated_types,
@@ -2809,7 +2856,7 @@ fn note_obligation_cause_code<T>(
                 ensure_sufficient_stack(|| {
                     self.note_obligation_cause_code(
                         err,
-                        &parent_predicate,
+                        parent_predicate,
                         param_env,
                         &data.parent_code,
                         obligated_types,
@@ -2824,7 +2871,7 @@ fn note_obligation_cause_code<T>(
                 ensure_sufficient_stack(|| {
                     self.note_obligation_cause_code(
                         err,
-                        &parent_predicate,
+                        parent_predicate,
                         param_env,
                         &data.parent_code,
                         obligated_types,
@@ -2836,44 +2883,16 @@ fn note_obligation_cause_code<T>(
                 arg_hir_id,
                 call_hir_id,
                 ref parent_code,
+                ..
             } => {
-                let hir = self.tcx.hir();
-                if let Some(Node::Expr(expr @ hir::Expr { kind: hir::ExprKind::Block(..), .. })) =
-                    hir.find(arg_hir_id)
-                {
-                    let parent_id = hir.get_parent_item(arg_hir_id);
-                    let typeck_results: &TypeckResults<'tcx> = match &self.typeck_results {
-                        Some(t) if t.hir_owner == parent_id => t,
-                        _ => self.tcx.typeck(parent_id.def_id),
-                    };
-                    let expr = expr.peel_blocks();
-                    let ty = typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error());
-                    let span = expr.span;
-                    if Some(span) != err.span.primary_span() {
-                        err.span_label(
-                            span,
-                            if ty.references_error() {
-                                String::new()
-                            } else {
-                                format!("this tail expression is of type `{:?}`", ty)
-                            },
-                        );
-                    }
-                }
-                if let Some(Node::Expr(hir::Expr {
-                    kind:
-                        hir::ExprKind::Call(hir::Expr { span, .. }, _)
-                        | hir::ExprKind::MethodCall(
-                            hir::PathSegment { ident: Ident { span, .. }, .. },
-                            ..,
-                        ),
-                    ..
-                })) = hir.find(call_hir_id)
-                {
-                    if Some(*span) != err.span.primary_span() {
-                        err.span_label(*span, "required by a bound introduced by this call");
-                    }
-                }
+                self.function_argument_obligation(
+                    arg_hir_id,
+                    err,
+                    parent_code,
+                    param_env,
+                    predicate,
+                    call_hir_id,
+                );
                 ensure_sufficient_stack(|| {
                     self.note_obligation_cause_code(
                         err,
@@ -2888,9 +2907,8 @@ fn note_obligation_cause_code<T>(
             ObligationCauseCode::CompareImplItemObligation { trait_item_def_id, kind, .. } => {
                 let item_name = self.tcx.item_name(trait_item_def_id);
                 let msg = format!(
-                    "the requirement `{}` appears on the `impl`'s {kind} `{}` but not on the \
-                     corresponding trait's {kind}",
-                    predicate, item_name,
+                    "the requirement `{predicate}` appears on the `impl`'s {kind} \
+                     `{item_name}` but not on the corresponding trait's {kind}",
                 );
                 let sp = self
                     .tcx
@@ -2900,7 +2918,7 @@ fn note_obligation_cause_code<T>(
                 let mut assoc_span: MultiSpan = sp.into();
                 assoc_span.push_span_label(
                     sp,
-                    format!("this trait's {kind} doesn't have the requirement `{}`", predicate),
+                    format!("this trait's {kind} doesn't have the requirement `{predicate}`"),
                 );
                 if let Some(ident) = self
                     .tcx
@@ -2919,7 +2937,7 @@ fn note_obligation_cause_code<T>(
             }
             ObligationCauseCode::OpaqueReturnType(expr_info) => {
                 if let Some((expr_ty, expr_span)) = expr_info {
-                    let expr_ty = self.resolve_vars_if_possible(expr_ty);
+                    let expr_ty = with_forced_trimmed_paths!(self.ty_to_string(expr_ty));
                     err.span_label(
                         expr_span,
                         format!("return type was inferred to be `{expr_ty}` here"),
@@ -2965,7 +2983,7 @@ fn suggest_await_before_try(
                     self.tcx.mk_projection(
                         item_def_id,
                         // Future::Output has no substs
-                        self.tcx.mk_substs_trait(trait_pred.self_ty(), []),
+                        [trait_pred.self_ty()],
                     )
                 });
                 let InferOk { value: projection_ty, .. } =
@@ -3099,6 +3117,392 @@ fn suggest_dereferencing_index(
             );
         }
     }
+    fn function_argument_obligation(
+        &self,
+        arg_hir_id: HirId,
+        err: &mut Diagnostic,
+        parent_code: &ObligationCauseCode<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+        predicate: ty::Predicate<'tcx>,
+        call_hir_id: HirId,
+    ) {
+        let tcx = self.tcx;
+        let hir = tcx.hir();
+        if let Some(Node::Expr(expr)) = hir.find(arg_hir_id) {
+            let parent_id = hir.get_parent_item(arg_hir_id);
+            let typeck_results: &TypeckResults<'tcx> = match &self.typeck_results {
+                Some(t) if t.hir_owner == parent_id => t,
+                _ => self.tcx.typeck(parent_id.def_id),
+            };
+            if let hir::Expr { kind: hir::ExprKind::Block(..), .. } = expr {
+                let expr = expr.peel_blocks();
+                let ty = typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error());
+                let span = expr.span;
+                if Some(span) != err.span.primary_span() {
+                    err.span_label(
+                        span,
+                        if ty.references_error() {
+                            String::new()
+                        } else {
+                            let ty = with_forced_trimmed_paths!(self.ty_to_string(ty));
+                            format!("this tail expression is of type `{ty}`")
+                        },
+                    );
+                }
+            }
+
+            // FIXME: visit the ty to see if there's any closure involved, and if there is,
+            // check whether its evaluated return type is the same as the one corresponding
+            // to an associated type (as seen from `trait_pred`) in the predicate. Like in
+            // trait_pred `S: Sum<<Self as Iterator>::Item>` and predicate `i32: Sum<&()>`
+            let mut type_diffs = vec![];
+
+            if let ObligationCauseCode::ExprBindingObligation(def_id, _, _, idx) = parent_code.deref()
+                && let predicates = self.tcx.predicates_of(def_id).instantiate_identity(self.tcx)
+                && let Some(pred) = predicates.predicates.get(*idx)
+            {
+                if let Ok(trait_pred) = pred.kind().try_map_bound(|pred| match pred {
+                    ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) => Ok(trait_pred),
+                    _ => Err(()),
+                })
+                    && let Ok(trait_predicate) = predicate.kind().try_map_bound(|pred| match pred {
+                        ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) => Ok(trait_pred),
+                        _ => Err(()),
+                    })
+                {
+                    let mut c = CollectAllMismatches {
+                        infcx: self.infcx,
+                        param_env,
+                        errors: vec![],
+                    };
+                    if let Ok(_) = c.relate(trait_pred, trait_predicate) {
+                        type_diffs = c.errors;
+                    }
+                } else if let ty::PredicateKind::Clause(
+                    ty::Clause::Projection(proj)
+                ) = pred.kind().skip_binder()
+                    && let ty::PredicateKind::Clause(
+                        ty::Clause::Projection(projection)
+                    ) = predicate.kind().skip_binder()
+                {
+                    type_diffs = vec![
+                        Sorts(ty::error::ExpectedFound {
+                            expected: self.tcx.mk_ty(ty::Alias(ty::Projection, proj.projection_ty)),
+                            found: projection.term.ty().unwrap(),
+                        }),
+                    ];
+                }
+            }
+            if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind
+                && let hir::Path { res: hir::def::Res::Local(hir_id), .. } = path
+                && let Some(hir::Node::Pat(binding)) = self.tcx.hir().find(*hir_id)
+                && let parent_hir_id = self.tcx.hir().get_parent_node(binding.hir_id)
+                && let Some(hir::Node::Local(local)) = self.tcx.hir().find(parent_hir_id)
+                && let Some(binding_expr) = local.init
+            {
+                // If the expression we're calling on is a binding, we want to point at the
+                // `let` when talking about the type. Otherwise we'll point at every part
+                // of the method chain with the type.
+                self.point_at_chain(binding_expr, typeck_results, type_diffs, param_env, err);
+            } else {
+                self.point_at_chain(expr, typeck_results, type_diffs, param_env, err);
+            }
+        }
+        let call_node = hir.find(call_hir_id);
+        if let Some(Node::Expr(hir::Expr {
+            kind: hir::ExprKind::MethodCall(path, rcvr, ..), ..
+        })) = call_node
+        {
+            if Some(rcvr.span) == err.span.primary_span() {
+                err.replace_span_with(path.ident.span);
+            }
+        }
+        if let Some(Node::Expr(hir::Expr {
+            kind:
+                hir::ExprKind::Call(hir::Expr { span, .. }, _)
+                | hir::ExprKind::MethodCall(hir::PathSegment { ident: Ident { span, .. }, .. }, ..),
+            ..
+        })) = hir.find(call_hir_id)
+        {
+            if Some(*span) != err.span.primary_span() {
+                err.span_label(*span, "required by a bound introduced by this call");
+            }
+        }
+    }
+
+    fn point_at_chain(
+        &self,
+        expr: &hir::Expr<'_>,
+        typeck_results: &TypeckResults<'tcx>,
+        type_diffs: Vec<TypeError<'tcx>>,
+        param_env: ty::ParamEnv<'tcx>,
+        err: &mut Diagnostic,
+    ) {
+        let mut primary_spans = vec![];
+        let mut span_labels = vec![];
+
+        let tcx = self.tcx;
+
+        let mut print_root_expr = true;
+        let mut assocs = vec![];
+        let mut expr = expr;
+        let mut prev_ty = self.resolve_vars_if_possible(
+            typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error()),
+        );
+        while let hir::ExprKind::MethodCall(_path_segment, rcvr_expr, _args, span) = expr.kind {
+            // Point at every method call in the chain with the resulting type.
+            // vec![1, 2, 3].iter().map(mapper).sum<i32>()
+            //               ^^^^^^ ^^^^^^^^^^^
+            expr = rcvr_expr;
+            let assocs_in_this_method =
+                self.probe_assoc_types_at_expr(&type_diffs, span, prev_ty, expr.hir_id, param_env);
+            assocs.push(assocs_in_this_method);
+            prev_ty = self.resolve_vars_if_possible(
+                typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error()),
+            );
+
+            if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind
+                && let hir::Path { res: hir::def::Res::Local(hir_id), .. } = path
+                && let Some(hir::Node::Pat(binding)) = self.tcx.hir().find(*hir_id)
+                && let parent_hir_id = self.tcx.hir().get_parent_node(binding.hir_id)
+                && let Some(parent) = self.tcx.hir().find(parent_hir_id)
+            {
+                // We've reached the root of the method call chain...
+                if let hir::Node::Local(local) = parent
+                    && let Some(binding_expr) = local.init
+                {
+                    // ...and it is a binding. Get the binding creation and continue the chain.
+                    expr = binding_expr;
+                }
+                if let hir::Node::Param(param) = parent {
+                    // ...and it is a an fn argument.
+                    let prev_ty = self.resolve_vars_if_possible(
+                        typeck_results.node_type_opt(param.hir_id).unwrap_or(tcx.ty_error()),
+                    );
+                    let assocs_in_this_method = self.probe_assoc_types_at_expr(&type_diffs, param.ty_span, prev_ty, param.hir_id, param_env);
+                    if assocs_in_this_method.iter().any(|a| a.is_some()) {
+                        assocs.push(assocs_in_this_method);
+                        print_root_expr = false;
+                    }
+                    break;
+                }
+            }
+        }
+        // We want the type before deref coercions, otherwise we talk about `&[_]`
+        // instead of `Vec<_>`.
+        if let Some(ty) = typeck_results.expr_ty_opt(expr) && print_root_expr {
+            let ty = with_forced_trimmed_paths!(self.ty_to_string(ty));
+            // Point at the root expression
+            // vec![1, 2, 3].iter().map(mapper).sum<i32>()
+            // ^^^^^^^^^^^^^
+            span_labels.push((expr.span, format!("this expression has type `{ty}`")));
+        };
+        // Only show this if it is not a "trivial" expression (not a method
+        // chain) and there are associated types to talk about.
+        let mut assocs = assocs.into_iter().peekable();
+        while let Some(assocs_in_method) = assocs.next() {
+            let Some(prev_assoc_in_method) = assocs.peek() else {
+                for entry in assocs_in_method {
+                    let Some((span, (assoc, ty))) = entry else { continue; };
+                    if primary_spans.is_empty() || type_diffs.iter().any(|diff| {
+                        let Sorts(expected_found) = diff else { return false; };
+                        self.can_eq(param_env, expected_found.found, ty).is_ok()
+                    }) {
+                        // FIXME: this doesn't quite work for `Iterator::collect`
+                        // because we have `Vec<i32>` and `()`, but we'd want `i32`
+                        // to point at the `.into_iter()` call, but as long as we
+                        // still point at the other method calls that might have
+                        // introduced the issue, this is fine for now.
+                        primary_spans.push(span);
+                    }
+                    span_labels.push((
+                        span,
+                        with_forced_trimmed_paths!(format!(
+                            "`{}` is `{ty}` here",
+                            self.tcx.def_path_str(assoc),
+                        )),
+                    ));
+                }
+                break;
+            };
+            for (entry, prev_entry) in
+                assocs_in_method.into_iter().zip(prev_assoc_in_method.into_iter())
+            {
+                match (entry, prev_entry) {
+                    (Some((span, (assoc, ty))), Some((_, (_, prev_ty)))) => {
+                        let ty_str = with_forced_trimmed_paths!(self.ty_to_string(ty));
+
+                        let assoc = with_forced_trimmed_paths!(self.tcx.def_path_str(assoc));
+                        if self.can_eq(param_env, ty, *prev_ty).is_err() {
+                            if type_diffs.iter().any(|diff| {
+                                let Sorts(expected_found) = diff else { return false; };
+                                self.can_eq(param_env, expected_found.found, ty).is_ok()
+                            }) {
+                                primary_spans.push(span);
+                            }
+                            span_labels
+                                .push((span, format!("`{assoc}` changed to `{ty_str}` here")));
+                        } else {
+                            span_labels.push((span, format!("`{assoc}` remains `{ty_str}` here")));
+                        }
+                    }
+                    (Some((span, (assoc, ty))), None) => {
+                        span_labels.push((
+                            span,
+                            with_forced_trimmed_paths!(format!(
+                                "`{}` is `{}` here",
+                                self.tcx.def_path_str(assoc),
+                                self.ty_to_string(ty),
+                            )),
+                        ));
+                    }
+                    (None, Some(_)) | (None, None) => {}
+                }
+            }
+        }
+        if !primary_spans.is_empty() {
+            let mut multi_span: MultiSpan = primary_spans.into();
+            for (span, label) in span_labels {
+                multi_span.push_span_label(span, label);
+            }
+            err.span_note(
+                multi_span,
+                format!("the method call chain might not have had the expected associated types"),
+            );
+        }
+    }
+
+    fn probe_assoc_types_at_expr(
+        &self,
+        type_diffs: &[TypeError<'tcx>],
+        span: Span,
+        prev_ty: Ty<'tcx>,
+        body_id: hir::HirId,
+        param_env: ty::ParamEnv<'tcx>,
+    ) -> Vec<Option<(Span, (DefId, Ty<'tcx>))>> {
+        let ocx = ObligationCtxt::new_in_snapshot(self.infcx);
+        let mut assocs_in_this_method = Vec::with_capacity(type_diffs.len());
+        for diff in type_diffs {
+            let Sorts(expected_found) = diff else { continue; };
+            let ty::Alias(ty::Projection, proj) = expected_found.expected.kind() else { continue; };
+
+            let origin = TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span };
+            let trait_def_id = proj.trait_def_id(self.tcx);
+            // Make `Self` be equivalent to the type of the call chain
+            // expression we're looking at now, so that we can tell what
+            // for example `Iterator::Item` is at this point in the chain.
+            let substs = InternalSubsts::for_item(self.tcx, trait_def_id, |param, _| {
+                match param.kind {
+                    ty::GenericParamDefKind::Type { .. } => {
+                        if param.index == 0 {
+                            return prev_ty.into();
+                        }
+                    }
+                    ty::GenericParamDefKind::Lifetime | ty::GenericParamDefKind::Const { .. } => {}
+                }
+                self.var_for_def(span, param)
+            });
+            // This will hold the resolved type of the associated type, if the
+            // current expression implements the trait that associated type is
+            // in. For example, this would be what `Iterator::Item` is here.
+            let ty_var = self.infcx.next_ty_var(origin);
+            // This corresponds to `<ExprTy as Iterator>::Item = _`.
+            let projection = ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::Projection(
+                ty::ProjectionPredicate {
+                    projection_ty: self.tcx.mk_alias_ty(proj.def_id, substs),
+                    term: ty_var.into(),
+                },
+            )));
+            // Add `<ExprTy as Iterator>::Item = _` obligation.
+            ocx.register_obligation(Obligation::misc(
+                self.tcx, span, body_id, param_env, projection,
+            ));
+            if ocx.select_where_possible().is_empty() {
+                // `ty_var` now holds the type that `Item` is for `ExprTy`.
+                let ty_var = self.resolve_vars_if_possible(ty_var);
+                assocs_in_this_method.push(Some((span, (proj.def_id, ty_var))));
+            } else {
+                // `<ExprTy as Iterator>` didn't select, so likely we've
+                // reached the end of the iterator chain, like the originating
+                // `Vec<_>`.
+                // Keep the space consistent for later zipping.
+                assocs_in_this_method.push(None);
+            }
+        }
+        assocs_in_this_method
+    }
+}
+
+/// Add a hint to add a missing borrow or remove an unnecessary one.
+fn hint_missing_borrow<'tcx>(
+    span: Span,
+    found_span: Span,
+    found: Ty<'tcx>,
+    expected: Ty<'tcx>,
+    found_node: Node<'_>,
+    err: &mut Diagnostic,
+) {
+    let found_args = match found.kind() {
+        ty::FnPtr(f) => f.inputs().skip_binder().iter(),
+        kind => {
+            span_bug!(span, "found was converted to a FnPtr above but is now {:?}", kind)
+        }
+    };
+    let expected_args = match expected.kind() {
+        ty::FnPtr(f) => f.inputs().skip_binder().iter(),
+        kind => {
+            span_bug!(span, "expected was converted to a FnPtr above but is now {:?}", kind)
+        }
+    };
+
+    let fn_decl = found_node
+        .fn_decl()
+        .unwrap_or_else(|| span_bug!(found_span, "found node must be a function"));
+
+    let arg_spans = fn_decl.inputs.iter().map(|ty| ty.span);
+
+    fn get_deref_type_and_refs<'tcx>(mut ty: Ty<'tcx>) -> (Ty<'tcx>, usize) {
+        let mut refs = 0;
+
+        while let ty::Ref(_, new_ty, _) = ty.kind() {
+            ty = *new_ty;
+            refs += 1;
+        }
+
+        (ty, refs)
+    }
+
+    let mut to_borrow = Vec::new();
+    let mut remove_borrow = Vec::new();
+
+    for ((found_arg, expected_arg), arg_span) in found_args.zip(expected_args).zip(arg_spans) {
+        let (found_ty, found_refs) = get_deref_type_and_refs(*found_arg);
+        let (expected_ty, expected_refs) = get_deref_type_and_refs(*expected_arg);
+
+        if found_ty == expected_ty {
+            if found_refs < expected_refs {
+                to_borrow.push((arg_span, expected_arg.to_string()));
+            } else if found_refs > expected_refs {
+                remove_borrow.push((arg_span, expected_arg.to_string()));
+            }
+        }
+    }
+
+    if !to_borrow.is_empty() {
+        err.multipart_suggestion(
+            "consider borrowing the argument",
+            to_borrow,
+            Applicability::MaybeIncorrect,
+        );
+    }
+
+    if !remove_borrow.is_empty() {
+        err.multipart_suggestion(
+            "do not borrow the argument",
+            remove_borrow,
+            Applicability::MaybeIncorrect,
+        );
+    }
 }
 
 /// Collect all the returned expressions within the input expression.
index ea4bf42c515b5fb5a7aa83413b4d3eca80236736..2566d793d78daa53e4a5b5be00e880ad0dd96b02 100644 (file)
@@ -425,13 +425,8 @@ pub fn fully_solve_bound<'tcx>(
     bound: DefId,
 ) -> Vec<FulfillmentError<'tcx>> {
     let tcx = infcx.tcx;
-    let trait_ref = ty::TraitRef { def_id: bound, substs: tcx.mk_substs_trait(ty, []) };
-    let obligation = Obligation {
-        cause,
-        recursion_depth: 0,
-        param_env,
-        predicate: ty::Binder::dummy(trait_ref).without_const().to_predicate(tcx),
-    };
+    let trait_ref = tcx.mk_trait_ref(bound, [ty]);
+    let obligation = Obligation::new(tcx, cause, param_env, ty::Binder::dummy(trait_ref));
 
     fully_solve_obligation(infcx, obligation)
 }
index a45749fe48cd48a5d625deb3d7e146ec942984e8..8b1ced78f4e8a06fe4a69ed1d0a4f49c8e043935 100644 (file)
@@ -589,7 +589,7 @@ fn object_ty_for_trait<'tcx>(
             let pred = obligation.predicate.to_opt_poly_projection_pred()?;
             Some(pred.map_bound(|p| {
                 ty::ExistentialPredicate::Projection(ty::ExistentialProjection {
-                    item_def_id: p.projection_ty.item_def_id,
+                    def_id: p.projection_ty.def_id,
                     substs: p.projection_ty.substs,
                     term: p.term,
                 })
@@ -694,18 +694,12 @@ fn receiver_is_dispatchable<'tcx>(
 
         // U: Trait<Arg1, ..., ArgN>
         let trait_predicate = {
-            let substs =
-                InternalSubsts::for_item(tcx, method.trait_container(tcx).unwrap(), |param, _| {
-                    if param.index == 0 {
-                        unsized_self_ty.into()
-                    } else {
-                        tcx.mk_param_from_def(param)
-                    }
-                });
+            let trait_def_id = method.trait_container(tcx).unwrap();
+            let substs = InternalSubsts::for_item(tcx, trait_def_id, |param, _| {
+                if param.index == 0 { unsized_self_ty.into() } else { tcx.mk_param_from_def(param) }
+            });
 
-            ty::Binder::dummy(ty::TraitRef { def_id: unsize_did, substs })
-                .without_const()
-                .to_predicate(tcx)
+            ty::Binder::dummy(tcx.mk_trait_ref(trait_def_id, substs)).to_predicate(tcx)
         };
 
         let caller_bounds: Vec<Predicate<'tcx>> =
@@ -794,13 +788,13 @@ fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
                         ControlFlow::CONTINUE
                     }
                 }
-                ty::Projection(ref data)
-                    if self.tcx.def_kind(data.item_def_id) == DefKind::ImplTraitPlaceholder =>
+                ty::Alias(ty::Projection, ref data)
+                    if self.tcx.def_kind(data.def_id) == DefKind::ImplTraitPlaceholder =>
                 {
                     // We'll deny these later in their own pass
                     ControlFlow::CONTINUE
                 }
-                ty::Projection(ref data) => {
+                ty::Alias(ty::Projection, ref data) => {
                     // This is a projected type `<Foo as SomeTrait>::X`.
 
                     // Compute supertraits of current trait lazily.
@@ -861,10 +855,10 @@ pub fn contains_illegal_impl_trait_in_trait<'tcx>(
     // FIXME(RPITIT): Perhaps we should use a visitor here?
     ty.skip_binder().walk().find_map(|arg| {
         if let ty::GenericArgKind::Type(ty) = arg.unpack()
-            && let ty::Projection(proj) = ty.kind()
-            && tcx.def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder
+            && let ty::Alias(ty::Projection, proj) = ty.kind()
+            && tcx.def_kind(proj.def_id) == DefKind::ImplTraitPlaceholder
         {
-            Some(MethodViolationCode::ReferencesImplTraitInTrait(tcx.def_span(proj.item_def_id)))
+            Some(MethodViolationCode::ReferencesImplTraitInTrait(tcx.def_span(proj.def_id)))
         } else {
             None
         }
index 5789754e4fcefd6f19fa458f1f80cd5e4d7e5445..84d7244c1db786a6144c32e6fdf6be92e2e1c3c2 100644 (file)
@@ -45,7 +45,7 @@
 
 pub type ProjectionObligation<'tcx> = Obligation<'tcx, ty::ProjectionPredicate<'tcx>>;
 
-pub type ProjectionTyObligation<'tcx> = Obligation<'tcx, ty::ProjectionTy<'tcx>>;
+pub type ProjectionTyObligation<'tcx> = Obligation<'tcx, ty::AliasTy<'tcx>>;
 
 pub(super) struct InProgress;
 
@@ -496,7 +496,9 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
             // This is really important. While we *can* handle this, this has
             // severe performance implications for large opaque types with
             // late-bound regions. See `issue-88862` benchmark.
-            ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => {
+            ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. })
+                if !substs.has_escaping_bound_vars() =>
+            {
                 // Only normalize `impl Trait` outside of type inference, usually in codegen.
                 match self.param_env.reveal() {
                     Reveal::UserFacing => ty.super_fold_with(self),
@@ -523,7 +525,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                 }
             }
 
-            ty::Projection(data) if !data.has_escaping_bound_vars() => {
+            ty::Alias(ty::Projection, data) if !data.has_escaping_bound_vars() => {
                 // This branch is *mostly* just an optimization: when we don't
                 // have escaping bound vars, we don't need to replace them with
                 // placeholders (see branch below). *Also*, we know that we can
@@ -562,7 +564,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                 normalized_ty.ty().unwrap()
             }
 
-            ty::Projection(data) => {
+            ty::Alias(ty::Projection, data) => {
                 // If there are escaping bound vars, we temporarily replace the
                 // bound vars with placeholders. Note though, that in the case
                 // that we still can't project for whatever reason (e.g. self
@@ -957,7 +959,7 @@ fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
 pub fn normalize_projection_type<'a, 'b, 'tcx>(
     selcx: &'a mut SelectionContext<'b, 'tcx>,
     param_env: ty::ParamEnv<'tcx>,
-    projection_ty: ty::ProjectionTy<'tcx>,
+    projection_ty: ty::AliasTy<'tcx>,
     cause: ObligationCause<'tcx>,
     depth: usize,
     obligations: &mut Vec<PredicateObligation<'tcx>>,
@@ -995,7 +997,7 @@ pub fn normalize_projection_type<'a, 'b, 'tcx>(
 fn opt_normalize_projection_type<'a, 'b, 'tcx>(
     selcx: &'a mut SelectionContext<'b, 'tcx>,
     param_env: ty::ParamEnv<'tcx>,
-    projection_ty: ty::ProjectionTy<'tcx>,
+    projection_ty: ty::AliasTy<'tcx>,
     cause: ObligationCause<'tcx>,
     depth: usize,
     obligations: &mut Vec<PredicateObligation<'tcx>>,
@@ -1177,7 +1179,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
 fn normalize_to_error<'a, 'tcx>(
     selcx: &mut SelectionContext<'a, 'tcx>,
     param_env: ty::ParamEnv<'tcx>,
-    projection_ty: ty::ProjectionTy<'tcx>,
+    projection_ty: ty::AliasTy<'tcx>,
     cause: ObligationCause<'tcx>,
     depth: usize,
 ) -> NormalizedTy<'tcx> {
@@ -1189,10 +1191,9 @@ fn normalize_to_error<'a, 'tcx>(
         predicate: trait_ref.without_const().to_predicate(selcx.tcx()),
     };
     let tcx = selcx.infcx.tcx;
-    let def_id = projection_ty.item_def_id;
     let new_value = selcx.infcx.next_ty_var(TypeVariableOrigin {
         kind: TypeVariableOriginKind::NormalizeProjectionType,
-        span: tcx.def_span(def_id),
+        span: tcx.def_span(projection_ty.def_id),
     });
     Normalized { value: new_value, obligations: vec![trait_obligation] }
 }
@@ -1270,7 +1271,7 @@ fn project<'cx, 'tcx>(
             // need to investigate whether or not this is fine.
             selcx
                 .tcx()
-                .mk_projection(obligation.predicate.item_def_id, obligation.predicate.substs)
+                .mk_projection(obligation.predicate.def_id, obligation.predicate.substs)
                 .into(),
         )),
         // Error occurred while trying to processing impls.
@@ -1290,13 +1291,12 @@ fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>(
     candidate_set: &mut ProjectionCandidateSet<'tcx>,
 ) {
     let tcx = selcx.tcx();
-    if tcx.def_kind(obligation.predicate.item_def_id) == DefKind::ImplTraitPlaceholder {
-        let trait_fn_def_id = tcx.impl_trait_in_trait_parent(obligation.predicate.item_def_id);
+    if tcx.def_kind(obligation.predicate.def_id) == DefKind::ImplTraitPlaceholder {
+        let trait_fn_def_id = tcx.impl_trait_in_trait_parent(obligation.predicate.def_id);
         // If we are trying to project an RPITIT with trait's default `Self` parameter,
         // then we must be within a default trait body.
         if obligation.predicate.self_ty()
-            == ty::InternalSubsts::identity_for_item(tcx, obligation.predicate.item_def_id)
-                .type_at(0)
+            == ty::InternalSubsts::identity_for_item(tcx, obligation.predicate.def_id).type_at(0)
             && tcx.associated_item(trait_fn_def_id).defaultness(tcx).has_value()
         {
             candidate_set.push_candidate(ProjectionCandidate::ImplTraitInTrait(
@@ -1309,8 +1309,7 @@ fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>(
         let trait_substs =
             obligation.predicate.substs.truncate_to(tcx, tcx.generics_of(trait_def_id));
         // FIXME(named-returns): Binders
-        let trait_predicate =
-            ty::Binder::dummy(ty::TraitRef { def_id: trait_def_id, substs: trait_substs });
+        let trait_predicate = ty::Binder::dummy(tcx.mk_trait_ref(trait_def_id, trait_substs));
 
         let _ = selcx.infcx.commit_if_ok(|_| {
             match selcx.select(&obligation.with(tcx, trait_predicate)) {
@@ -1377,8 +1376,7 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>(
     // Check whether the self-type is itself a projection.
     // If so, extract what we know from the trait and try to come up with a good answer.
     let bounds = match *obligation.predicate.self_ty().kind() {
-        ty::Projection(ref data) => tcx.bound_item_bounds(data.item_def_id).subst(tcx, data.substs),
-        ty::Opaque(def_id, substs) => tcx.bound_item_bounds(def_id).subst(tcx, substs),
+        ty::Alias(_, ref data) => tcx.bound_item_bounds(data.def_id).subst(tcx, data.substs),
         ty::Infer(ty::TyVar(_)) => {
             // If the self-type is an inference variable, then it MAY wind up
             // being a projected type, so induce an ambiguity.
@@ -1430,7 +1428,7 @@ fn assemble_candidates_from_object_ty<'cx, 'tcx>(
     };
     let env_predicates = data
         .projection_bounds()
-        .filter(|bound| bound.item_def_id() == obligation.predicate.item_def_id)
+        .filter(|bound| bound.item_def_id() == obligation.predicate.def_id)
         .map(|p| p.with_self_ty(tcx, object_ty).to_predicate(tcx));
 
     assemble_candidates_from_predicates(
@@ -1462,7 +1460,7 @@ fn assemble_candidates_from_predicates<'cx, 'tcx>(
             predicate.kind().skip_binder()
         {
             let data = bound_predicate.rebind(data);
-            if data.projection_def_id() != obligation.predicate.item_def_id {
+            if data.projection_def_id() != obligation.predicate.def_id {
                 continue;
             }
 
@@ -1503,7 +1501,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
     candidate_set: &mut ProjectionCandidateSet<'tcx>,
 ) {
     // Can't assemble candidate from impl for RPITIT
-    if selcx.tcx().def_kind(obligation.predicate.item_def_id) == DefKind::ImplTraitPlaceholder {
+    if selcx.tcx().def_kind(obligation.predicate.def_id) == DefKind::ImplTraitPlaceholder {
         return;
     }
 
@@ -1555,7 +1553,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
                 // NOTE: This should be kept in sync with the similar code in
                 // `rustc_ty_utils::instance::resolve_associated_item()`.
                 let node_item =
-                    assoc_def(selcx, impl_data.impl_def_id, obligation.predicate.item_def_id)
+                    assoc_def(selcx, impl_data.impl_def_id, obligation.predicate.def_id)
                         .map_err(|ErrorGuaranteed { .. }| ())?;
 
                 if node_item.is_final() {
@@ -1616,8 +1614,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
                          // type parameters, opaques, and unnormalized projections have pointer
                         // metadata if they're known (e.g. by the param_env) to be sized
                         ty::Param(_)
-                        | ty::Projection(..)
-                        | ty::Opaque(..)
+                        | ty::Alias(..)
                         | ty::Bound(..)
                         | ty::Placeholder(..)
                         | ty::Infer(..)
@@ -1671,7 +1668,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
 
                         // type parameters, opaques, and unnormalized projections have pointer
                         // metadata if they're known (e.g. by the param_env) to be sized
-                        ty::Param(_) | ty::Projection(..) | ty::Opaque(..)
+                        ty::Param(_) | ty::Alias(..)
                             if selcx.infcx.predicate_must_hold_modulo_regions(
                                 &obligation.with(
                                     selcx.tcx(),
@@ -1687,8 +1684,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
 
                         // FIXME(compiler-errors): are Bound and Placeholder types ever known sized?
                         ty::Param(_)
-                        | ty::Projection(..)
-                        | ty::Opaque(..)
+                        | ty::Alias(..)
                         | ty::Bound(..)
                         | ty::Placeholder(..)
                         | ty::Infer(..)
@@ -1788,7 +1784,7 @@ fn confirm_candidate<'cx, 'tcx>(
         ProjectionCandidate::ImplTraitInTrait(ImplTraitInTraitCandidate::Trait) => Progress {
             term: selcx
                 .tcx()
-                .mk_opaque(obligation.predicate.item_def_id, obligation.predicate.substs)
+                .mk_opaque(obligation.predicate.def_id, obligation.predicate.substs)
                 .into(),
             obligations: vec![],
         },
@@ -1860,7 +1856,7 @@ fn confirm_generator_candidate<'cx, 'tcx>(
         gen_sig,
     )
     .map_bound(|(trait_ref, yield_ty, return_ty)| {
-        let name = tcx.associated_item(obligation.predicate.item_def_id).name;
+        let name = tcx.associated_item(obligation.predicate.def_id).name;
         let ty = if name == sym::Return {
             return_ty
         } else if name == sym::Yield {
@@ -1870,10 +1866,7 @@ fn confirm_generator_candidate<'cx, 'tcx>(
         };
 
         ty::ProjectionPredicate {
-            projection_ty: ty::ProjectionTy {
-                substs: trait_ref.substs,
-                item_def_id: obligation.predicate.item_def_id,
-            },
+            projection_ty: tcx.mk_alias_ty(obligation.predicate.def_id, trait_ref.substs),
             term: ty.into(),
         }
     });
@@ -1909,13 +1902,10 @@ fn confirm_future_candidate<'cx, 'tcx>(
         gen_sig,
     )
     .map_bound(|(trait_ref, return_ty)| {
-        debug_assert_eq!(tcx.associated_item(obligation.predicate.item_def_id).name, sym::Output);
+        debug_assert_eq!(tcx.associated_item(obligation.predicate.def_id).name, sym::Output);
 
         ty::ProjectionPredicate {
-            projection_ty: ty::ProjectionTy {
-                substs: trait_ref.substs,
-                item_def_id: obligation.predicate.item_def_id,
-            },
+            projection_ty: tcx.mk_alias_ty(obligation.predicate.def_id, trait_ref.substs),
             term: return_ty.into(),
         }
     });
@@ -1934,7 +1924,7 @@ fn confirm_builtin_candidate<'cx, 'tcx>(
     let self_ty = obligation.predicate.self_ty();
     let substs = tcx.mk_substs([self_ty.into()].iter());
     let lang_items = tcx.lang_items();
-    let item_def_id = obligation.predicate.item_def_id;
+    let item_def_id = obligation.predicate.def_id;
     let trait_def_id = tcx.trait_of_item(item_def_id).unwrap();
     let (term, obligations) = if lang_items.discriminant_kind_trait() == Some(trait_def_id) {
         let discriminant_def_id = tcx.require_lang_item(LangItem::Discriminant, None);
@@ -1969,7 +1959,7 @@ fn confirm_builtin_candidate<'cx, 'tcx>(
     };
 
     let predicate =
-        ty::ProjectionPredicate { projection_ty: ty::ProjectionTy { substs, item_def_id }, term };
+        ty::ProjectionPredicate { projection_ty: tcx.mk_alias_ty(item_def_id, substs), term };
 
     confirm_param_env_candidate(selcx, obligation, ty::Binder::dummy(predicate), false)
         .with_addl_obligations(obligations)
@@ -2038,10 +2028,7 @@ fn confirm_callable_candidate<'cx, 'tcx>(
         flag,
     )
     .map_bound(|(trait_ref, ret_type)| ty::ProjectionPredicate {
-        projection_ty: ty::ProjectionTy {
-            substs: trait_ref.substs,
-            item_def_id: fn_once_output_def_id,
-        },
+        projection_ty: tcx.mk_alias_ty(fn_once_output_def_id, trait_ref.substs),
         term: ret_type.into(),
     });
 
@@ -2122,7 +2109,7 @@ fn confirm_impl_candidate<'cx, 'tcx>(
     let tcx = selcx.tcx();
 
     let ImplSourceUserDefinedData { impl_def_id, substs, mut nested } = impl_impl_source;
-    let assoc_item_id = obligation.predicate.item_def_id;
+    let assoc_item_id = obligation.predicate.def_id;
     let trait_def_id = tcx.trait_id_of_impl(impl_def_id).unwrap();
 
     let param_env = obligation.param_env;
@@ -2222,7 +2209,7 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>(
     let tcx = selcx.tcx();
     let mut obligations = data.nested;
 
-    let trait_fn_def_id = tcx.impl_trait_in_trait_parent(obligation.predicate.item_def_id);
+    let trait_fn_def_id = tcx.impl_trait_in_trait_parent(obligation.predicate.def_id);
     let Ok(leaf_def) = assoc_def(selcx, data.impl_def_id, trait_fn_def_id) else {
         return Progress { term: tcx.ty_error().into(), obligations };
     };
@@ -2233,9 +2220,7 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>(
     // Use the default `impl Trait` for the trait, e.g., for a default trait body
     if leaf_def.item.container == ty::AssocItemContainer::TraitContainer {
         return Progress {
-            term: tcx
-                .mk_opaque(obligation.predicate.item_def_id, obligation.predicate.substs)
-                .into(),
+            term: tcx.mk_opaque(obligation.predicate.def_id, obligation.predicate.substs).into(),
             obligations,
         };
     }
@@ -2302,7 +2287,7 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>(
         obligation.recursion_depth + 1,
         tcx.bound_trait_impl_trait_tys(impl_fn_def_id)
             .map_bound(|tys| {
-                tys.map_or_else(|_| tcx.ty_error(), |tys| tys[&obligation.predicate.item_def_id])
+                tys.map_or_else(|_| tcx.ty_error(), |tys| tys[&obligation.predicate.def_id])
             })
             .subst(tcx, impl_fn_substs),
         &mut obligations,
@@ -2320,7 +2305,7 @@ fn assoc_ty_own_obligations<'cx, 'tcx>(
 ) {
     let tcx = selcx.tcx();
     let own = tcx
-        .predicates_of(obligation.predicate.item_def_id)
+        .predicates_of(obligation.predicate.def_id)
         .instantiate_own(tcx, obligation.predicate.substs);
     for (predicate, span) in std::iter::zip(own.predicates, own.spans) {
         let normalized = normalize_with_depth_to(
@@ -2343,13 +2328,13 @@ fn assoc_ty_own_obligations<'cx, 'tcx>(
             ObligationCause::new(
                 obligation.cause.span,
                 obligation.cause.body_id,
-                super::ItemObligation(obligation.predicate.item_def_id),
+                super::ItemObligation(obligation.predicate.def_id),
             )
         } else {
             ObligationCause::new(
                 obligation.cause.span,
                 obligation.cause.body_id,
-                super::BindingObligation(obligation.predicate.item_def_id, span),
+                super::BindingObligation(obligation.predicate.def_id, span),
             )
         };
         nested.push(Obligation::with_depth(
index aad3c37f84e5a783250e31ad60ad9d512a103c47..0f21813bc40ae1a85dfd1185f7199ecd2eec708a 100644 (file)
@@ -62,9 +62,8 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
 
         // The following *might* require a destructor: needs deeper inspection.
         ty::Dynamic(..)
-        | ty::Projection(..)
+        | ty::Alias(..)
         | ty::Param(_)
-        | ty::Opaque(..)
         | ty::Placeholder(..)
         | ty::Infer(_)
         | ty::Bound(..)
index 7ad532d8a34645544996dd1930fbf45284d9d1b7..c6ef13e185b2d7526e6870397a3932e451e6a49c 100644 (file)
@@ -205,7 +205,9 @@ fn try_fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
             // This is really important. While we *can* handle this, this has
             // severe performance implications for large opaque types with
             // late-bound regions. See `issue-88862` benchmark.
-            ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => {
+            ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. })
+                if !substs.has_escaping_bound_vars() =>
+            {
                 // Only normalize `impl Trait` outside of type inference, usually in codegen.
                 match self.param_env.reveal() {
                     Reveal::UserFacing => ty.try_super_fold_with(self),
@@ -242,7 +244,7 @@ fn try_fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
                 }
             }
 
-            ty::Projection(data) if !data.has_escaping_bound_vars() => {
+            ty::Alias(ty::Projection, data) if !data.has_escaping_bound_vars() => {
                 // This branch is just an optimization: when we don't have escaping bound vars,
                 // we don't need to replace them with placeholders (see branch below).
 
@@ -291,7 +293,7 @@ fn try_fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
                 }
             }
 
-            ty::Projection(data) => {
+            ty::Alias(ty::Projection, data) => {
                 // See note in `rustc_trait_selection::traits::project`
 
                 let tcx = self.infcx.tcx;
index bfa318787e546869e2c0efe8ebcbb679579feaf0..34b5fc4891eb36643e65c2412e8ac70330559e55 100644 (file)
@@ -26,7 +26,7 @@ pub(crate) fn update<'tcx, T>(
                 .kind()
                 .rebind(
                     // (*) binder moved here
-                    ty::PredicateKind::Clause(ty::Clause::Trait(tpred.with_self_type(infcx.tcx, new_self_ty)))
+                    ty::PredicateKind::Clause(ty::Clause::Trait(tpred.with_self_ty(infcx.tcx, new_self_ty)))
                 ),
         );
         // Don't report overflow errors. Otherwise equivalent to may_hold.
index e4b70f0d2ffa7afbfc54dbf7fdaa252400ef1226..c54d901e9b10aff43f7e9106632beef59ae3e495 100644 (file)
@@ -138,7 +138,7 @@ fn assemble_candidates_from_projected_tys(
         // Before we go into the whole placeholder thing, just
         // quickly check if the self-type is a projection at all.
         match obligation.predicate.skip_binder().trait_ref.self_ty().kind() {
-            ty::Projection(_) | ty::Opaque(..) => {}
+            ty::Alias(..) => {}
             ty::Infer(ty::TyVar(_)) => {
                 span_bug!(
                     obligation.cause.span,
@@ -394,7 +394,7 @@ fn assemble_candidates_from_auto_impls(
                     // still be provided by a manual implementation for
                     // this trait and type.
                 }
-                ty::Param(..) | ty::Projection(..) => {
+                ty::Param(..) | ty::Alias(ty::Projection, ..) => {
                     // In these cases, we don't know what the actual
                     // type is.  Therefore, we cannot break it down
                     // into its constituent types. So we don't
@@ -536,10 +536,7 @@ fn need_migrate_deref_output_trait_object(
             let ty = traits::normalize_projection_type(
                 self,
                 param_env,
-                ty::ProjectionTy {
-                    item_def_id: tcx.lang_items().deref_target()?,
-                    substs: trait_ref.substs,
-                },
+                tcx.mk_alias_ty(tcx.lang_items().deref_target()?, trait_ref.substs),
                 cause.clone(),
                 0,
                 // We're *intentionally* throwing these away,
@@ -737,13 +734,12 @@ fn assemble_const_destruct_candidates(
 
         let self_ty = self.infcx.shallow_resolve(obligation.self_ty());
         match self_ty.skip_binder().kind() {
-            ty::Opaque(..)
+            ty::Alias(..)
             | ty::Dynamic(..)
             | ty::Error(_)
             | ty::Bound(..)
             | ty::Param(_)
-            | ty::Placeholder(_)
-            | ty::Projection(_) => {
+            | ty::Placeholder(_) => {
                 // We don't know if these are `~const Destruct`, at least
                 // not structurally... so don't push a candidate.
             }
@@ -829,8 +825,7 @@ fn assemble_candidate_for_tuple(
             | ty::Generator(_, _, _)
             | ty::GeneratorWitness(_)
             | ty::Never
-            | ty::Projection(_)
-            | ty::Opaque(_, _)
+            | ty::Alias(..)
             | ty::Param(_)
             | ty::Bound(_, _)
             | ty::Error(_)
index fda415155c469b556c3206ad8223431625388eaa..f6fe71fbd4f889ce18c08f0c08b890b4939363c1 100644 (file)
@@ -155,8 +155,7 @@ fn confirm_projection_candidate(
         let placeholder_self_ty = placeholder_trait_predicate.self_ty();
         let placeholder_trait_predicate = ty::Binder::dummy(placeholder_trait_predicate);
         let (def_id, substs) = match *placeholder_self_ty.kind() {
-            ty::Projection(proj) => (proj.item_def_id, proj.substs),
-            ty::Opaque(def_id, substs) => (def_id, substs),
+            ty::Alias(_, ty::AliasTy { def_id, substs, .. }) => (def_id, substs),
             _ => bug!("projection candidate for unexpected type: {:?}", placeholder_self_ty),
         };
 
@@ -184,7 +183,7 @@ fn confirm_projection_candidate(
                 .map_err(|_| Unimplemented)
         })?);
 
-        if let ty::Projection(..) = placeholder_self_ty.kind() {
+        if let ty::Alias(ty::Projection, ..) = placeholder_self_ty.kind() {
             let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, substs).predicates;
             debug!(?predicates, "projection predicates");
             for predicate in predicates {
@@ -1279,7 +1278,7 @@ fn confirm_const_destruct_candidate(
 
                 // If we have a projection type, make sure to normalize it so we replace it
                 // with a fresh infer variable
-                ty::Projection(..) => {
+                ty::Alias(ty::Projection, ..) => {
                     let predicate = normalize_with_depth_to(
                         self,
                         obligation.param_env,
index 035deb61639817c57d897a9ffdcb75db304aacaa..792933096b15c61a731b3a2e1cee0d87c1347926 100644 (file)
@@ -1595,8 +1595,7 @@ fn match_projection_obligation_against_definition_bounds(
 
         let tcx = self.infcx.tcx;
         let (def_id, substs) = match *placeholder_trait_predicate.trait_ref.self_ty().kind() {
-            ty::Projection(ref data) => (data.item_def_id, data.substs),
-            ty::Opaque(def_id, substs) => (def_id, substs),
+            ty::Alias(_, ty::AliasTy { def_id, substs, .. }) => (def_id, substs),
             _ => {
                 span_bug!(
                     obligation.cause.span,
@@ -1745,7 +1744,7 @@ pub(super) fn match_projection_projections(
             });
 
         if is_match {
-            let generics = self.tcx().generics_of(obligation.predicate.item_def_id);
+            let generics = self.tcx().generics_of(obligation.predicate.def_id);
             // FIXME(generic-associated-types): Addresses aggressive inference in #92917.
             // If this type is a GAT, and of the GAT substs resolve to something new,
             // that means that we must have newly inferred something about the GAT.
@@ -2067,7 +2066,7 @@ fn sized_conditions(
                 }))
             }
 
-            ty::Projection(_) | ty::Param(_) | ty::Opaque(..) => None,
+            ty::Alias(..) | ty::Param(_) => None,
             ty::Infer(ty::TyVar(_)) => Ambiguous,
 
             ty::Placeholder(..)
@@ -2167,7 +2166,7 @@ fn copy_clone_conditions(
                 }
             }
 
-            ty::Adt(..) | ty::Projection(..) | ty::Param(..) | ty::Opaque(..) => {
+            ty::Adt(..) | ty::Alias(..) | ty::Param(..) => {
                 // Fallback to whatever user-defined impls exist in this case.
                 None
             }
@@ -2220,7 +2219,7 @@ fn constituent_types_for_ty(
             | ty::Dynamic(..)
             | ty::Param(..)
             | ty::Foreign(..)
-            | ty::Projection(..)
+            | ty::Alias(ty::Projection, ..)
             | ty::Bound(..)
             | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
                 bug!("asked to assemble constituent types of unexpected type: {:?}", t);
@@ -2260,7 +2259,7 @@ fn constituent_types_for_ty(
                 t.rebind(def.all_fields().map(|f| f.ty(self.tcx(), substs)).collect())
             }
 
-            ty::Opaque(def_id, substs) => {
+            ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
                 // We can resolve the `impl Trait` to its concrete type,
                 // which enforces a DAG between the functions requiring
                 // the auto trait bounds in question.
index 4dc08e0f9dab0da99be2c049b08e755c9f7c5b04..892a7afd799c73c64ff0a5c6ba5bbf156b68fa9e 100644 (file)
@@ -95,10 +95,7 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
             ty::Foreign(_) => {
                 return ControlFlow::Break(ty);
             }
-            ty::Opaque(..) => {
-                return ControlFlow::Break(ty);
-            }
-            ty::Projection(..) => {
+            ty::Alias(..) => {
                 return ControlFlow::Break(ty);
             }
             ty::Closure(..) => {
index fe2d53a7aad73ce020796f7bf446285d953c7426..0e0a883d9f5908ffcf0dfe5c41a34daa5c1639e2 100644 (file)
@@ -234,9 +234,9 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>(
             // projection coming from another associated type. See
             // `src/test/ui/associated-types/point-at-type-on-obligation-failure.rs` and
             // `traits-assoc-type-in-supertrait-bad.rs`.
-            if let Some(ty::Projection(projection_ty)) = proj.term.ty().map(|ty| ty.kind())
+            if let Some(ty::Alias(ty::Projection, projection_ty)) = proj.term.ty().map(|ty| ty.kind())
                 && let Some(&impl_item_id) =
-                    tcx.impl_item_implementor_ids(impl_def_id).get(&projection_ty.item_def_id)
+                    tcx.impl_item_implementor_ids(impl_def_id).get(&projection_ty.def_id)
                 && let Some(impl_item_span) = items
                     .iter()
                     .find(|item| item.id.owner_id.to_def_id() == impl_item_id)
@@ -249,9 +249,9 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>(
             // An associated item obligation born out of the `trait` failed to be met. An example
             // can be seen in `ui/associated-types/point-at-type-on-obligation-failure-2.rs`.
             debug!("extended_cause_with_original_assoc_item_obligation trait proj {:?}", pred);
-            if let ty::Projection(ty::ProjectionTy { item_def_id, .. }) = *pred.self_ty().kind()
+            if let ty::Alias(ty::Projection, ty::AliasTy { def_id, .. }) = *pred.self_ty().kind()
                 && let Some(&impl_item_id) =
-                    tcx.impl_item_implementor_ids(impl_def_id).get(&item_def_id)
+                    tcx.impl_item_implementor_ids(impl_def_id).get(&def_id)
                 && let Some(impl_item_span) = items
                     .iter()
                     .find(|item| item.id.owner_id.to_def_id() == impl_item_id)
@@ -369,7 +369,7 @@ fn compute_trait_pred(&mut self, trait_pred: &ty::TraitPredicate<'tcx>, elaborat
 
     /// Pushes the obligations required for `trait_ref::Item` to be WF
     /// into `self.out`.
-    fn compute_projection(&mut self, data: ty::ProjectionTy<'tcx>) {
+    fn compute_projection(&mut self, data: ty::AliasTy<'tcx>) {
         // A projection is well-formed if
         //
         // (a) its predicates hold (*)
@@ -392,7 +392,7 @@ fn compute_projection(&mut self, data: ty::ProjectionTy<'tcx>) {
         //     `i32: Copy`
         // ]
         // Projection types do not require const predicates.
-        let obligations = self.nominal_obligations_without_const(data.item_def_id, data.substs);
+        let obligations = self.nominal_obligations_without_const(data.def_id, data.substs);
         self.out.extend(obligations);
 
         let tcx = self.tcx();
@@ -558,7 +558,7 @@ fn compute(&mut self, arg: GenericArg<'tcx>) {
                     // Simple cases that are WF if their type args are WF.
                 }
 
-                ty::Projection(data) => {
+                ty::Alias(ty::Projection, data) => {
                     walker.skip_current_subtree(); // Subtree handled by compute_projection.
                     self.compute_projection(data);
                 }
@@ -650,12 +650,12 @@ fn compute(&mut self, arg: GenericArg<'tcx>) {
                     // types appearing in the fn signature
                 }
 
-                ty::Opaque(did, substs) => {
+                ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
                     // All of the requirements on type parameters
                     // have already been checked for `impl Trait` in
                     // return position. We do need to check type-alias-impl-trait though.
-                    if ty::is_impl_trait_defn(self.tcx, did).is_none() {
-                        let obligations = self.nominal_obligations(did, substs);
+                    if ty::is_impl_trait_defn(self.tcx, def_id).is_none() {
+                        let obligations = self.nominal_obligations(def_id, substs);
                         self.out.extend(obligations);
                     }
                 }
index 344c8b93c170489dfb726ff7b12eabc1cb47025b..bc4a52c5040d1fa5f2647d6acd6c7105a814009c 100644 (file)
@@ -432,7 +432,10 @@ fn impl_provided_for(
                         (ast::Mutability::Not, chalk_ir::Mutability::Not) => true,
                     }
                 }
-                (&ty::Opaque(def_id, ..), OpaqueType(opaque_ty_id, ..)) => def_id == opaque_ty_id.0,
+                (
+                    &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }),
+                    OpaqueType(opaque_ty_id, ..),
+                ) => def_id == opaque_ty_id.0,
                 (&ty::FnDef(def_id, ..), FnDef(fn_def_id, ..)) => def_id == fn_def_id.0,
                 (&ty::Str, Str) => true,
                 (&ty::Never, Never) => true,
@@ -786,7 +789,7 @@ fn fold_binder<T: TypeFoldable<'tcx>>(
     }
 
     fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
-        if let ty::Opaque(def_id, substs) = *ty.kind() {
+        if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) = *ty.kind() {
             if def_id == self.opaque_ty_id.0 && substs == self.identity_substs {
                 return self.tcx.mk_ty(ty::Bound(
                     self.binder_index,
index c4ab86e9e9bab343d8b96b27cc0901ffbd52a607..9712abb708f2762c61c6c2b0b922e642c681fb83 100644 (file)
@@ -66,15 +66,6 @@ fn lower_into(self, interner: RustInterner<'tcx>) -> SubstsRef<'tcx> {
     }
 }
 
-impl<'tcx> LowerInto<'tcx, chalk_ir::AliasTy<RustInterner<'tcx>>> for ty::ProjectionTy<'tcx> {
-    fn lower_into(self, interner: RustInterner<'tcx>) -> chalk_ir::AliasTy<RustInterner<'tcx>> {
-        chalk_ir::AliasTy::Projection(chalk_ir::ProjectionTy {
-            associated_ty_id: chalk_ir::AssocTypeId(self.item_def_id),
-            substitution: self.substs.lower_into(interner),
-        })
-    }
-}
-
 impl<'tcx> LowerInto<'tcx, chalk_ir::InEnvironment<chalk_ir::Goal<RustInterner<'tcx>>>>
     for ChalkEnvironmentAndGoal<'tcx>
 {
@@ -255,7 +246,10 @@ fn lower_into(self, interner: RustInterner<'tcx>) -> chalk_ir::AliasEq<RustInter
         // FIXME(associated_const_equality): teach chalk about terms for alias eq.
         chalk_ir::AliasEq {
             ty: self.term.ty().unwrap().lower_into(interner),
-            alias: self.projection_ty.lower_into(interner),
+            alias: chalk_ir::AliasTy::Projection(chalk_ir::ProjectionTy {
+                associated_ty_id: chalk_ir::AssocTypeId(self.projection_ty.def_id),
+                substitution: self.projection_ty.substs.lower_into(interner),
+            }),
         }
     }
 }
@@ -353,8 +347,13 @@ fn lower_into(self, interner: RustInterner<'tcx>) -> chalk_ir::Ty<RustInterner<'
             ty::Tuple(types) => {
                 chalk_ir::TyKind::Tuple(types.len(), types.as_substs().lower_into(interner))
             }
-            ty::Projection(proj) => chalk_ir::TyKind::Alias(proj.lower_into(interner)),
-            ty::Opaque(def_id, substs) => {
+            ty::Alias(ty::Projection, ty::AliasTy { def_id, substs, .. }) => {
+                chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Projection(chalk_ir::ProjectionTy {
+                    associated_ty_id: chalk_ir::AssocTypeId(def_id),
+                    substitution: substs.lower_into(interner),
+                }))
+            }
+            ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
                 chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Opaque(chalk_ir::OpaqueTy {
                     opaque_ty_id: chalk_ir::OpaqueTyId(def_id),
                     substitution: substs.lower_into(interner),
@@ -442,13 +441,14 @@ fn lower_into(self, interner: RustInterner<'tcx>) -> Ty<'tcx> {
                 mutbl.lower_into(interner),
             ),
             TyKind::Str => ty::Str,
-            TyKind::OpaqueType(opaque_ty, substitution) => {
-                ty::Opaque(opaque_ty.0, substitution.lower_into(interner))
-            }
-            TyKind::AssociatedType(assoc_ty, substitution) => ty::Projection(ty::ProjectionTy {
-                substs: substitution.lower_into(interner),
-                item_def_id: assoc_ty.0,
-            }),
+            TyKind::OpaqueType(opaque_ty, substitution) => ty::Alias(
+                ty::Opaque,
+                interner.tcx.mk_alias_ty(opaque_ty.0, substitution.lower_into(interner)),
+            ),
+            TyKind::AssociatedType(assoc_ty, substitution) => ty::Alias(
+                ty::Projection,
+                interner.tcx.mk_alias_ty(assoc_ty.0, substitution.lower_into(interner)),
+            ),
             TyKind::Foreign(def_id) => ty::Foreign(def_id.0),
             TyKind::Error => return interner.tcx.ty_error(),
             TyKind::Placeholder(placeholder) => ty::Placeholder(ty::Placeholder {
@@ -456,13 +456,20 @@ fn lower_into(self, interner: RustInterner<'tcx>) -> Ty<'tcx> {
                 name: ty::BoundVar::from_usize(placeholder.idx),
             }),
             TyKind::Alias(alias_ty) => match alias_ty {
-                chalk_ir::AliasTy::Projection(projection) => ty::Projection(ty::ProjectionTy {
-                    item_def_id: projection.associated_ty_id.0,
-                    substs: projection.substitution.lower_into(interner),
-                }),
-                chalk_ir::AliasTy::Opaque(opaque) => {
-                    ty::Opaque(opaque.opaque_ty_id.0, opaque.substitution.lower_into(interner))
-                }
+                chalk_ir::AliasTy::Projection(projection) => ty::Alias(
+                    ty::Projection,
+                    interner.tcx.mk_alias_ty(
+                        projection.associated_ty_id.0,
+                        projection.substitution.lower_into(interner),
+                    ),
+                ),
+                chalk_ir::AliasTy::Opaque(opaque) => ty::Alias(
+                    ty::Opaque,
+                    interner.tcx.mk_alias_ty(
+                        opaque.opaque_ty_id.0,
+                        opaque.substitution.lower_into(interner),
+                    ),
+                ),
             },
             TyKind::Function(_quantified_ty) => unimplemented!(),
             TyKind::BoundVar(_bound) => ty::Bound(
@@ -688,7 +695,7 @@ fn lower_into(
                     binders.clone(),
                     chalk_ir::WhereClause::AliasEq(chalk_ir::AliasEq {
                         alias: chalk_ir::AliasTy::Projection(chalk_ir::ProjectionTy {
-                            associated_ty_id: chalk_ir::AssocTypeId(predicate.item_def_id),
+                            associated_ty_id: chalk_ir::AssocTypeId(predicate.def_id),
                             substitution: interner
                                 .tcx
                                 .mk_substs_trait(self_ty, predicate.substs)
@@ -844,7 +851,7 @@ fn lower_into(
         let (trait_ref, own_substs) = self.projection_ty.trait_ref_and_own_substs(interner.tcx);
         chalk_solve::rust_ir::AliasEqBound {
             trait_bound: trait_ref.lower_into(interner),
-            associated_ty_id: chalk_ir::AssocTypeId(self.projection_ty.item_def_id),
+            associated_ty_id: chalk_ir::AssocTypeId(self.projection_ty.def_id),
             parameters: own_substs.iter().map(|arg| arg.lower_into(interner)).collect(),
             value: self.term.ty().unwrap().lower_into(interner),
         }
index 66ab742f15782ae6689314daebb663653635eb41..3f661ce69235caaf0cb69c8df90277e9fdbfb0be 100644 (file)
@@ -112,7 +112,7 @@ fn dropck_outlives<'tcx>(
 
                     // A projection that we couldn't resolve - it
                     // might have a destructor.
-                    ty::Projection(..) | ty::Opaque(..) => {
+                    ty::Alias(..) => {
                         result.kinds.push(ty.into());
                     }
 
@@ -268,7 +268,7 @@ fn dtorck_constraint_for_ty<'tcx>(
         }
 
         // Types that can't be resolved. Pass them forward.
-        ty::Projection(..) | ty::Opaque(..) | ty::Param(..) => {
+        ty::Alias(..) | ty::Param(..) => {
             constraints.dtorck_types.push(ty);
         }
 
index c6f2b16ca210226db5b9482d7233e87676418292..2da98d3342984bb7231514d46caeec899e442075 100644 (file)
@@ -44,7 +44,13 @@ fn inner_resolve_instance<'tcx>(
 
     let result = if let Some(trait_def_id) = tcx.trait_of_item(def.did) {
         debug!(" => associated item, attempting to find impl in param_env {:#?}", param_env);
-        resolve_associated_item(tcx, def.did, param_env, trait_def_id, substs)
+        resolve_associated_item(
+            tcx,
+            def.did,
+            param_env,
+            trait_def_id,
+            tcx.normalize_erasing_regions(param_env, substs),
+        )
     } else {
         let ty = tcx.type_of(def.def_id_for_type_of());
         let item_type = tcx.subst_and_normalize_erasing_regions(substs, param_env, ty);
index f4672a70072b2b30ce8435d350d898bfa2e8c4c3..c761a4dbe4500bfbc78b9576bbfabb873a4de662 100644 (file)
@@ -444,7 +444,7 @@ fn layout_of_uncached<'tcx>(
         }
 
         // Types with no meaningful known layout.
-        ty::Projection(_) | ty::Opaque(..) => {
+        ty::Alias(..) => {
             // NOTE(eddyb) `layout_of` query should've normalized these away,
             // if that was possible, so there's no reason to try again here.
             return Err(LayoutError::Unknown(ty));
@@ -919,7 +919,7 @@ fn variant_info_for_generator<'tcx>(
     def_id: DefId,
     substs: ty::SubstsRef<'tcx>,
 ) -> (Vec<VariantInfo>, Option<Size>) {
-    let Variants::Multiple { tag, ref tag_encoding, .. } = layout.variants else {
+    let Variants::Multiple { tag, ref tag_encoding, tag_field, .. } = layout.variants else {
         return (vec![], None);
     };
 
@@ -975,12 +975,28 @@ fn variant_info_for_generator<'tcx>(
             if variant_size == Size::ZERO {
                 variant_size = upvars_size;
             }
-            // We need to add the discriminant size back into min_size, since it is subtracted
-            // later during printing.
-            variant_size += match tag_encoding {
-                TagEncoding::Direct => tag.size(cx),
-                _ => Size::ZERO,
-            };
+
+            // This `if` deserves some explanation.
+            //
+            // The layout code has a choice of where to place the discriminant of this generator.
+            // If the discriminant of the generator is placed early in the layout (before the
+            // variant's own fields), then it'll implicitly be counted towards the size of the
+            // variant, since we use the maximum offset to calculate size.
+            //    (side-note: I know this is a bit problematic given upvars placement, etc).
+            //
+            // This is important, since the layout printing code always subtracts this discriminant
+            // size from the variant size if the struct is "enum"-like, so failing to account for it
+            // will either lead to numerical underflow, or an underreported variant size...
+            //
+            // However, if the discriminant is placed past the end of the variant, then we need
+            // to factor in the size of the discriminant manually. This really should be refactored
+            // better, but this "works" for now.
+            if layout.fields.offset(tag_field) >= variant_size {
+                variant_size += match tag_encoding {
+                    TagEncoding::Direct => tag.size(cx),
+                    _ => Size::ZERO,
+                };
+            }
 
             VariantInfo {
                 name: Some(Symbol::intern(&ty::GeneratorSubsts::variant_name(variant_idx))),
index 024dcd591bd77d68d321bb27a7016ee9b1b544e7..0df060fc5fb71eae719d70216303c22e90f8af17 100644 (file)
@@ -152,7 +152,7 @@ fn next(&mut self) -> Option<NeedsDropResult<Ty<'tcx>>> {
                             queue_type(self, required);
                         }
                     }
-                    ty::Array(..) | ty::Opaque(..) | ty::Projection(..) | ty::Param(_) => {
+                    ty::Array(..) | ty::Alias(..) | ty::Param(_) => {
                         if ty == component {
                             // Return the type to the caller: they may be able
                             // to normalize further than we can.
index 5fc9bcac1b19e35bcb55098d7eb06c273dd44dc4..5279fc69a31b3cb6a72b1cd2e665efff89fbd316 100644 (file)
@@ -37,7 +37,7 @@ fn sized_constraint_for_ty<'tcx>(
                 .collect()
         }
 
-        Projection(..) | Opaque(..) => {
+        Alias(..) => {
             // must calculate explicitly.
             // FIXME: consider special-casing always-Sized projections
             vec![ty]
index e3f7a1bd033cea39b7ed706a45ed49ce7e8474e6..c992dbccd62d5656439cc6ca72578f8656200075 100644 (file)
@@ -42,7 +42,7 @@ pub trait Interner {
     type ListBinderExistentialPredicate: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
     type BinderListTy: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
     type ListTy: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
-    type ProjectionTy: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
+    type AliasTy: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
     type ParamTy: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
     type BoundTy: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
     type PlaceholderType: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
index 9aa2be124e294871f24d11a82d2d168755d5fc00..f30ae82d7cdd2b4fd4d596c0e207f016efa4aada 100644 (file)
 use rustc_serialize::{Decodable, Decoder, Encodable};
 
 /// Specifies how a trait object is represented.
-#[derive(
-    Clone,
-    Copy,
-    PartialEq,
-    Eq,
-    PartialOrd,
-    Ord,
-    Hash,
-    Debug,
-    Encodable,
-    Decodable,
-    HashStable_Generic
-)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+#[derive(Encodable, Decodable, HashStable_Generic)]
 pub enum DynKind {
     /// An unsized `dyn Trait` object
     Dyn,
@@ -46,6 +35,13 @@ pub enum DynKind {
     DynStar,
 }
 
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+#[derive(Encodable, Decodable, HashStable_Generic)]
+pub enum AliasKind {
+    Projection,
+    Opaque,
+}
+
 /// Defines the kinds of types used by the type system.
 ///
 /// Types written by the user start out as `hir::TyKind` and get
@@ -170,21 +166,8 @@ pub enum TyKind<I: Interner> {
     /// A tuple type. For example, `(i32, bool)`.
     Tuple(I::ListTy),
 
-    /// The projection of an associated type. For example,
-    /// `<T as Trait<..>>::N`.
-    Projection(I::ProjectionTy),
-
-    /// Opaque (`impl Trait`) type found in a return type.
-    ///
-    /// The `DefId` comes either from
-    /// * the `impl Trait` ast::Ty node,
-    /// * or the `type Foo = impl Trait` declaration
-    ///
-    /// For RPIT the substitutions are for the generics of the function,
-    /// while for TAIT it is used for the generic parameters of the alias.
-    ///
-    /// During codegen, `tcx.type_of(def_id)` can be used to get the underlying type.
-    Opaque(I::DefId, I::SubstsRef),
+    /// A projection or opaque type. Both of these types
+    Alias(AliasKind, I::AliasTy),
 
     /// A type parameter; for example, `T` in `fn f<T>(x: T) {}`.
     Param(I::ParamTy),
@@ -252,13 +235,12 @@ const fn tykind_discriminant<I: Interner>(value: &TyKind<I>) -> usize {
         GeneratorWitness(_) => 17,
         Never => 18,
         Tuple(_) => 19,
-        Projection(_) => 20,
-        Opaque(_, _) => 21,
-        Param(_) => 22,
-        Bound(_, _) => 23,
-        Placeholder(_) => 24,
-        Infer(_) => 25,
-        Error(_) => 26,
+        Alias(_, _) => 20,
+        Param(_) => 21,
+        Bound(_, _) => 22,
+        Placeholder(_) => 23,
+        Infer(_) => 24,
+        Error(_) => 25,
     }
 }
 
@@ -268,9 +250,9 @@ fn clone(&self) -> Self {
         match self {
             Bool => Bool,
             Char => Char,
-            Int(i) => Int(i.clone()),
-            Uint(u) => Uint(u.clone()),
-            Float(f) => Float(f.clone()),
+            Int(i) => Int(*i),
+            Uint(u) => Uint(*u),
+            Float(f) => Float(*f),
             Adt(d, s) => Adt(d.clone(), s.clone()),
             Foreign(d) => Foreign(d.clone()),
             Str => Str,
@@ -280,16 +262,15 @@ fn clone(&self) -> Self {
             Ref(r, t, m) => Ref(r.clone(), t.clone(), m.clone()),
             FnDef(d, s) => FnDef(d.clone(), s.clone()),
             FnPtr(s) => FnPtr(s.clone()),
-            Dynamic(p, r, repr) => Dynamic(p.clone(), r.clone(), repr.clone()),
+            Dynamic(p, r, repr) => Dynamic(p.clone(), r.clone(), *repr),
             Closure(d, s) => Closure(d.clone(), s.clone()),
             Generator(d, s, m) => Generator(d.clone(), s.clone(), m.clone()),
             GeneratorWitness(g) => GeneratorWitness(g.clone()),
             Never => Never,
             Tuple(t) => Tuple(t.clone()),
-            Projection(p) => Projection(p.clone()),
-            Opaque(d, s) => Opaque(d.clone(), s.clone()),
+            Alias(k, p) => Alias(*k, p.clone()),
             Param(p) => Param(p.clone()),
-            Bound(d, b) => Bound(d.clone(), b.clone()),
+            Bound(d, b) => Bound(*d, b.clone()),
             Placeholder(p) => Placeholder(p.clone()),
             Infer(t) => Infer(t.clone()),
             Error(e) => Error(e.clone()),
@@ -323,8 +304,7 @@ fn eq(&self, other: &TyKind<I>) -> bool {
                 }
                 (GeneratorWitness(a_g), GeneratorWitness(b_g)) => a_g == b_g,
                 (Tuple(a_t), Tuple(b_t)) => a_t == b_t,
-                (Projection(a_p), Projection(b_p)) => a_p == b_p,
-                (Opaque(a_d, a_s), Opaque(b_d, b_s)) => a_d == b_d && a_s == b_s,
+                (Alias(a_i, a_p), Alias(b_i, b_p)) => a_i == b_i && a_p == b_p,
                 (Param(a_p), Param(b_p)) => a_p == b_p,
                 (Bound(a_d, a_b), Bound(b_d, b_b)) => a_d == b_d && a_b == b_b,
                 (Placeholder(a_p), Placeholder(b_p)) => a_p == b_p,
@@ -381,8 +361,7 @@ fn cmp(&self, other: &TyKind<I>) -> Ordering {
                 }
                 (GeneratorWitness(a_g), GeneratorWitness(b_g)) => a_g.cmp(b_g),
                 (Tuple(a_t), Tuple(b_t)) => a_t.cmp(b_t),
-                (Projection(a_p), Projection(b_p)) => a_p.cmp(b_p),
-                (Opaque(a_d, a_s), Opaque(b_d, b_s)) => a_d.cmp(b_d).then_with(|| a_s.cmp(b_s)),
+                (Alias(a_i, a_p), Alias(b_i, b_p)) => a_i.cmp(b_i).then_with(|| a_p.cmp(b_p)),
                 (Param(a_p), Param(b_p)) => a_p.cmp(b_p),
                 (Bound(a_d, a_b), Bound(b_d, b_b)) => a_d.cmp(b_d).then_with(|| a_b.cmp(b_b)),
                 (Placeholder(a_p), Placeholder(b_p)) => a_p.cmp(b_p),
@@ -443,10 +422,9 @@ fn hash<__H: hash::Hasher>(&self, state: &mut __H) -> () {
             }
             GeneratorWitness(g) => g.hash(state),
             Tuple(t) => t.hash(state),
-            Projection(p) => p.hash(state),
-            Opaque(d, s) => {
-                d.hash(state);
-                s.hash(state)
+            Alias(i, p) => {
+                i.hash(state);
+                p.hash(state);
             }
             Param(p) => p.hash(state),
             Bound(d, b) => {
@@ -485,8 +463,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
             GeneratorWitness(g) => f.debug_tuple_field1_finish("GeneratorWitness", g),
             Never => f.write_str("Never"),
             Tuple(t) => f.debug_tuple_field1_finish("Tuple", t),
-            Projection(p) => f.debug_tuple_field1_finish("Projection", p),
-            Opaque(d, s) => f.debug_tuple_field2_finish("Opaque", d, s),
+            Alias(i, a) => f.debug_tuple_field2_finish("Alias", i, a),
             Param(p) => f.debug_tuple_field1_finish("Param", p),
             Bound(d, b) => f.debug_tuple_field2_finish("Bound", d, b),
             Placeholder(p) => f.debug_tuple_field1_finish("Placeholder", p),
@@ -513,7 +490,7 @@ impl<I: Interner, E: TyEncoder> Encodable<E> for TyKind<I>
     I::ListBinderExistentialPredicate: Encodable<E>,
     I::BinderListTy: Encodable<E>,
     I::ListTy: Encodable<E>,
-    I::ProjectionTy: Encodable<E>,
+    I::AliasTy: Encodable<E>,
     I::ParamTy: Encodable<E>,
     I::BoundTy: Encodable<E>,
     I::PlaceholderType: Encodable<E>,
@@ -586,13 +563,10 @@ fn encode(&self, e: &mut E) {
             Tuple(substs) => e.emit_enum_variant(disc, |e| {
                 substs.encode(e);
             }),
-            Projection(p) => e.emit_enum_variant(disc, |e| {
+            Alias(k, p) => e.emit_enum_variant(disc, |e| {
+                k.encode(e);
                 p.encode(e);
             }),
-            Opaque(def_id, substs) => e.emit_enum_variant(disc, |e| {
-                def_id.encode(e);
-                substs.encode(e);
-            }),
             Param(p) => e.emit_enum_variant(disc, |e| {
                 p.encode(e);
             }),
@@ -630,8 +604,9 @@ impl<I: Interner, D: TyDecoder<I = I>> Decodable<D> for TyKind<I>
     I::ListBinderExistentialPredicate: Decodable<D>,
     I::BinderListTy: Decodable<D>,
     I::ListTy: Decodable<D>,
-    I::ProjectionTy: Decodable<D>,
+    I::AliasTy: Decodable<D>,
     I::ParamTy: Decodable<D>,
+    I::AliasTy: Decodable<D>,
     I::BoundTy: Decodable<D>,
     I::PlaceholderType: Decodable<D>,
     I::InferTy: Decodable<D>,
@@ -660,13 +635,12 @@ fn decode(d: &mut D) -> Self {
             17 => GeneratorWitness(Decodable::decode(d)),
             18 => Never,
             19 => Tuple(Decodable::decode(d)),
-            20 => Projection(Decodable::decode(d)),
-            21 => Opaque(Decodable::decode(d), Decodable::decode(d)),
-            22 => Param(Decodable::decode(d)),
-            23 => Bound(Decodable::decode(d), Decodable::decode(d)),
-            24 => Placeholder(Decodable::decode(d)),
-            25 => Infer(Decodable::decode(d)),
-            26 => Error(Decodable::decode(d)),
+            20 => Alias(Decodable::decode(d), Decodable::decode(d)),
+            21 => Param(Decodable::decode(d)),
+            22 => Bound(Decodable::decode(d), Decodable::decode(d)),
+            23 => Placeholder(Decodable::decode(d)),
+            24 => Infer(Decodable::decode(d)),
+            25 => Error(Decodable::decode(d)),
             _ => panic!(
                 "{}",
                 format!(
@@ -695,7 +669,7 @@ impl<CTX: HashStableContext, I: Interner> HashStable<CTX> for TyKind<I>
     I::Mutability: HashStable<CTX>,
     I::BinderListTy: HashStable<CTX>,
     I::ListTy: HashStable<CTX>,
-    I::ProjectionTy: HashStable<CTX>,
+    I::AliasTy: HashStable<CTX>,
     I::BoundTy: HashStable<CTX>,
     I::ParamTy: HashStable<CTX>,
     I::PlaceholderType: HashStable<CTX>,
@@ -772,13 +746,10 @@ fn hash_stable(
             Tuple(substs) => {
                 substs.hash_stable(__hcx, __hasher);
             }
-            Projection(p) => {
+            Alias(k, p) => {
+                k.hash_stable(__hcx, __hasher);
                 p.hash_stable(__hcx, __hasher);
             }
-            Opaque(def_id, substs) => {
-                def_id.hash_stable(__hcx, __hasher);
-                substs.hash_stable(__hcx, __hasher);
-            }
             Param(p) => {
                 p.hash_stable(__hcx, __hasher);
             }
@@ -965,7 +936,7 @@ impl<I: Interner> Clone for RegionKind<I> {
     fn clone(&self) -> Self {
         match self {
             ReEarlyBound(r) => ReEarlyBound(r.clone()),
-            ReLateBound(d, r) => ReLateBound(d.clone(), r.clone()),
+            ReLateBound(d, r) => ReLateBound(*d, r.clone()),
             ReFree(r) => ReFree(r.clone()),
             ReStatic => ReStatic,
             ReVar(r) => ReVar(r.clone()),
index fdd56cb4eaa8e462dab96f6816813b9812df2f81..4a8302ee404c109117d56b4e43ee7c7b8ad4f73c 100644 (file)
@@ -26,7 +26,7 @@
 /// to be modified, it can additionally implement [`BorrowMut<T>`].
 ///
 /// Further, when providing implementations for additional traits, it needs
-/// to be considered whether they should behave identical to those of the
+/// to be considered whether they should behave identically to those of the
 /// underlying type as a consequence of acting as a representation of that
 /// underlying type. Generic code typically uses `Borrow<T>` when it relies
 /// on the identical behavior of these additional trait implementations.
index 83c7e8977e9f3e22e842bef6a0581afe7be174a9..1cdee992137daebebe8cafa38c4786400d46e9fe 100644 (file)
@@ -1829,6 +1829,7 @@ fn by_ref(&mut self) -> &mut Self
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[must_use = "if you really need to exhaust the iterator, consider `.for_each(drop)` instead"]
+    #[cfg_attr(not(test), rustc_diagnostic_item = "iterator_collect_fn")]
     fn collect<B: FromIterator<Self::Item>>(self) -> B
     where
         Self: Sized,
index 505d964e518d7d7ffc1fd9fc66d673588a715429..39462dca4ff3ea46b1f7c8ecf7216eb9b34b624a 100644 (file)
 //! }
 //! ```
 //!
+//! # The question mark operator, `?`
+//!
+//! Similar to the [`Result`] type, when writing code that calls many functions that return the
+//! [`Option`] type, handling `Some`/`None` can be tedious. The question mark
+//! operator, [`?`], hides some of the boilerplate of propagating values
+//! up the call stack.
+//!
+//! It replaces this:
+//!
+//! ```
+//! # #![allow(dead_code)]
+//! fn add_last_numbers(stack: &mut Vec<i32>) -> Option<i32> {
+//!     let a = stack.pop();
+//!     let b = stack.pop();
+//!
+//!     match (a, b) {
+//!         (Some(x), Some(y)) => Some(x + y),
+//!         _ => None,
+//!     }
+//! }
+//!
+//! ```
+//!
+//! With this:
+//!
+//! ```
+//! # #![allow(dead_code)]
+//! fn add_last_numbers(stack: &mut Vec<i32>) -> Option<i32> {
+//!     Some(stack.pop()? + stack.pop()?)
+//! }
+//! ```
+//!
+//! *It's much nicer!*
+//!
+//! Ending the expression with [`?`] will result in the [`Some`]'s unwrapped value, unless the
+//! result is [`None`], in which case [`None`] is returned early from the enclosing function.
+//!
+//! [`?`] can be used in functions that return [`Option`] because of the
+//! early return of [`None`] that it provides.
+//!
+//! [`?`]: crate::ops::Try
+//! [`Some`]: Some
+//! [`None`]: None
+//!
 //! # Representation
 //!
 //! Rust guarantees to optimize the following types `T` such that
index 3f33c5fd6ca36fd7d78d04536cfe47c49cf9e0a1..f00c40f35d584765176c7c46a708d993bb240326 100644 (file)
 //!
 //! *It's much nicer!*
 //!
-//! Ending the expression with [`?`] will result in the unwrapped
-//! success ([`Ok`]) value, unless the result is [`Err`], in which case
-//! [`Err`] is returned early from the enclosing function.
+//! Ending the expression with [`?`] will result in the [`Ok`]'s unwrapped value, unless the result
+//! is [`Err`], in which case [`Err`] is returned early from the enclosing function.
 //!
-//! [`?`] can only be used in functions that return [`Result`] because of the
+//! [`?`] can be used in functions that return [`Result`] because of the
 //! early return of [`Err`] that it provides.
 //!
 //! [`expect`]: Result::expect
index c65c275000ce82bdf56d7e103a9b08aa0e9604d3..301ad41c96634407ff2c6e3791542f69a7743bab 100644 (file)
@@ -138,7 +138,7 @@ pub const fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T> {
         unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().inner) }
     }
 
-    /// Build a _mutable_ references to an `Exclusive<T>` from
+    /// Build a _mutable_ reference to an `Exclusive<T>` from
     /// a _mutable_ reference to a `T`. This allows you to skip
     /// building an `Exclusive` with [`Exclusive::new`].
     #[unstable(feature = "exclusive_wrapper", issue = "98407")]
@@ -149,7 +149,7 @@ pub const fn from_mut(r: &'_ mut T) -> &'_ mut Exclusive<T> {
         unsafe { &mut *(r as *mut T as *mut Exclusive<T>) }
     }
 
-    /// Build a _pinned mutable_ references to an `Exclusive<T>` from
+    /// Build a _pinned mutable_ reference to an `Exclusive<T>` from
     /// a _pinned mutable_ reference to a `T`. This allows you to skip
     /// building an `Exclusive` with [`Exclusive::new`].
     #[unstable(feature = "exclusive_wrapper", issue = "98407")]
index 0d3fc2c5244e03fe20af3b33a2814f4c020640db..f0e4f5d8a8013d613098c4ecd0a2dfee921ac24a 100644 (file)
@@ -1493,7 +1493,7 @@ pub mod tracked_env {
     use std::ffi::OsStr;
 
     /// Retrieve an environment variable and add it to build dependency info.
-    /// Build system executing the compiler will know that the variable was accessed during
+    /// The build system executing the compiler will know that the variable was accessed during
     /// compilation, and will be able to rerun the build when the value of that variable changes.
     /// Besides the dependency tracking this function should be equivalent to `env::var` from the
     /// standard library, except that the argument must be UTF-8.
index fb8d06c66820cf0b47a41a48cfdfd8064d3c7f5f..818914a2df074d3f3d0ba46a57ef805f42dc6347 100644 (file)
@@ -1759,8 +1759,13 @@ mod remove_dir_impl {
     use crate::sys::common::small_c_string::run_path_with_cstr;
     use crate::sys::{cvt, cvt_r};
 
-    #[cfg(not(all(target_os = "macos", not(target_arch = "aarch64")),))]
+    #[cfg(not(any(
+        target_os = "linux",
+        all(target_os = "macos", not(target_arch = "aarch64"))
+    )))]
     use libc::{fdopendir, openat, unlinkat};
+    #[cfg(target_os = "linux")]
+    use libc::{fdopendir, openat64 as openat, unlinkat};
     #[cfg(all(target_os = "macos", not(target_arch = "aarch64")))]
     use macos_weak::{fdopendir, openat, unlinkat};
 
index 94546ca09d00d859bdf3863eb4cead3f9223d120..6fa85e859c05b303495ac8e2d808832a13fd0e5b 100644 (file)
 use crate::sync::atomic::{AtomicBool, AtomicU8, Ordering};
 use crate::sys::cvt;
 use crate::sys::weak::syscall;
+#[cfg(not(target_os = "linux"))]
+use libc::sendfile as sendfile64;
+#[cfg(target_os = "linux")]
+use libc::sendfile64;
 use libc::{EBADF, EINVAL, ENOSYS, EOPNOTSUPP, EOVERFLOW, EPERM, EXDEV};
 
 #[cfg(test)]
@@ -647,7 +651,7 @@ fn splice(
 
         let result = match mode {
             SpliceMode::Sendfile => {
-                cvt(unsafe { libc::sendfile(writer, reader, ptr::null_mut(), chunk_size) })
+                cvt(unsafe { sendfile64(writer, reader, ptr::null_mut(), chunk_size) })
             }
             SpliceMode::Splice => cvt(unsafe {
                 splice(reader, ptr::null_mut(), writer, ptr::null_mut(), chunk_size, 0)
index 9055a011c515e18bd33b44953477220266f17f23..3d60941e84e393c0a7fac39d1fb70f736ed448db 100644 (file)
@@ -95,6 +95,10 @@ unsafe fn sanitize_standard_fds() {
         )))]
         'poll: {
             use crate::sys::os::errno;
+            #[cfg(not(target_os = "linux"))]
+            use libc::open as open64;
+            #[cfg(target_os = "linux")]
+            use libc::open64;
             let pfds: &mut [_] = &mut [
                 libc::pollfd { fd: 0, events: 0, revents: 0 },
                 libc::pollfd { fd: 1, events: 0, revents: 0 },
@@ -116,7 +120,7 @@ unsafe fn sanitize_standard_fds() {
                 if pfd.revents & libc::POLLNVAL == 0 {
                     continue;
                 }
-                if libc::open("/dev/null\0".as_ptr().cast(), libc::O_RDWR, 0) == -1 {
+                if open64("/dev/null\0".as_ptr().cast(), libc::O_RDWR, 0) == -1 {
                     // If the stream is closed but we failed to reopen it, abort the
                     // process. Otherwise we wouldn't preserve the safety of
                     // operations on the corresponding Rust object Stdin, Stdout, or
@@ -139,9 +143,13 @@ unsafe fn sanitize_standard_fds() {
         )))]
         {
             use crate::sys::os::errno;
+            #[cfg(not(target_os = "linux"))]
+            use libc::open as open64;
+            #[cfg(target_os = "linux")]
+            use libc::open64;
             for fd in 0..3 {
                 if libc::fcntl(fd, libc::F_GETFD) == -1 && errno() == libc::EBADF {
-                    if libc::open("/dev/null\0".as_ptr().cast(), libc::O_RDWR, 0) == -1 {
+                    if open64("/dev/null\0".as_ptr().cast(), libc::O_RDWR, 0) == -1 {
                         // If the stream is closed but we failed to reopen it, abort the
                         // process. Otherwise we wouldn't preserve the safety of
                         // operations on the corresponding Rust object Stdin, Stdout, or
index 56a805cef7318fe8e6ed00f57997d90647a03b22..c0716a089bc38b1b2b3be521c41165e259daeb46 100644 (file)
@@ -66,14 +66,15 @@ pub fn spawn(
         //
         // Note that as soon as we're done with the fork there's no need to hold
         // a lock any more because the parent won't do anything and the child is
-        // in its own process. Thus the parent drops the lock guard while the child
-        // forgets it to avoid unlocking it on a new thread, which would be invalid.
+        // in its own process. Thus the parent drops the lock guard immediately.
+        // The child calls `mem::forget` to leak the lock, which is crucial because
+        // releasing a lock is not async-signal-safe.
         let env_lock = sys::os::env_read_lock();
         let (pid, pidfd) = unsafe { self.do_fork()? };
 
         if pid == 0 {
             crate::panic::always_abort();
-            mem::forget(env_lock);
+            mem::forget(env_lock); // avoid non-async-signal-safe unlocking
             drop(input);
             let Err(err) = unsafe { self.do_exec(theirs, envp.as_ref()) };
             let errno = err.raw_os_error().unwrap_or(libc::EINVAL) as u32;
index 75a5c0f927982b3e8b542048839b7e9a0a8e7278..957e086798fd3cd786acd7f01970f42b813f2231 100644 (file)
@@ -45,7 +45,10 @@ mod imp {
     use crate::thread;
 
     use libc::MAP_FAILED;
-    use libc::{mmap, munmap};
+    #[cfg(not(target_os = "linux"))]
+    use libc::{mmap as mmap64, munmap};
+    #[cfg(target_os = "linux")]
+    use libc::{mmap64, munmap};
     use libc::{sigaction, sighandler_t, SA_ONSTACK, SA_SIGINFO, SIGBUS, SIG_DFL};
     use libc::{sigaltstack, SIGSTKSZ, SS_DISABLE};
     use libc::{MAP_ANON, MAP_PRIVATE, PROT_NONE, PROT_READ, PROT_WRITE, SIGSEGV};
@@ -135,7 +138,7 @@ unsafe fn get_stackp() -> *mut libc::c_void {
         #[cfg(not(any(target_os = "openbsd", target_os = "netbsd", target_os = "linux",)))]
         let flags = MAP_PRIVATE | MAP_ANON;
         let stackp =
-            mmap(ptr::null_mut(), SIGSTKSZ + page_size(), PROT_READ | PROT_WRITE, flags, -1, 0);
+            mmap64(ptr::null_mut(), SIGSTKSZ + page_size(), PROT_READ | PROT_WRITE, flags, -1, 0);
         if stackp == MAP_FAILED {
             panic!("failed to allocate an alternative stack: {}", io::Error::last_os_error());
         }
index 6ecf5bdcf86d2bf792695eb1720f3c10c403eadf..d454a2a717c0639a326555d3dc8b21a60450b1dd 100644 (file)
@@ -653,7 +653,10 @@ pub unsafe fn init() -> Option<Guard> {
 ))]
 #[cfg_attr(test, allow(dead_code))]
 pub mod guard {
-    use libc::{mmap, mprotect};
+    #[cfg(not(target_os = "linux"))]
+    use libc::{mmap as mmap64, mprotect};
+    #[cfg(target_os = "linux")]
+    use libc::{mmap64, mprotect};
     use libc::{MAP_ANON, MAP_FAILED, MAP_FIXED, MAP_PRIVATE, PROT_NONE, PROT_READ, PROT_WRITE};
 
     use crate::io;
@@ -803,7 +806,7 @@ pub unsafe fn init() -> Option<Guard> {
             // read/write permissions and only then mprotect() it to
             // no permissions at all. See issue #50313.
             let stackptr = get_stack_start_aligned()?;
-            let result = mmap(
+            let result = mmap64(
                 stackptr,
                 page_size,
                 PROT_READ | PROT_WRITE,
index be5c9bb07880891cbe23550c952f2aed26a93c9a..05f25af68ea8fe5985e11370df9bbe03c2951e01 100644 (file)
@@ -89,16 +89,16 @@ fn hash<H: Hasher>(&self, state: &mut H) {
 
 impl<T: Internable + Deref> Deref for Interned<T> {
     type Target = T::Target;
-    fn deref(&self) -> &'static Self::Target {
+    fn deref(&self) -> &Self::Target {
         let l = T::intern_cache().lock().unwrap();
-        unsafe { mem::transmute::<&Self::Target, &'static Self::Target>(l.get(*self)) }
+        unsafe { mem::transmute::<&Self::Target, &Self::Target>(l.get(*self)) }
     }
 }
 
 impl<T: Internable + AsRef<U>, U: ?Sized> AsRef<U> for Interned<T> {
-    fn as_ref(&self) -> &'static U {
+    fn as_ref(&self) -> &U {
         let l = T::intern_cache().lock().unwrap();
-        unsafe { mem::transmute::<&U, &'static U>(l.get(*self).as_ref()) }
+        unsafe { mem::transmute::<&U, &U>(l.get(*self).as_ref()) }
     }
 }
 
index 2fef7f65827dd65c90e43c4b2141b964a4943fef..3cb0eccd324d42574b082e4c1af721ada6a6bb77 100644 (file)
@@ -1470,7 +1470,7 @@ fn filter(contents: &str, marker: &str) -> String {
 
         let xform = |p: &Path| {
             let mut contents = t!(fs::read_to_string(p));
-            for tool in &["rust-demangler"] {
+            for tool in &["rust-demangler", "miri"] {
                 if !built_tools.contains(tool) {
                     contents = filter(&contents, tool);
                 }
@@ -1510,9 +1510,8 @@ fn filter(contents: &str, marker: &str) -> String {
             prepare("rust-std");
             prepare("rust-analysis");
             prepare("clippy");
-            prepare("miri");
             prepare("rust-analyzer");
-            for tool in &["rust-docs", "rust-demangler"] {
+            for tool in &["rust-docs", "rust-demangler", "miri"] {
                 if built_tools.contains(tool) {
                     prepare(tool);
                 }
@@ -1571,9 +1570,8 @@ fn filter(contents: &str, marker: &str) -> String {
             prepare("rust-docs");
             prepare("rust-std");
             prepare("clippy");
-            prepare("miri");
             prepare("rust-analyzer");
-            for tool in &["rust-demangler"] {
+            for tool in &["rust-demangler", "miri"] {
                 if built_tools.contains(tool) {
                     prepare(tool);
                 }
@@ -1710,23 +1708,25 @@ fn filter(contents: &str, marker: &str) -> String {
                         .arg(etc.join("msi/remove-duplicates.xsl")),
                 );
             }
-            builder.run(
-                Command::new(&heat)
-                    .current_dir(&exe)
-                    .arg("dir")
-                    .arg("miri")
-                    .args(&heat_flags)
-                    .arg("-cg")
-                    .arg("MiriGroup")
-                    .arg("-dr")
-                    .arg("Miri")
-                    .arg("-var")
-                    .arg("var.MiriDir")
-                    .arg("-out")
-                    .arg(exe.join("MiriGroup.wxs"))
-                    .arg("-t")
-                    .arg(etc.join("msi/remove-duplicates.xsl")),
-            );
+            if built_tools.contains("miri") {
+                builder.run(
+                    Command::new(&heat)
+                        .current_dir(&exe)
+                        .arg("dir")
+                        .arg("miri")
+                        .args(&heat_flags)
+                        .arg("-cg")
+                        .arg("MiriGroup")
+                        .arg("-dr")
+                        .arg("Miri")
+                        .arg("-var")
+                        .arg("var.MiriDir")
+                        .arg("-out")
+                        .arg(exe.join("MiriGroup.wxs"))
+                        .arg("-t")
+                        .arg(etc.join("msi/remove-duplicates.xsl")),
+                );
+            }
             builder.run(
                 Command::new(&heat)
                     .current_dir(&exe)
@@ -1774,7 +1774,6 @@ fn filter(contents: &str, marker: &str) -> String {
                     .arg("-dStdDir=rust-std")
                     .arg("-dAnalysisDir=rust-analysis")
                     .arg("-dClippyDir=clippy")
-                    .arg("-dMiriDir=miri")
                     .arg("-arch")
                     .arg(&arch)
                     .arg("-out")
@@ -1788,6 +1787,9 @@ fn filter(contents: &str, marker: &str) -> String {
                 if built_tools.contains("rust-analyzer") {
                     cmd.arg("-dRustAnalyzerDir=rust-analyzer");
                 }
+                if built_tools.contains("miri") {
+                    cmd.arg("-dMiriDir=miri");
+                }
                 if target.ends_with("windows-gnu") {
                     cmd.arg("-dGccDir=rust-mingw");
                 }
@@ -1801,7 +1803,9 @@ fn filter(contents: &str, marker: &str) -> String {
             candle("CargoGroup.wxs".as_ref());
             candle("StdGroup.wxs".as_ref());
             candle("ClippyGroup.wxs".as_ref());
-            candle("MiriGroup.wxs".as_ref());
+            if built_tools.contains("miri") {
+                candle("MiriGroup.wxs".as_ref());
+            }
             if built_tools.contains("rust-demangler") {
                 candle("RustDemanglerGroup.wxs".as_ref());
             }
@@ -1837,9 +1841,11 @@ fn filter(contents: &str, marker: &str) -> String {
                 .arg("StdGroup.wixobj")
                 .arg("AnalysisGroup.wixobj")
                 .arg("ClippyGroup.wixobj")
-                .arg("MiriGroup.wixobj")
                 .current_dir(&exe);
 
+            if built_tools.contains("miri") {
+                cmd.arg("MiriGroup.wixobj");
+            }
             if built_tools.contains("rust-analyzer") {
                 cmd.arg("RustAnalyzerGroup.wixobj");
             }
index a2708d16947f0c92ed302106fba70382792eee2f..3e86339859dd360528d5ff6719286f58ae407a8d 100755 (executable)
@@ -346,7 +346,7 @@ class TestEnvironment:
                 "-f",
                 self.ssh_keyfile_path(),
                 "-C",
-                "Generated by test_toolchain.py",
+                "Generated by fuchsia-test-runner.py",
             ],
             stdout=self.subprocess_output(),
             stderr=self.subprocess_output(),
index d1ba46ad30de6d08c82176a41b7e894c87358704..5a0397a3d123cf714bb63dbf40b4a87a9ae9f69a 100644 (file)
@@ -467,7 +467,7 @@ jobs:
           - name: dist-x86_64-apple
             env:
               SCRIPT: ./x.py dist bootstrap --include-default-paths --host=x86_64-apple-darwin --target=x86_64-apple-darwin
-              RUST_CONFIGURE_ARGS: --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false --set rust.lto=thin
+              RUST_CONFIGURE_ARGS: --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false
               RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
               MACOSX_DEPLOYMENT_TARGET: 10.7
               SELECT_XCODE: /Applications/Xcode_13.4.1.app
index 953f4aa8a1b482137f4f24d4cd9447ed84b76c25..4d6f1524732f77453e2ce2489cd3eee1b6f848e8 100644 (file)
@@ -44,7 +44,7 @@ fn generate_for_trait(
         discard_positive_impl: bool,
     ) -> Option<Item> {
         let tcx = self.cx.tcx;
-        let trait_ref = tcx.mk_trait_ref(trait_def_id, [ty]);
+        let trait_ref = ty::Binder::dummy(tcx.mk_trait_ref(trait_def_id, [ty]));
         if !self.cx.generated_synthetics.insert((ty, trait_def_id)) {
             debug!("get_auto_trait_impl_for({:?}): already generated, aborting", trait_ref);
             return None;
@@ -124,7 +124,7 @@ fn generate_for_trait(
                 unsafety: hir::Unsafety::Normal,
                 generics: new_generics,
                 trait_: Some(clean_trait_ref_with_bindings(self.cx, trait_ref, ThinVec::new())),
-                for_: clean_middle_ty(ty, self.cx, None),
+                for_: clean_middle_ty(ty::Binder::dummy(ty), self.cx, None),
                 items: Vec::new(),
                 polarity,
                 kind: ImplKind::Auto,
index a1145b90d6580c7da0f996dbd4d9420eff7d5d7b..4ef5747596bb39a7d4900a393c216f84626f3447 100644 (file)
@@ -105,10 +105,10 @@ pub(crate) fn get_blanket_impls(&mut self, item_def_id: DefId) -> Vec<Item> {
                         // the post-inference `trait_ref`, as it's more accurate.
                         trait_: Some(clean_trait_ref_with_bindings(
                             cx,
-                            trait_ref.0,
+                            ty::Binder::dummy(trait_ref.0),
                             ThinVec::new(),
                         )),
-                        for_: clean_middle_ty(ty.0, cx, None),
+                        for_: clean_middle_ty(ty::Binder::dummy(ty.0), cx, None),
                         items: cx
                             .tcx
                             .associated_items(impl_def_id)
@@ -117,7 +117,7 @@ pub(crate) fn get_blanket_impls(&mut self, item_def_id: DefId) -> Vec<Item> {
                             .collect::<Vec<_>>(),
                         polarity: ty::ImplPolarity::Positive,
                         kind: ImplKind::Blanket(Box::new(clean_middle_ty(
-                            trait_ref.0.self_ty(),
+                            ty::Binder::dummy(trait_ref.0.self_ty()),
                             cx,
                             None,
                         ))),
index e7c3e5a45e8387f079015a7db93c30212ca8075f..50caef3553fdaf5f47d8e2248762494b06229750 100644 (file)
@@ -293,7 +293,7 @@ fn build_union(cx: &mut DocContext<'_>, did: DefId) -> clean::Union {
 
 fn build_type_alias(cx: &mut DocContext<'_>, did: DefId) -> Box<clean::Typedef> {
     let predicates = cx.tcx.explicit_predicates_of(did);
-    let type_ = clean_middle_ty(cx.tcx.type_of(did), cx, Some(did));
+    let type_ = clean_middle_ty(ty::Binder::dummy(cx.tcx.type_of(did)), cx, Some(did));
 
     Box::new(clean::Typedef {
         type_,
@@ -405,7 +405,7 @@ pub(crate) fn build_impl(
 
     let for_ = match &impl_item {
         Some(impl_) => clean_ty(impl_.self_ty, cx),
-        None => clean_middle_ty(tcx.type_of(did), cx, Some(did)),
+        None => clean_middle_ty(ty::Binder::dummy(tcx.type_of(did)), cx, Some(did)),
     };
 
     // Only inline impl if the implementing type is
@@ -496,7 +496,8 @@ pub(crate) fn build_impl(
         ),
     };
     let polarity = tcx.impl_polarity(did);
-    let trait_ = associated_trait.map(|t| clean_trait_ref_with_bindings(cx, t, ThinVec::new()));
+    let trait_ = associated_trait
+        .map(|t| clean_trait_ref_with_bindings(cx, ty::Binder::dummy(t), ThinVec::new()));
     if trait_.as_ref().map(|t| t.def_id()) == tcx.lang_items().deref_trait() {
         super::build_deref_target_impls(cx, &trait_items, ret);
     }
@@ -640,14 +641,14 @@ pub(crate) fn print_inlined_const(tcx: TyCtxt<'_>, did: DefId) -> String {
 
 fn build_const(cx: &mut DocContext<'_>, def_id: DefId) -> clean::Constant {
     clean::Constant {
-        type_: clean_middle_ty(cx.tcx.type_of(def_id), cx, Some(def_id)),
+        type_: clean_middle_ty(ty::Binder::dummy(cx.tcx.type_of(def_id)), cx, Some(def_id)),
         kind: clean::ConstantKind::Extern { def_id },
     }
 }
 
 fn build_static(cx: &mut DocContext<'_>, did: DefId, mutable: bool) -> clean::Static {
     clean::Static {
-        type_: clean_middle_ty(cx.tcx.type_of(did), cx, Some(did)),
+        type_: clean_middle_ty(ty::Binder::dummy(cx.tcx.type_of(did)), cx, Some(did)),
         mutability: if mutable { Mutability::Mut } else { Mutability::Not },
         expr: None,
     }
index 2a2a9470d25c0ee4da19badf253f0207a6dcdda7..92886bbfe26b4e5d03953f9eb3362bfe03bd3ae9 100644 (file)
@@ -22,6 +22,7 @@
 use rustc_middle::middle::resolve_lifetime as rl;
 use rustc_middle::ty::fold::TypeFolder;
 use rustc_middle::ty::InternalSubsts;
+use rustc_middle::ty::TypeVisitable;
 use rustc_middle::ty::{self, AdtKind, DefIdTree, EarlyBinder, Ty, TyCtxt};
 use rustc_middle::{bug, span_bug};
 use rustc_span::hygiene::{AstPass, MacroKind};
@@ -127,7 +128,7 @@ fn clean_generic_bound<'tcx>(
         hir::GenericBound::LangItemTrait(lang_item, span, _, generic_args) => {
             let def_id = cx.tcx.require_lang_item(lang_item, Some(span));
 
-            let trait_ref = ty::TraitRef::identity(cx.tcx, def_id).skip_binder();
+            let trait_ref = ty::TraitRef::identity(cx.tcx, def_id);
 
             let generic_args = clean_generic_args(generic_args, cx);
             let GenericArgs::AngleBracketed { bindings, .. } = generic_args
@@ -156,17 +157,18 @@ fn clean_generic_bound<'tcx>(
 
 pub(crate) fn clean_trait_ref_with_bindings<'tcx>(
     cx: &mut DocContext<'tcx>,
-    trait_ref: ty::TraitRef<'tcx>,
+    trait_ref: ty::PolyTraitRef<'tcx>,
     bindings: ThinVec<TypeBinding>,
 ) -> Path {
-    let kind = cx.tcx.def_kind(trait_ref.def_id).into();
+    let kind = cx.tcx.def_kind(trait_ref.def_id()).into();
     if !matches!(kind, ItemType::Trait | ItemType::TraitAlias) {
-        span_bug!(cx.tcx.def_span(trait_ref.def_id), "`TraitRef` had unexpected kind {:?}", kind);
+        span_bug!(cx.tcx.def_span(trait_ref.def_id()), "`TraitRef` had unexpected kind {:?}", kind);
     }
-    inline::record_extern_fqn(cx, trait_ref.def_id, kind);
-    let path = external_path(cx, trait_ref.def_id, true, bindings, trait_ref.substs);
+    inline::record_extern_fqn(cx, trait_ref.def_id(), kind);
+    let path =
+        external_path(cx, trait_ref.def_id(), true, bindings, trait_ref.map_bound(|tr| tr.substs));
 
-    debug!("ty::TraitRef\n  subst: {:?}\n", trait_ref.substs);
+    debug!(?trait_ref);
 
     path
 }
@@ -187,7 +189,7 @@ fn clean_poly_trait_ref_with_bindings<'tcx>(
         })
         .collect();
 
-    let trait_ = clean_trait_ref_with_bindings(cx, poly_trait_ref.skip_binder(), bindings);
+    let trait_ = clean_trait_ref_with_bindings(cx, poly_trait_ref, bindings);
     GenericBound::TraitBound(
         PolyTrait { trait_, generic_params: late_bound_regions },
         hir::TraitBoundModifier::None,
@@ -212,19 +214,19 @@ fn clean_lifetime<'tcx>(lifetime: &hir::Lifetime, cx: &mut DocContext<'tcx>) ->
 pub(crate) fn clean_const<'tcx>(constant: &hir::ConstArg, cx: &mut DocContext<'tcx>) -> Constant {
     let def_id = cx.tcx.hir().body_owner_def_id(constant.value.body).to_def_id();
     Constant {
-        type_: clean_middle_ty(cx.tcx.type_of(def_id), cx, Some(def_id)),
+        type_: clean_middle_ty(ty::Binder::dummy(cx.tcx.type_of(def_id)), cx, Some(def_id)),
         kind: ConstantKind::Anonymous { body: constant.value.body },
     }
 }
 
 pub(crate) fn clean_middle_const<'tcx>(
-    constant: ty::Const<'tcx>,
+    constant: ty::Binder<'tcx, ty::Const<'tcx>>,
     cx: &mut DocContext<'tcx>,
 ) -> Constant {
     // FIXME: instead of storing the stringified expression, store `self` directly instead.
     Constant {
-        type_: clean_middle_ty(constant.ty(), cx, None),
-        kind: ConstantKind::TyConst { expr: constant.to_string().into() },
+        type_: clean_middle_ty(constant.map_bound(|c| c.ty()), cx, None),
+        kind: ConstantKind::TyConst { expr: constant.skip_binder().to_string().into() },
     }
 }
 
@@ -333,7 +335,7 @@ fn clean_poly_trait_predicate<'tcx>(
 
     let poly_trait_ref = pred.map_bound(|pred| pred.trait_ref);
     Some(WherePredicate::BoundPredicate {
-        ty: clean_middle_ty(poly_trait_ref.skip_binder().self_ty(), cx, None),
+        ty: clean_middle_ty(poly_trait_ref.self_ty(), cx, None),
         bounds: vec![clean_poly_trait_ref_with_bindings(cx, poly_trait_ref, ThinVec::new())],
         bound_params: Vec::new(),
     })
@@ -359,7 +361,7 @@ fn clean_type_outlives_predicate<'tcx>(
     let ty::OutlivesPredicate(ty, lt) = pred;
 
     Some(WherePredicate::BoundPredicate {
-        ty: clean_middle_ty(ty, cx, None),
+        ty: clean_middle_ty(ty::Binder::dummy(ty), cx, None),
         bounds: vec![GenericBound::Outlives(
             clean_middle_region(lt).expect("failed to clean lifetimes"),
         )],
@@ -367,10 +369,13 @@ fn clean_type_outlives_predicate<'tcx>(
     })
 }
 
-fn clean_middle_term<'tcx>(term: ty::Term<'tcx>, cx: &mut DocContext<'tcx>) -> Term {
-    match term.unpack() {
-        ty::TermKind::Ty(ty) => Term::Type(clean_middle_ty(ty, cx, None)),
-        ty::TermKind::Const(c) => Term::Constant(clean_middle_const(c, cx)),
+fn clean_middle_term<'tcx>(
+    term: ty::Binder<'tcx, ty::Term<'tcx>>,
+    cx: &mut DocContext<'tcx>,
+) -> Term {
+    match term.skip_binder().unpack() {
+        ty::TermKind::Ty(ty) => Term::Type(clean_middle_ty(term.rebind(ty), cx, None)),
+        ty::TermKind::Const(c) => Term::Constant(clean_middle_const(term.rebind(c), cx)),
     }
 }
 
@@ -379,7 +384,10 @@ fn clean_hir_term<'tcx>(term: &hir::Term<'tcx>, cx: &mut DocContext<'tcx>) -> Te
         hir::Term::Ty(ty) => Term::Type(clean_ty(ty, cx)),
         hir::Term::Const(c) => {
             let def_id = cx.tcx.hir().local_def_id(c.hir_id);
-            Term::Constant(clean_middle_const(ty::Const::from_anon_const(cx.tcx, def_id), cx))
+            Term::Constant(clean_middle_const(
+                ty::Binder::dummy(ty::Const::from_anon_const(cx.tcx, def_id)),
+                cx,
+            ))
         }
     }
 }
@@ -398,32 +406,31 @@ fn clean_projection_predicate<'tcx>(
         })
         .collect();
 
-    let ty::ProjectionPredicate { projection_ty, term } = pred.skip_binder();
-
     WherePredicate::EqPredicate {
-        lhs: Box::new(clean_projection(projection_ty, cx, None)),
-        rhs: Box::new(clean_middle_term(term, cx)),
+        lhs: Box::new(clean_projection(pred.map_bound(|p| p.projection_ty), cx, None)),
+        rhs: Box::new(clean_middle_term(pred.map_bound(|p| p.term), cx)),
         bound_params: late_bound_regions,
     }
 }
 
 fn clean_projection<'tcx>(
-    ty: ty::ProjectionTy<'tcx>,
+    ty: ty::Binder<'tcx, ty::AliasTy<'tcx>>,
     cx: &mut DocContext<'tcx>,
     def_id: Option<DefId>,
 ) -> Type {
-    if cx.tcx.def_kind(ty.item_def_id) == DefKind::ImplTraitPlaceholder {
+    if cx.tcx.def_kind(ty.skip_binder().def_id) == DefKind::ImplTraitPlaceholder {
         let bounds = cx
             .tcx
-            .explicit_item_bounds(ty.item_def_id)
+            .explicit_item_bounds(ty.skip_binder().def_id)
             .iter()
-            .map(|(bound, _)| EarlyBinder(*bound).subst(cx.tcx, ty.substs))
+            .map(|(bound, _)| EarlyBinder(*bound).subst(cx.tcx, ty.skip_binder().substs))
             .collect::<Vec<_>>();
         return clean_middle_opaque_bounds(cx, bounds);
     }
 
-    let trait_ = clean_trait_ref_with_bindings(cx, ty.trait_ref(cx.tcx), ThinVec::new());
-    let self_type = clean_middle_ty(ty.self_ty(), cx, None);
+    let trait_ =
+        clean_trait_ref_with_bindings(cx, ty.map_bound(|ty| ty.trait_ref(cx.tcx)), ThinVec::new());
+    let self_type = clean_middle_ty(ty.map_bound(|ty| ty.self_ty()), cx, None);
     let self_def_id = if let Some(def_id) = def_id {
         cx.tcx.opt_parent(def_id).or(Some(def_id))
     } else {
@@ -446,15 +453,16 @@ fn compute_should_show_cast(self_def_id: Option<DefId>, trait_: &Path, self_type
 }
 
 fn projection_to_path_segment<'tcx>(
-    ty: ty::ProjectionTy<'tcx>,
+    ty: ty::Binder<'tcx, ty::AliasTy<'tcx>>,
     cx: &mut DocContext<'tcx>,
 ) -> PathSegment {
-    let item = cx.tcx.associated_item(ty.item_def_id);
-    let generics = cx.tcx.generics_of(ty.item_def_id);
+    let item = cx.tcx.associated_item(ty.skip_binder().def_id);
+    let generics = cx.tcx.generics_of(ty.skip_binder().def_id);
     PathSegment {
         name: item.name,
         args: GenericArgs::AngleBracketed {
-            args: substs_to_args(cx, &ty.substs[generics.parent_count..], false).into(),
+            args: substs_to_args(cx, ty.map_bound(|ty| &ty.substs[generics.parent_count..]), false)
+                .into(),
             bindings: Default::default(),
         },
     }
@@ -470,7 +478,11 @@ fn clean_generic_param_def<'tcx>(
         }
         ty::GenericParamDefKind::Type { has_default, synthetic, .. } => {
             let default = if has_default {
-                Some(clean_middle_ty(cx.tcx.type_of(def.def_id), cx, Some(def.def_id)))
+                Some(clean_middle_ty(
+                    ty::Binder::dummy(cx.tcx.type_of(def.def_id)),
+                    cx,
+                    Some(def.def_id),
+                ))
             } else {
                 None
             };
@@ -488,7 +500,11 @@ fn clean_generic_param_def<'tcx>(
             def.name,
             GenericParamDefKind::Const {
                 did: def.def_id,
-                ty: Box::new(clean_middle_ty(cx.tcx.type_of(def.def_id), cx, Some(def.def_id))),
+                ty: Box::new(clean_middle_ty(
+                    ty::Binder::dummy(cx.tcx.type_of(def.def_id)),
+                    cx,
+                    Some(def.def_id),
+                )),
                 default: match has_default {
                     true => Some(Box::new(cx.tcx.const_param_default(def.def_id).to_string())),
                     false => None,
@@ -733,8 +749,10 @@ fn clean_ty_generics<'tcx>(
         .collect::<ThinVec<GenericParamDef>>();
 
     // param index -> [(trait DefId, associated type name & generics, type, higher-ranked params)]
-    let mut impl_trait_proj =
-        FxHashMap::<u32, Vec<(DefId, PathSegment, Ty<'_>, Vec<GenericParamDef>)>>::default();
+    let mut impl_trait_proj = FxHashMap::<
+        u32,
+        Vec<(DefId, PathSegment, ty::Binder<'_, Ty<'_>>, Vec<GenericParamDef>)>,
+    >::default();
 
     let where_predicates = preds
         .predicates
@@ -783,8 +801,8 @@ fn clean_ty_generics<'tcx>(
 
                     let proj = projection.map(|p| {
                         (
-                            clean_projection(p.skip_binder().projection_ty, cx, None),
-                            p.skip_binder().term,
+                            clean_projection(p.map_bound(|p| p.projection_ty), cx, None),
+                            p.map_bound(|p| p.term),
                         )
                     });
                     if let Some(((_, trait_did, name), rhs)) = proj
@@ -795,7 +813,7 @@ fn clean_ty_generics<'tcx>(
                         impl_trait_proj.entry(param_idx).or_default().push((
                             trait_did,
                             name,
-                            rhs.ty().unwrap(),
+                            rhs.map_bound(|rhs| rhs.ty().unwrap()),
                             p.get_bound_params()
                                 .into_iter()
                                 .flatten()
@@ -1066,7 +1084,7 @@ fn clean_fn_decl_from_did_and_sig<'tcx>(
 
     // We assume all empty tuples are default return type. This theoretically can discard `-> ()`,
     // but shouldn't change any code meaning.
-    let output = match clean_middle_ty(sig.skip_binder().output(), cx, None) {
+    let output = match clean_middle_ty(sig.output(), cx, None) {
         Type::Tuple(inner) if inner.is_empty() => DefaultReturn,
         ty => Return(ty),
     };
@@ -1076,11 +1094,10 @@ fn clean_fn_decl_from_did_and_sig<'tcx>(
         c_variadic: sig.skip_binder().c_variadic,
         inputs: Arguments {
             values: sig
-                .skip_binder()
                 .inputs()
                 .iter()
                 .map(|t| Argument {
-                    type_: clean_middle_ty(*t, cx, None),
+                    type_: clean_middle_ty(t.map_bound(|t| *t), cx, None),
                     name: names
                         .next()
                         .map(|i| i.name)
@@ -1134,7 +1151,8 @@ fn clean_trait_item<'tcx>(trait_item: &hir::TraitItem<'tcx>, cx: &mut DocContext
             hir::TraitItemKind::Type(bounds, Some(default)) => {
                 let generics = enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx));
                 let bounds = bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect();
-                let item_type = clean_middle_ty(hir_ty_to_ty(cx.tcx, default), cx, None);
+                let item_type =
+                    clean_middle_ty(ty::Binder::dummy(hir_ty_to_ty(cx.tcx, default)), cx, None);
                 AssocTypeItem(
                     Box::new(Typedef {
                         type_: clean_ty(default, cx),
@@ -1173,7 +1191,8 @@ pub(crate) fn clean_impl_item<'tcx>(
             hir::ImplItemKind::Type(hir_ty) => {
                 let type_ = clean_ty(hir_ty, cx);
                 let generics = clean_generics(impl_.generics, cx);
-                let item_type = clean_middle_ty(hir_ty_to_ty(cx.tcx, hir_ty), cx, None);
+                let item_type =
+                    clean_middle_ty(ty::Binder::dummy(hir_ty_to_ty(cx.tcx, hir_ty)), cx, None);
                 AssocTypeItem(
                     Box::new(Typedef { type_, generics, item_type: Some(item_type) }),
                     Vec::new(),
@@ -1192,7 +1211,11 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
     let tcx = cx.tcx;
     let kind = match assoc_item.kind {
         ty::AssocKind::Const => {
-            let ty = clean_middle_ty(tcx.type_of(assoc_item.def_id), cx, Some(assoc_item.def_id));
+            let ty = clean_middle_ty(
+                ty::Binder::dummy(tcx.type_of(assoc_item.def_id)),
+                cx,
+                Some(assoc_item.def_id),
+            );
 
             let provided = match assoc_item.container {
                 ty::ImplContainer => true,
@@ -1375,7 +1398,7 @@ fn param_eq_arg(param: &GenericParamDef, arg: &GenericArg) -> bool {
                     AssocTypeItem(
                         Box::new(Typedef {
                             type_: clean_middle_ty(
-                                tcx.type_of(assoc_item.def_id),
+                                ty::Binder::dummy(tcx.type_of(assoc_item.def_id)),
                                 cx,
                                 Some(assoc_item.def_id),
                             ),
@@ -1393,7 +1416,7 @@ fn param_eq_arg(param: &GenericParamDef, arg: &GenericArg) -> bool {
                 AssocTypeItem(
                     Box::new(Typedef {
                         type_: clean_middle_ty(
-                            tcx.type_of(assoc_item.def_id),
+                            ty::Binder::dummy(tcx.type_of(assoc_item.def_id)),
                             cx,
                             Some(assoc_item.def_id),
                         ),
@@ -1437,8 +1460,11 @@ fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type
         hir::QPath::Resolved(Some(qself), p) => {
             // Try to normalize `<X as Y>::T` to a type
             let ty = hir_ty_to_ty(cx.tcx, hir_ty);
-            if let Some(normalized_value) = normalize(cx, ty) {
-                return clean_middle_ty(normalized_value, cx, None);
+            // `hir_to_ty` can return projection types with escaping vars for GATs, e.g. `<() as Trait>::Gat<'_>`
+            if !ty.has_escaping_bound_vars() {
+                if let Some(normalized_value) = normalize(cx, ty::Binder::dummy(ty)) {
+                    return clean_middle_ty(normalized_value, cx, None);
+                }
             }
 
             let trait_segments = &p.segments[..p.segments.len() - 1];
@@ -1461,11 +1487,13 @@ fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type
         hir::QPath::TypeRelative(qself, segment) => {
             let ty = hir_ty_to_ty(cx.tcx, hir_ty);
             let res = match ty.kind() {
-                ty::Projection(proj) => Res::Def(DefKind::Trait, proj.trait_ref(cx.tcx).def_id),
+                ty::Alias(ty::Projection, proj) => {
+                    Res::Def(DefKind::Trait, proj.trait_ref(cx.tcx).def_id)
+                }
                 // Rustdoc handles `ty::Error`s by turning them into `Type::Infer`s.
                 ty::Error(_) => return Type::Infer,
                 // Otherwise, this is an inherent associated type.
-                _ => return clean_middle_ty(ty, cx, None),
+                _ => return clean_middle_ty(ty::Binder::dummy(ty), cx, None),
             };
             let trait_ = clean_path(&hir::Path { span, res, segments: &[] }, cx);
             register_res(cx, trait_.res);
@@ -1632,7 +1660,10 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
 }
 
 /// Returns `None` if the type could not be normalized
-fn normalize<'tcx>(cx: &mut DocContext<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
+fn normalize<'tcx>(
+    cx: &mut DocContext<'tcx>,
+    ty: ty::Binder<'tcx, Ty<'tcx>>,
+) -> Option<ty::Binder<'tcx, Ty<'tcx>>> {
     // HACK: low-churn fix for #79459 while we wait for a trait normalization fix
     if !cx.tcx.sess.opts.unstable_opts.normalize_docs {
         return None;
@@ -1660,14 +1691,14 @@ fn normalize<'tcx>(cx: &mut DocContext<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'tcx>>
     }
 }
 
+#[instrument(level = "trace", skip(cx), ret)]
 pub(crate) fn clean_middle_ty<'tcx>(
-    ty: Ty<'tcx>,
+    bound_ty: ty::Binder<'tcx, Ty<'tcx>>,
     cx: &mut DocContext<'tcx>,
     def_id: Option<DefId>,
 ) -> Type {
-    trace!("cleaning type: {:?}", ty);
-    let ty = normalize(cx, ty).unwrap_or(ty);
-    match *ty.kind() {
+    let bound_ty = normalize(cx, bound_ty).unwrap_or(bound_ty);
+    match *bound_ty.skip_binder().kind() {
         ty::Never => Primitive(PrimitiveType::Never),
         ty::Bool => Primitive(PrimitiveType::Bool),
         ty::Char => Primitive(PrimitiveType::Char),
@@ -1675,20 +1706,23 @@ pub(crate) fn clean_middle_ty<'tcx>(
         ty::Uint(uint_ty) => Primitive(uint_ty.into()),
         ty::Float(float_ty) => Primitive(float_ty.into()),
         ty::Str => Primitive(PrimitiveType::Str),
-        ty::Slice(ty) => Slice(Box::new(clean_middle_ty(ty, cx, None))),
+        ty::Slice(ty) => Slice(Box::new(clean_middle_ty(bound_ty.rebind(ty), cx, None))),
         ty::Array(ty, mut n) => {
             n = n.eval(cx.tcx, ty::ParamEnv::reveal_all());
             let n = print_const(cx, n);
-            Array(Box::new(clean_middle_ty(ty, cx, None)), n.into())
+            Array(Box::new(clean_middle_ty(bound_ty.rebind(ty), cx, None)), n.into())
+        }
+        ty::RawPtr(mt) => {
+            RawPointer(mt.mutbl, Box::new(clean_middle_ty(bound_ty.rebind(mt.ty), cx, None)))
         }
-        ty::RawPtr(mt) => RawPointer(mt.mutbl, Box::new(clean_middle_ty(mt.ty, cx, None))),
         ty::Ref(r, ty, mutbl) => BorrowedRef {
             lifetime: clean_middle_region(r),
             mutability: mutbl,
-            type_: Box::new(clean_middle_ty(ty, cx, None)),
+            type_: Box::new(clean_middle_ty(bound_ty.rebind(ty), cx, None)),
         },
         ty::FnDef(..) | ty::FnPtr(_) => {
-            let sig = ty.fn_sig(cx.tcx);
+            // FIXME: should we merge the outer and inner binders somehow?
+            let sig = bound_ty.skip_binder().fn_sig(cx.tcx);
             let decl = clean_fn_decl_from_did_and_sig(cx, None, sig);
             BareFunction(Box::new(BareFunctionDecl {
                 unsafety: sig.unsafety(),
@@ -1705,12 +1739,18 @@ pub(crate) fn clean_middle_ty<'tcx>(
                 AdtKind::Enum => ItemType::Enum,
             };
             inline::record_extern_fqn(cx, did, kind);
-            let path = external_path(cx, did, false, ThinVec::new(), substs);
+            let path = external_path(cx, did, false, ThinVec::new(), bound_ty.rebind(substs));
             Type::Path { path }
         }
         ty::Foreign(did) => {
             inline::record_extern_fqn(cx, did, ItemType::ForeignType);
-            let path = external_path(cx, did, false, ThinVec::new(), InternalSubsts::empty());
+            let path = external_path(
+                cx,
+                did,
+                false,
+                ThinVec::new(),
+                ty::Binder::dummy(InternalSubsts::empty()),
+            );
             Type::Path { path }
         }
         ty::Dynamic(obj, ref reg, _) => {
@@ -1721,11 +1761,11 @@ pub(crate) fn clean_middle_ty<'tcx>(
             let did = obj
                 .principal_def_id()
                 .or_else(|| dids.next())
-                .unwrap_or_else(|| panic!("found trait object `{:?}` with no traits?", ty));
+                .unwrap_or_else(|| panic!("found trait object `{bound_ty:?}` with no traits?"));
             let substs = match obj.principal() {
-                Some(principal) => principal.skip_binder().substs,
+                Some(principal) => principal.map_bound(|p| p.substs),
                 // marker traits have no substs.
-                _ => cx.tcx.intern_substs(&[]),
+                _ => ty::Binder::dummy(InternalSubsts::empty()),
             };
 
             inline::record_extern_fqn(cx, did, ItemType::Trait);
@@ -1736,7 +1776,7 @@ pub(crate) fn clean_middle_ty<'tcx>(
             let lifetime = clean_middle_region(*reg);
             let mut bounds = dids
                 .map(|did| {
-                    let empty = cx.tcx.intern_substs(&[]);
+                    let empty = ty::Binder::dummy(InternalSubsts::empty());
                     let path = external_path(cx, did, false, ThinVec::new(), empty);
                     inline::record_extern_fqn(cx, did, ItemType::Trait);
                     PolyTrait { trait_: path, generic_params: Vec::new() }
@@ -1747,15 +1787,17 @@ pub(crate) fn clean_middle_ty<'tcx>(
                 .projection_bounds()
                 .map(|pb| TypeBinding {
                     assoc: projection_to_path_segment(
-                        pb.skip_binder()
-                            // HACK(compiler-errors): Doesn't actually matter what self
-                            // type we put here, because we're only using the GAT's substs.
-                            .with_self_ty(cx.tcx, cx.tcx.types.self_param)
-                            .projection_ty,
+                        pb.map_bound(|pb| {
+                            pb
+                                // HACK(compiler-errors): Doesn't actually matter what self
+                                // type we put here, because we're only using the GAT's substs.
+                                .with_self_ty(cx.tcx, cx.tcx.types.self_param)
+                                .projection_ty
+                        }),
                         cx,
                     ),
                     kind: TypeBindingKind::Equality {
-                        term: clean_middle_term(pb.skip_binder().term, cx),
+                        term: clean_middle_term(pb.map_bound(|pb| pb.term), cx),
                     },
                 })
                 .collect();
@@ -1779,9 +1821,11 @@ pub(crate) fn clean_middle_ty<'tcx>(
 
             DynTrait(bounds, lifetime)
         }
-        ty::Tuple(t) => Tuple(t.iter().map(|t| clean_middle_ty(t, cx, None)).collect()),
+        ty::Tuple(t) => {
+            Tuple(t.iter().map(|t| clean_middle_ty(bound_ty.rebind(t), cx, None)).collect())
+        }
 
-        ty::Projection(ref data) => clean_projection(*data, cx, def_id),
+        ty::Alias(ty::Projection, ref data) => clean_projection(bound_ty.rebind(*data), cx, def_id),
 
         ty::Param(ref p) => {
             if let Some(bounds) = cx.impl_trait_bounds.remove(&p.index.into()) {
@@ -1791,7 +1835,7 @@ pub(crate) fn clean_middle_ty<'tcx>(
             }
         }
 
-        ty::Opaque(def_id, substs) => {
+        ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
             // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
             // by looking up the bounds associated with the def_id.
             let bounds = cx
@@ -1854,9 +1898,12 @@ fn clean_middle_opaque_bounds<'tcx>(
                     {
                         if proj.projection_ty.trait_ref(cx.tcx) == trait_ref.skip_binder() {
                             Some(TypeBinding {
-                                assoc: projection_to_path_segment(proj.projection_ty, cx),
+                                assoc: projection_to_path_segment(
+                                    bound.kind().rebind(proj.projection_ty),
+                                    cx,
+                                ),
                                 kind: TypeBindingKind::Equality {
-                                    term: clean_middle_term(proj.term, cx),
+                                    term: clean_middle_term(bound.kind().rebind(proj.term), cx),
                                 },
                             })
                         } else {
@@ -1887,7 +1934,7 @@ pub(crate) fn clean_middle_field<'tcx>(field: &ty::FieldDef, cx: &mut DocContext
     clean_field_with_def_id(
         field.did,
         field.name,
-        clean_middle_ty(cx.tcx.type_of(field.did), cx, Some(field.did)),
+        clean_middle_ty(ty::Binder::dummy(cx.tcx.type_of(field.did)), cx, Some(field.did)),
         cx,
     )
 }
@@ -2100,7 +2147,7 @@ fn clean_maybe_renamed_item<'tcx>(
             }),
             ItemKind::TyAlias(hir_ty, generics) => {
                 let rustdoc_ty = clean_ty(hir_ty, cx);
-                let ty = clean_middle_ty(hir_ty_to_ty(cx.tcx, hir_ty), cx, None);
+                let ty = clean_middle_ty(ty::Binder::dummy(hir_ty_to_ty(cx.tcx, hir_ty)), cx, None);
                 TypedefItem(Box::new(Typedef {
                     type_: rustdoc_ty,
                     generics: clean_generics(generics, cx),
@@ -2211,7 +2258,9 @@ fn clean_impl<'tcx>(
 
     let for_ = clean_ty(impl_.self_ty, cx);
     let type_alias = for_.def_id(&cx.cache).and_then(|did| match tcx.def_kind(did) {
-        DefKind::TyAlias => Some(clean_middle_ty(tcx.type_of(did), cx, Some(did))),
+        DefKind::TyAlias => {
+            Some(clean_middle_ty(ty::Binder::dummy(tcx.type_of(did)), cx, Some(did)))
+        }
         _ => None,
     });
     let mut make_item = |trait_: Option<Path>, for_: Type, items: Vec<Item>| {
index 98329e7fc91935d61601a784ced2f4773fd4c866..7a7313c4bc99d90e5987fa6d2864d7fedfea3a17 100644 (file)
@@ -1343,7 +1343,7 @@ pub(crate) enum GenericBound {
 impl GenericBound {
     pub(crate) fn maybe_sized(cx: &mut DocContext<'_>) -> GenericBound {
         let did = cx.tcx.require_lang_item(LangItem::Sized, None);
-        let empty = cx.tcx.intern_substs(&[]);
+        let empty = ty::Binder::dummy(ty::InternalSubsts::empty());
         let path = external_path(cx, did, false, ThinVec::new(), empty);
         inline::record_extern_fqn(cx, did, ItemType::Trait);
         GenericBound::TraitBound(
index 246560bad291ffcc173fd72610030f1138951f75..a12f764fa8e3b739404df7937b83969a10e6bb8f 100644 (file)
@@ -78,12 +78,16 @@ pub(crate) fn krate(cx: &mut DocContext<'_>) -> Crate {
 
 pub(crate) fn substs_to_args<'tcx>(
     cx: &mut DocContext<'tcx>,
-    substs: &[ty::subst::GenericArg<'tcx>],
+    substs: ty::Binder<'tcx, &[ty::subst::GenericArg<'tcx>]>,
     mut skip_first: bool,
 ) -> Vec<GenericArg> {
     let mut ret_val =
-        Vec::with_capacity(substs.len().saturating_sub(if skip_first { 1 } else { 0 }));
-    ret_val.extend(substs.iter().filter_map(|kind| match kind.unpack() {
+        Vec::with_capacity(substs.skip_binder().len().saturating_sub(if skip_first {
+            1
+        } else {
+            0
+        }));
+    ret_val.extend(substs.iter().filter_map(|kind| match kind.skip_binder().unpack() {
         GenericArgKind::Lifetime(lt) => {
             Some(GenericArg::Lifetime(clean_middle_region(lt).unwrap_or(Lifetime::elided())))
         }
@@ -91,8 +95,12 @@ pub(crate) fn substs_to_args<'tcx>(
             skip_first = false;
             None
         }
-        GenericArgKind::Type(ty) => Some(GenericArg::Type(clean_middle_ty(ty, cx, None))),
-        GenericArgKind::Const(ct) => Some(GenericArg::Const(Box::new(clean_middle_const(ct, cx)))),
+        GenericArgKind::Type(ty) => {
+            Some(GenericArg::Type(clean_middle_ty(kind.rebind(ty), cx, None)))
+        }
+        GenericArgKind::Const(ct) => {
+            Some(GenericArg::Const(Box::new(clean_middle_const(kind.rebind(ct), cx))))
+        }
     }));
     ret_val
 }
@@ -102,15 +110,20 @@ fn external_generic_args<'tcx>(
     did: DefId,
     has_self: bool,
     bindings: ThinVec<TypeBinding>,
-    substs: SubstsRef<'tcx>,
+    substs: ty::Binder<'tcx, SubstsRef<'tcx>>,
 ) -> GenericArgs {
-    let args = substs_to_args(cx, substs, has_self);
+    let args = substs_to_args(cx, substs.map_bound(|substs| &substs[..]), has_self);
 
     if cx.tcx.fn_trait_kind_from_def_id(did).is_some() {
+        let ty = substs
+            .iter()
+            .nth(if has_self { 1 } else { 0 })
+            .unwrap()
+            .map_bound(|arg| arg.expect_ty());
         let inputs =
             // The trait's first substitution is the one after self, if there is one.
-            match substs.iter().nth(if has_self { 1 } else { 0 }).unwrap().expect_ty().kind() {
-                ty::Tuple(tys) => tys.iter().map(|t| clean_middle_ty(t, cx, None)).collect::<Vec<_>>().into(),
+            match ty.skip_binder().kind() {
+                ty::Tuple(tys) => tys.iter().map(|t| clean_middle_ty(ty.rebind(t), cx, None)).collect::<Vec<_>>().into(),
                 _ => return GenericArgs::AngleBracketed { args: args.into(), bindings },
             };
         let output = bindings.into_iter().next().and_then(|binding| match binding.kind {
@@ -130,7 +143,7 @@ pub(super) fn external_path<'tcx>(
     did: DefId,
     has_self: bool,
     bindings: ThinVec<TypeBinding>,
-    substs: SubstsRef<'tcx>,
+    substs: ty::Binder<'tcx, SubstsRef<'tcx>>,
 ) -> Path {
     let def_kind = cx.tcx.def_kind(did);
     let name = cx.tcx.item_name(did);
index f21e60a64e0055f87060c44de8b5b492866deb66..2f1f4cbf3592457e7972dc043e04e6b86f27c3ae 100644 (file)
@@ -177,6 +177,9 @@ pub(crate) fn as_str(&self) -> &'static str {
             ItemType::TraitAlias => "traitalias",
         }
     }
+    pub(crate) fn is_method(&self) -> bool {
+        matches!(*self, ItemType::Method | ItemType::TyMethod)
+    }
 }
 
 impl fmt::Display for ItemType {
index 1e1c657b0bf22f7d71306f57099be4ac8d9c3145..b141820fe423c549217a41e58745f56d763009b6 100644 (file)
@@ -236,12 +236,12 @@ fn next(&mut self) -> Option<Self::Item> {
             return event;
         };
 
-        let mut origtext = String::new();
+        let mut original_text = String::new();
         for event in &mut self.inner {
             match event {
                 Event::End(Tag::CodeBlock(..)) => break,
                 Event::Text(ref s) => {
-                    origtext.push_str(s);
+                    original_text.push_str(s);
                 }
                 _ => {}
             }
@@ -258,7 +258,7 @@ fn next(&mut self) -> Option<Self::Item> {
                                  <pre class=\"language-{}\"><code>{}</code></pre>\
                              </div>",
                             lang,
-                            Escape(&origtext),
+                            Escape(&original_text),
                         )
                         .into(),
                     ));
@@ -268,7 +268,7 @@ fn next(&mut self) -> Option<Self::Item> {
             CodeBlockKind::Indented => Default::default(),
         };
 
-        let lines = origtext.lines().filter_map(|l| map_line(l).for_html());
+        let lines = original_text.lines().filter_map(|l| map_line(l).for_html());
         let text = lines.intersperse("\n".into()).collect::<String>();
 
         compile_fail = parse_result.compile_fail;
@@ -285,7 +285,7 @@ fn next(&mut self) -> Option<Self::Item> {
             if url.is_empty() {
                 return None;
             }
-            let test = origtext
+            let test = original_text
                 .lines()
                 .map(|l| map_line(l).for_code())
                 .intersperse("\n".into())
index 73690c86f4f72b97070c9c42718fe47022c2b468..d4d3e4f6ea7952c0399ca2c3e5066d361b222e64 100644 (file)
@@ -637,7 +637,7 @@ fn after_krate(&mut self) -> Result<(), Error> {
                             You need to enable Javascript be able to update your settings.\
                         </section>\
                      </noscript>\
-                     <link rel=\"stylesheet\" type=\"text/css\" \
+                     <link rel=\"stylesheet\" \
                          href=\"{static_root_path}{settings_css}\">\
                      <script defer src=\"{static_root_path}{settings_js}\"></script>",
                     static_root_path = page.get_static_root_path(),
index 36d15ec3b8640cde9642b080ffe1db218dc848a7..80fbe9c1f066c6dbc139027e4235475f15318674 100644 (file)
@@ -1512,8 +1512,7 @@ fn doc_impl_item(
 
         let toggled = !doc_buffer.is_empty();
         if toggled {
-            let method_toggle_class =
-                if item_type == ItemType::Method { " method-toggle" } else { "" };
+            let method_toggle_class = if item_type.is_method() { " method-toggle" } else { "" };
             write!(w, "<details class=\"rustdoc-toggle{}\" open><summary>", method_toggle_class);
         }
         match &*item.kind {
index acbe3f22889cc03d10cf4f541477c8f6a2b9d8f7..a7b57c373e3bec3b4a9219758d8d020f2b1a0642 100644 (file)
@@ -732,7 +732,8 @@ fn trait_item(w: &mut Buffer, cx: &mut Context<'_>, m: &clean::Item, t: &clean::
         document(&mut content, cx, m, Some(t), HeadingOffset::H5);
         let toggled = !content.is_empty();
         if toggled {
-            write!(w, "<details class=\"rustdoc-toggle method-toggle\" open><summary>");
+            let method_toggle_class = if item_type.is_method() { " method-toggle" } else { "" };
+            write!(w, "<details class=\"rustdoc-toggle{method_toggle_class}\" open><summary>");
         }
         write!(w, "<section id=\"{}\" class=\"method has-srclink\">", id);
         render_rightside(w, cx, m, t, RenderMode::Normal);
index 91162ca4892ca0a43caa71b64d54696bee1a69a7..bc1e15b359371be7ae9f83b3861b9bbeaef94697 100644 (file)
@@ -523,7 +523,6 @@ ul.block, .block li {
 }
 
 .source .content pre.rust {
-       overflow: auto;
        padding-left: 0;
 }
 
@@ -586,8 +585,8 @@ ul.block, .block li {
        text-overflow: ellipsis;
 }
 /* Wrap non-pre code blocks (`text`) but not (```text```). */
-.docblock :not(pre) > code,
-.docblock-short code {
+.docblock :not(pre) > code,
+.docblock-short code {
        white-space: pre-wrap;
 }
 
@@ -903,10 +902,11 @@ so that we can apply CSS-filters to change the arrow color in themes */
        top: 100%;
        right: 0;
        z-index: 2;
-       display: block;
        margin-top: 7px;
        border-radius: 3px;
        border: 1px solid var(--border-color);
+       background-color: var(--main-background-color);
+       color: var(--main-color);
        --popover-arrow-offset: 11px;
 }
 
@@ -917,16 +917,12 @@ so that we can apply CSS-filters to change the arrow color in themes */
        right: var(--popover-arrow-offset);
        border: solid var(--border-color);
        border-width: 1px 1px 0 0;
+       background-color: var(--main-background-color);
        padding: 4px;
        transform: rotate(-45deg);
        top: -5px;
 }
 
-.popover, .popover::before {
-       background-color: var(--main-background-color);
-       color: var(--main-color);
-}
-
 /* use larger max-width for help popover, but not for help.html */
 #help.popover {
        max-width: 600px;
@@ -1400,7 +1396,6 @@ kbd {
        vertical-align: middle;
        border: solid 1px var(--border-color);
        border-radius: 3px;
-       cursor: default;
        color: var(--kbd--color);
        background-color: var(--kbd-background);
        box-shadow: inset 0 -1px 0 var(--kbd-box-shadow-color);
@@ -1873,6 +1868,7 @@ in storage.js
 }
 
 .variants > .docblock,
+.implementors-toggle > .docblock,
 .impl-items > .rustdoc-toggle[open]:not(:last-child),
 .methods > .rustdoc-toggle[open]:not(:last-child),
 .implementors-toggle[open]:not(:last-child) {
@@ -1973,7 +1969,6 @@ in storage.js
 }
 
 .scraped-example .code-wrapper .src-line-numbers {
-       margin: 0;
        padding: 14px 0;
 }
 
index eba845bf5a91565f2219f56f71c9eeb8701526a2..a4097c456135dad24cd093f23ad34e489de489a9 100644 (file)
@@ -150,8 +150,6 @@ pre, .rustdoc.source .example-wrap {
        color: #c5c5c5;
 }
 
-.content .item-info::before { color: #ccc; }
-
 .sidebar h2 a,
 .sidebar h3 a {
        color: white;
index d945e956c533e20b52fea54d922924363acd449d..a11aba12e0ac77a739f3cc0144373e451917b489 100644 (file)
@@ -85,8 +85,6 @@
        --table-alt-row-background-color: #2A2A2A;
 }
 
-.content .item-info::before { color: #ccc; }
-
 body.source .example-wrap pre.rust a {
        background: #333;
 }
index 58955a79316af3f2485c68e681ba9ac247454934..f697724468fb3c647794acfdc31fad0ea2c978fa 100644 (file)
@@ -82,8 +82,6 @@
        --table-alt-row-background-color: #F5F5F5;
 }
 
-.content .item-info::before { color: #ccc; }
-
 body.source .example-wrap pre.rust a {
        background: #eee;
 }
index 152116089c7fc2c6f1c400f7f353fb16d879e66d..3f97e4e2e39f05ffbcb47f3f4329f952e69bd4e9 100644 (file)
@@ -184,7 +184,6 @@ function browserSupportsHistoryApi() {
 function loadCss(cssUrl) {
     const link = document.createElement("link");
     link.href = cssUrl;
-    link.type = "text/css";
     link.rel = "stylesheet";
     document.getElementsByTagName("head")[0].appendChild(link);
 }
index 044e051440c52bb9117416d75ca0a3fa52885b86..5f4ad6d2aea345073d79b30dcf5baf38dbfeeda8 100644 (file)
@@ -53,7 +53,7 @@ pub(crate) fn render<P: AsRef<Path>>(
 
     let mut css = String::new();
     for name in &options.markdown_css {
-        write!(css, r#"<link rel="stylesheet" type="text/css" href="{name}">"#)
+        write!(css, r#"<link rel="stylesheet" href="{name}">"#)
             .expect("Writing to a String can't fail");
     }
 
index 37a28b6b7bd84a17282686cdc40dc816d1e70ce6..4f0eb8b8076e5fae8214dfb8a71ace1658385d36 100644 (file)
@@ -538,11 +538,10 @@ fn def_id_to_res(&self, ty_id: DefId) -> Option<Res> {
             ty::Adt(ty::AdtDef(Interned(&ty::AdtDefData { did, .. }, _)), _) | ty::Foreign(did) => {
                 Res::from_def_id(self.cx.tcx, did)
             }
-            ty::Projection(_)
+            ty::Alias(..)
             | ty::Closure(..)
             | ty::Generator(..)
             | ty::GeneratorWitness(_)
-            | ty::Opaque(..)
             | ty::Dynamic(..)
             | ty::Param(_)
             | ty::Bound(..)
index cbbcfad3ef4833016debbc3b8ad3eb299f0fb5b5..e9740e30da483d6a5231c8e47a17fe2a678d015a 100644 (file)
@@ -9,7 +9,7 @@
 // It also validates that functions can be called through function pointers
 // through traits.
 
-#![feature(no_core, lang_items, unboxed_closures, arbitrary_self_types)]
+#![feature(no_core, lang_items, intrinsics, unboxed_closures, arbitrary_self_types)]
 #![crate_type = "lib"]
 #![no_core]
 
@@ -49,6 +49,10 @@ pub trait Fn<Args: Tuple>: FnOnce<Args> {
     extern "rust-call" fn call(&self, args: Args) -> Self::Output;
 }
 
+extern "rust-intrinsic" {
+    pub fn transmute<Src, Dst>(src: Src) -> Dst;
+}
+
 pub static mut STORAGE_FOO: fn(&usize, &mut u32) -> Result<(), ()> = arbitrary_black_box;
 pub static mut STORAGE_BAR: u32 = 12;
 
@@ -87,3 +91,21 @@ pub extern "C" fn test() {
         STORAGE_FOO(&1, &mut buf);
     }
 }
+
+// Validate that we can codegen transmutes between data ptrs and fn ptrs.
+
+// CHECK: define{{.+}}{{void \(\) addrspace\(1\)\*|ptr addrspace\(1\)}} @transmute_data_ptr_to_fn({{\{\}\*|ptr}}{{.*}} %x)
+#[no_mangle]
+pub unsafe fn transmute_data_ptr_to_fn(x: *const ()) -> fn() {
+    // It doesn't matter precisely how this is codegenned (through memory or an addrspacecast),
+    // as long as it doesn't cause a verifier error by using `bitcast`.
+    transmute(x)
+}
+
+// CHECK: define{{.+}}{{\{\}\*|ptr}} @transmute_fn_ptr_to_data({{void \(\) addrspace\(1\)\*|ptr addrspace\(1\)}}{{.*}} %x)
+#[no_mangle]
+pub unsafe fn transmute_fn_ptr_to_data(x: fn()) -> *const () {
+    // It doesn't matter precisely how this is codegenned (through memory or an addrspacecast),
+    // as long as it doesn't cause a verifier error by using `bitcast`.
+    transmute(x)
+}
index a12cd0d021e59cf910896954d410af5c5eae0bec..ada541e644a3130236366d1b562303afe9059f38 100644 (file)
@@ -187,9 +187,9 @@ pub fn change_continue_label() {
 }
 
 #[cfg(not(any(cfail1,cfail4)))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, typeck")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
-#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, typeck, optimized_mir")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
 #[rustc_clean(cfg="cfail6")]
 pub fn change_continue_label() {
     let mut _x = 0;
index f81855e42becbd67a13dc5f45f5b7e7e63a1ed81..88fd4d89b2827661b9d9f74dcaf4be3e5692d4d7 100644 (file)
@@ -158,9 +158,9 @@ pub fn change_break_label() {
 }
 
 #[cfg(not(any(cfail1,cfail4)))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
-#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail6")]
 pub fn change_break_label() {
     let mut _x = 0;
@@ -210,9 +210,9 @@ pub fn change_continue_label() {
 }
 
 #[cfg(not(any(cfail1,cfail4)))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
-#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail6")]
 pub fn change_continue_label() {
     let mut _x = 0;
index e432cf8fe4cc3068753af5b375c1408de6185a59..9b4d23757b871340e7418c03025e449d978ccf63 100644 (file)
@@ -158,9 +158,9 @@ pub fn change_break_label() {
 }
 
 #[cfg(not(any(cfail1,cfail4)))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
-#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail6")]
 pub fn change_break_label() {
     let mut _x = 0;
@@ -212,9 +212,9 @@ pub fn change_continue_label() {
 }
 
 #[cfg(not(any(cfail1,cfail4)))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
-#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail6")]
 pub fn change_continue_label() {
     let mut _x = 0;
index 9f8df44d762ce5f9402b144b6af81320dfec3b1e..3ce921c2c91cb1a3de4aef659a576085852ca4c7 100644 (file)
@@ -7,3 +7,7 @@ show-text: true // We need to enable text draw to be able to have the "real" siz
 // Little explanations for this test: if the text wasn't displayed on two lines, it would take
 // around 20px (which is the font size).
 assert-property: (".docblock p > code", {"offsetHeight": "44"})
+
+// Same check, but where the long code block is also a link
+goto: "file://" + |DOC_PATH| + "/test_docs/long_code_block_link/index.html"
+assert-property: (".docblock p > a > code", {"offsetHeight": "44"})
index fec21ad35c3ebe098cbebcd4d24d7bf1e87d249f..b094c483876410365962462bcc910734c8492814 100644 (file)
@@ -33,7 +33,9 @@ assert-css: ("#settings", {"display": "block"})
 click: "input#line-numbers"
 wait-for: 100 // wait-for-false does not exist
 assert-false: "pre.example-line-numbers"
+assert-local-storage: {"rustdoc-line-numbers": "false" }
 
 // Finally, turn it on again.
 click: "input#line-numbers"
 wait-for: "pre.example-line-numbers"
+assert-local-storage: {"rustdoc-line-numbers": "true" }
index 799ba851c92f9a1aaa7892c758e87bba78d5b182..80203901ed3c4c5c4678d48cd7a3461e4a3f1ca5 100644 (file)
@@ -27,7 +27,6 @@ define-function: (
             "color": |color|,
             "background-color": |background|,
             "box-shadow": |box_shadow| + " 0px -1px 0px 0px inset",
-            "cursor": "default",
         }, ALL)),
     ],
 )
diff --git a/src/test/rustdoc-gui/impl-doc.goml b/src/test/rustdoc-gui/impl-doc.goml
new file mode 100644 (file)
index 0000000..7322032
--- /dev/null
@@ -0,0 +1,9 @@
+// A docblock on an impl must have a margin to separate it from the contents.
+goto: "file://" + |DOC_PATH| + "/test_docs/struct.TypeWithImplDoc.html"
+
+// The text is about 24px tall, so if there's a margin, then their position will be >24px apart
+compare-elements-position-near-false: (
+       "#implementations-list > .implementors-toggle > .docblock > p",
+       "#implementations-list > .implementors-toggle > .impl-items",
+       {"y": 24}
+)
index d6eeab803dfec3c7e9399be5f87f4cb3ba903b54..f1b69d4dc1d40ba174e47ff29422f24033ce7279 100644 (file)
@@ -154,6 +154,11 @@ pub mod huge_amount_of_consts {
 /// Very long code text `hereIgoWithLongTextBecauseWhyNotAndWhyWouldntI`.
 pub mod long_code_block {}
 
+/// Very long code text [`hereIgoWithLongTextBecauseWhyNotAndWhyWouldntI`][lnk].
+///
+/// [lnk]: crate::long_code_block_link
+pub mod long_code_block_link {}
+
 #[macro_export]
 macro_rules! repro {
     () => {};
@@ -442,3 +447,11 @@ fn function() {}
         fn function2() {}
     }
 }
+
+pub struct TypeWithImplDoc;
+
+/// impl doc
+impl TypeWithImplDoc {
+    /// fn doc
+    pub fn test_fn() {}
+}
index 94cf7b94241df8d79144969b852f538de8ccfa88..3537e669608d15faf6afbcc26b5410b865225720 100644 (file)
@@ -35,6 +35,7 @@
     -Z            dump-mir-exclude-pass-number=val -- exclude the pass number when dumping MIR (used in tests) (default: no)
     -Z                       dump-mir-graphviz=val -- in addition to `.mir` files, create graphviz `.dot` files (and with `-Z instrument-coverage`, also create a `.dot` file for the MIR-derived coverage graph) (default: no)
     -Z                       dump-mir-spanview=val -- in addition to `.mir` files, create `.html` files to view spans for all `statement`s (including terminators), only `terminator` spans, or computed `block` spans (one span encompassing a block's terminator and all statements). If `-Z instrument-coverage` is also enabled, create an additional `.html` file showing the computed coverage spans.
+    -Z                         dump-mono-stats=val -- output statistics about monomorphization collection (format: markdown)
     -Z                           dwarf-version=val -- version of DWARF debug information to emit (default: 2 or 4, depending on platform)
     -Z                               dylib-lto=val -- enables LTO for dylib crate type
     -Z                        emit-stack-sizes=val -- emit a section containing stack size metadata (default: no)
index e41422ce7c516b5033d7185ce068dce5b9f1e6f6..0a1f088b9ab5c8fb830f55120be7a6fb3d6b2f64 100644 (file)
@@ -4,6 +4,8 @@
 // summary. Trait methods with no documentation should not be wrapped.
 //
 // @has foo/trait.Foo.html
+// @has - '//details[@class="rustdoc-toggle"]//summary//h4[@class="code-header"]' 'type Item'
+// @!has - '//details[@class="rustdoc-toggle"]//summary//h4[@class="code-header"]' 'type Item2'
 // @has -  '//details[@class="rustdoc-toggle method-toggle"]//summary//h4[@class="code-header"]' 'is_documented()'
 // @!has - '//details[@class="rustdoc-toggle method-toggle"]//summary//h4[@class="code-header"]' 'not_documented()'
 // @has -  '//details[@class="rustdoc-toggle method-toggle"]//*[@class="docblock"]' 'is_documented is documented'
 // @!has - '//details[@class="rustdoc-toggle method-toggle"]//summary//h4[@class="code-header"]' 'not_documented_optional()'
 // @has -  '//details[@class="rustdoc-toggle method-toggle"]//*[@class="docblock"]' 'is_documented_optional is documented'
 pub trait Foo {
+    /// is documented
+    type Item;
+
+    type Item2;
+
     fn not_documented();
 
     /// is_documented is documented
index 2cb1ed6fcb76b349133493d7a627d91ba157e16a..3f7429a5fccf83cef8b9f289ac2b1d1c36527125 100644 (file)
@@ -33,8 +33,7 @@ fn main() {
         TyKind::GeneratorWitness(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
         TyKind::Never => (),                //~ ERROR usage of `ty::TyKind::<kind>`
         TyKind::Tuple(..) => (),            //~ ERROR usage of `ty::TyKind::<kind>`
-        TyKind::Projection(..) => (),       //~ ERROR usage of `ty::TyKind::<kind>`
-        TyKind::Opaque(..) => (),           //~ ERROR usage of `ty::TyKind::<kind>`
+        TyKind::Alias(..) => (),            //~ ERROR usage of `ty::TyKind::<kind>`
         TyKind::Param(..) => (),            //~ ERROR usage of `ty::TyKind::<kind>`
         TyKind::Bound(..) => (),            //~ ERROR usage of `ty::TyKind::<kind>`
         TyKind::Placeholder(..) => (),      //~ ERROR usage of `ty::TyKind::<kind>`
index 171f49087d6953fc4818eafa7c00b7794fa7a038..1f49d6b64646f0282b4d214c63f6ecd69f0e1a60 100644 (file)
@@ -133,53 +133,47 @@ LL |         TyKind::Tuple(..) => (),
 error: usage of `ty::TyKind::<kind>`
   --> $DIR/ty_tykind_usage.rs:36:9
    |
-LL |         TyKind::Projection(..) => (),
+LL |         TyKind::Alias(..) => (),
    |         ^^^^^^ help: try using `ty::<kind>` directly: `ty`
 
 error: usage of `ty::TyKind::<kind>`
   --> $DIR/ty_tykind_usage.rs:37:9
    |
-LL |         TyKind::Opaque(..) => (),
-   |         ^^^^^^ help: try using `ty::<kind>` directly: `ty`
-
-error: usage of `ty::TyKind::<kind>`
-  --> $DIR/ty_tykind_usage.rs:38:9
-   |
 LL |         TyKind::Param(..) => (),
    |         ^^^^^^ help: try using `ty::<kind>` directly: `ty`
 
 error: usage of `ty::TyKind::<kind>`
-  --> $DIR/ty_tykind_usage.rs:39:9
+  --> $DIR/ty_tykind_usage.rs:38:9
    |
 LL |         TyKind::Bound(..) => (),
    |         ^^^^^^ help: try using `ty::<kind>` directly: `ty`
 
 error: usage of `ty::TyKind::<kind>`
-  --> $DIR/ty_tykind_usage.rs:40:9
+  --> $DIR/ty_tykind_usage.rs:39:9
    |
 LL |         TyKind::Placeholder(..) => (),
    |         ^^^^^^ help: try using `ty::<kind>` directly: `ty`
 
 error: usage of `ty::TyKind::<kind>`
-  --> $DIR/ty_tykind_usage.rs:41:9
+  --> $DIR/ty_tykind_usage.rs:40:9
    |
 LL |         TyKind::Infer(..) => (),
    |         ^^^^^^ help: try using `ty::<kind>` directly: `ty`
 
 error: usage of `ty::TyKind::<kind>`
-  --> $DIR/ty_tykind_usage.rs:42:9
+  --> $DIR/ty_tykind_usage.rs:41:9
    |
 LL |         TyKind::Error(_) => (),
    |         ^^^^^^ help: try using `ty::<kind>` directly: `ty`
 
 error: usage of `ty::TyKind::<kind>`
-  --> $DIR/ty_tykind_usage.rs:47:12
+  --> $DIR/ty_tykind_usage.rs:46:12
    |
 LL |     if let TyKind::Int(int_ty) = kind {}
    |            ^^^^^^ help: try using `ty::<kind>` directly: `ty`
 
 error: usage of `ty::TyKind`
-  --> $DIR/ty_tykind_usage.rs:49:24
+  --> $DIR/ty_tykind_usage.rs:48:24
    |
 LL |     fn ty_kind(ty_bad: TyKind<'_>, ty_good: Ty<'_>) {}
    |                        ^^^^^^^^^^
@@ -187,7 +181,7 @@ LL |     fn ty_kind(ty_bad: TyKind<'_>, ty_good: Ty<'_>) {}
    = help: try using `Ty` instead
 
 error: usage of `ty::TyKind`
-  --> $DIR/ty_tykind_usage.rs:51:37
+  --> $DIR/ty_tykind_usage.rs:50:37
    |
 LL |     fn ir_ty_kind<I: Interner>(bad: IrTyKind<I>) -> IrTyKind<I> {
    |                                     ^^^^^^^^^^^
@@ -195,7 +189,7 @@ LL |     fn ir_ty_kind<I: Interner>(bad: IrTyKind<I>) -> IrTyKind<I> {
    = help: try using `Ty` instead
 
 error: usage of `ty::TyKind`
-  --> $DIR/ty_tykind_usage.rs:51:53
+  --> $DIR/ty_tykind_usage.rs:50:53
    |
 LL |     fn ir_ty_kind<I: Interner>(bad: IrTyKind<I>) -> IrTyKind<I> {
    |                                                     ^^^^^^^^^^^
@@ -203,12 +197,12 @@ LL |     fn ir_ty_kind<I: Interner>(bad: IrTyKind<I>) -> IrTyKind<I> {
    = help: try using `Ty` instead
 
 error: usage of `ty::TyKind::<kind>`
-  --> $DIR/ty_tykind_usage.rs:54:9
+  --> $DIR/ty_tykind_usage.rs:53:9
    |
 LL |         IrTyKind::Bool
    |         --------^^^^^^
    |         |
    |         help: try using `ty::<kind>` directly: `ty`
 
-error: aborting due to 33 previous errors
+error: aborting due to 32 previous errors
 
index cb4cd466590b626e5e2553dacda2df9e2047af42..c19b639a8d5819d1f84a23f9330cbd7a4f02f03d 100644 (file)
@@ -683,7 +683,7 @@ struct RawIdentDiagnosticArg {
 #[diag(compiletest_example)]
 struct SubdiagnosticBad {
     #[subdiagnostic(bad)]
-    //~^ ERROR `#[subdiagnostic(bad)]` is not a valid attribute
+    //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute
     note: Note,
 }
 
@@ -707,7 +707,7 @@ struct SubdiagnosticBadTwice {
 #[diag(compiletest_example)]
 struct SubdiagnosticBadLitStr {
     #[subdiagnostic("bad")]
-    //~^ ERROR `#[subdiagnostic("...")]` is not a valid attribute
+    //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute
     note: Note,
 }
 
@@ -723,6 +723,7 @@ struct SubdiagnosticEagerLint {
 #[diag(compiletest_example)]
 struct SubdiagnosticEagerCorrect {
     #[subdiagnostic(eager)]
+    //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute
     note: Note,
 }
 
@@ -743,6 +744,7 @@ pub(crate) struct SubdiagnosticWithSuggestion {
 #[diag(compiletest_example)]
 struct SubdiagnosticEagerSuggestion {
     #[subdiagnostic(eager)]
+    //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute
     sub: SubdiagnosticWithSuggestion,
 }
 
index b4c211db47cd9e090bdc8e6f5fc3e8be399628d9..f39d32a221cacc1084bbecd15b635a1ef43a7fb9 100644 (file)
@@ -533,21 +533,19 @@ LL | #[label]
    |
    = help: `#[label]` and `#[suggestion]` can only be applied to fields
 
-error: `#[subdiagnostic(bad)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:685:21
+error: `#[subdiagnostic(...)]` is not a valid attribute
+  --> $DIR/diagnostic-derive.rs:685:5
    |
 LL |     #[subdiagnostic(bad)]
-   |                     ^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: `eager` is the only supported nested attribute for `subdiagnostic`
+   = help: `subdiagnostic` does not support nested attributes
 
 error: `#[subdiagnostic = ...]` is not a valid attribute
   --> $DIR/diagnostic-derive.rs:693:5
    |
 LL |     #[subdiagnostic = "bad"]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: `eager` is the only supported nested attribute for `subdiagnostic`
 
 error: `#[subdiagnostic(...)]` is not a valid attribute
   --> $DIR/diagnostic-derive.rs:701:5
@@ -555,15 +553,15 @@ error: `#[subdiagnostic(...)]` is not a valid attribute
 LL |     #[subdiagnostic(bad, bad)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: `eager` is the only supported nested attribute for `subdiagnostic`
+   = help: `subdiagnostic` does not support nested attributes
 
-error: `#[subdiagnostic("...")]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:709:21
+error: `#[subdiagnostic(...)]` is not a valid attribute
+  --> $DIR/diagnostic-derive.rs:709:5
    |
 LL |     #[subdiagnostic("bad")]
-   |                     ^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: `eager` is the only supported nested attribute for `subdiagnostic`
+   = help: `subdiagnostic` does not support nested attributes
 
 error: `#[subdiagnostic(...)]` is not a valid attribute
   --> $DIR/diagnostic-derive.rs:717:5
@@ -571,22 +569,38 @@ error: `#[subdiagnostic(...)]` is not a valid attribute
 LL |     #[subdiagnostic(eager)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: eager subdiagnostics are not supported on lints
+   = help: `subdiagnostic` does not support nested attributes
+
+error: `#[subdiagnostic(...)]` is not a valid attribute
+  --> $DIR/diagnostic-derive.rs:725:5
+   |
+LL |     #[subdiagnostic(eager)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `subdiagnostic` does not support nested attributes
+
+error: `#[subdiagnostic(...)]` is not a valid attribute
+  --> $DIR/diagnostic-derive.rs:746:5
+   |
+LL |     #[subdiagnostic(eager)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `subdiagnostic` does not support nested attributes
 
 error: expected at least one string literal for `code(...)`
-  --> $DIR/diagnostic-derive.rs:775:18
+  --> $DIR/diagnostic-derive.rs:777:18
    |
 LL |     #[suggestion(code())]
    |                  ^^^^^^
 
 error: `code(...)` must contain only string literals
-  --> $DIR/diagnostic-derive.rs:783:23
+  --> $DIR/diagnostic-derive.rs:785:23
    |
 LL |     #[suggestion(code(foo))]
    |                       ^^^
 
 error: `code = "..."`/`code(...)` must contain only string literals
-  --> $DIR/diagnostic-derive.rs:791:18
+  --> $DIR/diagnostic-derive.rs:793:18
    |
 LL |     #[suggestion(code = 3)]
    |                  ^^^^^^^^
@@ -660,12 +674,9 @@ LL | #[derive(Diagnostic)]
    = help: normalized in stderr
 note: required by a bound in `DiagnosticBuilder::<'a, G>::set_arg`
   --> $COMPILER_DIR/rustc_errors/src/diagnostic_builder.rs:LL:CC
-   |
-LL |         arg: impl IntoDiagnosticArg,
-   |                   ^^^^^^^^^^^^^^^^^ required by this bound in `DiagnosticBuilder::<'a, G>::set_arg`
-   = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the derive macro `Diagnostic` which comes from the expansion of the macro `forward` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 83 previous errors
+error: aborting due to 85 previous errors
 
 Some errors have detailed explanations: E0277, E0425.
 For more information about an error, try `rustc --explain E0277`.
index adb652fe61659bcf94a699b7dc6b427980a81cd8..2673ee9f937fb1e87bee5d6ebf36c177d097622b 100644 (file)
@@ -17,9 +17,6 @@ LL | |  }
    = note: struct `core::alloc::Layout` and struct `Layout` have similar names, but are actually distinct types
 note: struct `core::alloc::Layout` is defined in crate `core`
   --> $SRC_DIR/core/src/alloc/layout.rs:LL:COL
-   |
-LL | pub struct Layout {
-   | ^^^^^^^^^^^^^^^^^
 note: struct `Layout` is defined in the current crate
   --> $DIR/alloc-error-handler-bad-signature-2.rs:7:1
    |
index bf5f642ca823d61b6e0517308a3c72bbccce8327..afb7f8fea92a1fae2aa6c205b9e55849c3720ddb 100644 (file)
@@ -13,6 +13,10 @@ note: required by a bound in `f1`
    |
 LL | fn f1<F>(_: F) where F: Fn(&(), &()) {}
    |                         ^^^^^^^^^^^^ required by this bound in `f1`
+help: consider borrowing the argument
+   |
+LL |     f1(|_: &(), _: &()| {});
+   |            ~~~     ~~~
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:3:5
@@ -29,6 +33,10 @@ note: required by a bound in `f2`
    |
 LL | fn f2<F>(_: F) where F: for<'a> Fn(&'a (), &()) {}
    |                         ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `f2`
+help: consider borrowing the argument
+   |
+LL |     f2(|_: &'a (), _: &()| {});
+   |            ~~~~~~     ~~~
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:4:5
@@ -45,6 +53,10 @@ note: required by a bound in `f3`
    |
 LL | fn f3<'a, F>(_: F) where F: Fn(&'a (), &()) {}
    |                             ^^^^^^^^^^^^^^^ required by this bound in `f3`
+help: consider borrowing the argument
+   |
+LL |     f3(|_: &(), _: &()| {});
+   |            ~~~     ~~~
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:5:5
@@ -61,6 +73,10 @@ note: required by a bound in `f4`
    |
 LL | fn f4<F>(_: F) where F: for<'r> Fn(&(), &'r ()) {}
    |                         ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `f4`
+help: consider borrowing the argument
+   |
+LL |     f4(|_: &(), _: &'r ()| {});
+   |            ~~~     ~~~~~~
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:6:5
@@ -77,13 +93,19 @@ note: required by a bound in `f5`
    |
 LL | fn f5<F>(_: F) where F: for<'r> Fn(&'r (), &'r ()) {}
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `f5`
+help: consider borrowing the argument
+   |
+LL |     f5(|_: &'r (), _: &'r ()| {});
+   |            ~~~~~~     ~~~~~~
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:7:5
    |
 LL |     g1(|_: (), _: ()| {});
-   |     ^^ -------------- found signature defined here
-   |     |
+   |     ^^ --------------
+   |     |  |   |
+   |     |  |   help: consider borrowing the argument: `&()`
+   |     |  found signature defined here
    |     expected due to this
    |
    = note: expected closure signature `for<'a> fn(&'a (), Box<(dyn for<'a> Fn(&'a ()) + 'static)>) -> _`
@@ -98,8 +120,10 @@ error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:8:5
    |
 LL |     g2(|_: (), _: ()| {});
-   |     ^^ -------------- found signature defined here
-   |     |
+   |     ^^ --------------
+   |     |  |   |
+   |     |  |   help: consider borrowing the argument: `&()`
+   |     |  found signature defined here
    |     expected due to this
    |
    = note: expected closure signature `for<'a> fn(&'a (), for<'a> fn(&'a ())) -> _`
@@ -114,8 +138,10 @@ error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:9:5
    |
 LL |     g3(|_: (), _: ()| {});
-   |     ^^ -------------- found signature defined here
-   |     |
+   |     ^^ --------------
+   |     |  |   |
+   |     |  |   help: consider borrowing the argument: `&'s ()`
+   |     |  found signature defined here
    |     expected due to this
    |
    = note: expected closure signature `for<'s> fn(&'s (), Box<(dyn for<'a> Fn(&'a ()) + 'static)>) -> _`
@@ -130,8 +156,10 @@ error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:10:5
    |
 LL |     g4(|_: (), _: ()| {});
-   |     ^^ -------------- found signature defined here
-   |     |
+   |     ^^ --------------
+   |     |  |   |
+   |     |  |   help: consider borrowing the argument: `&()`
+   |     |  found signature defined here
    |     expected due to this
    |
    = note: expected closure signature `for<'a> fn(&'a (), for<'r> fn(&'r ())) -> _`
@@ -157,6 +185,10 @@ note: required by a bound in `h1`
    |
 LL | fn h1<F>(_: F) where F: Fn(&(), Box<dyn Fn(&())>, &(), fn(&(), &())) {}
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `h1`
+help: consider borrowing the argument
+   |
+LL |     h1(|_: &(), _: (), _: &(), _: ()| {});
+   |            ~~~            ~~~
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:12:5
@@ -173,6 +205,10 @@ note: required by a bound in `h2`
    |
 LL | fn h2<F>(_: F) where F: for<'t0> Fn(&(), Box<dyn Fn(&())>, &'t0 (), fn(&(), &())) {}
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `h2`
+help: consider borrowing the argument
+   |
+LL |     h2(|_: &(), _: (), _: &'t0 (), _: ()| {});
+   |            ~~~            ~~~~~~~
 
 error: aborting due to 11 previous errors
 
diff --git a/src/test/ui/argument-suggestions/display-is-suggestable.rs b/src/test/ui/argument-suggestions/display-is-suggestable.rs
new file mode 100644 (file)
index 0000000..d765bc4
--- /dev/null
@@ -0,0 +1,8 @@
+use std::fmt::Display;
+
+fn foo(x: &(dyn Display + Send)) {}
+
+fn main() {
+    foo();
+    //~^ ERROR this function takes 1 argument but 0 arguments were supplied
+}
diff --git a/src/test/ui/argument-suggestions/display-is-suggestable.stderr b/src/test/ui/argument-suggestions/display-is-suggestable.stderr
new file mode 100644 (file)
index 0000000..edd72b5
--- /dev/null
@@ -0,0 +1,19 @@
+error[E0061]: this function takes 1 argument but 0 arguments were supplied
+  --> $DIR/display-is-suggestable.rs:6:5
+   |
+LL |     foo();
+   |     ^^^-- an argument of type `&dyn std::fmt::Display + Send` is missing
+   |
+note: function defined here
+  --> $DIR/display-is-suggestable.rs:3:4
+   |
+LL | fn foo(x: &(dyn Display + Send)) {}
+   |    ^^^ ------------------------
+help: provide the argument
+   |
+LL |     foo(/* &dyn std::fmt::Display + Send */);
+   |        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0061`.
index 919550cac3087df1ee0e968f8c56eeb6c78d4215..c2a509a196344b910131329e9e49d6de0971d92b 100644 (file)
@@ -6,8 +6,8 @@ LL |     let [_, _] = a.into();
    |
 help: consider giving this pattern a type
    |
-LL |     let [_, _]: _ = a.into();
-   |               +++
+LL |     let [_, _]: /* Type */ = a.into();
+   |               ++++++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/associated-item/issue-105449.rs b/src/test/ui/associated-item/issue-105449.rs
new file mode 100644 (file)
index 0000000..dd14e05
--- /dev/null
@@ -0,0 +1,59 @@
+// check-pass
+// compile-flags: -C debug_assertions=yes -Zunstable-options
+
+#[allow(dead_code)]
+fn problematic_function<Space>()
+where
+    DefaultAlloc: FinAllok<R1, Space>,
+{
+    let e = Edge2dElement;
+    let _ = Into::<Point>::into(e.map_reference_coords());
+}
+impl<N> Allocator<N, R0> for DefaultAlloc {
+    type Buffer = MStorage;
+}
+impl<N> Allocator<N, R1> for DefaultAlloc {
+    type Buffer = MStorage;
+}
+impl<N, D> From<VectorN<N, D>> for Point
+where
+    DefaultAlloc: Allocator<N, D>,
+{
+    fn from(_: VectorN<N, D>) -> Self {
+        unimplemented!()
+    }
+}
+impl<GeometryDim, NodalDim> FinAllok<GeometryDim, NodalDim> for DefaultAlloc
+where
+    DefaultAlloc: Allocator<Ure, GeometryDim>,
+    DefaultAlloc: Allocator<Ure, NodalDim>
+{
+}
+impl FiniteElement<R1> for Edge2dElement {
+    fn map_reference_coords(&self) -> VectorN<Ure, R1> {
+        unimplemented!()
+    }
+}
+type VectorN<N, R> = (N, R, <DefaultAlloc as Allocator<N, R>>::Buffer);
+struct DefaultAlloc;
+struct R0;
+struct R1;
+struct MStorage;
+struct Point;
+struct Edge2dElement;
+struct Ure;
+trait Allocator<N, R> {
+    type Buffer;
+}
+trait FinAllok<GeometryDim, NodalDim>:
+    Allocator<Ure, GeometryDim> +
+    Allocator<Ure, NodalDim> +
+{
+}
+trait FiniteElement<Rau>
+where
+    DefaultAlloc: FinAllok<Rau, Rau>,
+{
+    fn map_reference_coords(&self) -> VectorN<Ure, Rau>;
+}
+fn main() {}
diff --git a/src/test/ui/associated-type-bounds/const-projection-err.gce.stderr b/src/test/ui/associated-type-bounds/const-projection-err.gce.stderr
new file mode 100644 (file)
index 0000000..0f1ec9a
--- /dev/null
@@ -0,0 +1,24 @@
+warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/const-projection-err.rs:4:26
+   |
+LL | #![cfg_attr(gce, feature(generic_const_exprs))]
+   |                          ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0271]: type mismatch resolving `<T as TraitWAssocConst>::A == 1`
+  --> $DIR/const-projection-err.rs:14:11
+   |
+LL |     foo::<T>();
+   |           ^ expected `0`, found `1`
+   |
+note: required by a bound in `foo`
+  --> $DIR/const-projection-err.rs:11:28
+   |
+LL | fn foo<T: TraitWAssocConst<A = 1>>() {}
+   |                            ^^^^^ required by this bound in `foo`
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/src/test/ui/associated-type-bounds/const-projection-err.rs b/src/test/ui/associated-type-bounds/const-projection-err.rs
new file mode 100644 (file)
index 0000000..bead856
--- /dev/null
@@ -0,0 +1,18 @@
+// revisions: stock gce
+
+#![feature(associated_const_equality)]
+#![cfg_attr(gce, feature(generic_const_exprs))]
+//[gce]~^ WARN the feature `generic_const_exprs` is incomplete
+
+trait TraitWAssocConst {
+    const A: usize;
+}
+
+fn foo<T: TraitWAssocConst<A = 1>>() {}
+
+fn bar<T: TraitWAssocConst<A = 0>>() {
+    foo::<T>();
+    //~^ ERROR type mismatch resolving `<T as TraitWAssocConst>::A == 1`
+}
+
+fn main() {}
diff --git a/src/test/ui/associated-type-bounds/const-projection-err.stock.stderr b/src/test/ui/associated-type-bounds/const-projection-err.stock.stderr
new file mode 100644 (file)
index 0000000..bf08242
--- /dev/null
@@ -0,0 +1,17 @@
+error[E0271]: type mismatch resolving `<T as TraitWAssocConst>::A == 1`
+  --> $DIR/const-projection-err.rs:14:11
+   |
+LL |     foo::<T>();
+   |           ^ expected `1`, found `<T as TraitWAssocConst>::A`
+   |
+   = note: expected constant `1`
+              found constant `<T as TraitWAssocConst>::A`
+note: required by a bound in `foo`
+  --> $DIR/const-projection-err.rs:11:28
+   |
+LL | fn foo<T: TraitWAssocConst<A = 1>>() {}
+   |                            ^^^^^ required by this bound in `foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0271`.
index 1c20ead0556593267c0de5ff5de5e0e81c38309e..dc93c47dace2331381d8445925cde9e9befe1eea 100644 (file)
@@ -15,9 +15,6 @@ LL | fn get_iter(vec: &[i32]) -> impl Iterator<Item = {}> + '_ {
    |
 note: associated type defined here
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |     type Item;
-   |     ^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
index 26b9f4b3a92660ea78b923adb3884545ea4eb81a..fed60ccf089d05c85288a7ef3774506f7d2dbd96 100644 (file)
@@ -4,5 +4,5 @@
 
 fn main() {
     let _: &dyn I32Iterator<Item = u32> = &vec![42].into_iter();
-    //~^ ERROR expected `std::vec::IntoIter<u32>` to be an iterator that yields `i32`, but it yields `u32`
+    //~^ ERROR expected `IntoIter<u32>` to be an iterator that yields `i32`, but it yields `u32`
 }
index 2d25f68de44ad1c34a7c36976ce21a9300699deb..a28a0b74e4accd98c47bbf6f001d9562560f4ff8 100644 (file)
@@ -1,4 +1,4 @@
-error[E0271]: expected `std::vec::IntoIter<u32>` to be an iterator that yields `i32`, but it yields `u32`
+error[E0271]: expected `IntoIter<u32>` to be an iterator that yields `i32`, but it yields `u32`
   --> $DIR/associated-types-overridden-binding-2.rs:6:43
    |
 LL |     let _: &dyn I32Iterator<Item = u32> = &vec![42].into_iter();
index 8455f88f18e7a996cac6562c274689a65d7014f2..fc830b8d6768657f9ef06dc1a29b89088ac2d090 100644 (file)
@@ -7,9 +7,6 @@ LL |     type Ty = Vec<[u8]>;
    = help: the trait `Sized` is not implemented for `[u8]`
 note: required by a bound in `Vec`
   --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
-   |
-LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
-   |                ^ required by this bound in `Vec`
 
 error: aborting due to previous error
 
index 0edc9a556b7f6090402256492f1069d6fe7aad27..8e7cf86c4066f112e8125e443e759ebb606f0957 100644 (file)
@@ -6,9 +6,6 @@ LL | trait ArithmeticOps: Add<Output=Self> + Sub<Output=Self> + Mul<Output=Self>
    |
 note: required by a bound in `Add`
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL | pub trait Add<Rhs = Self> {
-   |               ^^^^^^^^^^ required by this bound in `Add`
 help: consider further restricting `Self`
    |
 LL | trait ArithmeticOps: Add<Output=Self> + Sub<Output=Self> + Mul<Output=Self> + Div<Output=Self> + Sized {}
index 616623ee07759eeabd7c7fb4dc211d435aedd462..f0f5245a3b42ba5d395058ed9bad1037146056b0 100644 (file)
@@ -68,14 +68,10 @@ note: future is not `Send` as this value is used across an await
   --> $DIR/async-await-let-else.rs:33:28
    |
 LL |         (Rc::new(()), bar().await);
-   |          -----------       ^^^^^^ await occurs here, with `Rc::new(())` maybe used later
-   |          |
+   |          -----------       ^^^^^^ - `Rc::new(())` is later dropped here
+   |          |                 |
+   |          |                 await occurs here, with `Rc::new(())` maybe used later
    |          has type `Rc<()>` which is not `Send`
-note: `Rc::new(())` is later dropped here
-  --> $DIR/async-await-let-else.rs:33:35
-   |
-LL |         (Rc::new(()), bar().await);
-   |                                   ^
 note: required by a bound in `is_send`
   --> $DIR/async-await-let-else.rs:19:15
    |
index 7f93563e28842119a6b983edbf1418a09b5955ec..d3c5e80a30df443ee5cf66c942c445ba95cec701 100644 (file)
@@ -53,14 +53,10 @@ note: future is not `Send` as this value is used across an await
   --> $DIR/async-await-let-else.rs:33:28
    |
 LL |         (Rc::new(()), bar().await);
-   |          -----------       ^^^^^^ await occurs here, with `Rc::new(())` maybe used later
-   |          |
+   |          -----------       ^^^^^^ - `Rc::new(())` is later dropped here
+   |          |                 |
+   |          |                 await occurs here, with `Rc::new(())` maybe used later
    |          has type `Rc<()>` which is not `Send`
-note: `Rc::new(())` is later dropped here
-  --> $DIR/async-await-let-else.rs:33:35
-   |
-LL |         (Rc::new(()), bar().await);
-   |                                   ^
 note: required by a bound in `is_send`
   --> $DIR/async-await-let-else.rs:19:15
    |
index 1686153acf9a63aa8a9cddb14e64f0a990a5cade..963c6ba57adf89448eac3463e72257edc5a0cbd1 100644 (file)
@@ -12,9 +12,6 @@ LL |     fun(async {}, async {});
               found `async` block `[async block@$DIR/generator-desc.rs:10:19: 10:27]`
 note: function defined here
   --> $SRC_DIR/core/src/future/mod.rs:LL:COL
-   |
-LL | pub const fn identity_future<O, Fut: Future<Output = O>>(f: Fut) -> Fut {
-   |              ^^^^^^^^^^^^^^^
 
 error[E0308]: mismatched types
   --> $DIR/generator-desc.rs:12:16
index 61d7e2520eab7a8cea7c3f8f97fd2a932aa4d5bd..1b1b3cffd58f3d81f2eccfd6d53a374a64c272aa 100644 (file)
@@ -1,4 +1,3 @@
-// check-pass
 // edition: 2021
 
 #![feature(async_fn_in_trait)]
@@ -13,11 +12,9 @@ trait MyTrait {
 }
 
 impl MyTrait for i32 {
-    // This will break once a PR that implements #102745 is merged
     fn foo(&self) -> Pin<Box<dyn Future<Output = i32> + '_>> {
-        Box::pin(async {
-            *self
-        })
+        //~^ ERROR method `foo` should be async
+        Box::pin(async { *self })
     }
 }
 
diff --git a/src/test/ui/async-await/in-trait/async-example-desugared-boxed.stderr b/src/test/ui/async-await/in-trait/async-example-desugared-boxed.stderr
new file mode 100644 (file)
index 0000000..60fa534
--- /dev/null
@@ -0,0 +1,11 @@
+error: method `foo` should be async because the method from the trait is async
+  --> $DIR/async-example-desugared-boxed.rs:15:5
+   |
+LL |     async fn foo(&self) -> i32;
+   |     --------------------------- required because the trait method is async
+...
+LL |     fn foo(&self) -> Pin<Box<dyn Future<Output = i32> + '_>> {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/async-await/in-trait/async-example-desugared-extra.rs b/src/test/ui/async-await/in-trait/async-example-desugared-extra.rs
new file mode 100644 (file)
index 0000000..81e1e59
--- /dev/null
@@ -0,0 +1,37 @@
+// check-pass
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![feature(return_position_impl_trait_in_trait)]
+#![allow(incomplete_features)]
+
+use std::future::Future;
+use std::pin::Pin;
+use std::task::Poll;
+
+trait MyTrait {
+    async fn foo(&self) -> i32;
+}
+
+#[derive(Clone)]
+struct MyFuture(i32);
+
+impl Future for MyFuture {
+    type Output = i32;
+    fn poll(
+        self: Pin<&mut Self>,
+        _: &mut std::task::Context<'_>,
+    ) -> Poll<<Self as Future>::Output> {
+        Poll::Ready(self.0)
+    }
+}
+
+impl MyTrait for i32 {
+    // FIXME: this should eventually require `#[refine]` to compile, because it also provides
+    // `Clone`.
+    fn foo(&self) -> impl Future<Output = i32> + Clone {
+        MyFuture(*self)
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/async-await/in-trait/async-example-desugared-manual.rs b/src/test/ui/async-await/in-trait/async-example-desugared-manual.rs
new file mode 100644 (file)
index 0000000..71473e7
--- /dev/null
@@ -0,0 +1,29 @@
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![feature(return_position_impl_trait_in_trait)]
+#![allow(incomplete_features)]
+
+use std::future::Future;
+use std::task::Poll;
+
+trait MyTrait {
+    async fn foo(&self) -> i32;
+}
+
+struct MyFuture;
+impl Future for MyFuture {
+    type Output = i32;
+    fn poll(self: std::pin::Pin<&mut Self>, _: &mut std::task::Context<'_>) -> Poll<Self::Output> {
+        Poll::Ready(0)
+    }
+}
+
+impl MyTrait for u32 {
+    fn foo(&self) -> MyFuture {
+        //~^ ERROR method `foo` should be async
+        MyFuture
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/async-await/in-trait/async-example-desugared-manual.stderr b/src/test/ui/async-await/in-trait/async-example-desugared-manual.stderr
new file mode 100644 (file)
index 0000000..567a36a
--- /dev/null
@@ -0,0 +1,11 @@
+error: method `foo` should be async because the method from the trait is async
+  --> $DIR/async-example-desugared-manual.rs:23:5
+   |
+LL |     async fn foo(&self) -> i32;
+   |     --------------------------- required because the trait method is async
+...
+LL |     fn foo(&self) -> MyFuture {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
index 1313c9edd861c213850af2725cadc84f52146fed..fb92ec786746f9cb9ba3c18b0c9a239da183fa1e 100644 (file)
@@ -12,11 +12,8 @@ trait MyTrait {
 }
 
 impl MyTrait for i32 {
-    // This will break once a PR that implements #102745 is merged
     fn foo(&self) -> impl Future<Output = i32> + '_ {
-        async {
-            *self
-        }
+        async { *self }
     }
 }
 
index f94d32145a290297c1750035ba89297ecf8220eb..9598d53bce8b2ec02cd2f6e91086eb8560b90595 100644 (file)
@@ -9,7 +9,7 @@ trait MyTrait {
 
 impl MyTrait for i32 {
     fn foo(&self) -> i32 {
-        //~^ ERROR: `i32` is not a future [E0277]
+        //~^ ERROR: method `foo` should be async
         *self
     }
 }
index 03321dc5b5af16a4ccbd9baa3f78fb005151201b..579801d0f3975cf89a8bbe03eae3dd7f9837fadc 100644 (file)
@@ -1,17 +1,11 @@
-error[E0277]: `i32` is not a future
-  --> $DIR/fn-not-async-err.rs:11:22
-   |
-LL |     fn foo(&self) -> i32 {
-   |                      ^^^ `i32` is not a future
-   |
-   = help: the trait `Future` is not implemented for `i32`
-   = note: i32 must be a future or must implement `IntoFuture` to be awaited
-note: required by a bound in `MyTrait::foo::{opaque#0}`
-  --> $DIR/fn-not-async-err.rs:7:28
+error: method `foo` should be async because the method from the trait is async
+  --> $DIR/fn-not-async-err.rs:11:5
    |
 LL |     async fn foo(&self) -> i32;
-   |                            ^^^ required by this bound in `MyTrait::foo::{opaque#0}`
+   |     --------------------------- required because the trait method is async
+...
+LL |     fn foo(&self) -> i32 {
+   |     ^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0277`.
index 594baa91ad8ba61c21eb6914ae4c0b24e5fedd0b..2c4ed5535801e95db3c17300b6784db11b3fbeb4 100644 (file)
@@ -12,9 +12,7 @@ trait MyTrait {
 impl MyTrait for i32 {
     fn foo(&self) -> impl Future<Output = i32> {
         //~^ ERROR `impl Trait` only allowed in function and inherent method return types, not in `impl` method return [E0562]
-        async {
-            *self
-        }
+        async { *self }
     }
 }
 
diff --git a/src/test/ui/async-await/in-trait/issue-104678.rs b/src/test/ui/async-await/in-trait/issue-104678.rs
new file mode 100644 (file)
index 0000000..e396df4
--- /dev/null
@@ -0,0 +1,31 @@
+// edition:2021
+// check-pass
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+use std::future::Future;
+pub trait Pool {
+    type Conn;
+
+    async fn async_callback<'a, F: FnOnce(&'a Self::Conn) -> Fut, Fut: Future<Output = ()>>(
+        &'a self,
+        callback: F,
+    ) -> ();
+}
+
+pub struct PoolImpl;
+pub struct ConnImpl;
+
+impl Pool for PoolImpl {
+    type Conn = ConnImpl;
+
+    async fn async_callback<'a, F: FnOnce(&'a Self::Conn) -> Fut, Fut: Future<Output = ()>>(
+        &'a self,
+        _callback: F,
+    ) -> () {
+        todo!()
+    }
+}
+
+fn main() {}
index 34b31198e4f613a16a485e4d1d5a0ea144e7f9e8..8036d82daa4a33f51f3dff008efa3c58b55c50bb 100644 (file)
@@ -12,14 +12,10 @@ LL |           baz(|| async{
    |  _____________-
 LL | |             foo(tx.clone());
 LL | |         }).await;
-   | |         - ^^^^^^ await occurs here, with the value maybe used later
-   | |_________|
+   | |         - ^^^^^^- the value is later dropped here
+   | |         | |
+   | |_________| await occurs here, with the value maybe used later
    |           has type `[closure@$DIR/issue-70935-complex-spans.rs:17:13: 17:15]` which is not `Send`
-note: the value is later dropped here
-  --> $DIR/issue-70935-complex-spans.rs:19:17
-   |
-LL |         }).await;
-   |                 ^
 
 error: aborting due to previous error
 
index 919abf646037deaa2bcd7ceae1f8aa14e4214d1f..4a1705715caccbae37ea337820e2a12a5c57d4cf 100644 (file)
@@ -8,9 +8,6 @@ LL |             let mut f = File::open(path.to_str())?;
    |
 note: required by a bound in `File::open`
   --> $SRC_DIR/std/src/fs.rs:LL:COL
-   |
-LL |     pub fn open<P: AsRef<Path>>(path: P) -> io::Result<File> {
-   |                    ^^^^^^^^^^^ required by this bound in `File::open`
 
 error: aborting due to previous error
 
index 45f5ec40cd758b08f914aabdce72e0d85bd7996f..40c0e72b20391047a5ff92bb21ff2aafa86e4883 100644 (file)
@@ -6,11 +6,6 @@ LL | async fn copy() -> Result<()>
    |                    |
    |                    expected 2 generic arguments
    |
-note: enum defined here, with 2 generic parameters: `T`, `E`
-  --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL | pub enum Result<T, E> {
-   |          ^^^^^^ -  -
 help: add missing generic argument
    |
 LL | async fn copy() -> Result<(), E>
index ab196dca20cc460bbf61e21bcbdd6ad43eb384cb..1033fa6cc8b344c474a9c79b6d74fdaa9eb903e9 100644 (file)
@@ -13,14 +13,10 @@ note: future is not `Send` as this value is used across an await
   --> $DIR/issue-65436-raw-ptr-not-send.rs:18:35
    |
 LL |         bar(Foo(std::ptr::null())).await;
-   |                 ----------------  ^^^^^^ await occurs here, with `std::ptr::null()` maybe used later
-   |                 |
+   |                 ----------------  ^^^^^^- `std::ptr::null()` is later dropped here
+   |                 |                 |
+   |                 |                 await occurs here, with `std::ptr::null()` maybe used later
    |                 has type `*const u8` which is not `Send`
-note: `std::ptr::null()` is later dropped here
-  --> $DIR/issue-65436-raw-ptr-not-send.rs:18:41
-   |
-LL |         bar(Foo(std::ptr::null())).await;
-   |                                         ^
 help: consider moving this into a `let` binding to create a shorter lived borrow
   --> $DIR/issue-65436-raw-ptr-not-send.rs:18:13
    |
index 316b6d06f932ac1189cbbe6370beb920c259a178..2ce68a782918cf064c449afedab10f6815a2f3e2 100644 (file)
@@ -9,14 +9,10 @@ note: future is not `Send` as this value is used across an await
   --> $DIR/auxiliary/issue_67893.rs:9:26
    |
 LL |     f(*x.lock().unwrap()).await;
-   |        ----------------- ^^^^^^ await occurs here, with `x.lock().unwrap()` maybe used later
-   |        |
+   |        ----------------- ^^^^^^- `x.lock().unwrap()` is later dropped here
+   |        |                 |
+   |        |                 await occurs here, with `x.lock().unwrap()` maybe used later
    |        has type `MutexGuard<'_, ()>` which is not `Send`
-note: `x.lock().unwrap()` is later dropped here
-  --> $DIR/auxiliary/issue_67893.rs:9:32
-   |
-LL |     f(*x.lock().unwrap()).await;
-   |                                ^
 note: required by a bound in `g`
   --> $DIR/issue-67893.rs:6:14
    |
index 83d1a02c876b19e3ca71523aba19fdc147b0005d..0a6f705e255ae4c89646860970e94e4cd53cbe93 100644 (file)
@@ -14,9 +14,6 @@ LL | struct Sleep(std::marker::PhantomPinned);
    |        ^^^^^
 note: required by a bound in `Pin::<P>::new`
   --> $SRC_DIR/core/src/pin.rs:LL:COL
-   |
-LL | impl<P: Deref<Target: Unpin>> Pin<P> {
-   |                       ^^^^^ required by this bound in `Pin::<P>::new`
 
 error: aborting due to previous error
 
index 2e8723b2743a79062274a8c25f471193dcaec66a..b1f4a73aafeabf317352e1ccf16cb163f9726e8c 100644 (file)
@@ -6,11 +6,9 @@ LL | struct Sleep;
 ...
 LL |         self.sleep.poll(cx)
    |                    ^^^^ method not found in `Sleep`
+  --> $SRC_DIR/core/src/future/future.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/future/future.rs:LL:COL
-   |
-LL |     fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>;
-   |        ---- the method is available for `Pin<&mut Sleep>` here
+   = note: the method is available for `Pin<&mut Sleep>` here
    |
 help: consider wrapping the receiver expression with the appropriate type
    |
diff --git a/src/test/ui/async-await/track-caller/async-block.rs b/src/test/ui/async-await/track-caller/async-block.rs
new file mode 100644 (file)
index 0000000..8e81387
--- /dev/null
@@ -0,0 +1,9 @@
+// edition:2021
+
+#![feature(closure_track_caller, stmt_expr_attributes)]
+
+fn main() {
+    let _ = #[track_caller] async {
+        //~^ ERROR attribute should be applied to a function definition [E0739]
+    };
+}
diff --git a/src/test/ui/async-await/track-caller/async-block.stderr b/src/test/ui/async-await/track-caller/async-block.stderr
new file mode 100644 (file)
index 0000000..4074399
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0739]: attribute should be applied to a function definition
+  --> $DIR/async-block.rs:6:13
+   |
+LL |       let _ = #[track_caller] async {
+   |  _____________^^^^^^^^^^^^^^^_-
+LL | |
+LL | |     };
+   | |_____- not a function definition
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0739`.
diff --git a/src/test/ui/async-await/track-caller/async-closure-gate.rs b/src/test/ui/async-await/track-caller/async-closure-gate.rs
new file mode 100644 (file)
index 0000000..9593fdb
--- /dev/null
@@ -0,0 +1,10 @@
+// edition:2021
+
+#![feature(async_closure, stmt_expr_attributes)]
+
+fn main() {
+    let _ = #[track_caller] async || {
+        //~^ ERROR `#[track_caller]` on closures is currently unstable [E0658]
+        //~| ERROR `#[track_caller]` on closures is currently unstable [E0658]
+    };
+}
diff --git a/src/test/ui/async-await/track-caller/async-closure-gate.stderr b/src/test/ui/async-await/track-caller/async-closure-gate.stderr
new file mode 100644 (file)
index 0000000..be3d110
--- /dev/null
@@ -0,0 +1,25 @@
+error[E0658]: `#[track_caller]` on closures is currently unstable
+  --> $DIR/async-closure-gate.rs:6:13
+   |
+LL |     let _ = #[track_caller] async || {
+   |             ^^^^^^^^^^^^^^^
+   |
+   = note: see issue #87417 <https://github.com/rust-lang/rust/issues/87417> for more information
+   = help: add `#![feature(closure_track_caller)]` to the crate attributes to enable
+
+error[E0658]: `#[track_caller]` on closures is currently unstable
+  --> $DIR/async-closure-gate.rs:6:38
+   |
+LL |       let _ = #[track_caller] async || {
+   |  ______________________________________^
+LL | |
+LL | |
+LL | |     };
+   | |_____^
+   |
+   = note: see issue #87417 <https://github.com/rust-lang/rust/issues/87417> for more information
+   = help: add `#![feature(closure_track_caller)]` to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
index 5ebfeb3f36ac162f402dc3b780f6767c2911d35a..066cf97628fa5cd9d5852847bfddb5f799c7555a 100644 (file)
@@ -1,7 +1,7 @@
 // run-pass
 // edition:2021
 // needs-unwind
-#![feature(closure_track_caller)]
+#![feature(closure_track_caller, async_closure, stmt_expr_attributes)]
 
 use std::future::Future;
 use std::panic;
@@ -67,6 +67,13 @@ async fn foo_assoc() {
     Foo::bar_assoc().await
 }
 
+async fn foo_closure() {
+    let c = #[track_caller] async || {
+        panic!();
+    };
+    c().await
+}
+
 fn panicked_at(f: impl FnOnce() + panic::UnwindSafe) -> u32 {
     let loc = Arc::new(Mutex::new(None));
 
@@ -87,4 +94,5 @@ fn main() {
     assert_eq!(panicked_at(|| block_on(foo())), 41);
     assert_eq!(panicked_at(|| block_on(foo_track_caller())), 54);
     assert_eq!(panicked_at(|| block_on(foo_assoc())), 67);
+    assert_eq!(panicked_at(|| block_on(foo_closure())), 74);
 }
index c734f8c1e17e3471dd2e82daf9bc2d5bc0cf2dce..6fbbb55437eb2f8b91a0d3dd17346411fbdcf7c4 100644 (file)
@@ -10,9 +10,6 @@ LL |     drop(lhs);
    |
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL |     fn add(self, rhs: Rhs) -> Self::Output;
-   |            ^^^^
 help: consider further restricting this bound
    |
 LL | fn add<A: Add<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
@@ -46,9 +43,6 @@ LL |     drop(lhs);
    |
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL |     fn sub(self, rhs: Rhs) -> Self::Output;
-   |            ^^^^
 help: consider further restricting this bound
    |
 LL | fn sub<A: Sub<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
@@ -82,9 +76,6 @@ LL |     drop(lhs);
    |
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL |     fn mul(self, rhs: Rhs) -> Self::Output;
-   |            ^^^^
 help: consider further restricting this bound
    |
 LL | fn mul<A: Mul<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
@@ -118,9 +109,6 @@ LL |     drop(lhs);
    |
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL |     fn div(self, rhs: Rhs) -> Self::Output;
-   |            ^^^^
 help: consider further restricting this bound
    |
 LL | fn div<A: Div<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
@@ -154,9 +142,6 @@ LL |     drop(lhs);
    |
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL |     fn rem(self, rhs: Rhs) -> Self::Output;
-   |            ^^^^
 help: consider further restricting this bound
    |
 LL | fn rem<A: Rem<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
@@ -190,9 +175,6 @@ LL |     drop(lhs);
    |
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
-   |
-LL |     fn bitand(self, rhs: Rhs) -> Self::Output;
-   |               ^^^^
 help: consider further restricting this bound
    |
 LL | fn bitand<A: BitAnd<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
@@ -226,9 +208,6 @@ LL |     drop(lhs);
    |
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
-   |
-LL |     fn bitor(self, rhs: Rhs) -> Self::Output;
-   |              ^^^^
 help: consider further restricting this bound
    |
 LL | fn bitor<A: BitOr<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
@@ -262,9 +241,6 @@ LL |     drop(lhs);
    |
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
-   |
-LL |     fn bitxor(self, rhs: Rhs) -> Self::Output;
-   |               ^^^^
 help: consider further restricting this bound
    |
 LL | fn bitxor<A: BitXor<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
@@ -298,9 +274,6 @@ LL |     drop(lhs);
    |
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
-   |
-LL |     fn shl(self, rhs: Rhs) -> Self::Output;
-   |            ^^^^
 help: consider further restricting this bound
    |
 LL | fn shl<A: Shl<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
@@ -334,9 +307,6 @@ LL |     drop(lhs);
    |
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
-   |
-LL |     fn shr(self, rhs: Rhs) -> Self::Output;
-   |            ^^^^
 help: consider further restricting this bound
    |
 LL | fn shr<A: Shr<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
index 994eaf9d8c77885a219ea90c5a0a41e07896e4ec..dae267da05d1758bd31791fff00a437cc3066a8a 100644 (file)
@@ -13,9 +13,6 @@ LL | |     x;
    |
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL |     fn add(self, rhs: Rhs) -> Self::Output;
-   |            ^^^^
 help: consider further restricting this bound
    |
 LL | fn double_move<T: Add<Output=()> + Copy>(x: T) {
@@ -78,9 +75,6 @@ LL | |     *n;
    |
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL |     fn add(self, rhs: Rhs) -> Self::Output;
-   |            ^^^^
 
 error[E0507]: cannot move out of `*n` which is behind a shared reference
   --> $DIR/binop-move-semantics.rs:32:5
index b9c7e1bea706a0d8f08036f950cb9d83548fdf50..6e236ca5296a17eee6b9489dbcb05e4b3a4b32b6 100644 (file)
@@ -11,11 +11,8 @@ note: an implementation of `Add<_>` might be missing for `A`
    |
 LL | struct A;
    | ^^^^^^^^ must implement `Add<_>`
-note: the following trait must be implemented
+note: the trait `Add` must be implemented
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL | pub trait Add<Rhs = Self> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0369]: cannot subtract `A` from `A`
   --> $DIR/issue-28837.rs:8:7
@@ -30,11 +27,8 @@ note: an implementation of `Sub<_>` might be missing for `A`
    |
 LL | struct A;
    | ^^^^^^^^ must implement `Sub<_>`
-note: the following trait must be implemented
+note: the trait `Sub` must be implemented
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL | pub trait Sub<Rhs = Self> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0369]: cannot multiply `A` by `A`
   --> $DIR/issue-28837.rs:10:7
@@ -49,11 +43,8 @@ note: an implementation of `Mul<_>` might be missing for `A`
    |
 LL | struct A;
    | ^^^^^^^^ must implement `Mul<_>`
-note: the following trait must be implemented
+note: the trait `Mul` must be implemented
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL | pub trait Mul<Rhs = Self> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0369]: cannot divide `A` by `A`
   --> $DIR/issue-28837.rs:12:7
@@ -68,11 +59,8 @@ note: an implementation of `Div<_>` might be missing for `A`
    |
 LL | struct A;
    | ^^^^^^^^ must implement `Div<_>`
-note: the following trait must be implemented
+note: the trait `Div` must be implemented
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL | pub trait Div<Rhs = Self> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0369]: cannot mod `A` by `A`
   --> $DIR/issue-28837.rs:14:7
@@ -87,11 +75,8 @@ note: an implementation of `Rem<_>` might be missing for `A`
    |
 LL | struct A;
    | ^^^^^^^^ must implement `Rem<_>`
-note: the following trait must be implemented
+note: the trait `Rem` must be implemented
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL | pub trait Rem<Rhs = Self> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0369]: no implementation for `A & A`
   --> $DIR/issue-28837.rs:16:7
@@ -106,11 +91,8 @@ note: an implementation of `BitAnd<_>` might be missing for `A`
    |
 LL | struct A;
    | ^^^^^^^^ must implement `BitAnd<_>`
-note: the following trait must be implemented
+note: the trait `BitAnd` must be implemented
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
-   |
-LL | pub trait BitAnd<Rhs = Self> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0369]: no implementation for `A | A`
   --> $DIR/issue-28837.rs:18:7
@@ -125,11 +107,8 @@ note: an implementation of `BitOr<_>` might be missing for `A`
    |
 LL | struct A;
    | ^^^^^^^^ must implement `BitOr<_>`
-note: the following trait must be implemented
+note: the trait `BitOr` must be implemented
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
-   |
-LL | pub trait BitOr<Rhs = Self> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0369]: no implementation for `A << A`
   --> $DIR/issue-28837.rs:20:7
@@ -144,11 +123,8 @@ note: an implementation of `Shl<_>` might be missing for `A`
    |
 LL | struct A;
    | ^^^^^^^^ must implement `Shl<_>`
-note: the following trait must be implemented
+note: the trait `Shl` must be implemented
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
-   |
-LL | pub trait Shl<Rhs = Self> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0369]: no implementation for `A >> A`
   --> $DIR/issue-28837.rs:22:7
@@ -163,11 +139,8 @@ note: an implementation of `Shr<_>` might be missing for `A`
    |
 LL | struct A;
    | ^^^^^^^^ must implement `Shr<_>`
-note: the following trait must be implemented
+note: the trait `Shr` must be implemented
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
-   |
-LL | pub trait Shr<Rhs = Self> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0369]: binary operation `==` cannot be applied to type `A`
   --> $DIR/issue-28837.rs:24:7
index f21f890691120cdd4e50c07fda0f9324e52aa4d5..c313ed6037f3ab043aef865989ef6725449c7fb7 100644 (file)
@@ -11,11 +11,8 @@ note: an implementation of `Mul<_>` might be missing for `Thing`
    |
 LL | struct Thing {
    | ^^^^^^^^^^^^ must implement `Mul<_>`
-note: the following trait must be implemented
+note: the trait `Mul` must be implemented
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL | pub trait Mul<Rhs = Self> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index 13a6277da14c0898b95ab55ef527e3b4fe8fa72e..abee72ba8cf97cb1ed9d5ca73462a894368d393b 100644 (file)
@@ -3,10 +3,15 @@ error[E0507]: cannot move out of `s` which is behind a shared reference
    |
 LL |         match *s { S(v) => v }
    |               ^^     -
-   |               |      |
-   |               |      data moved here
-   |               |      move occurs because `v` has type `Vec<isize>`, which does not implement the `Copy` trait
-   |               help: consider borrowing here: `&*s`
+   |                      |
+   |                      data moved here
+   |                      move occurs because `v` has type `Vec<isize>`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -         match *s { S(v) => v }
+LL +         match s { S(v) => v }
+   |
 
 error: aborting due to previous error
 
index 2eabc1f1d9df5844218a35a4640b537ea1e52136..f9ced03e0f038fd86afc5020f3c737349a99727b 100644 (file)
@@ -2,31 +2,46 @@ error[E0507]: cannot move out of a shared reference
   --> $DIR/borrowck-for-loop-correct-cmt-for-pattern.rs:12:15
    |
 LL |     for &a in x.iter() {
-   |         --    ^^^^^^^^
-   |         ||
-   |         |data moved here
-   |         |move occurs because `a` has type `&mut i32`, which does not implement the `Copy` trait
-   |         help: consider removing the `&`: `a`
+   |          -    ^^^^^^^^
+   |          |
+   |          data moved here
+   |          move occurs because `a` has type `&mut i32`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -     for &a in x.iter() {
+LL +     for a in x.iter() {
+   |
 
 error[E0507]: cannot move out of a shared reference
   --> $DIR/borrowck-for-loop-correct-cmt-for-pattern.rs:18:15
    |
 LL |     for &a in &f.a {
-   |         --    ^^^^
-   |         ||
-   |         |data moved here
-   |         |move occurs because `a` has type `Box<isize>`, which does not implement the `Copy` trait
-   |         help: consider removing the `&`: `a`
+   |          -    ^^^^
+   |          |
+   |          data moved here
+   |          move occurs because `a` has type `Box<isize>`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -     for &a in &f.a {
+LL +     for a in &f.a {
+   |
 
 error[E0507]: cannot move out of a shared reference
   --> $DIR/borrowck-for-loop-correct-cmt-for-pattern.rs:22:15
    |
 LL |     for &a in x.iter() {
-   |         --    ^^^^^^^^
-   |         ||
-   |         |data moved here
-   |         |move occurs because `a` has type `Box<i32>`, which does not implement the `Copy` trait
-   |         help: consider removing the `&`: `a`
+   |          -    ^^^^^^^^
+   |          |
+   |          data moved here
+   |          move occurs because `a` has type `Box<i32>`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -     for &a in x.iter() {
+LL +     for a in x.iter() {
+   |
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/borrowck/borrowck-issue-2657-2.fixed b/src/test/ui/borrowck/borrowck-issue-2657-2.fixed
new file mode 100644 (file)
index 0000000..625e7c3
--- /dev/null
@@ -0,0 +1,12 @@
+// run-rustfix
+fn main() {
+
+    let x: Option<Box<_>> = Some(Box::new(1));
+
+    match x {
+      Some(ref y) => {
+        let _b = y; //~ ERROR cannot move out
+      }
+      _ => {}
+    }
+}
index 7dbac02154a6e29bddf4ad389f38a403b7bf25b8..f79a846e70e7bcc9448267766c5050853ab43e20 100644 (file)
@@ -1,3 +1,4 @@
+// run-rustfix
 fn main() {
 
     let x: Option<Box<_>> = Some(Box::new(1));
index f9ba2ca416bdde0fe40b542b914bb91b155a8480..850bb9ae3930c87c80ed595f8e22ae5789262c9f 100644 (file)
@@ -1,11 +1,14 @@
 error[E0507]: cannot move out of `*y` which is behind a shared reference
-  --> $DIR/borrowck-issue-2657-2.rs:7:18
+  --> $DIR/borrowck-issue-2657-2.rs:8:18
    |
 LL |         let _b = *y;
-   |                  ^^
-   |                  |
-   |                  move occurs because `*y` has type `Box<i32>`, which does not implement the `Copy` trait
-   |                  help: consider borrowing here: `&*y`
+   |                  ^^ move occurs because `*y` has type `Box<i32>`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -         let _b = *y;
+LL +         let _b = y;
+   |
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-move-error-with-note.fixed b/src/test/ui/borrowck/borrowck-move-error-with-note.fixed
new file mode 100644 (file)
index 0000000..cf6c382
--- /dev/null
@@ -0,0 +1,56 @@
+// run-rustfix
+#![allow(unused)]
+enum Foo {
+    Foo1(Box<u32>, Box<u32>),
+    Foo2(Box<u32>),
+    Foo3,
+}
+
+
+
+fn blah() {
+    let f = &Foo::Foo1(Box::new(1), Box::new(2));
+    match f { //~ ERROR cannot move out of
+        Foo::Foo1(num1,
+                  num2) => (),
+        Foo::Foo2(num) => (),
+        Foo::Foo3 => ()
+    }
+}
+
+struct S {
+    f: String,
+    g: String
+}
+impl Drop for S {
+    fn drop(&mut self) { println!("{}", self.f); }
+}
+
+fn move_in_match() {
+    match (S {f: "foo".to_string(), g: "bar".to_string()}) {
+        //~^ ERROR cannot move out of type `S`, which implements the `Drop` trait
+        S {
+            f: ref _s,
+            g: ref _t
+        } => {}
+    }
+}
+
+// from issue-8064
+struct A {
+    a: Box<isize>,
+}
+
+fn free<T>(_: T) {}
+
+fn blah2() {
+    let a = &A { a: Box::new(1) };
+    match &a.a { //~ ERROR cannot move out of
+        n => {
+            free(n)
+        }
+    }
+    free(a)
+}
+
+fn main() {}
index ef38cbb63a5e3455cb31328eaa43ba5eb3ee5af2..f336ac4f994fa6990d648c9a9fa5a8303a020102 100644 (file)
@@ -1,3 +1,5 @@
+// run-rustfix
+#![allow(unused)]
 enum Foo {
     Foo1(Box<u32>, Box<u32>),
     Foo2(Box<u32>),
index 96246d9ae1a8909ce949a36ce288f00f3821828b..722c2c1443a7fd6d4a74d04f1920b44f1052c79c 100644 (file)
@@ -1,8 +1,8 @@
 error[E0507]: cannot move out of `f` as enum variant `Foo1` which is behind a shared reference
-  --> $DIR/borrowck-move-error-with-note.rs:11:11
+  --> $DIR/borrowck-move-error-with-note.rs:13:11
    |
 LL |     match *f {
-   |           ^^ help: consider borrowing here: `&*f`
+   |           ^^
 LL |         Foo::Foo1(num1,
    |                   ---- data moved here
 LL |                   num2) => (),
@@ -11,9 +11,14 @@ LL |         Foo::Foo2(num) => (),
    |                   --- ...and here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the dereference here
+   |
+LL -     match *f {
+LL +     match f {
+   |
 
 error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
-  --> $DIR/borrowck-move-error-with-note.rs:28:11
+  --> $DIR/borrowck-move-error-with-note.rs:30:11
    |
 LL |     match (S {f: "foo".to_string(), g: "bar".to_string()}) {
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of here
@@ -24,17 +29,30 @@ LL |             g: _t
    |                -- ...and here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider borrowing the pattern binding
+   |
+LL |             f: ref _s,
+   |                +++
+help: consider borrowing the pattern binding
+   |
+LL |             g: ref _t
+   |                +++
 
 error[E0507]: cannot move out of `a.a` which is behind a shared reference
-  --> $DIR/borrowck-move-error-with-note.rs:46:11
+  --> $DIR/borrowck-move-error-with-note.rs:48:11
    |
 LL |     match a.a {
-   |           ^^^ help: consider borrowing here: `&a.a`
+   |           ^^^
 LL |         n => {
    |         -
    |         |
    |         data moved here
    |         move occurs because `n` has type `Box<isize>`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     match &a.a {
+   |           +
 
 error: aborting due to 3 previous errors
 
index 7ac095e808a85a9537696b0e7834b6ca63bd1071..43fc102bd6256c90ea6a650670e487b1e0c49b60 100644 (file)
@@ -2,10 +2,13 @@ error[E0507]: cannot move out of `*x` which is behind a raw pointer
   --> $DIR/borrowck-move-from-unsafe-ptr.rs:2:13
    |
 LL |     let y = *x;
-   |             ^^
-   |             |
-   |             move occurs because `*x` has type `Box<isize>`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&*x`
+   |             ^^ move occurs because `*x` has type `Box<isize>`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let y = *x;
+LL +     let y = x;
+   |
 
 error: aborting due to previous error
 
index 6b19f9d977efab0f887398bc4a98e1e8e44a3342..21bd073321b8374dff41d9e842a537a21ec33fbb 100644 (file)
@@ -3,30 +3,45 @@ error[E0507]: cannot move out of a shared reference
    |
 LL | fn arg_item(&_x: &String) {}
    |             ^--
-   |             ||
-   |             |data moved here
-   |             |move occurs because `_x` has type `String`, which does not implement the `Copy` trait
-   |             help: consider removing the `&`: `_x`
+   |              |
+   |              data moved here
+   |              move occurs because `_x` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL - fn arg_item(&_x: &String) {}
+LL + fn arg_item(_x: &String) {}
+   |
 
 error[E0507]: cannot move out of a shared reference
   --> $DIR/borrowck-move-in-irrefut-pat.rs:7:11
    |
 LL |     with(|&_x| ())
    |           ^--
-   |           ||
-   |           |data moved here
-   |           |move occurs because `_x` has type `String`, which does not implement the `Copy` trait
-   |           help: consider removing the `&`: `_x`
+   |            |
+   |            data moved here
+   |            move occurs because `_x` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -     with(|&_x| ())
+LL +     with(|_x| ())
+   |
 
 error[E0507]: cannot move out of a shared reference
   --> $DIR/borrowck-move-in-irrefut-pat.rs:12:15
    |
 LL |     let &_x = &"hi".to_string();
-   |         ---   ^^^^^^^^^^^^^^^^^
-   |         ||
-   |         |data moved here
-   |         |move occurs because `_x` has type `String`, which does not implement the `Copy` trait
-   |         help: consider removing the `&`: `_x`
+   |          --   ^^^^^^^^^^^^^^^^^
+   |          |
+   |          data moved here
+   |          move occurs because `_x` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -     let &_x = &"hi".to_string();
+LL +     let _x = &"hi".to_string();
+   |
 
 error: aborting due to 3 previous errors
 
index 800f30b34e58921dd71977b9d9c753562928429a..ecf5382e863e00336d9ec449722a272f8044d628 100644 (file)
@@ -7,11 +7,8 @@ LL |     let _x = Rc::new(vec![1, 2]).into_iter();
    |              |                   value moved due to this method call
    |              move occurs because value has type `Vec<i32>`, which does not implement the `Copy` trait
    |
-note: this function takes ownership of the receiver `self`, which moves value
+note: `into_iter` takes ownership of the receiver `self`, which moves value
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-   |
-LL |     fn into_iter(self) -> Self::IntoIter;
-   |                  ^^^^
 
 error: aborting due to previous error
 
index 68994c2071bef2abcea6de94504e2b25e64e6933..599fa1e88dfecdd4dfd882aa6a31f94091c48ed6 100644 (file)
@@ -2,10 +2,13 @@ error[E0507]: cannot move out of an `Rc`
   --> $DIR/borrowck-move-out-of-overloaded-deref.rs:4:14
    |
 LL |     let _x = *Rc::new("hi".to_string());
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |              |
-   |              move occurs because value has type `String`, which does not implement the `Copy` trait
-   |              help: consider borrowing here: `&*Rc::new("hi".to_string())`
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ move occurs because value has type `String`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let _x = *Rc::new("hi".to_string());
+LL +     let _x = Rc::new("hi".to_string());
+   |
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.fixed b/src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.fixed
new file mode 100644 (file)
index 0000000..c463c65
--- /dev/null
@@ -0,0 +1,24 @@
+// run-rustfix
+#![allow(unused)]
+struct S {f:String}
+impl Drop for S {
+    fn drop(&mut self) { println!("{}", self.f); }
+}
+
+fn move_in_match() {
+    match (S {f:"foo".to_string()}) {
+        //~^ ERROR [E0509]
+        S {f:ref _s} => {}
+    }
+}
+
+fn move_in_let() {
+    let S {f:ref _s} = S {f:"foo".to_string()};
+    //~^ ERROR [E0509]
+}
+
+fn move_in_fn_arg(S {f:ref _s}: S) {
+    //~^ ERROR [E0509]
+}
+
+fn main() {}
index a429f4bc33b066ec22fba29668ff94f9a8b338ef..93183062d61b319ac075ee4249d6c8d291f47899 100644 (file)
@@ -1,3 +1,5 @@
+// run-rustfix
+#![allow(unused)]
 struct S {f:String}
 impl Drop for S {
     fn drop(&mut self) { println!("{}", self.f); }
index 7b00ac9f1c3a6c5fa7cd9f2f375a1e5c03f26ec3..58f706c65ff281fc78101fac28e4812d7a084877 100644 (file)
@@ -1,5 +1,5 @@
 error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
-  --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:7:11
+  --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:9:11
    |
 LL |     match (S {f:"foo".to_string()}) {
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of here
@@ -9,18 +9,28 @@ LL |         S {f:_s} => {}
    |              |
    |              data moved here
    |              move occurs because `_s` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |         S {f:ref _s} => {}
+   |              +++
 
 error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
-  --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:14:20
+  --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:16:20
    |
 LL |     let S {f:_s} = S {f:"foo".to_string()};
    |              --    ^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of here
    |              |
    |              data moved here
    |              move occurs because `_s` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |     let S {f:ref _s} = S {f:"foo".to_string()};
+   |              +++
 
 error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
-  --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:18:19
+  --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:20:19
    |
 LL | fn move_in_fn_arg(S {f:_s}: S) {
    |                   ^^^^^--^
@@ -28,6 +38,11 @@ LL | fn move_in_fn_arg(S {f:_s}: S) {
    |                   |    data moved here
    |                   |    move occurs because `_s` has type `String`, which does not implement the `Copy` trait
    |                   cannot move out of here
+   |
+help: consider borrowing the pattern binding
+   |
+LL | fn move_in_fn_arg(S {f:ref _s}: S) {
+   |                        +++
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.fixed b/src/test/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.fixed
new file mode 100644 (file)
index 0000000..bc2ddf8
--- /dev/null
@@ -0,0 +1,24 @@
+// run-rustfix
+#![allow(unused)]
+struct S(String);
+impl Drop for S {
+    fn drop(&mut self) { }
+}
+
+fn move_in_match() {
+    match S("foo".to_string()) {
+        //~^ ERROR cannot move out of type `S`, which implements the `Drop` trait
+        S(ref _s) => {}
+    }
+}
+
+fn move_in_let() {
+    let S(ref _s) = S("foo".to_string());
+    //~^ ERROR cannot move out of type `S`, which implements the `Drop` trait
+}
+
+fn move_in_fn_arg(S(ref _s): S) {
+    //~^ ERROR cannot move out of type `S`, which implements the `Drop` trait
+}
+
+fn main() {}
index 5bd32f82ebc447309fe7538a9834ce12a3cfbc54..f050bce87406799608f4e1db27e3c26f845ecc30 100644 (file)
@@ -1,3 +1,5 @@
+// run-rustfix
+#![allow(unused)]
 struct S(String);
 impl Drop for S {
     fn drop(&mut self) { }
index f00181b74689bb027c114c66ef02690e5f6b5c45..160a1f99f63f657c536ed8d63481af37d3246a42 100644 (file)
@@ -1,5 +1,5 @@
 error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
-  --> $DIR/borrowck-move-out-of-tuple-struct-with-dtor.rs:7:11
+  --> $DIR/borrowck-move-out-of-tuple-struct-with-dtor.rs:9:11
    |
 LL |     match S("foo".to_string()) {
    |           ^^^^^^^^^^^^^^^^^^^^ cannot move out of here
@@ -9,18 +9,28 @@ LL |         S(_s) => {}
    |           |
    |           data moved here
    |           move occurs because `_s` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |         S(ref _s) => {}
+   |           +++
 
 error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
-  --> $DIR/borrowck-move-out-of-tuple-struct-with-dtor.rs:14:17
+  --> $DIR/borrowck-move-out-of-tuple-struct-with-dtor.rs:16:17
    |
 LL |     let S(_s) = S("foo".to_string());
    |           --    ^^^^^^^^^^^^^^^^^^^^ cannot move out of here
    |           |
    |           data moved here
    |           move occurs because `_s` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |     let S(ref _s) = S("foo".to_string());
+   |           +++
 
 error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
-  --> $DIR/borrowck-move-out-of-tuple-struct-with-dtor.rs:18:19
+  --> $DIR/borrowck-move-out-of-tuple-struct-with-dtor.rs:20:19
    |
 LL | fn move_in_fn_arg(S(_s): S) {
    |                   ^^--^
@@ -28,6 +38,11 @@ LL | fn move_in_fn_arg(S(_s): S) {
    |                   | data moved here
    |                   | move occurs because `_s` has type `String`, which does not implement the `Copy` trait
    |                   cannot move out of here
+   |
+help: consider borrowing the pattern binding
+   |
+LL | fn move_in_fn_arg(S(ref _s): S) {
+   |                     +++
 
 error: aborting due to 3 previous errors
 
index a865812cb4a7c4708fc90d1354659f21fea9ffd6..9ff20a1f46a127ea3c5c6a970869eb53966d20f1 100644 (file)
@@ -10,10 +10,10 @@ LL |                   Foo { string: b }] => {
    |                                 - ...and here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
-help: consider removing the `&`
+help: consider removing the borrow
    |
-LL ~                 [Foo { string: a },
-LL ~                   Foo { string: b }] => {
+LL -                 &[Foo { string: a },
+LL +                 [Foo { string: a },
    |
 
 error: aborting due to previous error
index 2b4293b433e0190c8997f8179af9c1bbe67e5ba0..f5f4817e9bf3220f9a619064f3c8d75d5c766dc6 100644 (file)
@@ -2,10 +2,12 @@ error[E0507]: cannot move out of index of `MyVec<Box<i32>>`
   --> $DIR/borrowck-overloaded-index-move-from-vec.rs:20:15
    |
 LL |     let bad = v[0];
-   |               ^^^^
-   |               |
-   |               move occurs because value has type `Box<i32>`, which does not implement the `Copy` trait
-   |               help: consider borrowing here: `&v[0]`
+   |               ^^^^ move occurs because value has type `Box<i32>`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     let bad = &v[0];
+   |               +
 
 error: aborting due to previous error
 
index 8a9296c597828adb834b6cb0bebe93f6cfbb464f..0e9284a2cadd26cf48564328da88ebe070829077 100644 (file)
@@ -37,7 +37,7 @@ fn c() {
         &mut [_a,
         //~^ NOTE data moved here
         //~| NOTE move occurs because `_a` has type
-        //~| HELP consider removing the `&mut`
+        //~| HELP consider removing the mutable borrow
             ..
         ] => {
         }
@@ -56,7 +56,7 @@ fn d() {
         //~^ ERROR cannot move out
         //~| NOTE cannot move out
         &mut [
-        //~^ HELP consider removing the `&mut`
+        //~^ HELP consider removing the mutable borrow
          _b] => {}
         //~^ NOTE data moved here
         //~| NOTE move occurs because `_b` has type
@@ -79,7 +79,7 @@ fn e() {
         //~^ NOTE data moved here
         //~| NOTE and here
         //~| NOTE and here
-        //~| HELP consider removing the `&mut`
+        //~| HELP consider removing the mutable borrow
         _ => {}
     }
     let a = vec[0]; //~ ERROR cannot move out
index c3bcb7de65daa8fd07550695aaeaafae769f60a9..0dc5e64e4ff3022ee92075d07b49bd3c2134729e 100644 (file)
@@ -34,14 +34,10 @@ LL |         &mut [_a,
    |               data moved here
    |               move occurs because `_a` has type `Box<isize>`, which does not implement the `Copy` trait
    |
-help: consider removing the `&mut`
+help: consider removing the mutable borrow
    |
-LL ~         [_a,
-LL +
-LL +
-LL +
-LL +             ..
-LL ~         ] => {
+LL -         &mut [_a,
+LL +         [_a,
    |
 
 error[E0508]: cannot move out of type `[Box<isize>]`, a non-copy slice
@@ -52,7 +48,11 @@ LL |     let a = vec[0];
    |             |
    |             cannot move out of here
    |             move occurs because `vec[_]` has type `Box<isize>`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&vec[0]`
+   |
+help: consider borrowing here
+   |
+LL |     let a = &vec[0];
+   |             +
 
 error[E0508]: cannot move out of type `[Box<isize>]`, a non-copy slice
   --> $DIR/borrowck-vec-pattern-nesting.rs:55:11
@@ -66,11 +66,10 @@ LL |          _b] => {}
    |          data moved here
    |          move occurs because `_b` has type `Box<isize>`, which does not implement the `Copy` trait
    |
-help: consider removing the `&mut`
+help: consider removing the mutable borrow
    |
-LL ~         [
-LL +
-LL ~          _b] => {}
+LL -         &mut [
+LL +         [
    |
 
 error[E0508]: cannot move out of type `[Box<isize>]`, a non-copy slice
@@ -81,7 +80,11 @@ LL |     let a = vec[0];
    |             |
    |             cannot move out of here
    |             move occurs because `vec[_]` has type `Box<isize>`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&vec[0]`
+   |
+help: consider borrowing here
+   |
+LL |     let a = &vec[0];
+   |             +
 
 error[E0508]: cannot move out of type `[Box<isize>]`, a non-copy slice
   --> $DIR/borrowck-vec-pattern-nesting.rs:74:11
@@ -90,14 +93,17 @@ LL |     match vec {
    |           ^^^ cannot move out of here
 ...
 LL |         &mut [_a, _b, _c] => {}
-   |         -----------------
-   |         |     |   |   |
-   |         |     |   |   ...and here
-   |         |     |   ...and here
-   |         |     data moved here
-   |         help: consider removing the `&mut`: `[_a, _b, _c]`
+   |               --  --  -- ...and here
+   |               |   |
+   |               |   ...and here
+   |               data moved here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the mutable borrow
+   |
+LL -         &mut [_a, _b, _c] => {}
+LL +         [_a, _b, _c] => {}
+   |
 
 error[E0508]: cannot move out of type `[Box<isize>]`, a non-copy slice
   --> $DIR/borrowck-vec-pattern-nesting.rs:85:13
@@ -107,7 +113,11 @@ LL |     let a = vec[0];
    |             |
    |             cannot move out of here
    |             move occurs because `vec[_]` has type `Box<isize>`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&vec[0]`
+   |
+help: consider borrowing here
+   |
+LL |     let a = &vec[0];
+   |             +
 
 error: aborting due to 8 previous errors
 
diff --git a/src/test/ui/borrowck/issue-104639-lifetime-order.rs b/src/test/ui/borrowck/issue-104639-lifetime-order.rs
new file mode 100644 (file)
index 0000000..db1f8f8
--- /dev/null
@@ -0,0 +1,10 @@
+// edition:2018
+// check-pass
+
+#![allow(dead_code)]
+async fn fail<'a, 'b, 'c>(_: &'static str) where 'a: 'c, 'b: 'c, {}
+async fn pass<'a, 'c, 'b>(_: &'static str) where 'a: 'c, 'b: 'c, {}
+async fn pass2<'a, 'b, 'c>(_: &'static str) where 'a: 'c, 'b: 'c, 'c: 'a, {}
+async fn pass3<'a, 'b, 'c>(_: &'static str) where 'a: 'b, 'b: 'c, 'c: 'a, {}
+
+fn main() { }
index 984534bfb8b86cbe19adeef35ac5699d7343c72f..65aea5b1834b0dc750be678ea46c8216b05773f7 100644 (file)
@@ -2,10 +2,12 @@ error[E0507]: cannot move out of static item `FOO`
   --> $DIR/issue-17718-static-move.rs:6:14
    |
 LL |     let _a = FOO;
-   |              ^^^
-   |              |
-   |              move occurs because `FOO` has type `Foo`, which does not implement the `Copy` trait
-   |              help: consider borrowing here: `&FOO`
+   |              ^^^ move occurs because `FOO` has type `Foo`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     let _a = &FOO;
+   |              +
 
 error: aborting due to previous error
 
index d276231dc0c967103b894dff7784ed953f5daa48..215bf0100636949a6eda04a58eec81bdaab2dd8f 100644 (file)
@@ -2,37 +2,49 @@ error[E0507]: cannot move out of a mutable reference
   --> $DIR/issue-20801.rs:26:22
    |
 LL |     let a = unsafe { *mut_ref() };
-   |                      ^^^^^^^^^^
-   |                      |
-   |                      move occurs because value has type `T`, which does not implement the `Copy` trait
-   |                      help: consider borrowing here: `&*mut_ref()`
+   |                      ^^^^^^^^^^ move occurs because value has type `T`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let a = unsafe { *mut_ref() };
+LL +     let a = unsafe { mut_ref() };
+   |
 
 error[E0507]: cannot move out of a shared reference
   --> $DIR/issue-20801.rs:29:22
    |
 LL |     let b = unsafe { *imm_ref() };
-   |                      ^^^^^^^^^^
-   |                      |
-   |                      move occurs because value has type `T`, which does not implement the `Copy` trait
-   |                      help: consider borrowing here: `&*imm_ref()`
+   |                      ^^^^^^^^^^ move occurs because value has type `T`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let b = unsafe { *imm_ref() };
+LL +     let b = unsafe { imm_ref() };
+   |
 
 error[E0507]: cannot move out of a raw pointer
   --> $DIR/issue-20801.rs:32:22
    |
 LL |     let c = unsafe { *mut_ptr() };
-   |                      ^^^^^^^^^^
-   |                      |
-   |                      move occurs because value has type `T`, which does not implement the `Copy` trait
-   |                      help: consider borrowing here: `&*mut_ptr()`
+   |                      ^^^^^^^^^^ move occurs because value has type `T`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let c = unsafe { *mut_ptr() };
+LL +     let c = unsafe { mut_ptr() };
+   |
 
 error[E0507]: cannot move out of a raw pointer
   --> $DIR/issue-20801.rs:35:22
    |
 LL |     let d = unsafe { *const_ptr() };
-   |                      ^^^^^^^^^^^^
-   |                      |
-   |                      move occurs because value has type `T`, which does not implement the `Copy` trait
-   |                      help: consider borrowing here: `&*const_ptr()`
+   |                      ^^^^^^^^^^^^ move occurs because value has type `T`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let d = unsafe { *const_ptr() };
+LL +     let d = unsafe { const_ptr() };
+   |
 
 error: aborting due to 4 previous errors
 
index eb41af1cea80d6b47aed6ff53d6141cde4f92899..8d4918867f75ec1d9bf0d1675fe904225b39aa4f 100644 (file)
@@ -2,10 +2,12 @@ error[E0507]: cannot move out of static item `X`
   --> $DIR/issue-47215-ice-from-drop-elab.rs:17:21
    |
 LL |         let mut x = X;
-   |                     ^
-   |                     |
-   |                     move occurs because `X` has type `AtomicUsize`, which does not implement the `Copy` trait
-   |                     help: consider borrowing here: `&X`
+   |                     ^ move occurs because `X` has type `AtomicUsize`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         let mut x = &X;
+   |                     +
 
 error: aborting due to previous error
 
index f3decf7a9913c3207834c692d676a22b012fb423..6ec920cb81f3904120aefc21178b4bc5bfe79a52 100644 (file)
@@ -6,6 +6,11 @@ LL |             .find(|(&event_type, _)| event == event_type)
    |                      |
    |                      data moved here
    |                      move occurs because `event_type` has type `EventType`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |             .find(|(&ref event_type, _)| event == event_type)
+   |                      +++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/issue-51415.fixed b/src/test/ui/borrowck/issue-51415.fixed
new file mode 100644 (file)
index 0000000..92943f6
--- /dev/null
@@ -0,0 +1,12 @@
+// run-rustfix
+// Regression test for #51415: match default bindings were failing to
+// see the "move out" implied by `&s` below.
+
+fn main() {
+    let a = vec![String::from("a")];
+    let opt = a.iter().enumerate().find(|(_, &ref s)| {
+        //~^ ERROR cannot move out
+        *s == String::from("d")
+    }).map(|(i, _)| i);
+    println!("{:?}", opt);
+}
index f031308fb7871ff4c2b6aa6a5bf20fb32fe8a23b..56ed57a61a0feeb252c3acc6d6bc38491fc78c18 100644 (file)
@@ -1,3 +1,4 @@
+// run-rustfix
 // Regression test for #51415: match default bindings were failing to
 // see the "move out" implied by `&s` below.
 
index a88819efcf7989f0fac0ff0c08358e223270ca71..0d486b45592b5d7f792dd3f9779c1afb78cc7c03 100644 (file)
@@ -1,11 +1,16 @@
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/issue-51415.rs:6:42
+  --> $DIR/issue-51415.rs:7:42
    |
 LL |     let opt = a.iter().enumerate().find(|(_, &s)| {
    |                                          ^^^^^-^
    |                                               |
    |                                               data moved here
    |                                               move occurs because `s` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |     let opt = a.iter().enumerate().find(|(_, &ref s)| {
+   |                                               +++
 
 error: aborting due to previous error
 
index 1f9cbdb73425d3455acac1c24aa8dc57f59f94a2..99c63e4db50d3edbeff290d2a2a503b9b3f80cae 100644 (file)
@@ -2,10 +2,13 @@ error[E0507]: cannot move out of `*array` which is behind a shared reference
   --> $DIR/issue-54597-reject-move-out-of-borrow-via-pat.rs:14:13
    |
 LL |             *array
-   |             ^^^^^^
-   |             |
-   |             move occurs because `*array` has type `Vec<Value>`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&*array`
+   |             ^^^^^^ move occurs because `*array` has type `Vec<Value>`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -             *array
+LL +             array
+   |
 
 error: aborting due to previous error
 
index 2552fff860cd369a94b66b767d80f63f8a27df7e..a585bff0c654395b8c208ca5c29ca9f5f7a70d2b 100644 (file)
@@ -27,11 +27,8 @@ LL |         foo = Some(Struct);
 LL |     let _y = foo;
    |              ^^^ value used here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `foo`
+note: `Option::<T>::unwrap` takes ownership of the receiver `self`, which moves `foo`
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |     pub const fn unwrap(self) -> T {
-   |                         ^^^^
 
 error[E0382]: use of moved value: `foo`
   --> $DIR/issue-83760.rs:37:14
@@ -55,11 +52,8 @@ LL |         foo = Some(Struct);
 LL |     } else if true {
 LL |         foo = Some(Struct);
    |         ^^^^^^^^^^^^^^^^^^
-note: this function takes ownership of the receiver `self`, which moves `foo`
+note: `Option::<T>::unwrap` takes ownership of the receiver `self`, which moves `foo`
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |     pub const fn unwrap(self) -> T {
-   |                         ^^^^
 
 error: aborting due to 3 previous errors
 
index 039575a8d79a5633b3e37c6f0273760a4289a8d8..afd141125ac7c9b3204ab714eab1e35244ef84bc 100644 (file)
@@ -8,10 +8,12 @@ LL |     take_mut(|| {
    |              -- captured by this `FnMut` closure
 LL |
 LL |         let _foo: String = val;
-   |                            ^^^
-   |                            |
-   |                            move occurs because `val` has type `String`, which does not implement the `Copy` trait
-   |                            help: consider borrowing here: `&val`
+   |                            ^^^ move occurs because `val` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         let _foo: String = &val;
+   |                            +
 
 error: aborting due to previous error
 
index 984981ce2ea14c85a11b8ed87c03850633082754..8ac711e9e59db806a8d128dd54bb999c60be2fe1 100644 (file)
@@ -2,10 +2,7 @@ error[E0507]: cannot move out of static item `D`
   --> $DIR/move-error-snippets-ext.rs:5:17
    |
 LL |         let a = $c;
-   |                 ^^
-   |                 |
-   |                 move occurs because `D` has type `A`, which does not implement the `Copy` trait
-   |                 help: consider borrowing here: `&$c`
+   |                 ^^ move occurs because `D` has type `A`, which does not implement the `Copy` trait
    |
   ::: $DIR/move-error-snippets.rs:21:1
    |
@@ -13,6 +10,10 @@ LL | sss!();
    | ------ in this macro invocation
    |
    = note: this error originates in the macro `aaa` which comes from the expansion of the macro `sss` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider borrowing here
+   |
+LL |         let a = &$c;
+   |                 +
 
 error: aborting due to previous error
 
index 13a2005e2ef4c40ef38abd3ee3034f7fb972f656..ecd916a59fcbd725da4a3d607e951a71377ff885 100644 (file)
@@ -9,11 +9,8 @@ LL |
 LL |     fill_segment(state);
    |                  ^^^^^ value borrowed here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `state`
+note: `into_iter` takes ownership of the receiver `self`, which moves `state`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-   |
-LL |     fn into_iter(self) -> Self::IntoIter;
-   |                  ^^^^
 help: consider creating a fresh reborrow of `state` here
    |
 LL |     for _ in &mut *state {}
index b1af090aec2b03346a79cca26359c72d1dbece38..4621d8793514ac8dd2cf858dd6e1d424cd6c9eb8 100644 (file)
@@ -8,11 +8,8 @@ LL |     cb.map(|cb| cb());
    |     help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents
    |     move occurs because `*cb` has type `Option<&mut dyn FnMut()>`, which does not implement the `Copy` trait
    |
-note: this function takes ownership of the receiver `self`, which moves `*cb`
+note: `Option::<T>::map` takes ownership of the receiver `self`, which moves `*cb`
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |     pub const fn map<U, F>(self, f: F) -> Option<U>
-   |                            ^^^^
 
 error[E0596]: cannot borrow `*cb` as mutable, as it is behind a `&` reference
   --> $DIR/suggest-as-ref-on-mut-closure.rs:12:26
index 0c151b097077ec0475c6669fedf1fa9c8ffec71f..b1367c652188bd8f4bafd95c2addf26ea843e94b 100644 (file)
@@ -10,11 +10,8 @@ LL |         y.into_iter();
    |         |
    |         move occurs because `y` has type `Vec<String>`, which does not implement the `Copy` trait
    |
-note: this function takes ownership of the receiver `self`, which moves `y`
+note: `into_iter` takes ownership of the receiver `self`, which moves `y`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-   |
-LL |     fn into_iter(self) -> Self::IntoIter;
-   |                  ^^^^
 
 error: aborting due to previous error
 
index de654fdc1a4b5540125520e7825586a083a7f672..f102f666dc2769daf19207fafb13ed30af11cb3a 100644 (file)
@@ -9,9 +9,6 @@ LL |     let _ = Box::into_boxed_slice(boxed_slice);
    = help: the trait `Sized` is not implemented for `[u8]`
 note: required by a bound in `Box::<T, A>::into_boxed_slice`
   --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
-   |
-LL | impl<T, A: Allocator> Box<T, A> {
-   |      ^ required by this bound in `Box::<T, A>::into_boxed_slice`
 
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
   --> $DIR/into-boxed-slice-fail.rs:7:13
@@ -33,9 +30,6 @@ LL |     let _ = Box::into_boxed_slice(boxed_trait);
    = help: the trait `Sized` is not implemented for `dyn Debug`
 note: required by a bound in `Box::<T, A>::into_boxed_slice`
   --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
-   |
-LL | impl<T, A: Allocator> Box<T, A> {
-   |      ^ required by this bound in `Box::<T, A>::into_boxed_slice`
 
 error[E0277]: the size for values of type `dyn Debug` cannot be known at compilation time
   --> $DIR/into-boxed-slice-fail.rs:11:13
index d4c9f23164f8bcb1d55ec5e0fd19c8b2af78a703..f68d181291dd7f49456e8ae28eeaf9cbf445035b 100644 (file)
@@ -19,4 +19,11 @@ fn main() {
         &E::Foo => {}
         &E::Bar(ref identifier) => println!("{}", *identifier)
     };
+    if let &E::Bar(identifier) = &s.x { //~ ERROR cannot move
+        f(identifier.clone());
+    };
+    let &E::Bar(identifier) = &s.x else { //~ ERROR cannot move
+        return;
+    };
+    f(identifier.clone());
 }
index 0012f67cfa1cd02af3e7c1c8b9e802a0befd5cbc..203e37dc387c1526798c544ae1dec9e3c36b4963 100644 (file)
@@ -5,12 +5,47 @@ LL |     match &s.x {
    |           ^^^^
 LL |         &E::Foo => {}
 LL |         &E::Bar(identifier) => f(identifier.clone())
-   |         -------------------
-   |         |       |
-   |         |       data moved here
-   |         |       move occurs because `identifier` has type `String`, which does not implement the `Copy` trait
-   |         help: consider removing the `&`: `E::Bar(identifier)`
+   |                 ----------
+   |                 |
+   |                 data moved here
+   |                 move occurs because `identifier` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -         &E::Bar(identifier) => f(identifier.clone())
+LL +         E::Bar(identifier) => f(identifier.clone())
+   |
+
+error[E0507]: cannot move out of a shared reference
+  --> $DIR/by-move-pattern-binding.rs:22:34
+   |
+LL |     if let &E::Bar(identifier) = &s.x {
+   |                    ----------    ^^^^
+   |                    |
+   |                    data moved here
+   |                    move occurs because `identifier` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -     if let &E::Bar(identifier) = &s.x {
+LL +     if let E::Bar(identifier) = &s.x {
+   |
+
+error[E0507]: cannot move out of a shared reference
+  --> $DIR/by-move-pattern-binding.rs:25:31
+   |
+LL |     let &E::Bar(identifier) = &s.x else {
+   |                 ----------    ^^^^
+   |                 |
+   |                 data moved here
+   |                 move occurs because `identifier` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -     let &E::Bar(identifier) = &s.x else {
+LL +     let E::Bar(identifier) = &s.x else {
+   |
 
-error: aborting due to previous error
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0507`.
index 075bd1fc488e6b50d6782335b526417cb728a3e2..d1f13d52362da8bf6f8e89045d4a432e497a42f5 100644 (file)
@@ -63,11 +63,9 @@ error[E0412]: cannot find type `F` in this scope
    |
 LL |     self , ... ,   self ,   self , ... ) where F : FnOnce ( & 'a & 'b usize ) {
    |                                                ^
+  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
-   | -------------------------------------- similarly named trait `Fn` defined here
+   = note: similarly named trait `Fn` defined here
    |
 help: a trait with a similar name exists
    |
index 4804df133401b89ff13e53d2be426491469f223e..eda867f4159ff7d5f82f5a8f8050f904137cf01b 100644 (file)
@@ -14,9 +14,6 @@ LL | | }
    = note: [async fn body@$DIR/async.rs:7:29: 9:2] must be a future or must implement `IntoFuture` to be awaited
 note: required by a bound in `identity_future`
   --> $SRC_DIR/core/src/future/mod.rs:LL:COL
-   |
-LL | pub const fn identity_future<O, Fut: Future<Output = O>>(f: Fut) -> Fut {
-   |                                      ^^^^^^^^^^^^^^^^^^ required by this bound in `identity_future`
 
 error[E0277]: the size for values of type `<[async fn body@$DIR/async.rs:7:29: 9:2] as Future>::Output` cannot be known at compilation time
   --> $DIR/async.rs:7:29
@@ -30,9 +27,6 @@ LL | | }
    = help: the trait `Sized` is not implemented for `<[async fn body@$DIR/async.rs:7:29: 9:2] as Future>::Output`
 note: required by a bound in `identity_future`
   --> $SRC_DIR/core/src/future/mod.rs:LL:COL
-   |
-LL | pub const fn identity_future<O, Fut: Future<Output = O>>(f: Fut) -> Fut {
-   |                              ^ required by this bound in `identity_future`
 
 error[E0277]: `[async fn body@$DIR/async.rs:7:29: 9:2]` is not a future
   --> $DIR/async.rs:7:25
index 31939f7f6db5d9fd098d716a62bce8ebb6c8dee0..b13700a4ea5ba9fedaee2a266d22dc47b392e564 100644 (file)
@@ -58,10 +58,12 @@ error[E0507]: cannot move out of static item `x`
   --> $DIR/check-static-values-constraints.rs:110:45
    |
 LL |     let y = { static x: Box<isize> = box 3; x };
-   |                                             ^
-   |                                             |
-   |                                             move occurs because `x` has type `Box<isize>`, which does not implement the `Copy` trait
-   |                                             help: consider borrowing here: `&x`
+   |                                             ^ move occurs because `x` has type `Box<isize>`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     let y = { static x: Box<isize> = box 3; &x };
+   |                                             +
 
 error[E0010]: allocations are not allowed in statics
   --> $DIR/check-static-values-constraints.rs:110:38
index d5432755cfed3fd2981c31270e6effbfacd50fec..7a04ed7381e66d198123edeacbee33379f1eb7dc 100644 (file)
@@ -6,8 +6,8 @@ LL |     with_closure(|x: u32, y| {});
    |
 help: consider giving this closure parameter an explicit type
    |
-LL |     with_closure(|x: u32, y: _| {});
-   |                            +++
+LL |     with_closure(|x: u32, y: /* Type */| {});
+   |                            ++++++++++++
 
 error: aborting due to previous error
 
index 7ffe3c1ef954ab6378d2c072698f6189be11a194..87a5d67a420c498c2a7926dfbaf6f4300eb83d5f 100644 (file)
@@ -10,9 +10,6 @@ LL |     let y = x.or_else(4);
    = note: wrap the `{integer}` in a closure with no arguments: `|| { /* code */ }`
 note: required by a bound in `Option::<T>::or_else`
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |         F: ~const FnOnce() -> Option<T>,
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Option::<T>::or_else`
 
 error: aborting due to previous error
 
index a2ca06b4e6e1aa7917d8a5a1864ea51d6238a08b..64e3b51ea713bf25e60f05b4ab0a9befcba53042 100644 (file)
@@ -19,9 +19,6 @@ LL |     let t = thread::spawn(|| {
    |                           ^^
 note: required by a bound in `spawn`
   --> $SRC_DIR/std/src/thread/mod.rs:LL:COL
-   |
-LL |     F: Send + 'static,
-   |        ^^^^ required by this bound in `spawn`
 
 error[E0277]: `Sender<()>` cannot be shared between threads safely
   --> $DIR/closure-move-sync.rs:18:19
@@ -40,9 +37,6 @@ LL |     thread::spawn(|| tx.send(()).unwrap());
    |                   ^^
 note: required by a bound in `spawn`
   --> $SRC_DIR/std/src/thread/mod.rs:LL:COL
-   |
-LL |     F: Send + 'static,
-   |        ^^^^ required by this bound in `spawn`
 
 error: aborting due to 2 previous errors
 
index 6ce63e829b314f5faa831247a4021492c5b04ef6..449cd0b317757bfef4d48f71d1fd4e9d1a84fa6c 100644 (file)
@@ -10,9 +10,6 @@ LL |     let x: Option<&[u8]> = Some("foo").map(std::mem::transmute);
    = note: unsafe function cannot be called generically without an unsafe block
 note: required by a bound in `Option::<T>::map`
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |         F: ~const FnOnce(T) -> U,
-   |            ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Option::<T>::map`
 
 error: aborting due to previous error
 
index 4c24a54bbbe014ddc03ee083e274aa58d97110de..9ba24c7a886958ab32b9d2ddfae01774d4438ea0 100644 (file)
@@ -12,8 +12,8 @@ LL |     [(); &(&'static: loop { |x| {}; }) as *const _ as usize]
    |
 help: consider giving this closure parameter an explicit type
    |
-LL |     [(); &(&'static: loop { |x: _| {}; }) as *const _ as usize]
-   |                               +++
+LL |     [(); &(&'static: loop { |x: /* Type */| {}; }) as *const _ as usize]
+   |                               ++++++++++++
 
 error: aborting due to 2 previous errors
 
index da3f539a0071d27a651c8ab8d34c839dc69963cc..1e860d32b2a06ea523cfc0ec086cf25cf61c35d1 100644 (file)
@@ -9,11 +9,9 @@ error[E0412]: cannot find type `F` in this scope
    |
 LL |     _func: F,
    |            ^
+  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
-   | -------------------------------------- similarly named trait `Fn` defined here
+   = note: similarly named trait `Fn` defined here
    |
 help: a trait with a similar name exists
    |
index 0e788a16eb0411fffe661c2069146868aa732f0a..72337892734e6af3a29009053ff42133f6f92f51 100644 (file)
@@ -8,9 +8,6 @@ LL |     Ok(())
    |
 note: tuple variant defined here
   --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL |     Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^
 
 error[E0308]: mismatched types
   --> $DIR/issue-87461.rs:17:8
@@ -22,9 +19,6 @@ LL |     Ok(())
    |
 note: tuple variant defined here
   --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL |     Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^
 
 error[E0308]: mismatched types
   --> $DIR/issue-87461.rs:26:12
@@ -36,9 +30,6 @@ LL |         Ok(())
    |
 note: tuple variant defined here
   --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL |     Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^
 
 error: aborting due to 3 previous errors
 
index a482750fbd016bf61dcb0383277d3991a8b9d10f..4a578b4d7f536204cfc6ae09a79ab5338f82c55e 100644 (file)
@@ -3,11 +3,9 @@ error[E0412]: cannot find type `n` in this scope
    |
 LL |     type_ascribe!(2, n([u8; || 1]))
    |                      ^ help: a trait with a similar name exists: `Fn`
+  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
-   | -------------------------------------- similarly named trait `Fn` defined here
+   = note: similarly named trait `Fn` defined here
 
 error[E0308]: mismatched types
   --> $DIR/issue-90871.rs:4:29
index eefc123fed7ac3ed07714d9666abfafc89141c6f..da26302c9d8a48219e8845a02c3820b764b95d4d 100644 (file)
@@ -2,8 +2,10 @@ error[E0631]: type mismatch in closure arguments
   --> $DIR/multiple-fn-bounds.rs:10:5
    |
 LL |     foo(move |x| v);
-   |     ^^^ -------- found signature defined here
-   |     |
+   |     ^^^ --------
+   |     |   |     |
+   |     |   |     help: do not borrow the argument: `char`
+   |     |   found signature defined here
    |     expected due to this
    |
    = note: expected closure signature `fn(char) -> _`
index 080f6c39449f040993ae98e851ad7fc8e5fbaeea..e0e369124a4be83557473cfd87160a5837647408 100644 (file)
@@ -9,11 +9,8 @@ LL |     {
 LL |         println!("{:?}", some_vec);
    |                          ^^^^^^^^ value borrowed here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `some_vec`
+note: `into_iter` takes ownership of the receiver `self`, which moves `some_vec`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-   |
-LL |     fn into_iter(self) -> Self::IntoIter;
-   |                  ^^^^
    = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider cloning the value if the performance cost is acceptable
    |
index 34debb6831734568330e7b6d8ccfaa32ae753e3f..3906d64c9462453682f8edf42d47332c5619b14f 100644 (file)
@@ -1,4 +1,4 @@
-error[E0599]: no method named `closure` found for reference `&Obj<[closure@$DIR/issue-33784.rs:25:43: 25:45]>` in the current scope
+error[E0599]: no method named `closure` found for reference `&Obj<[closure@issue-33784.rs:25:43]>` in the current scope
   --> $DIR/issue-33784.rs:27:7
    |
 LL |     p.closure();
@@ -9,7 +9,7 @@ help: to call the function stored in `closure`, surround the field access with p
 LL |     (p.closure)();
    |     +         +
 
-error[E0599]: no method named `fn_ptr` found for reference `&&Obj<[closure@$DIR/issue-33784.rs:25:43: 25:45]>` in the current scope
+error[E0599]: no method named `fn_ptr` found for reference `&&Obj<[closure@issue-33784.rs:25:43]>` in the current scope
   --> $DIR/issue-33784.rs:29:7
    |
 LL |     q.fn_ptr();
index 688db695fa848cc4b7761acf444292bbe0fc2785..13ea4a295afd75dbc4ee43c746c528e9b6c4ea5b 100644 (file)
@@ -5,11 +5,14 @@ LL |     let y = Mask::<_, _>::splat(false);
    |         ^   ------------------- type must be known at this point
    |
    = note: cannot satisfy `_: MaskElement`
+   = help: the following types implement trait `MaskElement`:
+             i16
+             i32
+             i64
+             i8
+             isize
 note: required by a bound in `Mask::<T, LANES>::splat`
   --> $SRC_DIR/core/src/../../portable-simd/crates/core_simd/src/masks.rs:LL:COL
-   |
-LL |     T: MaskElement,
-   |        ^^^^^^^^^^^ required by this bound in `Mask::<T, LANES>::splat`
 help: consider giving `y` an explicit type, where the type for type parameter `T` is specified
    |
 LL |     let y: Mask<_, LANES> = Mask::<_, _>::splat(false);
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-105608.rs b/src/test/ui/const-generics/generic_const_exprs/issue-105608.rs
new file mode 100644 (file)
index 0000000..e28ba3b
--- /dev/null
@@ -0,0 +1,15 @@
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+struct Combination<const STRATEGIES: usize>;
+
+impl<const STRATEGIES: usize> Combination<STRATEGIES> {
+    fn and<M>(self) -> Combination<{ STRATEGIES + 1 }> {
+        Combination
+    }
+}
+
+pub fn main() {
+    Combination::<0>.and::<_>().and::<_>();
+    //~^ ERROR: type annotations needed
+}
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-105608.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-105608.stderr
new file mode 100644 (file)
index 0000000..0be4c43
--- /dev/null
@@ -0,0 +1,14 @@
+error[E0282]: type annotations needed
+  --> $DIR/issue-105608.rs:13:22
+   |
+LL |     Combination::<0>.and::<_>().and::<_>();
+   |                      ^^^ cannot infer type of the type parameter `M` declared on the associated function `and`
+   |
+help: consider specifying the generic argument
+   |
+LL |     Combination::<0>.and::<_>().and::<_>();
+   |                         ~~~~~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
index 4d0d0253f1b6d4a08206836089a6ee89fda0f6f6..0af5493f81675502ced616895b8f4bf9b1ccc503 100644 (file)
@@ -40,7 +40,17 @@ error[E0283]: type annotations needed: cannot satisfy `IsLessOrEqual<I, 8>: True
 LL |     IsLessOrEqual<I, 8>: True,
    |                          ^^^^
    |
-   = note: cannot satisfy `IsLessOrEqual<I, 8>: True`
+note: multiple `impl`s or `where` clauses satisfying `IsLessOrEqual<I, 8>: True` found
+  --> $DIR/issue-72787.rs:10:1
+   |
+LL | impl<const LHS: u32, const RHS: u32> True for IsLessOrEqual<LHS, RHS> where
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     IsLessOrEqual<I, 8>: True,
+   |                          ^^^^
+...
+LL |     IsLessOrEqual<{ 8 - I }, { 8 - J }>: True,
+   |                                          ^^^^
 
 error[E0283]: type annotations needed: cannot satisfy `IsLessOrEqual<I, 8>: True`
   --> $DIR/issue-72787.rs:21:26
@@ -48,7 +58,17 @@ error[E0283]: type annotations needed: cannot satisfy `IsLessOrEqual<I, 8>: True
 LL |     IsLessOrEqual<I, 8>: True,
    |                          ^^^^
    |
-   = note: cannot satisfy `IsLessOrEqual<I, 8>: True`
+note: multiple `impl`s or `where` clauses satisfying `IsLessOrEqual<I, 8>: True` found
+  --> $DIR/issue-72787.rs:10:1
+   |
+LL | impl<const LHS: u32, const RHS: u32> True for IsLessOrEqual<LHS, RHS> where
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     IsLessOrEqual<I, 8>: True,
+   |                          ^^^^
+...
+LL |     IsLessOrEqual<{ 8 - I }, { 8 - J }>: True,
+   |                                          ^^^^
 
 error: aborting due to 6 previous errors
 
index bf1b411ee7ccfdffe5485386a183c7ac81dd9376..a08c9912527c732eb8de4b647310e3c2628d019d 100644 (file)
@@ -1,14 +1,10 @@
 error[E0080]: evaluation of `Inline::<dyn std::fmt::Debug>::{constant#0}` failed
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
    |
-LL |     intrinsics::size_of::<T>()
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ size_of called on unsized type `dyn Debug`
+   = note: size_of called on unsized type `dyn Debug`
    |
 note: inside `std::mem::size_of::<dyn Debug>`
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
-   |
-LL |     intrinsics::size_of::<T>()
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `Inline::<dyn Debug>::{constant#0}`
   --> $DIR/issue-80742.rs:22:10
    |
@@ -23,11 +19,9 @@ LL | struct Inline<T>
 ...
 LL |     let dst = Inline::<dyn Debug>::new(0);
    |                                    ^^^ function or associated item cannot be called on `Inline<dyn Debug>` due to unsatisfied trait bounds
+  --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-   |
-LL | pub trait Debug {
-   | --------------- doesn't satisfy `dyn Debug: Sized`
+   = note: doesn't satisfy `dyn Debug: Sized`
    |
    = note: the following trait bounds were not satisfied:
            `dyn Debug: Sized`
@@ -35,14 +29,10 @@ LL | pub trait Debug {
 error[E0080]: evaluation of `Inline::<dyn std::fmt::Debug>::{constant#0}` failed
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
    |
-LL |     intrinsics::size_of::<T>()
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ size_of called on unsized type `dyn Debug`
+   = note: size_of called on unsized type `dyn Debug`
    |
 note: inside `std::mem::size_of::<dyn Debug>`
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
-   |
-LL |     intrinsics::size_of::<T>()
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `Inline::<dyn Debug>::{constant#0}`
   --> $DIR/issue-80742.rs:14:10
    |
index d955b4f9651daa4906530e94bb19a0278ac331af..8c76ca6902962df686e03c185f2bd4c3f4ba9a6f 100644 (file)
@@ -4,11 +4,6 @@ error[E0107]: this associated function takes 0 generic arguments but 1 generic a
 LL |     let _: u32 = 5i32.try_into::<32>().unwrap();
    |                       ^^^^^^^^ expected 0 generic arguments
    |
-note: associated function defined here, with 0 generic parameters
-  --> $SRC_DIR/core/src/convert/mod.rs:LL:COL
-   |
-LL |     fn try_into(self) -> Result<T, Self::Error>;
-   |        ^^^^^^^^
 help: consider moving this generic argument to the `TryInto` trait, which takes up to 1 argument
    |
 LL |     let _: u32 = TryInto::<32>::try_into(5i32).unwrap();
index 1400d2bf5a7ba64ff65b98d3bad000bb0fb93cab..993b63518e44cbb8b40f3c6c7138405475b6ab47 100644 (file)
@@ -5,12 +5,6 @@ LL |     let _: Cell<&str, "a"> = Cell::new("");
    |            ^^^^       --- help: remove this generic argument
    |            |
    |            expected 1 generic argument
-   |
-note: struct defined here, with 1 generic parameter: `T`
-  --> $SRC_DIR/core/src/cell.rs:LL:COL
-   |
-LL | pub struct Cell<T: ?Sized> {
-   |            ^^^^ -
 
 error: aborting due to previous error
 
index 362b8554b2fcb91617bc1a4c371c44753b4928a2..7491fdc8a693e413a79937c04443cdad93df9995 100644 (file)
@@ -6,8 +6,8 @@ LL |     let _ = foo([0; 1]);
    |
 help: consider giving this pattern a type
    |
-LL |     let _: _ = foo([0; 1]);
-   |          +++
+LL |     let _: /* Type */ = foo([0; 1]);
+   |          ++++++++++++
 
 error: aborting due to previous error
 
index 563f3ffd6744f0650cab1cd129d4688a99440c0f..0079bb3aad6df5b72e8fb68ff9f1d7844c5a581b 100644 (file)
@@ -1,14 +1,10 @@
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
    |
-LL |         &*ptr::slice_from_raw_parts(data, len)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: null pointer is a dangling pointer (it has no provenance)
+   = note: dereferencing pointer failed: null pointer is a dangling pointer (it has no provenance)
    |
 note: inside `std::slice::from_raw_parts::<'_, u32>`
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
-   |
-LL |         &*ptr::slice_from_raw_parts(data, len)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `S0`
   --> $DIR/forbidden_slices.rs:18:34
    |
@@ -18,14 +14,10 @@ LL | pub static S0: &[u32] = unsafe { from_raw_parts(ptr::null(), 0) };
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
    |
-LL |         &*ptr::slice_from_raw_parts(data, len)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: null pointer is a dangling pointer (it has no provenance)
+   = note: dereferencing pointer failed: null pointer is a dangling pointer (it has no provenance)
    |
 note: inside `std::slice::from_raw_parts::<'_, ()>`
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
-   |
-LL |         &*ptr::slice_from_raw_parts(data, len)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `S1`
   --> $DIR/forbidden_slices.rs:19:33
    |
@@ -35,14 +27,10 @@ LL | pub static S1: &[()] = unsafe { from_raw_parts(ptr::null(), 0) };
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
    |
-LL |         &*ptr::slice_from_raw_parts(data, len)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: ALLOC_ID has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds
+   = note: dereferencing pointer failed: allocN has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds
    |
 note: inside `std::slice::from_raw_parts::<'_, u32>`
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
-   |
-LL |         &*ptr::slice_from_raw_parts(data, len)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `S2`
   --> $DIR/forbidden_slices.rs:22:34
    |
@@ -57,7 +45,7 @@ LL | pub static S4: &[u8] = unsafe { from_raw_parts((&D1) as *const _ as _, 1) }
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾─ALLOC_ID─╼ 01 00 00 00                         │ ╾──╼....
+               ╾ALLOC_ID╼ 01 00 00 00                         │ ╾──╼....
            }
 
 error[E0080]: it is undefined behavior to use this value
@@ -69,7 +57,7 @@ LL | pub static S5: &[u8] = unsafe { from_raw_parts((&D3) as *const _ as _, size
    = help: this code performed an operation that depends on the underlying bytes representing a pointer
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
    = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾─ALLOC_ID─╼ 04 00 00 00                         │ ╾──╼....
+               ╾ALLOC_ID╼ 04 00 00 00                         │ ╾──╼....
            }
 
 error[E0080]: it is undefined behavior to use this value
@@ -80,31 +68,27 @@ LL | pub static S6: &[bool] = unsafe { from_raw_parts((&D0) as *const _ as _, 4)
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾─ALLOC_ID─╼ 04 00 00 00                         │ ╾──╼....
+               ╾ALLOC_ID╼ 04 00 00 00                         │ ╾──╼....
            }
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/forbidden_slices.rs:32:1
    |
 LL | pub static S7: &[u16] = unsafe {
-   | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned reference (required 2 byte alignment but found 1)
+   | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[1]: encountered uninitialized bytes
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾─A_ID+0x1─╼ 04 00 00 00                         │ ╾──╼....
+               ╾ALLOC_ID+0x2╼ 04 00 00 00                         │ ╾──╼....
            }
 
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
    |
-LL |         &*ptr::slice_from_raw_parts(data, len)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: ALLOC_ID has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds
+   = note: dereferencing pointer failed: allocN has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds
    |
 note: inside `std::slice::from_raw_parts::<'_, u64>`
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
-   |
-LL |         &*ptr::slice_from_raw_parts(data, len)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `S8`
   --> $DIR/forbidden_slices.rs:43:5
    |
@@ -114,19 +98,12 @@ LL |     from_raw_parts(ptr, 1)
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: null pointer is a dangling pointer (it has no provenance)
+   = note: out-of-bounds offset_from: null pointer is a dangling pointer (it has no provenance)
    |
 note: inside `ptr::const_ptr::<impl *const u32>::sub_ptr`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `from_ptr_range::<'_, u32>`
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
-   |
-LL |     unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
-   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `R0`
   --> $DIR/forbidden_slices.rs:46:34
    |
@@ -136,19 +113,12 @@ LL | pub static R0: &[u32] = unsafe { from_ptr_range(ptr::null()..ptr::null()) }
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         assert!(0 < pointee_size && pointee_size <= isize::MAX as usize);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'assertion failed: 0 < pointee_size && pointee_size <= isize::MAX as usize', $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   = note: the evaluated program panicked at 'assertion failed: 0 < pointee_size && pointee_size <= isize::MAX as usize', $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
 note: inside `ptr::const_ptr::<impl *const ()>::sub_ptr`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         assert!(0 < pointee_size && pointee_size <= isize::MAX as usize);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `from_ptr_range::<'_, ()>`
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
-   |
-LL |     unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
-   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `R1`
   --> $DIR/forbidden_slices.rs:47:33
    |
@@ -159,19 +129,12 @@ LL | pub static R1: &[()] = unsafe { from_ptr_range(ptr::null()..ptr::null()) };
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer arithmetic: ALLOC_ID has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds
+   = note: out-of-bounds pointer arithmetic: allocN has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds
    |
 note: inside `ptr::const_ptr::<impl *const u32>::offset`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `ptr::const_ptr::<impl *const u32>::add`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { self.offset(count as isize) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `R2`
   --> $DIR/forbidden_slices.rs:50:25
    |
@@ -186,7 +149,7 @@ LL | pub static R4: &[u8] = unsafe {
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
-               â\95¾ALLOC_IDâ\94\80â\95¼ 01 00 00 00                         â\94\82 â\95¾â\94\80â\94\80â\95¼....
+               ╾ALLOC_ID╼ 01 00 00 00                         │ ╾──╼....
            }
 
 error[E0080]: it is undefined behavior to use this value
@@ -198,7 +161,7 @@ LL | pub static R5: &[u8] = unsafe {
    = help: this code performed an operation that depends on the underlying bytes representing a pointer
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
    = note: the raw bytes of the constant (size: 8, align: 4) {
-               â\95¾ALLOC_IDâ\94\80â\95¼ 04 00 00 00                         â\94\82 â\95¾â\94\80â\94\80â\95¼....
+               ╾ALLOC_ID╼ 04 00 00 00                         │ ╾──╼....
            }
 
 error[E0080]: it is undefined behavior to use this value
@@ -209,38 +172,35 @@ LL | pub static R6: &[bool] = unsafe {
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
-               â\95¾ALLOC_IDâ\94\80â\95¼ 04 00 00 00                         â\94\82 â\95¾â\94\80â\94\80â\95¼....
+               ╾ALLOC_ID╼ 04 00 00 00                         │ ╾──╼....
            }
 
-error[E0080]: it is undefined behavior to use this value
-  --> $DIR/forbidden_slices.rs:67:1
+error[E0080]: could not evaluate static initializer
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
    |
-LL | pub static R7: &[u16] = unsafe {
-   | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned reference (required 2 byte alignment but found 1)
+   = note: accessing memory with alignment 1, but alignment 2 is required
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
-   = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾A_ID+0x1─╼ 04 00 00 00                         │ ╾──╼....
-           }
+note: inside `std::slice::from_raw_parts::<'_, u16>`
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+note: inside `from_ptr_range::<'_, u16>`
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+note: inside `R7`
+  --> $DIR/forbidden_slices.rs:69:5
+   |
+LL |     from_ptr_range(ptr..ptr.add(4))
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer arithmetic: ALLOC_ID has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds
+   = note: out-of-bounds pointer arithmetic: allocN has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds
    |
 note: inside `ptr::const_ptr::<impl *const u64>::offset`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `ptr::const_ptr::<impl *const u64>::add`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { self.offset(count as isize) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `R8`
-  --> $DIR/forbidden_slices.rs:74:25
+  --> $DIR/forbidden_slices.rs:73:25
    |
 LL |     from_ptr_range(ptr..ptr.add(1))
    |                         ^^^^^^^^^^
@@ -248,21 +208,14 @@ LL |     from_ptr_range(ptr..ptr.add(1))
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from_unsigned` called on pointers into different allocations
+   = note: `ptr_offset_from_unsigned` called on pointers into different allocations
    |
 note: inside `ptr::const_ptr::<impl *const u32>::sub_ptr`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `from_ptr_range::<'_, u32>`
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
-   |
-LL |     unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
-   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `R9`
-  --> $DIR/forbidden_slices.rs:79:34
+  --> $DIR/forbidden_slices.rs:78:34
    |
 LL | pub static R9: &[u32] = unsafe { from_ptr_range(&D0..(&D0 as *const u32).add(1)) };
    |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -270,21 +223,14 @@ LL | pub static R9: &[u32] = unsafe { from_ptr_range(&D0..(&D0 as *const u32).ad
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from_unsigned` called on pointers into different allocations
+   = note: `ptr_offset_from_unsigned` called on pointers into different allocations
    |
 note: inside `ptr::const_ptr::<impl *const u32>::sub_ptr`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `from_ptr_range::<'_, u32>`
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
-   |
-LL |     unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
-   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `R10`
-  --> $DIR/forbidden_slices.rs:80:35
+  --> $DIR/forbidden_slices.rs:79:35
    |
 LL | pub static R10: &[u32] = unsafe { from_ptr_range(&D0..&D0) };
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^^
index 43529d57f4021aabc40869804ed85b177fece5ac..f4f9fe69516a6a258a1abb022c7c35b5b135d37a 100644 (file)
@@ -1,14 +1,10 @@
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
    |
-LL |         &*ptr::slice_from_raw_parts(data, len)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: null pointer is a dangling pointer (it has no provenance)
+   = note: dereferencing pointer failed: null pointer is a dangling pointer (it has no provenance)
    |
 note: inside `std::slice::from_raw_parts::<'_, u32>`
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
-   |
-LL |         &*ptr::slice_from_raw_parts(data, len)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `S0`
   --> $DIR/forbidden_slices.rs:18:34
    |
@@ -18,14 +14,10 @@ LL | pub static S0: &[u32] = unsafe { from_raw_parts(ptr::null(), 0) };
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
    |
-LL |         &*ptr::slice_from_raw_parts(data, len)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: null pointer is a dangling pointer (it has no provenance)
+   = note: dereferencing pointer failed: null pointer is a dangling pointer (it has no provenance)
    |
 note: inside `std::slice::from_raw_parts::<'_, ()>`
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
-   |
-LL |         &*ptr::slice_from_raw_parts(data, len)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `S1`
   --> $DIR/forbidden_slices.rs:19:33
    |
@@ -35,14 +27,10 @@ LL | pub static S1: &[()] = unsafe { from_raw_parts(ptr::null(), 0) };
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
    |
-LL |         &*ptr::slice_from_raw_parts(data, len)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: ALLOC_ID has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds
+   = note: dereferencing pointer failed: allocN has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds
    |
 note: inside `std::slice::from_raw_parts::<'_, u32>`
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
-   |
-LL |         &*ptr::slice_from_raw_parts(data, len)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `S2`
   --> $DIR/forbidden_slices.rs:22:34
    |
@@ -57,7 +45,7 @@ LL | pub static S4: &[u8] = unsafe { from_raw_parts((&D1) as *const _ as _, 1) }
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾───────ALLOC_ID───────╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........
+               ╾ALLOC_ID╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........
            }
 
 error[E0080]: it is undefined behavior to use this value
@@ -69,7 +57,7 @@ LL | pub static S5: &[u8] = unsafe { from_raw_parts((&D3) as *const _ as _, size
    = help: this code performed an operation that depends on the underlying bytes representing a pointer
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾───────ALLOC_ID───────╼ 08 00 00 00 00 00 00 00 │ ╾──────╼........
+               ╾ALLOC_ID╼ 08 00 00 00 00 00 00 00 │ ╾──────╼........
            }
 
 error[E0080]: it is undefined behavior to use this value
@@ -80,31 +68,27 @@ LL | pub static S6: &[bool] = unsafe { from_raw_parts((&D0) as *const _ as _, 4)
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾───────ALLOC_ID───────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
+               ╾ALLOC_ID╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
            }
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/forbidden_slices.rs:32:1
    |
 LL | pub static S7: &[u16] = unsafe {
-   | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned reference (required 2 byte alignment but found 1)
+   | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[1]: encountered uninitialized bytes
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾─────ALLOC_ID+0x1─────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
+               ╾ALLOC_ID+0x2╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
            }
 
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
    |
-LL |         &*ptr::slice_from_raw_parts(data, len)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: ALLOC_ID has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds
+   = note: dereferencing pointer failed: allocN has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds
    |
 note: inside `std::slice::from_raw_parts::<'_, u64>`
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
-   |
-LL |         &*ptr::slice_from_raw_parts(data, len)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `S8`
   --> $DIR/forbidden_slices.rs:43:5
    |
@@ -114,19 +98,12 @@ LL |     from_raw_parts(ptr, 1)
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: null pointer is a dangling pointer (it has no provenance)
+   = note: out-of-bounds offset_from: null pointer is a dangling pointer (it has no provenance)
    |
 note: inside `ptr::const_ptr::<impl *const u32>::sub_ptr`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `from_ptr_range::<'_, u32>`
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
-   |
-LL |     unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
-   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `R0`
   --> $DIR/forbidden_slices.rs:46:34
    |
@@ -136,19 +113,12 @@ LL | pub static R0: &[u32] = unsafe { from_ptr_range(ptr::null()..ptr::null()) }
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         assert!(0 < pointee_size && pointee_size <= isize::MAX as usize);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'assertion failed: 0 < pointee_size && pointee_size <= isize::MAX as usize', $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   = note: the evaluated program panicked at 'assertion failed: 0 < pointee_size && pointee_size <= isize::MAX as usize', $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
 note: inside `ptr::const_ptr::<impl *const ()>::sub_ptr`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         assert!(0 < pointee_size && pointee_size <= isize::MAX as usize);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `from_ptr_range::<'_, ()>`
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
-   |
-LL |     unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
-   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `R1`
   --> $DIR/forbidden_slices.rs:47:33
    |
@@ -159,19 +129,12 @@ LL | pub static R1: &[()] = unsafe { from_ptr_range(ptr::null()..ptr::null()) };
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer arithmetic: ALLOC_ID has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds
+   = note: out-of-bounds pointer arithmetic: allocN has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds
    |
 note: inside `ptr::const_ptr::<impl *const u32>::offset`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `ptr::const_ptr::<impl *const u32>::add`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { self.offset(count as isize) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `R2`
   --> $DIR/forbidden_slices.rs:50:25
    |
@@ -186,7 +149,7 @@ LL | pub static R4: &[u8] = unsafe {
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾──────ALLOC_ID───────╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........
+               ╾ALLOC_ID╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........
            }
 
 error[E0080]: it is undefined behavior to use this value
@@ -198,7 +161,7 @@ LL | pub static R5: &[u8] = unsafe {
    = help: this code performed an operation that depends on the underlying bytes representing a pointer
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾──────ALLOC_ID───────╼ 08 00 00 00 00 00 00 00 │ ╾──────╼........
+               ╾ALLOC_ID╼ 08 00 00 00 00 00 00 00 │ ╾──────╼........
            }
 
 error[E0080]: it is undefined behavior to use this value
@@ -209,38 +172,35 @@ LL | pub static R6: &[bool] = unsafe {
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾──────ALLOC_ID───────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
+               ╾ALLOC_ID╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
            }
 
-error[E0080]: it is undefined behavior to use this value
-  --> $DIR/forbidden_slices.rs:67:1
+error[E0080]: could not evaluate static initializer
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
    |
-LL | pub static R7: &[u16] = unsafe {
-   | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned reference (required 2 byte alignment but found 1)
+   = note: accessing memory with alignment 1, but alignment 2 is required
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
-   = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾────ALLOC_ID+0x1─────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
-           }
+note: inside `std::slice::from_raw_parts::<'_, u16>`
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+note: inside `from_ptr_range::<'_, u16>`
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+note: inside `R7`
+  --> $DIR/forbidden_slices.rs:69:5
+   |
+LL |     from_ptr_range(ptr..ptr.add(4))
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer arithmetic: ALLOC_ID has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds
+   = note: out-of-bounds pointer arithmetic: allocN has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds
    |
 note: inside `ptr::const_ptr::<impl *const u64>::offset`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `ptr::const_ptr::<impl *const u64>::add`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { self.offset(count as isize) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `R8`
-  --> $DIR/forbidden_slices.rs:74:25
+  --> $DIR/forbidden_slices.rs:73:25
    |
 LL |     from_ptr_range(ptr..ptr.add(1))
    |                         ^^^^^^^^^^
@@ -248,21 +208,14 @@ LL |     from_ptr_range(ptr..ptr.add(1))
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from_unsigned` called on pointers into different allocations
+   = note: `ptr_offset_from_unsigned` called on pointers into different allocations
    |
 note: inside `ptr::const_ptr::<impl *const u32>::sub_ptr`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `from_ptr_range::<'_, u32>`
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
-   |
-LL |     unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
-   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `R9`
-  --> $DIR/forbidden_slices.rs:79:34
+  --> $DIR/forbidden_slices.rs:78:34
    |
 LL | pub static R9: &[u32] = unsafe { from_ptr_range(&D0..(&D0 as *const u32).add(1)) };
    |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -270,21 +223,14 @@ LL | pub static R9: &[u32] = unsafe { from_ptr_range(&D0..(&D0 as *const u32).ad
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from_unsigned` called on pointers into different allocations
+   = note: `ptr_offset_from_unsigned` called on pointers into different allocations
    |
 note: inside `ptr::const_ptr::<impl *const u32>::sub_ptr`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `from_ptr_range::<'_, u32>`
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
-   |
-LL |     unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
-   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `R10`
-  --> $DIR/forbidden_slices.rs:80:35
+  --> $DIR/forbidden_slices.rs:79:35
    |
 LL | pub static R10: &[u32] = unsafe { from_ptr_range(&D0..&D0) };
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^^
index e2184911f422c47cfe2318fd641c688e7d4cc90a..cc6100226dc1c00794ec90bbaf9524e9489f5f88 100644 (file)
@@ -1,6 +1,6 @@
 // stderr-per-bitwidth
-// normalize-stderr-test "alloc[0-9]+" -> "ALLOC_ID"
-// normalize-stderr-test "a[0-9]+\+0x" -> "A_ID+0x"
+// normalize-stderr-test "╾─*a(lloc)?[0-9]+(\+[a-z0-9]+)?─*╼" -> "╾ALLOC_ID$2╼"
+// normalize-stderr-test "alloc\d+" -> "allocN"
 // error-pattern: could not evaluate static initializer
 #![feature(
     slice_from_ptr_range,
@@ -31,7 +31,7 @@
 // Reading padding is not ok
 pub static S7: &[u16] = unsafe {
     //~^ ERROR: it is undefined behavior to use this value
-    let ptr = (&D2 as *const Struct as *const u16).byte_add(1);
+    let ptr = (&D2 as *const Struct as *const u16).add(1);
 
     from_raw_parts(ptr, 4)
 };
     from_ptr_range(ptr..ptr.add(4))
 };
 pub static R7: &[u16] = unsafe {
-    //~^ ERROR: it is undefined behavior to use this value
     let ptr = (&D2 as *const Struct as *const u16).byte_add(1);
-    from_ptr_range(ptr..ptr.add(4))
+    from_ptr_range(ptr..ptr.add(4)) //~ inside `R7`
 };
 pub static R8: &[u64] = unsafe {
     let ptr = (&D4 as *const [u32; 2] as *const u32).byte_add(1).cast::<u64>();
-    from_ptr_range(ptr..ptr.add(1))
+    from_ptr_range(ptr..ptr.add(1)) //~ inside `R8`
 };
 
 // This is sneaky: &D0 and &D0 point to different objects
index bca29b4688136542bae551591938a27e90fa9de1..3e7b09a5982d9597c17e44f7db08f5be6840dab9 100644 (file)
@@ -1,14 +1,10 @@
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
    |
-LL |         copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
+   = note: memory access failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
    |
 note: inside `std::ptr::read::<u32>`
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-   |
-LL |         copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `_READ`
   --> $DIR/out_of_bounds_read.rs:12:33
    |
@@ -18,19 +14,12 @@ LL |     const _READ: u32 = unsafe { ptr::read(PAST_END_PTR) };
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
    |
-LL |         copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
+   = note: memory access failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
    |
 note: inside `std::ptr::read::<u32>`
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-   |
-LL |         copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `ptr::const_ptr::<impl *const u32>::read`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { read(self) }
-   |                  ^^^^^^^^^^
 note: inside `_CONST_READ`
   --> $DIR/out_of_bounds_read.rs:13:39
    |
@@ -40,19 +29,12 @@ LL |     const _CONST_READ: u32 = unsafe { PAST_END_PTR.read() };
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
    |
-LL |         copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
+   = note: memory access failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
    |
 note: inside `std::ptr::read::<u32>`
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-   |
-LL |         copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `ptr::mut_ptr::<impl *mut u32>::read`
   --> $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
-   |
-LL |         unsafe { read(self) }
-   |                  ^^^^^^^^^^
 note: inside `_MUT_READ`
   --> $DIR/out_of_bounds_read.rs:14:37
    |
index e5b5c7a846c116f0cd6092036eed1473f323254c..a0a8d76d10d2d9b86e6fbd6733ddd3662f0b6026 100644 (file)
@@ -1,5 +1,5 @@
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref-ptr.rs:13:1
+  --> $DIR/ub-ref-ptr.rs:14:1
    |
 LL | const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) };
    | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned reference (required 2 byte alignment but found 1)
@@ -10,7 +10,7 @@ LL | const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref-ptr.rs:17:1
+  --> $DIR/ub-ref-ptr.rs:18:1
    |
 LL | const UNALIGNED_BOX: Box<u16> = unsafe { mem::transmute(&[0u8; 4]) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned box (required 2 byte alignment but found 1)
@@ -21,7 +21,7 @@ LL | const UNALIGNED_BOX: Box<u16> = unsafe { mem::transmute(&[0u8; 4]) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref-ptr.rs:21:1
+  --> $DIR/ub-ref-ptr.rs:22:1
    |
 LL | const NULL: &u16 = unsafe { mem::transmute(0usize) };
    | ^^^^^^^^^^^^^^^^ constructing invalid value: encountered a null reference
@@ -32,7 +32,7 @@ LL | const NULL: &u16 = unsafe { mem::transmute(0usize) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref-ptr.rs:24:1
+  --> $DIR/ub-ref-ptr.rs:25:1
    |
 LL | const NULL_BOX: Box<u16> = unsafe { mem::transmute(0usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a null box
@@ -43,7 +43,7 @@ LL | const NULL_BOX: Box<u16> = unsafe { mem::transmute(0usize) };
            }
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-ref-ptr.rs:31:1
+  --> $DIR/ub-ref-ptr.rs:32:1
    |
 LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -52,7 +52,7 @@ LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) };
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-ref-ptr.rs:34:39
+  --> $DIR/ub-ref-ptr.rs:35:39
    |
 LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
    |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -61,13 +61,13 @@ LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 note: erroneous constant used
-  --> $DIR/ub-ref-ptr.rs:34:38
+  --> $DIR/ub-ref-ptr.rs:35:38
    |
 LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
    |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-ref-ptr.rs:37:86
+  --> $DIR/ub-ref-ptr.rs:38:86
    |
 LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) };
    |                                                                                      ^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -76,13 +76,13 @@ LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[us
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 note: erroneous constant used
-  --> $DIR/ub-ref-ptr.rs:37:85
+  --> $DIR/ub-ref-ptr.rs:38:85
    |
 LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) };
    |                                                                                     ^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref-ptr.rs:40:1
+  --> $DIR/ub-ref-ptr.rs:41:1
    |
 LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (address 0x539 is unallocated)
@@ -93,7 +93,7 @@ LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref-ptr.rs:43:1
+  --> $DIR/ub-ref-ptr.rs:44:1
    |
 LL | const USIZE_AS_BOX: Box<u8> = unsafe { mem::transmute(1337usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling box (address 0x539 is unallocated)
@@ -104,13 +104,13 @@ LL | const USIZE_AS_BOX: Box<u8> = unsafe { mem::transmute(1337usize) };
            }
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-ref-ptr.rs:46:41
+  --> $DIR/ub-ref-ptr.rs:47:41
    |
 LL | const UNINIT_PTR: *const i32 = unsafe { MaybeUninit { uninit: () }.init };
    |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref-ptr.rs:50:1
+  --> $DIR/ub-ref-ptr.rs:51:1
    |
 LL | const NULL_FN_PTR: fn() = unsafe { mem::transmute(0usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered null pointer, but expected a function pointer
@@ -121,13 +121,13 @@ LL | const NULL_FN_PTR: fn() = unsafe { mem::transmute(0usize) };
            }
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-ref-ptr.rs:52:38
+  --> $DIR/ub-ref-ptr.rs:53:38
    |
 LL | const UNINIT_FN_PTR: fn() = unsafe { MaybeUninit { uninit: () }.init };
    |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref-ptr.rs:55:1
+  --> $DIR/ub-ref-ptr.rs:56:1
    |
 LL | const DANGLING_FN_PTR: fn() = unsafe { mem::transmute(13usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0xd[noalloc], but expected a function pointer
@@ -138,7 +138,7 @@ LL | const DANGLING_FN_PTR: fn() = unsafe { mem::transmute(13usize) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref-ptr.rs:57:1
+  --> $DIR/ub-ref-ptr.rs:58:1
    |
 LL | const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) };
    | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered alloc41, but expected a function pointer
@@ -148,6 +148,39 @@ LL | const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) };
                ╾─alloc41─╼                                     │ ╾──╼
            }
 
-error: aborting due to 14 previous errors
+error: accessing memory with alignment 1, but alignment 4 is required
+  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+   |
+   = 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 #68585 <https://github.com/rust-lang/rust/issues/104616>
+note: inside `std::ptr::read::<u32>`
+  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+note: inside `ptr::const_ptr::<impl *const u32>::read`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `UNALIGNED_READ`
+  --> $DIR/ub-ref-ptr.rs:65:5
+   |
+LL |     ptr.read();
+   |     ^^^^^^^^^^
+   = note: `#[deny(invalid_alignment)]` on by default
+
+error: aborting due to 15 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
+Future incompatibility report: Future breakage diagnostic:
+error: accessing memory with alignment 1, but alignment 4 is required
+  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+   |
+   = 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 #68585 <https://github.com/rust-lang/rust/issues/104616>
+note: inside `std::ptr::read::<u32>`
+  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+note: inside `ptr::const_ptr::<impl *const u32>::read`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `UNALIGNED_READ`
+  --> $DIR/ub-ref-ptr.rs:65:5
+   |
+LL |     ptr.read();
+   |     ^^^^^^^^^^
+   = note: `#[deny(invalid_alignment)]` on by default
+
index 607366cabc4e9d30c5a2ba70964fe4eb69854d61..d53b44671e3f48eb53a2c6f1c3a085cb95b92d7b 100644 (file)
@@ -1,5 +1,5 @@
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref-ptr.rs:13:1
+  --> $DIR/ub-ref-ptr.rs:14:1
    |
 LL | const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) };
    | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned reference (required 2 byte alignment but found 1)
@@ -10,7 +10,7 @@ LL | const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref-ptr.rs:17:1
+  --> $DIR/ub-ref-ptr.rs:18:1
    |
 LL | const UNALIGNED_BOX: Box<u16> = unsafe { mem::transmute(&[0u8; 4]) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned box (required 2 byte alignment but found 1)
@@ -21,7 +21,7 @@ LL | const UNALIGNED_BOX: Box<u16> = unsafe { mem::transmute(&[0u8; 4]) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref-ptr.rs:21:1
+  --> $DIR/ub-ref-ptr.rs:22:1
    |
 LL | const NULL: &u16 = unsafe { mem::transmute(0usize) };
    | ^^^^^^^^^^^^^^^^ constructing invalid value: encountered a null reference
@@ -32,7 +32,7 @@ LL | const NULL: &u16 = unsafe { mem::transmute(0usize) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref-ptr.rs:24:1
+  --> $DIR/ub-ref-ptr.rs:25:1
    |
 LL | const NULL_BOX: Box<u16> = unsafe { mem::transmute(0usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a null box
@@ -43,7 +43,7 @@ LL | const NULL_BOX: Box<u16> = unsafe { mem::transmute(0usize) };
            }
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-ref-ptr.rs:31:1
+  --> $DIR/ub-ref-ptr.rs:32:1
    |
 LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -52,7 +52,7 @@ LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) };
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-ref-ptr.rs:34:39
+  --> $DIR/ub-ref-ptr.rs:35:39
    |
 LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
    |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -61,13 +61,13 @@ LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 note: erroneous constant used
-  --> $DIR/ub-ref-ptr.rs:34:38
+  --> $DIR/ub-ref-ptr.rs:35:38
    |
 LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
    |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-ref-ptr.rs:37:86
+  --> $DIR/ub-ref-ptr.rs:38:86
    |
 LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) };
    |                                                                                      ^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -76,13 +76,13 @@ LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[us
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 note: erroneous constant used
-  --> $DIR/ub-ref-ptr.rs:37:85
+  --> $DIR/ub-ref-ptr.rs:38:85
    |
 LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) };
    |                                                                                     ^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref-ptr.rs:40:1
+  --> $DIR/ub-ref-ptr.rs:41:1
    |
 LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (address 0x539 is unallocated)
@@ -93,7 +93,7 @@ LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref-ptr.rs:43:1
+  --> $DIR/ub-ref-ptr.rs:44:1
    |
 LL | const USIZE_AS_BOX: Box<u8> = unsafe { mem::transmute(1337usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling box (address 0x539 is unallocated)
@@ -104,13 +104,13 @@ LL | const USIZE_AS_BOX: Box<u8> = unsafe { mem::transmute(1337usize) };
            }
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-ref-ptr.rs:46:41
+  --> $DIR/ub-ref-ptr.rs:47:41
    |
 LL | const UNINIT_PTR: *const i32 = unsafe { MaybeUninit { uninit: () }.init };
    |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref-ptr.rs:50:1
+  --> $DIR/ub-ref-ptr.rs:51:1
    |
 LL | const NULL_FN_PTR: fn() = unsafe { mem::transmute(0usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered null pointer, but expected a function pointer
@@ -121,13 +121,13 @@ LL | const NULL_FN_PTR: fn() = unsafe { mem::transmute(0usize) };
            }
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-ref-ptr.rs:52:38
+  --> $DIR/ub-ref-ptr.rs:53:38
    |
 LL | const UNINIT_FN_PTR: fn() = unsafe { MaybeUninit { uninit: () }.init };
    |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref-ptr.rs:55:1
+  --> $DIR/ub-ref-ptr.rs:56:1
    |
 LL | const DANGLING_FN_PTR: fn() = unsafe { mem::transmute(13usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0xd[noalloc], but expected a function pointer
@@ -138,7 +138,7 @@ LL | const DANGLING_FN_PTR: fn() = unsafe { mem::transmute(13usize) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref-ptr.rs:57:1
+  --> $DIR/ub-ref-ptr.rs:58:1
    |
 LL | const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) };
    | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered alloc41, but expected a function pointer
@@ -148,6 +148,39 @@ LL | const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) };
                ╾───────alloc41───────╼                         │ ╾──────╼
            }
 
-error: aborting due to 14 previous errors
+error: accessing memory with alignment 1, but alignment 4 is required
+  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+   |
+   = 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 #68585 <https://github.com/rust-lang/rust/issues/104616>
+note: inside `std::ptr::read::<u32>`
+  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+note: inside `ptr::const_ptr::<impl *const u32>::read`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `UNALIGNED_READ`
+  --> $DIR/ub-ref-ptr.rs:65:5
+   |
+LL |     ptr.read();
+   |     ^^^^^^^^^^
+   = note: `#[deny(invalid_alignment)]` on by default
+
+error: aborting due to 15 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
+Future incompatibility report: Future breakage diagnostic:
+error: accessing memory with alignment 1, but alignment 4 is required
+  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+   |
+   = 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 #68585 <https://github.com/rust-lang/rust/issues/104616>
+note: inside `std::ptr::read::<u32>`
+  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+note: inside `ptr::const_ptr::<impl *const u32>::read`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `UNALIGNED_READ`
+  --> $DIR/ub-ref-ptr.rs:65:5
+   |
+LL |     ptr.read();
+   |     ^^^^^^^^^^
+   = note: `#[deny(invalid_alignment)]` on by default
+
index a1c81239009ac0569e45d8217764ccf07ad9c81a..b0fc3c196a49fc3457915955dd277d352d6154c0 100644 (file)
@@ -1,6 +1,7 @@
 // ignore-tidy-linelength
 // stderr-per-bitwidth
 #![allow(invalid_value)]
+#![feature(const_ptr_read)]
 
 use std::mem;
 
@@ -57,4 +58,12 @@ union MaybeUninit<T: Copy> {
 const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) };
 //~^ ERROR it is undefined behavior to use this value
 
+
+const UNALIGNED_READ: () = unsafe {
+    let x = &[0u8; 4];
+    let ptr = x.as_ptr().cast::<u32>();
+    ptr.read(); //~ inside `UNALIGNED_READ`
+};
+
+
 fn main() {}
index 9994c2e5a83458c27cb6e3ad8ee66071eeabad14..90a3dcada058d691ec0dfee66edc0e1e87ad53da 100644 (file)
@@ -1,27 +1,27 @@
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:36:1
+  --> $DIR/ub-wide-ptr.rs:37:1
    |
 LL | const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation)
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾─allocN──╼ e7 03 00 00                         │ ╾──╼....
+               ╾ALLOC_ID╼ e7 03 00 00                         │ ╾──╼....
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:38:1
+  --> $DIR/ub-wide-ptr.rs:39:1
    |
 LL | const NESTED_STR_MUCH_TOO_LONG: (&str,) = (unsafe { mem::transmute((&42, usize::MAX)) },);
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered invalid reference metadata: slice is bigger than largest supported object
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾─allocN─╼ ff ff ff ff                         │ ╾──╼....
+               ╾ALLOC_ID╼ ff ff ff ff                         │ ╾──╼....
            }
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:41:1
+  --> $DIR/ub-wide-ptr.rs:42:1
    |
 LL | const STR_LENGTH_PTR: &str = unsafe { mem::transmute((&42u8, &3)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -30,7 +30,7 @@ LL | const STR_LENGTH_PTR: &str = unsafe { mem::transmute((&42u8, &3)) };
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:44:1
+  --> $DIR/ub-wide-ptr.rs:45:1
    |
 LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -39,68 +39,68 @@ LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) };
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:46:1
+  --> $DIR/ub-wide-ptr.rs:47:1
    |
 LL | const MY_STR_MUCH_TOO_LONG: &MyStr = unsafe { mem::transmute((&42u8, usize::MAX)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾─allocN─╼ ff ff ff ff                         │ ╾──╼....
+               ╾ALLOC_ID╼ ff ff ff ff                         │ ╾──╼....
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:50:1
+  --> $DIR/ub-wide-ptr.rs:51:1
    |
 LL | const STR_NO_INIT: &str = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit::<u8> { uninit: () }]) };
    | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>: encountered uninitialized data in `str`
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾─allocN─╼ 01 00 00 00                         │ ╾──╼....
+               ╾ALLOC_ID╼ 01 00 00 00                         │ ╾──╼....
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:53:1
+  --> $DIR/ub-wide-ptr.rs:54:1
    |
 LL | const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit::<u8> { uninit: () }]) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.0: encountered uninitialized data in `str`
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾─allocN─╼ 01 00 00 00                         │ ╾──╼....
+               ╾ALLOC_ID╼ 01 00 00 00                         │ ╾──╼....
            }
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:60:1
+  --> $DIR/ub-wide-ptr.rs:61:1
    |
 LL | const SLICE_LENGTH_UNINIT: &[u8] = unsafe {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:67:1
+  --> $DIR/ub-wide-ptr.rs:68:1
    |
 LL | const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation)
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾─allocN─╼ e7 03 00 00                         │ ╾──╼....
+               ╾ALLOC_ID╼ e7 03 00 00                         │ ╾──╼....
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:70:1
+  --> $DIR/ub-wide-ptr.rs:71:1
    |
 LL | const SLICE_TOO_LONG_OVERFLOW: &[u32] = unsafe { mem::transmute((&42u32, isize::MAX)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾─allocN─╼ ff ff ff 7f                         │ ╾──╼....
+               ╾ALLOC_ID╼ ff ff ff 7f                         │ ╾──╼....
            }
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:73:1
+  --> $DIR/ub-wide-ptr.rs:74:1
    |
 LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -109,18 +109,18 @@ LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) };
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:76:1
+  --> $DIR/ub-wide-ptr.rs:77:1
    |
 LL | const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999usize)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling box (going beyond the bounds of its allocation)
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾─allocN─╼ e7 03 00 00                         │ ╾──╼....
+               ╾ALLOC_ID╼ e7 03 00 00                         │ ╾──╼....
            }
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:79:1
+  --> $DIR/ub-wide-ptr.rs:80:1
    |
 LL | const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -129,165 +129,165 @@ LL | const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3)
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:83:1
+  --> $DIR/ub-wide-ptr.rs:84:1
    |
 LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered 0x03, but expected a boolean
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 4, align: 4) {
-               ╾─allocN─╼                                     │ ╾──╼
+               ╾ALLOC_ID╼                                     │ ╾──╼
            }
 
 note: erroneous constant used
-  --> $DIR/ub-wide-ptr.rs:83:40
+  --> $DIR/ub-wide-ptr.rs:84:40
    |
 LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
    |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:90:1
+  --> $DIR/ub-wide-ptr.rs:91:1
    |
 LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]);
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.0: encountered 0x03, but expected a boolean
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 4, align: 4) {
-               ╾allocN─╼                                     │ ╾──╼
+               ╾ALLOC_ID╼                                     │ ╾──╼
            }
 
 note: erroneous constant used
-  --> $DIR/ub-wide-ptr.rs:90:42
+  --> $DIR/ub-wide-ptr.rs:91:42
    |
 LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]);
    |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:94:1
+  --> $DIR/ub-wide-ptr.rs:95:1
    |
 LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]);
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.1[0]: encountered 0x03, but expected a boolean
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 4, align: 4) {
-               ╾allocN─╼                                     │ ╾──╼
+               ╾ALLOC_ID╼                                     │ ╾──╼
            }
 
 note: erroneous constant used
-  --> $DIR/ub-wide-ptr.rs:94:42
+  --> $DIR/ub-wide-ptr.rs:95:42
    |
 LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]);
    |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:102:1
+  --> $DIR/ub-wide-ptr.rs:103:1
    |
 LL | const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:111:1
+  --> $DIR/ub-wide-ptr.rs:112:1
    |
 LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u8))) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾allocN─╼ ╾allocN─╼                         │ ╾──╼╾──╼
+               ╾ALLOC_ID╼ ╾ALLOC_ID╼                         │ ╾──╼╾──╼
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:115:1
+  --> $DIR/ub-wide-ptr.rs:116:1
    |
 LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u64))) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾allocN─╼ ╾allocN─╼                         │ ╾──╼╾──╼
+               ╾ALLOC_ID╼ ╾ALLOC_ID╼                         │ ╾──╼╾──╼
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:119:1
+  --> $DIR/ub-wide-ptr.rs:120:1
    |
 LL | const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, 4usize))) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered 0x4[noalloc], but expected a vtable pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾allocN─╼ 04 00 00 00                         │ ╾──╼....
+               ╾ALLOC_ID╼ 04 00 00 00                         │ ╾──╼....
            }
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:122:57
+  --> $DIR/ub-wide-ptr.rs:123:57
    |
 LL | const TRAIT_OBJ_UNALIGNED_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, &[0u8; 128])) };
    |                                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:125:57
+  --> $DIR/ub-wide-ptr.rs:126:57
    |
 LL | const TRAIT_OBJ_BAD_DROP_FN_NULL: &dyn Trait = unsafe { mem::transmute((&92u8, &[0usize; 8])) };
    |                                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:128:56
+  --> $DIR/ub-wide-ptr.rs:129:56
    |
 LL | const TRAIT_OBJ_BAD_DROP_FN_INT: &dyn Trait = unsafe { mem::transmute((&92u8, &[1usize; 8])) };
    |                                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:131:1
+  --> $DIR/ub-wide-ptr.rs:132:1
    |
 LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾allocN─╼ ╾allocN─╼                         │ ╾──╼╾──╼
+               ╾ALLOC_ID╼ ╾ALLOC_ID╼                         │ ╾──╼╾──╼
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:136:1
+  --> $DIR/ub-wide-ptr.rs:137:1
    |
 LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.<dyn-downcast>: encountered 0x03, but expected a boolean
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾allocN─╼ ╾allocN─╼                         │ ╾──╼╾──╼
+               ╾ALLOC_ID╼ ╾ALLOC_ID╼                         │ ╾──╼╾──╼
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:141:1
+  --> $DIR/ub-wide-ptr.rs:142:1
    |
 LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered null pointer, but expected a vtable pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾allocN─╼ 00 00 00 00                         │ ╾──╼....
+               ╾ALLOC_ID╼ 00 00 00 00                         │ ╾──╼....
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:143:1
+  --> $DIR/ub-wide-ptr.rs:144:1
    |
 LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered allocN, but expected a vtable pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾allocN─╼ ╾allocN─╼                         │ ╾──╼╾──╼
+               ╾ALLOC_ID╼ ╾ALLOC_ID╼                         │ ╾──╼╾──╼
            }
 
 error[E0080]: could not evaluate static initializer
-  --> $DIR/ub-wide-ptr.rs:149:5
+  --> $DIR/ub-wide-ptr.rs:150:5
    |
 LL |     mem::transmute::<_, &dyn Trait>((&92u8, 0usize))
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
 
 error[E0080]: could not evaluate static initializer
-  --> $DIR/ub-wide-ptr.rs:153:5
+  --> $DIR/ub-wide-ptr.rs:154:5
    |
 LL |     mem::transmute::<_, &dyn Trait>((&92u8, &3u64))
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable
index 06a377d9f7c97982b8d7c29cac7a628b6eee2832..ab25303ddc0cf611df2a306a549d4fde936f52e0 100644 (file)
@@ -1,27 +1,27 @@
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:36:1
+  --> $DIR/ub-wide-ptr.rs:37:1
    |
 LL | const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation)
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾───────allocN────────╼ e7 03 00 00 00 00 00 00 │ ╾──────╼........
+               ╾ALLOC_ID╼ e7 03 00 00 00 00 00 00 │ ╾──────╼........
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:38:1
+  --> $DIR/ub-wide-ptr.rs:39:1
    |
 LL | const NESTED_STR_MUCH_TOO_LONG: (&str,) = (unsafe { mem::transmute((&42, usize::MAX)) },);
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered invalid reference metadata: slice is bigger than largest supported object
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾───────allocN───────╼ ff ff ff ff ff ff ff ff │ ╾──────╼........
+               ╾ALLOC_ID╼ ff ff ff ff ff ff ff ff │ ╾──────╼........
            }
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:41:1
+  --> $DIR/ub-wide-ptr.rs:42:1
    |
 LL | const STR_LENGTH_PTR: &str = unsafe { mem::transmute((&42u8, &3)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -30,7 +30,7 @@ LL | const STR_LENGTH_PTR: &str = unsafe { mem::transmute((&42u8, &3)) };
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:44:1
+  --> $DIR/ub-wide-ptr.rs:45:1
    |
 LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -39,68 +39,68 @@ LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) };
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:46:1
+  --> $DIR/ub-wide-ptr.rs:47:1
    |
 LL | const MY_STR_MUCH_TOO_LONG: &MyStr = unsafe { mem::transmute((&42u8, usize::MAX)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾───────allocN───────╼ ff ff ff ff ff ff ff ff │ ╾──────╼........
+               ╾ALLOC_ID╼ ff ff ff ff ff ff ff ff │ ╾──────╼........
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:50:1
+  --> $DIR/ub-wide-ptr.rs:51:1
    |
 LL | const STR_NO_INIT: &str = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit::<u8> { uninit: () }]) };
    | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>: encountered uninitialized data in `str`
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾───────allocN───────╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........
+               ╾ALLOC_ID╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:53:1
+  --> $DIR/ub-wide-ptr.rs:54:1
    |
 LL | const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit::<u8> { uninit: () }]) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.0: encountered uninitialized data in `str`
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾───────allocN───────╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........
+               ╾ALLOC_ID╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........
            }
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:60:1
+  --> $DIR/ub-wide-ptr.rs:61:1
    |
 LL | const SLICE_LENGTH_UNINIT: &[u8] = unsafe {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:67:1
+  --> $DIR/ub-wide-ptr.rs:68:1
    |
 LL | const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation)
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾───────allocN───────╼ e7 03 00 00 00 00 00 00 │ ╾──────╼........
+               ╾ALLOC_ID╼ e7 03 00 00 00 00 00 00 │ ╾──────╼........
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:70:1
+  --> $DIR/ub-wide-ptr.rs:71:1
    |
 LL | const SLICE_TOO_LONG_OVERFLOW: &[u32] = unsafe { mem::transmute((&42u32, isize::MAX)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾───────allocN───────╼ ff ff ff ff ff ff ff 7f │ ╾──────╼........
+               ╾ALLOC_ID╼ ff ff ff ff ff ff ff 7f │ ╾──────╼........
            }
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:73:1
+  --> $DIR/ub-wide-ptr.rs:74:1
    |
 LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -109,18 +109,18 @@ LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) };
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:76:1
+  --> $DIR/ub-wide-ptr.rs:77:1
    |
 LL | const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999usize)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling box (going beyond the bounds of its allocation)
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾───────allocN───────╼ e7 03 00 00 00 00 00 00 │ ╾──────╼........
+               ╾ALLOC_ID╼ e7 03 00 00 00 00 00 00 │ ╾──────╼........
            }
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:79:1
+  --> $DIR/ub-wide-ptr.rs:80:1
    |
 LL | const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -129,165 +129,165 @@ LL | const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3)
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:83:1
+  --> $DIR/ub-wide-ptr.rs:84:1
    |
 LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered 0x03, but expected a boolean
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {
-               ╾───────allocN───────╼                         │ ╾──────╼
+               ╾ALLOC_ID╼                         │ ╾──────╼
            }
 
 note: erroneous constant used
-  --> $DIR/ub-wide-ptr.rs:83:40
+  --> $DIR/ub-wide-ptr.rs:84:40
    |
 LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
    |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:90:1
+  --> $DIR/ub-wide-ptr.rs:91:1
    |
 LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]);
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.0: encountered 0x03, but expected a boolean
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {
-               ╾──────allocN───────╼                         │ ╾──────╼
+               ╾ALLOC_ID╼                         │ ╾──────╼
            }
 
 note: erroneous constant used
-  --> $DIR/ub-wide-ptr.rs:90:42
+  --> $DIR/ub-wide-ptr.rs:91:42
    |
 LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]);
    |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:94:1
+  --> $DIR/ub-wide-ptr.rs:95:1
    |
 LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]);
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.1[0]: encountered 0x03, but expected a boolean
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {
-               ╾──────allocN───────╼                         │ ╾──────╼
+               ╾ALLOC_ID╼                         │ ╾──────╼
            }
 
 note: erroneous constant used
-  --> $DIR/ub-wide-ptr.rs:94:42
+  --> $DIR/ub-wide-ptr.rs:95:42
    |
 LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]);
    |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:102:1
+  --> $DIR/ub-wide-ptr.rs:103:1
    |
 LL | const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:111:1
+  --> $DIR/ub-wide-ptr.rs:112:1
    |
 LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u8))) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾──────allocN───────╼ ╾──────allocN───────╼ │ ╾──────╼╾──────╼
+               ╾ALLOC_ID╼ ╾ALLOC_ID╼ │ ╾──────╼╾──────╼
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:115:1
+  --> $DIR/ub-wide-ptr.rs:116:1
    |
 LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u64))) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾──────allocN───────╼ ╾──────allocN───────╼ │ ╾──────╼╾──────╼
+               ╾ALLOC_ID╼ ╾ALLOC_ID╼ │ ╾──────╼╾──────╼
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:119:1
+  --> $DIR/ub-wide-ptr.rs:120:1
    |
 LL | const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, 4usize))) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered 0x4[noalloc], but expected a vtable pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾──────allocN───────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
+               ╾ALLOC_ID╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
            }
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:122:57
+  --> $DIR/ub-wide-ptr.rs:123:57
    |
 LL | const TRAIT_OBJ_UNALIGNED_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, &[0u8; 128])) };
    |                                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:125:57
+  --> $DIR/ub-wide-ptr.rs:126:57
    |
 LL | const TRAIT_OBJ_BAD_DROP_FN_NULL: &dyn Trait = unsafe { mem::transmute((&92u8, &[0usize; 8])) };
    |                                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:128:56
+  --> $DIR/ub-wide-ptr.rs:129:56
    |
 LL | const TRAIT_OBJ_BAD_DROP_FN_INT: &dyn Trait = unsafe { mem::transmute((&92u8, &[1usize; 8])) };
    |                                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:131:1
+  --> $DIR/ub-wide-ptr.rs:132:1
    |
 LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾──────allocN───────╼ ╾──────allocN───────╼ │ ╾──────╼╾──────╼
+               ╾ALLOC_ID╼ ╾ALLOC_ID╼ │ ╾──────╼╾──────╼
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:136:1
+  --> $DIR/ub-wide-ptr.rs:137:1
    |
 LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.<dyn-downcast>: encountered 0x03, but expected a boolean
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾──────allocN───────╼ ╾──────allocN───────╼ │ ╾──────╼╾──────╼
+               ╾ALLOC_ID╼ ╾ALLOC_ID╼ │ ╾──────╼╾──────╼
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:141:1
+  --> $DIR/ub-wide-ptr.rs:142:1
    |
 LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered null pointer, but expected a vtable pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾──────allocN───────╼ 00 00 00 00 00 00 00 00 │ ╾──────╼........
+               ╾ALLOC_ID╼ 00 00 00 00 00 00 00 00 │ ╾──────╼........
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:143:1
+  --> $DIR/ub-wide-ptr.rs:144:1
    |
 LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered allocN, but expected a vtable pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾──────allocN───────╼ ╾──────allocN───────╼ │ ╾──────╼╾──────╼
+               ╾ALLOC_ID╼ ╾ALLOC_ID╼ │ ╾──────╼╾──────╼
            }
 
 error[E0080]: could not evaluate static initializer
-  --> $DIR/ub-wide-ptr.rs:149:5
+  --> $DIR/ub-wide-ptr.rs:150:5
    |
 LL |     mem::transmute::<_, &dyn Trait>((&92u8, 0usize))
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
 
 error[E0080]: could not evaluate static initializer
-  --> $DIR/ub-wide-ptr.rs:153:5
+  --> $DIR/ub-wide-ptr.rs:154:5
    |
 LL |     mem::transmute::<_, &dyn Trait>((&92u8, &3u64))
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable
index 2894ef831884cda462a4acbf9bbd9d643bd9fb6d..d12e5e2bed93ef20daa6f5b98b4cb27b3920146a 100644 (file)
@@ -4,6 +4,7 @@
 
 use std::mem;
 
+// normalize-stderr-test "╾─*a(lloc)?[0-9]+(\+[a-z0-9]+)?─*╼" -> "╾ALLOC_ID$2╼"
 // normalize-stderr-test "offset \d+" -> "offset N"
 // normalize-stderr-test "alloc\d+" -> "allocN"
 // normalize-stderr-test "size \d+" -> "size N"
index 195a087ffa5b0aad0c0c8abd0e41b7885cf29fd2..7ad02252094203a3f8b6865b53a6f7382bfe88e6 100644 (file)
@@ -1,19 +1,12 @@
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/num/f32.rs:LL:COL
    |
-LL |                     panic!("const-eval error: cannot use f32::to_bits on a NaN")
-   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'const-eval error: cannot use f32::to_bits on a NaN', $SRC_DIR/core/src/num/f32.rs:LL:COL
+   = note: the evaluated program panicked at 'const-eval error: cannot use f32::to_bits on a NaN', $SRC_DIR/core/src/num/f32.rs:LL:COL
    |
 note: inside `core::f32::<impl f32>::to_bits::ct_f32_to_u32`
   --> $SRC_DIR/core/src/num/f32.rs:LL:COL
-   |
-LL |                     panic!("const-eval error: cannot use f32::to_bits on a NaN")
-   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `core::f32::<impl f32>::to_bits`
   --> $SRC_DIR/core/src/num/f32.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::const_eval_select((self,), ct_f32_to_u32, rt_f32_to_u32) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `f32::MASKED_NAN1`
   --> $DIR/const-float-bits-reject-conv.rs:28:30
    |
@@ -24,19 +17,12 @@ LL |     const MASKED_NAN1: u32 = f32::NAN.to_bits() ^ 0x002A_AAAA;
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/num/f32.rs:LL:COL
    |
-LL |                     panic!("const-eval error: cannot use f32::to_bits on a NaN")
-   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'const-eval error: cannot use f32::to_bits on a NaN', $SRC_DIR/core/src/num/f32.rs:LL:COL
+   = note: the evaluated program panicked at 'const-eval error: cannot use f32::to_bits on a NaN', $SRC_DIR/core/src/num/f32.rs:LL:COL
    |
 note: inside `core::f32::<impl f32>::to_bits::ct_f32_to_u32`
   --> $SRC_DIR/core/src/num/f32.rs:LL:COL
-   |
-LL |                     panic!("const-eval error: cannot use f32::to_bits on a NaN")
-   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `core::f32::<impl f32>::to_bits`
   --> $SRC_DIR/core/src/num/f32.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::const_eval_select((self,), ct_f32_to_u32, rt_f32_to_u32) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `f32::MASKED_NAN2`
   --> $DIR/const-float-bits-reject-conv.rs:30:30
    |
@@ -71,19 +57,12 @@ LL |     const_assert!(f32::from_bits(MASKED_NAN2).to_bits(), MASKED_NAN2);
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/num/f64.rs:LL:COL
    |
-LL |                     panic!("const-eval error: cannot use f64::to_bits on a NaN")
-   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'const-eval error: cannot use f64::to_bits on a NaN', $SRC_DIR/core/src/num/f64.rs:LL:COL
+   = note: the evaluated program panicked at 'const-eval error: cannot use f64::to_bits on a NaN', $SRC_DIR/core/src/num/f64.rs:LL:COL
    |
 note: inside `core::f64::<impl f64>::to_bits::ct_f64_to_u64`
   --> $SRC_DIR/core/src/num/f64.rs:LL:COL
-   |
-LL |                     panic!("const-eval error: cannot use f64::to_bits on a NaN")
-   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `core::f64::<impl f64>::to_bits`
   --> $SRC_DIR/core/src/num/f64.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::const_eval_select((self,), ct_f64_to_u64, rt_f64_to_u64) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `f64::MASKED_NAN1`
   --> $DIR/const-float-bits-reject-conv.rs:50:30
    |
@@ -94,19 +73,12 @@ LL |     const MASKED_NAN1: u64 = f64::NAN.to_bits() ^ 0x000A_AAAA_AAAA_AAAA;
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/num/f64.rs:LL:COL
    |
-LL |                     panic!("const-eval error: cannot use f64::to_bits on a NaN")
-   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'const-eval error: cannot use f64::to_bits on a NaN', $SRC_DIR/core/src/num/f64.rs:LL:COL
+   = note: the evaluated program panicked at 'const-eval error: cannot use f64::to_bits on a NaN', $SRC_DIR/core/src/num/f64.rs:LL:COL
    |
 note: inside `core::f64::<impl f64>::to_bits::ct_f64_to_u64`
   --> $SRC_DIR/core/src/num/f64.rs:LL:COL
-   |
-LL |                     panic!("const-eval error: cannot use f64::to_bits on a NaN")
-   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `core::f64::<impl f64>::to_bits`
   --> $SRC_DIR/core/src/num/f64.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::const_eval_select((self,), ct_f64_to_u64, rt_f64_to_u64) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `f64::MASKED_NAN2`
   --> $DIR/const-float-bits-reject-conv.rs:52:30
    |
index 02960b363e78f695824f372021ff5c280c73d709..f6b532fb6586590a33aa1ce6e96d563c3ffe370c 100644 (file)
@@ -21,9 +21,6 @@ LL |     for i in 0..x {
    |
 note: impl defined here, but it is not `const`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-   |
-LL | impl<I: Iterator> const IntoIterator for I {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
 
 error[E0658]: mutable references are not allowed in constant functions
index 11e4ae309c01f5abddb458968d476586dc84dd63..294ea627d8544e9fbf91135146432570b0adbf5a 100644 (file)
@@ -6,9 +6,6 @@ LL |     for _ in 0..5 {}
    |
 note: impl defined here, but it is not `const`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-   |
-LL | impl<I: Iterator> const IntoIterator for I {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: calls in constants are limited to constant functions, tuple structs and tuple variants
 
 error[E0015]: cannot call non-const fn `<std::ops::Range<i32> as Iterator>::next` in constants
index cbc7cac937ae1b5b945e34a8c4f411780f26bd70..593a51bfe8fea6f7282a4b8d6804bff8c891e2a8 100644 (file)
@@ -1,14 +1,10 @@
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/hint.rs:LL:COL
    |
-LL |         intrinsics::unreachable()
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^ entering unreachable code
+   = note: entering unreachable code
    |
 note: inside `unreachable_unchecked`
   --> $SRC_DIR/core/src/hint.rs:LL:COL
-   |
-LL |         intrinsics::unreachable()
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `foo`
   --> $DIR/const_unsafe_unreachable_ub.rs:6:18
    |
index 249bbb5991cc98dc6da6f19feff3bdb06b4bff36..94d7bdc6bae9ff6222411821a5a3b912f6728fbf 100644 (file)
@@ -17,7 +17,7 @@
     // Since we are not copying anything, this should be allowed.
     let src = ();
     let mut dst = ();
-    copy_nonoverlapping(&src as *const _ as *const i32, &mut dst as *mut _ as *mut i32, 0);
+    copy_nonoverlapping(&src as *const _ as *const u8, &mut dst as *mut _ as *mut u8, 0);
 };
 
 const COPY_OOB_1: () = unsafe {
index 9c239c8a100f991e60176a3364a15478940bf252..e2f8149883b1d980978e431889112462f1dd4e85 100644 (file)
     //[with_flag]~| invalid value
 };
 
-const UNALIGNED_READ: () = {
-    INNER; //[with_flag]~ constant
-    // There is an error here but its span is in the standard library so we cannot match it...
-    // so we have this in a *nested* const, such that the *outer* const fails to use it.
-    const INNER: () = unsafe {
-        let x = &[0u8; 4];
-        let ptr = x.as_ptr().cast::<u32>();
-        ptr.read();
-    };
-};
-
 fn main() {}
index 2603a73583ebda4b6b007a9668a8ece944b3c545..b2a5fd90149a3eee815afc6625507556b9a01c45 100644 (file)
@@ -28,34 +28,6 @@ error[E0080]: evaluation of constant value failed
 LL |     let _x: &u32 = transmute(&[0u8; 4]);
    |                    ^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned reference (required 4 byte alignment but found 1)
 
-error[E0080]: evaluation of constant value failed
-  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-   |
-LL |         copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ accessing memory with alignment 1, but alignment 4 is required
-   |
-note: inside `std::ptr::read::<u32>`
-  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-   |
-LL |         copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: inside `ptr::const_ptr::<impl *const u32>::read`
-  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { read(self) }
-   |                  ^^^^^^^^^^
-note: inside `INNER`
-  --> $DIR/detect-extra-ub.rs:38:9
-   |
-LL |         ptr.read();
-   |         ^^^^^^^^^^
-
-note: erroneous constant used
-  --> $DIR/detect-extra-ub.rs:32:5
-   |
-LL |     INNER;
-   |     ^^^^^
-
-error: aborting due to 5 previous errors
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
index 1f82e1777af5bf43de2242ccd75029923cf5fc71..61865b1dad764240adeb9cfaead4efedb5cc9806 100644 (file)
@@ -1,21 +1,14 @@
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
    |
-LL |         copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to copy parts of a pointer from memory at ALLOC
+   = note: unable to copy parts of a pointer from memory at ALLOC
    |
    = help: this code performed an operation that depends on the underlying bytes representing a pointer
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 note: inside `std::ptr::read::<u8>`
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-   |
-LL |         copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `ptr::const_ptr::<impl *const u8>::read`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { read(self) }
-   |                  ^^^^^^^^^^
 note: inside `C`
   --> $DIR/issue-miri-1910.rs:8:5
    |
index b26f121dba0612946658cb27fc97dbf5dddaa642..e1da43c3aea4134f15025cd694071cbca338dbc2 100644 (file)
@@ -1,19 +1,12 @@
 error[E0080]: evaluation of `<std::string::String as Bar<std::vec::Vec<u32>, std::string::String>>::F` failed
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
    |
-LL | pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ calling non-const function `<Vec<u32> as Drop>::drop`
+   = note: calling non-const function `<Vec<u32> as Drop>::drop`
    |
 note: inside `std::ptr::drop_in_place::<Vec<u32>> - shim(Some(Vec<u32>))`
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-   |
-LL | pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `std::ptr::drop_in_place::<(Vec<u32>, u32)> - shim(Some((Vec<u32>, u32)))`
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-   |
-LL | pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `<String as Bar<Vec<u32>, String>>::F`
   --> $DIR/assoc_const.rs:12:31
    |
index e2e2f16d5a02500fc5d03ffd14412dc9e2be89ef..4f60b8820691ba0fb23de283c30845d8442ca100 100644 (file)
@@ -1,14 +1,10 @@
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
    |
-LL | pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ calling non-const function `<Vec<i32> as Drop>::drop`
+   = note: calling non-const function `<Vec<i32> as Drop>::drop`
    |
 note: inside `std::ptr::drop_in_place::<Vec<i32>> - shim(Some(Vec<i32>))`
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-   |
-LL | pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `TEST_BAD`
   --> $DIR/drop.rs:17:1
    |
index c4930b73aaab8996def56ae74f102f09f8c823a4..dd2b81c5af2bc93171c26e86d80175aae019bc60 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: -Z simulate-remapped-rust-src-base=/rustc/FAKE_PREFIX -Z translate-remapped-path-to-local-path=no -Z ui-testing=no
+// compile-flags: -Z ui-testing=no
 // normalize-stderr-test "alloc[0-9]+" -> "ALLOC_ID"
 
 #![feature(const_swap)]
index 9578d90ea9d8827762177a1be47df1d3a080745a..fff4729689f54058a1969380dfa67407af7a274c 100644 (file)
@@ -7,14 +7,10 @@ LL |     let offset = unsafe { ptr_offset_from(field_ptr, base_ptr) };
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::ptr_offset_from(self, origin) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called on pointers into different allocations
+   = note: `ptr_offset_from` called on pointers into different allocations
    |
 note: inside `ptr::const_ptr::<impl *const u8>::offset_from`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::ptr_offset_from(self, origin) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `NOT_PTR`
   --> $DIR/offset_from_ub.rs:24:14
    |
@@ -90,14 +86,10 @@ LL |     unsafe { ptr_offset_from_unsigned(ptr2, ptr1) }
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::ptr_offset_from(self, origin) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: null pointer is a dangling pointer (it has no provenance)
+   = note: out-of-bounds offset_from: null pointer is a dangling pointer (it has no provenance)
    |
 note: inside `ptr::const_ptr::<impl *const u8>::offset_from`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::ptr_offset_from(self, origin) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `OFFSET_VERY_FAR1`
   --> $DIR/offset_from_ub.rs:115:14
    |
@@ -107,14 +99,10 @@ LL |     unsafe { ptr2.offset_from(ptr1) }
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::ptr_offset_from(self, origin) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: null pointer is a dangling pointer (it has no provenance)
+   = note: out-of-bounds offset_from: null pointer is a dangling pointer (it has no provenance)
    |
 note: inside `ptr::const_ptr::<impl *const u8>::offset_from`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::ptr_offset_from(self, origin) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `OFFSET_VERY_FAR2`
   --> $DIR/offset_from_ub.rs:121:14
    |
index 7938f70a2695ed60f43b0123a4177340da9b5902..c0c851df5076e078bb5529b11f9b612d9740010a 100644 (file)
@@ -1,14 +1,10 @@
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing in-bounds pointer arithmetic
+   = note: overflowing in-bounds pointer arithmetic
    |
 note: inside `ptr::const_ptr::<impl *const u8>::offset`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `BEFORE_START`
   --> $DIR/offset_ub.rs:7:46
    |
@@ -18,14 +14,10 @@ LL | pub const BEFORE_START: *const u8 = unsafe { (&0u8 as *const u8).offset(-1)
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer arithmetic: allocN has size 1, so pointer to 2 bytes starting at offset 0 is out-of-bounds
+   = note: out-of-bounds pointer arithmetic: allocN has size 1, so pointer to 2 bytes starting at offset 0 is out-of-bounds
    |
 note: inside `ptr::const_ptr::<impl *const u8>::offset`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `AFTER_END`
   --> $DIR/offset_ub.rs:8:43
    |
@@ -35,14 +27,10 @@ LL | pub const AFTER_END: *const u8 = unsafe { (&0u8 as *const u8).offset(2) };
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer arithmetic: allocN has size 100, so pointer to 101 bytes starting at offset 0 is out-of-bounds
+   = note: out-of-bounds pointer arithmetic: allocN has size 100, so pointer to 101 bytes starting at offset 0 is out-of-bounds
    |
 note: inside `ptr::const_ptr::<impl *const u8>::offset`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `AFTER_ARRAY`
   --> $DIR/offset_ub.rs:9:45
    |
@@ -52,14 +40,10 @@ LL | pub const AFTER_ARRAY: *const u8 = unsafe { [0u8; 100].as_ptr().offset(101)
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing in-bounds pointer arithmetic
+   = note: overflowing in-bounds pointer arithmetic
    |
 note: inside `ptr::const_ptr::<impl *const u16>::offset`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `OVERFLOW`
   --> $DIR/offset_ub.rs:11:43
    |
@@ -69,14 +53,10 @@ LL | pub const OVERFLOW: *const u16 = unsafe { [0u16; 1].as_ptr().offset(isize::
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing in-bounds pointer arithmetic
+   = note: overflowing in-bounds pointer arithmetic
    |
 note: inside `ptr::const_ptr::<impl *const u16>::offset`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `UNDERFLOW`
   --> $DIR/offset_ub.rs:12:44
    |
@@ -86,14 +66,10 @@ LL | pub const UNDERFLOW: *const u16 = unsafe { [0u16; 1].as_ptr().offset(isize:
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing in-bounds pointer arithmetic
+   = note: overflowing in-bounds pointer arithmetic
    |
 note: inside `ptr::const_ptr::<impl *const u8>::offset`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `OVERFLOW_ADDRESS_SPACE`
   --> $DIR/offset_ub.rs:13:56
    |
@@ -103,14 +79,10 @@ LL | pub const OVERFLOW_ADDRESS_SPACE: *const u8 = unsafe { (usize::MAX as *cons
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing in-bounds pointer arithmetic
+   = note: overflowing in-bounds pointer arithmetic
    |
 note: inside `ptr::const_ptr::<impl *const u8>::offset`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `UNDERFLOW_ADDRESS_SPACE`
   --> $DIR/offset_ub.rs:14:57
    |
@@ -120,14 +92,10 @@ LL | pub const UNDERFLOW_ADDRESS_SPACE: *const u8 = unsafe { (1 as *const u8).of
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer arithmetic: allocN has size 1, so pointer to 2 bytes starting at offset -4 is out-of-bounds
+   = note: out-of-bounds pointer arithmetic: allocN has size 1, so pointer to 2 bytes starting at offset -4 is out-of-bounds
    |
 note: inside `ptr::const_ptr::<impl *const u8>::offset`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `NEGATIVE_OFFSET`
   --> $DIR/offset_ub.rs:15:49
    |
@@ -137,14 +105,10 @@ LL | pub const NEGATIVE_OFFSET: *const u8 = unsafe { [0u8; 1].as_ptr().wrapping_
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer arithmetic: allocN has size 0, so pointer to 1 byte starting at offset 0 is out-of-bounds
+   = note: out-of-bounds pointer arithmetic: allocN has size 0, so pointer to 1 byte starting at offset 0 is out-of-bounds
    |
 note: inside `ptr::const_ptr::<impl *const u8>::offset`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `ZERO_SIZED_ALLOC`
   --> $DIR/offset_ub.rs:17:50
    |
@@ -154,14 +118,10 @@ LL | pub const ZERO_SIZED_ALLOC: *const u8 = unsafe { [0u8; 0].as_ptr().offset(1
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::offset(self, count) as *mut T }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer arithmetic: 0x1[noalloc] is a dangling pointer (it has no provenance)
+   = note: out-of-bounds pointer arithmetic: 0x1[noalloc] is a dangling pointer (it has no provenance)
    |
 note: inside `ptr::mut_ptr::<impl *mut u8>::offset`
   --> $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::offset(self, count) as *mut T }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `DANGLING`
   --> $DIR/offset_ub.rs:18:42
    |
@@ -171,14 +131,10 @@ LL | pub const DANGLING: *const u8 = unsafe { ptr::NonNull::<u8>::dangling().as_
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer arithmetic: null pointer is a dangling pointer (it has no provenance)
+   = note: out-of-bounds pointer arithmetic: null pointer is a dangling pointer (it has no provenance)
    |
 note: inside `ptr::const_ptr::<impl *const u8>::offset`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `NULL_OFFSET_ZERO`
   --> $DIR/offset_ub.rs:21:50
    |
@@ -188,14 +144,10 @@ LL | pub const NULL_OFFSET_ZERO: *const u8 = unsafe { ptr::null::<u8>().offset(0
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer arithmetic: 0x7f..f[noalloc] is a dangling pointer (it has no provenance)
+   = note: out-of-bounds pointer arithmetic: 0x7f..f[noalloc] is a dangling pointer (it has no provenance)
    |
 note: inside `ptr::const_ptr::<impl *const u8>::offset`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `UNDERFLOW_ABS`
   --> $DIR/offset_ub.rs:24:47
    |
index 274753ef1bc234c4a5cae52520870ec906aa6085..fea924d12e54ee60a79799be0f8845a707b3cf4a 100644 (file)
@@ -1,14 +1,10 @@
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer arithmetic: alloc3 has size $WORD, so pointer to $TWO_WORDS bytes starting at offset 0 is out-of-bounds
+   = note: out-of-bounds pointer arithmetic: alloc3 has size $WORD, so pointer to $TWO_WORDS bytes starting at offset 0 is out-of-bounds
    |
 note: inside `ptr::const_ptr::<impl *const usize>::offset`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `_`
   --> $DIR/ptr_comparisons.rs:50:34
    |
index e3fb234b96e4153b51ade0849d30f6a36c2a3a97..2be69a30b1c122222de25596e628ff372f5f9504 100644 (file)
@@ -9,9 +9,6 @@ LL |      x: Error
    |
 note: required by a bound in `AssertParamIsEq`
   --> $SRC_DIR/core/src/cmp.rs:LL:COL
-   |
-LL | pub struct AssertParamIsEq<T: Eq + ?Sized> {
-   |                               ^^ required by this bound in `AssertParamIsEq`
    = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider annotating `Error` with `#[derive(Eq)]`
    |
index 4e10c3f69e735a5df6d17b558f156aad35661078..4f4f821cca3e7c735302daf8c1c8b3103a67d80b 100644 (file)
@@ -9,9 +9,6 @@ LL |      Error
    |
 note: required by a bound in `AssertParamIsEq`
   --> $SRC_DIR/core/src/cmp.rs:LL:COL
-   |
-LL | pub struct AssertParamIsEq<T: Eq + ?Sized> {
-   |                               ^^ required by this bound in `AssertParamIsEq`
    = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider annotating `Error` with `#[derive(Eq)]`
    |
index bfdab052a2ed42167c6d6398d2dbbc5b8e11cba4..f15659c3e166c9807c66cc7cef251465884b933e 100644 (file)
@@ -9,9 +9,6 @@ LL |     x: Error
    |
 note: required by a bound in `AssertParamIsEq`
   --> $SRC_DIR/core/src/cmp.rs:LL:COL
-   |
-LL | pub struct AssertParamIsEq<T: Eq + ?Sized> {
-   |                               ^^ required by this bound in `AssertParamIsEq`
    = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider annotating `Error` with `#[derive(Eq)]`
    |
index 26b8be343336b95ac9f7947ccf639103d01ef928..4e5659b35f47a5434459c7681e33d7ccb1391a83 100644 (file)
@@ -9,9 +9,6 @@ LL |     Error
    |
 note: required by a bound in `AssertParamIsEq`
   --> $SRC_DIR/core/src/cmp.rs:LL:COL
-   |
-LL | pub struct AssertParamIsEq<T: Eq + ?Sized> {
-   |                               ^^ required by this bound in `AssertParamIsEq`
    = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider annotating `Error` with `#[derive(Eq)]`
    |
index f3ff95a85da1a3b314ed0a30af84a166a279f54f..053d34f68251a44082558ca4678c750b593aaf9d 100644 (file)
@@ -3,22 +3,18 @@ error: cannot find derive macro `Eqr` in this scope
    |
 LL | #[derive(Eqr)]
    |          ^^^ help: a derive macro with a similar name exists: `Eq`
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/cmp.rs:LL:COL
-   |
-LL | pub macro Eq($item:item) {
-   | ------------ similarly named derive macro `Eq` defined here
+   = note: similarly named derive macro `Eq` defined here
 
 error: cannot find derive macro `Eqr` in this scope
   --> $DIR/deriving-meta-unknown-trait.rs:1:10
    |
 LL | #[derive(Eqr)]
    |          ^^^ help: a derive macro with a similar name exists: `Eq`
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/cmp.rs:LL:COL
-   |
-LL | pub macro Eq($item:item) {
-   | ------------ similarly named derive macro `Eq` defined here
+   = note: similarly named derive macro `Eq` defined here
 
 error: aborting due to 2 previous errors
 
index ee3528fe1062ddd7f418667689da0e7376c0c352..b18e1e5098b34ba08ed6cfd5f7a39d06aa060d23 100644 (file)
@@ -20,9 +20,6 @@ LL |     Float(Option<f64>),
    = note: required for `Option<f64>` to implement `Eq`
 note: required by a bound in `AssertParamIsEq`
   --> $SRC_DIR/core/src/cmp.rs:LL:COL
-   |
-LL | pub struct AssertParamIsEq<T: Eq + ?Sized> {
-   |                               ^^ required by this bound in `AssertParamIsEq`
    = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
index e45344aa51fc335c3db50d7d8b91bee8c2d7be90..8a88332b73e105f8b06c85c634f8cdeefba70f7e 100644 (file)
@@ -49,11 +49,8 @@ note: an implementation of `AddAssign<_>` might be missing for `S`
    |
 LL | struct S { x: u8, y: u8 }
    | ^^^^^^^^ must implement `AddAssign<_>`
-note: the following trait must be implemented
+note: the trait `AddAssign` must be implemented
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL | pub trait AddAssign<Rhs = Self> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0067]: invalid left-hand side of assignment
   --> $DIR/note-unsupported.rs:17:22
diff --git a/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.fixed b/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.fixed
new file mode 100644 (file)
index 0000000..ae0a84e
--- /dev/null
@@ -0,0 +1,21 @@
+// run-rustfix
+struct X {
+    x: String,
+}
+
+impl Drop for X {
+    fn drop(&mut self) {
+        println!("value: {}", self.x);
+    }
+}
+
+fn unwrap(x: X) -> String {
+    let X { x: ref y } = x; //~ ERROR cannot move out of type
+    y.to_string()
+}
+
+fn main() {
+    let x = X { x: "hello".to_string() };
+    let y = unwrap(x);
+    println!("contents: {}", y);
+}
index 8e394498a2349bd040bcdd7f8704c66fd40ffabc..c8db78610681336c8f03c060a6f6f3a353d69027 100644 (file)
@@ -1,3 +1,4 @@
+// run-rustfix
 struct X {
     x: String,
 }
@@ -10,7 +11,7 @@ fn drop(&mut self) {
 
 fn unwrap(x: X) -> String {
     let X { x: y } = x; //~ ERROR cannot move out of type
-    y
+    y.to_string()
 }
 
 fn main() {
index cda81d136699561c954b6ac95dbeee126a2d2be8..596ad4bf784bb531187d7b9c159925926fd2ef97 100644 (file)
@@ -1,11 +1,16 @@
 error[E0509]: cannot move out of type `X`, which implements the `Drop` trait
-  --> $DIR/disallowed-deconstructing-destructing-struct-let.rs:12:22
+  --> $DIR/disallowed-deconstructing-destructing-struct-let.rs:13:22
    |
 LL |     let X { x: y } = x;
    |                -     ^ cannot move out of here
    |                |
    |                data moved here
    |                move occurs because `y` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |     let X { x: ref y } = x;
+   |                +++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.fixed b/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.fixed
new file mode 100644 (file)
index 0000000..c8a451e
--- /dev/null
@@ -0,0 +1,19 @@
+// run-rustfix
+struct X {
+    x: String,
+}
+
+impl Drop for X {
+    fn drop(&mut self) {
+        println!("value: {}", self.x);
+    }
+}
+
+fn main() {
+    let x = X { x: "hello".to_string() };
+
+    match x {
+    //~^ ERROR cannot move out of type `X`, which implements the `Drop` trait
+        X { x: ref y } => println!("contents: {}", y)
+    }
+}
index 70cdd6446c8d987b1eef6a1676e6fc610ec3224c..e32a4dd44114963a94d804bc19bb6f20937675d7 100644 (file)
@@ -1,5 +1,5 @@
 error[E0509]: cannot move out of type `X`, which implements the `Drop` trait
-  --> $DIR/disallowed-deconstructing-destructing-struct-match.rs:14:11
+  --> $DIR/disallowed-deconstructing-destructing-struct-match.rs:15:11
    |
 LL |     match x {
    |           ^ cannot move out of here
@@ -9,6 +9,11 @@ LL |         X { x: y } => println!("contents: {}", y)
    |                |
    |                data moved here
    |                move occurs because `y` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |         X { x: ref y } => println!("contents: {}", y)
+   |                +++
 
 error: aborting due to previous error
 
index 727f4d843033fd132349d2571fffd4fd812420e3..8d0a82b707ddaa07ffcebd0df4cc2b9bd60b1227 100644 (file)
@@ -9,9 +9,6 @@ LL |     let _x: Box<str> = Box::new(*"hello world");
    = help: the trait `Sized` is not implemented for `str`
 note: required by a bound in `Box::<T>::new`
   --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
-   |
-LL | impl<T> Box<T> {
-   |      ^ required by this bound in `Box::<T>::new`
 
 error[E0277]: the size for values of type `[isize]` cannot be known at compilation time
   --> $DIR/dst-rvalue.rs:8:37
@@ -24,9 +21,6 @@ LL |     let _x: Box<[isize]> = Box::new(*array);
    = help: the trait `Sized` is not implemented for `[isize]`
 note: required by a bound in `Box::<T>::new`
   --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
-   |
-LL | impl<T> Box<T> {
-   |      ^ required by this bound in `Box::<T>::new`
 
 error: aborting due to 2 previous errors
 
index e1a7a02a56869ad056ca3a15f05c57805b31c2eb..0e580aedeaa921e7fd548624dc075a660864600d 100644 (file)
@@ -100,22 +100,22 @@ help: a unit struct with a similar name exists
 LL |     let xe1 = XEmpty2();
    |               ~~~~~~~
 
-error[E0599]: no variant or associated item named `Empty3` found for enum `empty_struct::XE` in the current scope
+error[E0599]: no variant or associated item named `Empty3` found for enum `XE` in the current scope
   --> $DIR/empty-struct-braces-expr.rs:25:19
    |
 LL |     let xe3 = XE::Empty3;
    |                   ^^^^^^
    |                   |
-   |                   variant or associated item not found in `empty_struct::XE`
+   |                   variant or associated item not found in `XE`
    |                   help: there is a variant with a similar name: `XEmpty3`
 
-error[E0599]: no variant or associated item named `Empty3` found for enum `empty_struct::XE` in the current scope
+error[E0599]: no variant or associated item named `Empty3` found for enum `XE` in the current scope
   --> $DIR/empty-struct-braces-expr.rs:26:19
    |
 LL |     let xe3 = XE::Empty3();
    |                   ^^^^^^
    |                   |
-   |                   variant or associated item not found in `empty_struct::XE`
+   |                   variant or associated item not found in `XE`
    |                   help: there is a variant with a similar name: `XEmpty3`
 
 error[E0599]: no variant named `Empty1` found for enum `empty_struct::XE`
index 6f5bb4309c350e77fb6160671bab8620e0eff6c7..e829bac196f7962b27bb1ef0554b7717356d0879 100644 (file)
@@ -6,15 +6,12 @@ LL |     match x { }
    |
 note: `Option<i32>` defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
+  ::: $SRC_DIR/core/src/option.rs:LL:COL
    |
-LL | pub enum Option<T> {
-   | ------------------
-...
-LL |     None,
-   |     ^^^^ not covered
-...
-LL |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^^^ not covered
+   = note: not covered
+  ::: $SRC_DIR/core/src/option.rs:LL:COL
+   |
+   = note: not covered
    = note: the matched value is of type `Option<i32>`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
    |
index de8e6bac486c1238b985e7b76b0c5ddcd1d59722..0f179259356d50430ed09f38bf96f01e2762ed25 100644 (file)
@@ -8,12 +8,9 @@ LL |     let Some(y) = x;
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
 note: `Option<i32>` defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
+  ::: $SRC_DIR/core/src/option.rs:LL:COL
    |
-LL | pub enum Option<T> {
-   | ------------------
-...
-LL |     None,
-   |     ^^^^ not covered
+   = note: not covered
    = note: the matched value is of type `Option<i32>`
 help: you might want to use `if let` to ignore the variant that isn't matched
    |
index f331d0142260e92c0d3447521274bb856d68117b..4f6abb22ab2f03f9ef63d1e81d1cb8669c4f49fb 100644 (file)
@@ -6,9 +6,6 @@ LL | fn foo<F: Fn<i32>>(f: F) -> F::Output { f(3) }
    |
 note: required by a bound in `Fn`
   --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
-   |                    ^^^^^ required by this bound in `Fn`
 
 error: aborting due to previous error
 
index d01aa3617c764c1fe9f0c95b65a69bf689c59dc1..892d3a81f27f9543e5b87663e64dcb3e2894cb21 100644 (file)
@@ -6,8 +6,8 @@ LL |     let x = "hello".chars().rev().collect();
    |
 help: consider giving `x` an explicit type
    |
-LL |     let x: _ = "hello".chars().rev().collect();
-   |          +++
+LL |     let x: Vec<_> = "hello".chars().rev().collect();
+   |          ++++++++
 
 error: aborting due to previous error
 
index 693b079238d71d47f0a53b6a9a6aeaad83ab2efb..903422f3b9b8a59ba9b02f526ce33cd634bde089 100644 (file)
@@ -6,12 +6,9 @@ LL |     for Some(x) in xs {}
    |
 note: `Option<i32>` defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
+  ::: $SRC_DIR/core/src/option.rs:LL:COL
    |
-LL | pub enum Option<T> {
-   | ------------------
-...
-LL |     None,
-   |     ^^^^ not covered
+   = note: not covered
    = note: the matched value is of type `Option<i32>`
 
 error: aborting due to previous error
index 9687eca61fab0b5d16a1968fda5f18defde0bfd9..fa4b91cacef7261c169b3692128daa38199f88af 100644 (file)
@@ -59,7 +59,7 @@ note: required by a bound in `bfnr`
    |
 LL |     fn bfnr<U, V: Baz<U>, W: Fn()>(y: T) {
    |                              ^^^^ required by this bound in `bfnr`
-help: consider specifying the type arguments in the function call
+help: consider specifying the generic arguments
    |
 LL |     bfnr::<U, V, W>(x);
    |         +++++++++++
index ce8d1ef03493c277c960ec783ee3da0f1e1d2697..03630f38987e23cc95304050b8b4b7105373c89a 100644 (file)
@@ -7,7 +7,7 @@ LL |     x.borrow().nothing_is_true();
    |     |          value moved due to this method call
    |     move occurs because value has type `TheDarkKnight`, which does not implement the `Copy` trait
    |
-note: this function takes ownership of the receiver `self`, which moves value
+note: `TheDarkKnight::nothing_is_true` takes ownership of the receiver `self`, which moves value
   --> $DIR/E0507.rs:6:24
    |
 LL |     fn nothing_is_true(self) {}
index b69d7743b6c2c98839dde8ad4ea8eb2a6f65a033..208ba30729f8b31b97c9b2860196801ff6f2c646 100644 (file)
@@ -6,7 +6,11 @@ LL |     let _value = array[0];
    |                  |
    |                  cannot move out of here
    |                  move occurs because `array[_]` has type `NonCopy`, which does not implement the `Copy` trait
-   |                  help: consider borrowing here: `&array[0]`
+   |
+help: consider borrowing here
+   |
+LL |     let _value = &array[0];
+   |                  +
 
 error: aborting due to previous error
 
index 5e7b56dcd372a7d257768702ed40eec12f72f88f..df2d3b0d311c93652b67f3c9b67418fddc672971 100644 (file)
@@ -6,7 +6,11 @@ LL |     let _value = array[0];
    |                  |
    |                  cannot move out of here
    |                  move occurs because `array[_]` has type `NonCopy`, which does not implement the `Copy` trait
-   |                  help: consider borrowing here: `&array[0]`
+   |
+help: consider borrowing here
+   |
+LL |     let _value = &array[0];
+   |                  +
 
 error: aborting due to previous error
 
index cbfbc3ccf6a879c2e95cc0c262e79b8877a7042e..c00d9142e750559552589fb6881319869969c50c 100644 (file)
@@ -6,7 +6,11 @@ LL |     let fancy_field = drop_struct.fancy;
    |                       |
    |                       cannot move out of here
    |                       move occurs because `drop_struct.fancy` has type `FancyNum`, which does not implement the `Copy` trait
-   |                       help: consider borrowing here: `&drop_struct.fancy`
+   |
+help: consider borrowing here
+   |
+LL |     let fancy_field = &drop_struct.fancy;
+   |                       +
 
 error: aborting due to previous error
 
index 43122c13efba88cdca97cd3f0176bf6d082a20f7..fe9956b70bdd75f3e9cb374adbb589cde91d2e50 100644 (file)
@@ -41,11 +41,8 @@ note: an implementation of `Not` might be missing for `Question`
    |
 LL | enum Question {
    | ^^^^^^^^^^^^^ must implement `Not`
-note: the following trait must be implemented
+note: the trait `Not` must be implemented
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
-   |
-LL | pub trait Not {
-   | ^^^^^^^^^^^^^
 
 error[E0604]: only `u8` can be cast as `char`, not `u32`
   --> $DIR/error-festival.rs:25:5
index 759d79493a9cf6e89803649b6d4676be1605b5df..2f9d10d70a2fea087ef955ca6a2ad9e22dcb4108 100644 (file)
@@ -14,7 +14,7 @@ LL |       let p = Some(45).and_then({
 LL | |
 LL | |         |x| println!("doubling {}", x);
 LL | |         Some(x * 2)
-   | |         ----------- this tail expression is of type `std::option::Option<_>`
+   | |         ----------- this tail expression is of type `Option<_>`
 LL | |
 LL | |     });
    | |_____^ expected an `FnOnce<({integer},)>` closure, found `Option<_>`
@@ -22,9 +22,6 @@ LL | |     });
    = help: the trait `FnOnce<({integer},)>` is not implemented for `Option<_>`
 note: required by a bound in `Option::<T>::and_then`
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |         F: ~const FnOnce(T) -> Option<U>,
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Option::<T>::and_then`
 
 error: aborting due to 2 previous errors
 
index 5ced344f13f38b510154bea9a586113f923a3fe8..e253e4791e8bd095b8941ffc4ce6f5a3f47e20fa 100644 (file)
@@ -8,12 +8,9 @@ LL |     let Ok(_x) = foo();
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
 note: `Result<u32, !>` defined here
   --> $SRC_DIR/core/src/result.rs:LL:COL
+  ::: $SRC_DIR/core/src/result.rs:LL:COL
    |
-LL | pub enum Result<T, E> {
-   | ---------------------
-...
-LL |     Err(#[stable(feature = "rust1", since = "1.0.0")] E),
-   |     ^^^ not covered
+   = note: not covered
    = note: the matched value is of type `Result<u32, !>`
 help: you might want to use `if let` to ignore the variant that isn't matched
    |
index 1b595a50e998494085ffe416afd18889946efa12..a8a2a47fe46e1f6ed7a478b9f99d3e9d1167dddf 100644 (file)
@@ -309,9 +309,6 @@ LL |     println!("{} {:.*} {}", 1, 3.2, 4);
               found reference `&{float}`
 note: associated function defined here
   --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-   |
-LL |     pub fn from_usize(x: &usize) -> ArgumentV1<'_> {
-   |            ^^^^^^^^^^
    = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0308]: mismatched types
@@ -327,9 +324,6 @@ LL |     println!("{} {:07$.*} {}", 1, 3.2, 4);
               found reference `&{float}`
 note: associated function defined here
   --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-   |
-LL |     pub fn from_usize(x: &usize) -> ArgumentV1<'_> {
-   |            ^^^^^^^^^^
    = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 38 previous errors
index 0e34f913511a3121913f6f496ee34690384de497..be321c3c5c08f1279e539132933ba9d391027627 100644 (file)
@@ -17,9 +17,6 @@ LL |     format!("{:X}", "3");
    = note: required for `&str` to implement `UpperHex`
 note: required by a bound in `ArgumentV1::<'a>::new_upper_hex`
   --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-   |
-LL |     arg_new!(new_upper_hex, UpperHex);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `ArgumentV1::<'a>::new_upper_hex`
    = note: this error originates in the macro `$crate::__export::format_args` which comes from the expansion of the macro `arg_new` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
index 2296666219eef2fbb284e11e7699db91b4adb20d..463ac7684ecdfea3a73122953e24915249278b66 100644 (file)
@@ -17,11 +17,11 @@ note: `Bar` defines an item `bar`, perhaps you need to implement it
 LL | trait Bar {
    | ^^^^^^^^^
 
-error[E0599]: no method named `bar` found for struct `Arc<[closure@$DIR/fn-help-with-err.rs:22:36: 22:38]>` in the current scope
+error[E0599]: no method named `bar` found for struct `Arc<[closure@fn-help-with-err.rs:22:36]>` in the current scope
   --> $DIR/fn-help-with-err.rs:23:10
    |
 LL |     arc2.bar();
-   |          ^^^ method not found in `Arc<[closure@$DIR/fn-help-with-err.rs:22:36: 22:38]>`
+   |          ^^^ method not found in `Arc<[closure@fn-help-with-err.rs:22:36]>`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
 note: `Bar` defines an item `bar`, perhaps you need to implement it
index 7b4d5021325176b33b55008a850a4607c83d1c46..afb39c9e594d17887c8890ca793d7dcad17a3df0 100644 (file)
@@ -6,9 +6,6 @@ LL |     Pin::new(&mut b).resume();
    |
 note: associated function defined here
   --> $SRC_DIR/core/src/ops/generator.rs:LL:COL
-   |
-LL |     fn resume(self: Pin<&mut Self>, arg: R) -> GeneratorState<Self::Yield, Self::Return>;
-   |        ^^^^^^
 help: provide the argument
    |
 LL |     Pin::new(&mut b).resume(());
index ea2a48d13cee62dc4a23d2bedda93ecd411cad73..fb34540d969dae4e9401c2281f0363d93e797038 100644 (file)
@@ -20,9 +20,6 @@ LL |    Pin::new(&mut gen).resume(());
    = help: the trait `Sized` is not implemented for `str`
 note: required by a bound in `GeneratorState`
   --> $SRC_DIR/core/src/ops/generator.rs:LL:COL
-   |
-LL | pub enum GeneratorState<Y, R> {
-   |                         ^ required by this bound in `GeneratorState`
 
 error: aborting due to 2 previous errors
 
index b4e94cb83f7388c2647df7aaaf46f5205da55069..422ac5484271d519b82c04d253ef709720b9178a 100644 (file)
@@ -1,10 +1,8 @@
 error[E0277]: the trait bound `for<'a> &'a mut (): Foo<&'a mut ()>` is not satisfied
-  --> $DIR/issue-101020.rs:31:5
+  --> $DIR/issue-101020.rs:31:22
    |
 LL |     (&mut EmptyIter).consume(());
-   |     ^^^^^^^^^^^^^^^^ ------- required by a bound introduced by this call
-   |     |
-   |     the trait `for<'a> Foo<&'a mut ()>` is not implemented for `&'a mut ()`
+   |                      ^^^^^^^ the trait `for<'a> Foo<&'a mut ()>` is not implemented for `&'a mut ()`
    |
 note: required for `&'a mut ()` to implement `for<'a> FuncInput<'a, &'a mut ()>`
   --> $DIR/issue-101020.rs:27:20
index 0475eb908a779d0e1174b6be53bd444937013ddf..b48966a1a1ed0c66f351b39ab7e7b8c5de8ddd8e 100644 (file)
@@ -889,11 +889,6 @@ error[E0107]: missing generics for struct `HashMap`
 LL |         type A = HashMap;
    |                  ^^^^^^^ expected at least 2 generic arguments
    |
-note: struct defined here, with at least 2 generic parameters: `K`, `V`
-  --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
-   |
-LL | pub struct HashMap<K, V, S = RandomState> {
-   |            ^^^^^^^ -  -
 help: add missing generic arguments
    |
 LL |         type A = HashMap<K, V>;
@@ -907,11 +902,6 @@ LL |         type B = HashMap<String>;
    |                  |
    |                  expected at least 2 generic arguments
    |
-note: struct defined here, with at least 2 generic parameters: `K`, `V`
-  --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
-   |
-LL | pub struct HashMap<K, V, S = RandomState> {
-   |            ^^^^^^^ -  -
 help: add missing generic argument
    |
 LL |         type B = HashMap<String, V>;
@@ -924,12 +914,6 @@ LL |         type C = HashMap<'static>;
    |                  ^^^^^^^--------- help: remove these generics
    |                  |
    |                  expected 0 lifetime arguments
-   |
-note: struct defined here, with 0 lifetime parameters
-  --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
-   |
-LL | pub struct HashMap<K, V, S = RandomState> {
-   |            ^^^^^^^
 
 error[E0107]: this struct takes at least 2 generic arguments but 0 generic arguments were supplied
   --> $DIR/wrong-number-of-args.rs:318:18
@@ -937,11 +921,6 @@ error[E0107]: this struct takes at least 2 generic arguments but 0 generic argum
 LL |         type C = HashMap<'static>;
    |                  ^^^^^^^ expected at least 2 generic arguments
    |
-note: struct defined here, with at least 2 generic parameters: `K`, `V`
-  --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
-   |
-LL | pub struct HashMap<K, V, S = RandomState> {
-   |            ^^^^^^^ -  -
 help: add missing generic arguments
    |
 LL |         type C = HashMap<'static, K, V>;
@@ -954,12 +933,6 @@ LL |         type D = HashMap<usize, String, char, f64>;
    |                  ^^^^^^^                      --- help: remove this generic argument
    |                  |
    |                  expected at most 3 generic arguments
-   |
-note: struct defined here, with at most 3 generic parameters: `K`, `V`, `S`
-  --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
-   |
-LL | pub struct HashMap<K, V, S = RandomState> {
-   |            ^^^^^^^ -  -  ---------------
 
 error[E0107]: this struct takes at least 2 generic arguments but 0 generic arguments were supplied
   --> $DIR/wrong-number-of-args.rs:328:18
@@ -967,11 +940,6 @@ error[E0107]: this struct takes at least 2 generic arguments but 0 generic argum
 LL |         type E = HashMap<>;
    |                  ^^^^^^^ expected at least 2 generic arguments
    |
-note: struct defined here, with at least 2 generic parameters: `K`, `V`
-  --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
-   |
-LL | pub struct HashMap<K, V, S = RandomState> {
-   |            ^^^^^^^ -  -
 help: add missing generic arguments
    |
 LL |         type E = HashMap<K, V>;
@@ -983,11 +951,6 @@ error[E0107]: missing generics for enum `Result`
 LL |         type A = Result;
    |                  ^^^^^^ expected 2 generic arguments
    |
-note: enum defined here, with 2 generic parameters: `T`, `E`
-  --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL | pub enum Result<T, E> {
-   |          ^^^^^^ -  -
 help: add missing generic arguments
    |
 LL |         type A = Result<T, E>;
@@ -1001,11 +964,6 @@ LL |         type B = Result<String>;
    |                  |
    |                  expected 2 generic arguments
    |
-note: enum defined here, with 2 generic parameters: `T`, `E`
-  --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL | pub enum Result<T, E> {
-   |          ^^^^^^ -  -
 help: add missing generic argument
    |
 LL |         type B = Result<String, E>;
@@ -1018,12 +976,6 @@ LL |         type C = Result<'static>;
    |                  ^^^^^^--------- help: remove these generics
    |                  |
    |                  expected 0 lifetime arguments
-   |
-note: enum defined here, with 0 lifetime parameters
-  --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL | pub enum Result<T, E> {
-   |          ^^^^^^
 
 error[E0107]: this enum takes 2 generic arguments but 0 generic arguments were supplied
   --> $DIR/wrong-number-of-args.rs:342:18
@@ -1031,11 +983,6 @@ error[E0107]: this enum takes 2 generic arguments but 0 generic arguments were s
 LL |         type C = Result<'static>;
    |                  ^^^^^^ expected 2 generic arguments
    |
-note: enum defined here, with 2 generic parameters: `T`, `E`
-  --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL | pub enum Result<T, E> {
-   |          ^^^^^^ -  -
 help: add missing generic arguments
    |
 LL |         type C = Result<'static, T, E>;
@@ -1048,12 +995,6 @@ LL |         type D = Result<usize, String, char>;
    |                  ^^^^^^                ---- help: remove this generic argument
    |                  |
    |                  expected 2 generic arguments
-   |
-note: enum defined here, with 2 generic parameters: `T`, `E`
-  --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL | pub enum Result<T, E> {
-   |          ^^^^^^ -  -
 
 error[E0107]: this enum takes 2 generic arguments but 0 generic arguments were supplied
   --> $DIR/wrong-number-of-args.rs:352:18
@@ -1061,11 +1002,6 @@ error[E0107]: this enum takes 2 generic arguments but 0 generic arguments were s
 LL |         type E = Result<>;
    |                  ^^^^^^ expected 2 generic arguments
    |
-note: enum defined here, with 2 generic parameters: `T`, `E`
-  --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL | pub enum Result<T, E> {
-   |          ^^^^^^ -  -
 help: add missing generic arguments
    |
 LL |         type E = Result<T, E>;
diff --git a/src/test/ui/higher-rank-trait-bounds/hang-on-deeply-nested-dyn.rs b/src/test/ui/higher-rank-trait-bounds/hang-on-deeply-nested-dyn.rs
new file mode 100644 (file)
index 0000000..d34b7a2
--- /dev/null
@@ -0,0 +1,16 @@
+// normalize-stderr-test: "long-type-\d+" -> "long-type-hash"
+
+fn id(
+    f: &dyn Fn(u32),
+) -> &dyn Fn(
+    &dyn Fn(
+        &dyn Fn(
+            &dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(u32))))))))),
+        ),
+    ),
+) {
+    f
+    //~^ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/src/test/ui/higher-rank-trait-bounds/hang-on-deeply-nested-dyn.stderr b/src/test/ui/higher-rank-trait-bounds/hang-on-deeply-nested-dyn.stderr
new file mode 100644 (file)
index 0000000..71e196c
--- /dev/null
@@ -0,0 +1,22 @@
+error[E0308]: mismatched types
+  --> $DIR/hang-on-deeply-nested-dyn.rs:12:5
+   |
+LL |   ) -> &dyn Fn(
+   |  ______-
+LL | |     &dyn Fn(
+LL | |         &dyn Fn(
+LL | |             &dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(u32))))))))),
+LL | |         ),
+LL | |     ),
+LL | | ) {
+   | |_- expected `&dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn Fn(u32) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a))` because of return type
+LL |       f
+   |       ^ expected reference, found `u32`
+   |
+   = note: expected reference `&dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a ...) + 'a)) + 'a)) + 'a))`
+           the full type name has been written to '$TEST_BUILD_DIR/higher-rank-trait-bounds/hang-on-deeply-nested-dyn/hang-on-deeply-nested-dyn.long-type-hash.txt'
+              found reference `&dyn Fn(u32)`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
index c1e235441d65df68f775e99f1de85b897185d040..0458d2535f2f56ad83eac2b0d3be6ceaaf28c22b 100644 (file)
@@ -1,4 +1,4 @@
-error[E0599]: the method `filterx` exists for struct `Map<Repeat, [closure@$DIR/issue-30786.rs:117:27: 117:34]>`, but its trait bounds were not satisfied
+error[E0599]: the method `filterx` exists for struct `Map<Repeat, [closure@issue-30786.rs:117:27]>`, but its trait bounds were not satisfied
   --> $DIR/issue-30786.rs:118:22
    |
 LL | pub struct Map<S, F> {
@@ -8,7 +8,7 @@ LL | pub struct Map<S, F> {
    | doesn't satisfy `_: StreamExt`
 ...
 LL |     let filter = map.filterx(|x: &_| true);
-   |                      ^^^^^^^ method cannot be called on `Map<Repeat, [closure@$DIR/issue-30786.rs:117:27: 117:34]>` due to unsatisfied trait bounds
+   |                      ^^^^^^^ method cannot be called on `Map<Repeat, [closure@issue-30786.rs:117:27]>` due to unsatisfied trait bounds
    |
 note: the following trait bounds were not satisfied:
       `&'a mut &Map<Repeat, [closure@$DIR/issue-30786.rs:117:27: 117:34]>: Stream`
@@ -19,7 +19,7 @@ note: the following trait bounds were not satisfied:
 LL | impl<T> StreamExt for T where for<'a> &'a mut T: Stream {}
    |         ---------     -                          ^^^^^^ unsatisfied trait bound introduced here
 
-error[E0599]: the method `countx` exists for struct `Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:129:30: 129:37]>`, but its trait bounds were not satisfied
+error[E0599]: the method `countx` exists for struct `Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, [closure@issue-30786.rs:129:30]>`, but its trait bounds were not satisfied
   --> $DIR/issue-30786.rs:130:24
    |
 LL | pub struct Filter<S, F> {
@@ -29,7 +29,7 @@ LL | pub struct Filter<S, F> {
    | doesn't satisfy `_: StreamExt`
 ...
 LL |     let count = filter.countx();
-   |                        ^^^^^^ method cannot be called on `Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:129:30: 129:37]>` due to unsatisfied trait bounds
+   |                        ^^^^^^ method cannot be called due to unsatisfied trait bounds
    |
 note: the following trait bounds were not satisfied:
       `&'a mut &Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:129:30: 129:37]>: Stream`
index ab5598e364fc4f522b95e66080a7196a1c0cba93..fdd192f43137067a274ebe008c03d2641a9fad0b 100644 (file)
@@ -30,7 +30,7 @@ LL |     where
 LL |         F: for<'r> T0<'r, (<Self as Ty<'r>>::V,), O = <B as Ty<'r>>::V>,
    |                                                   ^^^^^^^^^^^^^^^^^^^^ required by this bound in `T1::m`
 
-error[E0271]: expected `[closure@$DIR/issue-62203-hrtb-ice.rs:42:16: 42:19]` to be a closure that returns `Unit3`, but it returns `Unit4`
+error[E0271]: expected `[closure@issue-62203-hrtb-ice.rs:42:16]` to be a closure that returns `Unit3`, but it returns `Unit4`
   --> $DIR/issue-62203-hrtb-ice.rs:39:9
    |
 LL |       let v = Unit2.m(
diff --git a/src/test/ui/illegal-sized-bound/mutability-mismatch.rs b/src/test/ui/illegal-sized-bound/mutability-mismatch.rs
new file mode 100644 (file)
index 0000000..deb84f6
--- /dev/null
@@ -0,0 +1,34 @@
+struct MutType;
+
+pub trait MutTrait {
+    fn function(&mut self)
+    where
+        Self: Sized;
+    //~^ this has a `Sized` requirement
+}
+
+impl MutTrait for MutType {
+    fn function(&mut self) {}
+}
+
+struct Type;
+
+pub trait Trait {
+    fn function(&self)
+    where
+        Self: Sized;
+    //~^ this has a `Sized` requirement
+}
+
+impl Trait for Type {
+    fn function(&self) {}
+}
+
+fn main() {
+    (&MutType as &dyn MutTrait).function();
+    //~^ ERROR the `function` method cannot be invoked on a trait object
+    //~| NOTE you need `&mut dyn MutTrait` instead of `&dyn MutTrait`
+    (&mut Type as &mut dyn Trait).function();
+    //~^ ERROR the `function` method cannot be invoked on a trait object
+    //~| NOTE you need `&dyn Trait` instead of `&mut dyn Trait`
+}
diff --git a/src/test/ui/illegal-sized-bound/mutability-mismatch.stderr b/src/test/ui/illegal-sized-bound/mutability-mismatch.stderr
new file mode 100644 (file)
index 0000000..dbbf79a
--- /dev/null
@@ -0,0 +1,24 @@
+error: the `function` method cannot be invoked on a trait object
+  --> $DIR/mutability-mismatch.rs:28:33
+   |
+LL |         Self: Sized;
+   |               ----- this has a `Sized` requirement
+...
+LL |     (&MutType as &dyn MutTrait).function();
+   |                                 ^^^^^^^^
+   |
+   = note: you need `&mut dyn MutTrait` instead of `&dyn MutTrait`
+
+error: the `function` method cannot be invoked on a trait object
+  --> $DIR/mutability-mismatch.rs:31:35
+   |
+LL |         Self: Sized;
+   |               ----- this has a `Sized` requirement
+...
+LL |     (&mut Type as &mut dyn Trait).function();
+   |                                   ^^^^^^^^
+   |
+   = note: you need `&dyn Trait` instead of `&mut dyn Trait`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/illegal-sized-bound/regular.rs b/src/test/ui/illegal-sized-bound/regular.rs
new file mode 100644 (file)
index 0000000..7abd27e
--- /dev/null
@@ -0,0 +1,32 @@
+struct MutType;
+
+pub trait MutTrait {
+    fn function(&mut self)
+    where
+        Self: Sized;
+    //~^ this has a `Sized` requirement
+}
+
+impl MutTrait for MutType {
+    fn function(&mut self) {}
+}
+
+struct Type;
+
+pub trait Trait {
+    fn function(&self)
+    where
+        Self: Sized;
+    //~^ this has a `Sized` requirement
+}
+
+impl Trait for Type {
+    fn function(&self) {}
+}
+
+fn main() {
+    (&mut MutType as &mut dyn MutTrait).function();
+    //~^ ERROR the `function` method cannot be invoked on a trait object
+    (&Type as &dyn Trait).function();
+    //~^ ERROR the `function` method cannot be invoked on a trait object
+}
diff --git a/src/test/ui/illegal-sized-bound/regular.stderr b/src/test/ui/illegal-sized-bound/regular.stderr
new file mode 100644 (file)
index 0000000..7f37441
--- /dev/null
@@ -0,0 +1,20 @@
+error: the `function` method cannot be invoked on a trait object
+  --> $DIR/regular.rs:28:41
+   |
+LL |         Self: Sized;
+   |               ----- this has a `Sized` requirement
+...
+LL |     (&mut MutType as &mut dyn MutTrait).function();
+   |                                         ^^^^^^^^
+
+error: the `function` method cannot be invoked on a trait object
+  --> $DIR/regular.rs:30:27
+   |
+LL |         Self: Sized;
+   |               ----- this has a `Sized` requirement
+...
+LL |     (&Type as &dyn Trait).function();
+   |                           ^^^^^^^^
+
+error: aborting due to 2 previous errors
+
index 542f02d7ec5673c82ebaf2d95564ec3959b0e739..973b65bfd625a6188cdf5c199dfa31284b5b4dbc 100644 (file)
@@ -46,11 +46,9 @@ error[E0643]: method `hash` has incompatible signature for trait
    |
 LL |     fn hash(&self, hasher: &mut impl Hasher) {}
    |                                 ^^^^^^^^^^^ expected generic parameter, found `impl Trait`
+  --> $SRC_DIR/core/src/hash/mod.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/hash/mod.rs:LL:COL
-   |
-LL |     fn hash<H: Hasher>(&self, state: &mut H);
-   |             - declaration in trait here
+   = note: declaration in trait here
 
 error: aborting due to 4 previous errors
 
index 92e36841b70c208c4387bc1365b7a2d09368a3ec..03cc4c2b93bed3948427b7ae028dd11a4da4e70a 100644 (file)
@@ -7,9 +7,6 @@ LL |     fn nya() -> impl Wf<Vec<[u8]>>;
    = help: the trait `Sized` is not implemented for `[u8]`
 note: required by a bound in `Vec`
   --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
-   |
-LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
-   |                ^ required by this bound in `Vec`
 
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
   --> $DIR/wf-bounds.rs:12:23
index 34f4dc2cef37dd3348af6f125f195abb12ea746d..bc342dc46893b80e02778235fc7437037bb9d406 100644 (file)
@@ -25,7 +25,7 @@ LL | pub struct SafeImpl<T: ?Sized, A: Raw<T>>(PhantomData<(A, T)>);
    |
    = note: the following trait bounds were not satisfied:
            `RawImpl<()>: Raw<()>`
-note: the following trait must be implemented
+note: the trait `Raw` must be implemented
   --> $DIR/issue-62742.rs:12:1
    |
 LL | pub trait Raw<T: ?Sized> {
index 09047cdcbe15ca5f8d0b211bfc0075ed8b51d203..7592418fdfd62f412eeef998debec2ea78919c30 100644 (file)
@@ -20,8 +20,8 @@ LL |         |_| true
    |
 help: consider giving this closure parameter an explicit type
    |
-LL |         |_: _| true
-   |           +++
+LL |         |_: /* Type */| true
+   |           ++++++++++++
 
 error: aborting due to 3 previous errors
 
index 34d5c2d61dc41148c07043a0c698f8b8352b7550..f09c14d3df1df216b7a01e75be34e8ab972b70ca 100644 (file)
@@ -4,11 +4,6 @@ error[E0107]: missing generics for struct `Vec`
 LL | fn f<T>(data: &[T]) -> impl Iterator<Item = Vec> {
    |                                             ^^^ expected at least 1 generic argument
    |
-note: struct defined here, with at least 1 generic parameter: `T`
-  --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
-   |
-LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
-   |            ^^^ -
 help: add missing generic argument
    |
 LL | fn f<T>(data: &[T]) -> impl Iterator<Item = Vec<T>> {
index 3d4ae11e5767039ab3659d58f60c79c32545ad86..548c89d0a3871372e87270fd08b5ad3b2e1421a4 100644 (file)
@@ -145,11 +145,11 @@ note: `foo::Bar` defines an item `method2`, perhaps you need to implement it
 LL |     pub trait Bar {
    |     ^^^^^^^^^^^^^
 
-error[E0599]: no method named `method2` found for struct `no_method_suggested_traits::Foo` in the current scope
+error[E0599]: no method named `method2` found for struct `Foo` in the current scope
   --> $DIR/no-method-suggested-traits.rs:50:37
    |
 LL |     no_method_suggested_traits::Foo.method2();
-   |                                     ^^^^^^^ method not found in `no_method_suggested_traits::Foo`
+   |                                     ^^^^^^^ method not found in `Foo`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
 note: `foo::Bar` defines an item `method2`, perhaps you need to implement it
@@ -158,11 +158,11 @@ note: `foo::Bar` defines an item `method2`, perhaps you need to implement it
 LL |     pub trait Bar {
    |     ^^^^^^^^^^^^^
 
-error[E0599]: no method named `method2` found for struct `Rc<&mut Box<&no_method_suggested_traits::Foo>>` in the current scope
+error[E0599]: no method named `method2` found for struct `Rc<&mut Box<&Foo>>` in the current scope
   --> $DIR/no-method-suggested-traits.rs:52:71
    |
 LL |     std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Foo)).method2();
-   |                                                                       ^^^^^^^ method not found in `Rc<&mut Box<&no_method_suggested_traits::Foo>>`
+   |                                                                       ^^^^^^^ method not found in `Rc<&mut Box<&Foo>>`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
 note: `foo::Bar` defines an item `method2`, perhaps you need to implement it
@@ -171,11 +171,11 @@ note: `foo::Bar` defines an item `method2`, perhaps you need to implement it
 LL |     pub trait Bar {
    |     ^^^^^^^^^^^^^
 
-error[E0599]: no method named `method2` found for enum `no_method_suggested_traits::Bar` in the current scope
+error[E0599]: no method named `method2` found for enum `Bar` in the current scope
   --> $DIR/no-method-suggested-traits.rs:54:40
    |
 LL |     no_method_suggested_traits::Bar::X.method2();
-   |                                        ^^^^^^^ method not found in `no_method_suggested_traits::Bar`
+   |                                        ^^^^^^^ method not found in `Bar`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
 note: `foo::Bar` defines an item `method2`, perhaps you need to implement it
@@ -184,11 +184,11 @@ note: `foo::Bar` defines an item `method2`, perhaps you need to implement it
 LL |     pub trait Bar {
    |     ^^^^^^^^^^^^^
 
-error[E0599]: no method named `method2` found for struct `Rc<&mut Box<&no_method_suggested_traits::Bar>>` in the current scope
+error[E0599]: no method named `method2` found for struct `Rc<&mut Box<&Bar>>` in the current scope
   --> $DIR/no-method-suggested-traits.rs:56:74
    |
 LL |     std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Bar::X)).method2();
-   |                                                                          ^^^^^^^ method not found in `Rc<&mut Box<&no_method_suggested_traits::Bar>>`
+   |                                                                          ^^^^^^^ method not found in `Rc<&mut Box<&Bar>>`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
 note: `foo::Bar` defines an item `method2`, perhaps you need to implement it
@@ -255,29 +255,29 @@ error[E0599]: no method named `method3` found for struct `Rc<&mut Box<&usize>>`
 LL |     std::rc::Rc::new(&mut Box::new(&1_usize)).method3();
    |                                               ^^^^^^^ method not found in `Rc<&mut Box<&usize>>`
 
-error[E0599]: no method named `method3` found for struct `no_method_suggested_traits::Foo` in the current scope
+error[E0599]: no method named `method3` found for struct `Foo` in the current scope
   --> $DIR/no-method-suggested-traits.rs:71:37
    |
 LL |     no_method_suggested_traits::Foo.method3();
-   |                                     ^^^^^^^ method not found in `no_method_suggested_traits::Foo`
+   |                                     ^^^^^^^ method not found in `Foo`
 
-error[E0599]: no method named `method3` found for struct `Rc<&mut Box<&no_method_suggested_traits::Foo>>` in the current scope
+error[E0599]: no method named `method3` found for struct `Rc<&mut Box<&Foo>>` in the current scope
   --> $DIR/no-method-suggested-traits.rs:72:71
    |
 LL |     std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Foo)).method3();
-   |                                                                       ^^^^^^^ method not found in `Rc<&mut Box<&no_method_suggested_traits::Foo>>`
+   |                                                                       ^^^^^^^ method not found in `Rc<&mut Box<&Foo>>`
 
-error[E0599]: no method named `method3` found for enum `no_method_suggested_traits::Bar` in the current scope
+error[E0599]: no method named `method3` found for enum `Bar` in the current scope
   --> $DIR/no-method-suggested-traits.rs:74:40
    |
 LL |     no_method_suggested_traits::Bar::X.method3();
-   |                                        ^^^^^^^ method not found in `no_method_suggested_traits::Bar`
+   |                                        ^^^^^^^ method not found in `Bar`
 
-error[E0599]: no method named `method3` found for struct `Rc<&mut Box<&no_method_suggested_traits::Bar>>` in the current scope
+error[E0599]: no method named `method3` found for struct `Rc<&mut Box<&Bar>>` in the current scope
   --> $DIR/no-method-suggested-traits.rs:75:74
    |
 LL |     std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Bar::X)).method3();
-   |                                                                          ^^^^^^^ method not found in `Rc<&mut Box<&no_method_suggested_traits::Bar>>`
+   |                                                                          ^^^^^^^ method not found in `Rc<&mut Box<&Bar>>`
 
 error: aborting due to 24 previous errors
 
index c31c8840381537217a3ac5273b2561718a1da352..ade479ed1022128a4bef62cabae71c1bccd4d10d 100644 (file)
@@ -24,11 +24,8 @@ LL |         extern crate std as Vec;
 ...
 LL | define_vec!();
    | ------------- in this macro invocation
-note: `Vec` could also refer to the struct defined here
+note: `Vec` could also refer to a struct from prelude
   --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
-   |
-LL |     pub use super::v1::*;
-   |             ^^^^^^^^^^^^
    = note: this error originates in the macro `define_vec` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 2 previous errors
index 5c52e7bcfab694f5c494fc7a3733be25facadba3..9be18286480113cb04682887824884706c221faf 100644 (file)
@@ -10,10 +10,10 @@ note: required by a bound in `foo`
    |
 LL | fn foo<T, K, W: Default, Z: Default>(t: T, k: K) -> Foo<T, K, W, Z> {
    |                 ^^^^^^^ required by this bound in `foo`
-help: consider specifying the type arguments in the function call
+help: consider giving `foo` an explicit type, where the type for type parameter `W` is specified
    |
-LL |     let foo = foo::<T, K, W, Z>(1, "");
-   |                  ++++++++++++++
+LL |     let foo: Foo<i32, &str, W, Z> = foo(1, "");
+   |            ++++++++++++++++++++++
 
 error[E0283]: type annotations needed for `Bar<i32, &str, Z>`
   --> $DIR/erase-type-params-in-label.rs:5:9
@@ -27,10 +27,10 @@ note: required by a bound in `bar`
    |
 LL | fn bar<T, K, Z: Default>(t: T, k: K) -> Bar<T, K, Z> {
    |                 ^^^^^^^ required by this bound in `bar`
-help: consider specifying the type arguments in the function call
+help: consider giving `bar` an explicit type, where the type for type parameter `Z` is specified
    |
-LL |     let bar = bar::<T, K, Z>(1, "");
-   |                  +++++++++++
+LL |     let bar: Bar<i32, &str, Z> = bar(1, "");
+   |            +++++++++++++++++++
 
 error: aborting due to 2 previous errors
 
index 79bee33280d2e45769cbc0e8a49e28e4d426b034..01b37f2acaa14444d7b043e2d1ab7c31572b7772 100644 (file)
@@ -12,9 +12,6 @@ LL |         .get(&"key".into())
              where T: ?Sized;
 note: required by a bound in `HashMap::<K, V, S>::get`
   --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
-   |
-LL |         K: Borrow<Q>,
-   |            ^^^^^^^^^ required by this bound in `HashMap::<K, V, S>::get`
 help: consider specifying the generic argument
    |
 LL |         .get::<Q>(&"key".into())
index d4eeda07366a8015c2a4c04374f6ee6b4fc32bf7..8eda71ec09bd3bf1410fb293eb00232808ea7508 100644 (file)
@@ -32,8 +32,8 @@ LL |     |x| String::from("x".as_ref());
    |
 help: consider giving this closure parameter an explicit type
    |
-LL |     |x: _| String::from("x".as_ref());
-   |       +++
+LL |     |x: /* Type */| String::from("x".as_ref());
+   |       ++++++++++++
 
 error[E0283]: type annotations needed
   --> $DIR/issue-72690.rs:12:26
diff --git a/src/test/ui/inline-const/expr-unsafe-err.mir.stderr b/src/test/ui/inline-const/expr-unsafe-err.mir.stderr
new file mode 100644 (file)
index 0000000..1bec41e
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
+  --> $DIR/expr-unsafe-err.rs:8:9
+   |
+LL |         require_unsafe();
+   |         ^^^^^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/inline-const/expr-unsafe-err.rs b/src/test/ui/inline-const/expr-unsafe-err.rs
new file mode 100644 (file)
index 0000000..adf05d3
--- /dev/null
@@ -0,0 +1,11 @@
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+#![feature(inline_const)]
+const unsafe fn require_unsafe() -> usize { 1 }
+
+fn main() {
+    const {
+        require_unsafe();
+        //~^ ERROR [E0133]
+    }
+}
diff --git a/src/test/ui/inline-const/expr-unsafe-err.thir.stderr b/src/test/ui/inline-const/expr-unsafe-err.thir.stderr
new file mode 100644 (file)
index 0000000..c971e8a
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0133]: call to unsafe function `require_unsafe` is unsafe and requires unsafe function or block
+  --> $DIR/expr-unsafe-err.rs:8:9
+   |
+LL |         require_unsafe();
+   |         ^^^^^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/inline-const/expr-unsafe.mir.stderr b/src/test/ui/inline-const/expr-unsafe.mir.stderr
new file mode 100644 (file)
index 0000000..1ab6e42
--- /dev/null
@@ -0,0 +1,14 @@
+warning: unnecessary `unsafe` block
+  --> $DIR/expr-unsafe.rs:12:13
+   |
+LL |             unsafe {}
+   |             ^^^^^^ unnecessary `unsafe` block
+   |
+note: the lint level is defined here
+  --> $DIR/expr-unsafe.rs:4:9
+   |
+LL | #![warn(unused_unsafe)]
+   |         ^^^^^^^^^^^^^
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/inline-const/expr-unsafe.rs b/src/test/ui/inline-const/expr-unsafe.rs
new file mode 100644 (file)
index 0000000..d71efd3
--- /dev/null
@@ -0,0 +1,16 @@
+// check-pass
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+#![warn(unused_unsafe)]
+#![feature(inline_const)]
+const unsafe fn require_unsafe() -> usize { 1 }
+
+fn main() {
+    unsafe {
+        const {
+            require_unsafe();
+            unsafe {}
+            //~^ WARNING unnecessary `unsafe` block
+        }
+    }
+}
diff --git a/src/test/ui/inline-const/expr-unsafe.thir.stderr b/src/test/ui/inline-const/expr-unsafe.thir.stderr
new file mode 100644 (file)
index 0000000..4737444
--- /dev/null
@@ -0,0 +1,17 @@
+warning: unnecessary `unsafe` block
+  --> $DIR/expr-unsafe.rs:12:13
+   |
+LL |     unsafe {
+   |     ------ because it's nested under this `unsafe` block
+...
+LL |             unsafe {}
+   |             ^^^^^^ unnecessary `unsafe` block
+   |
+note: the lint level is defined here
+  --> $DIR/expr-unsafe.rs:4:9
+   |
+LL | #![warn(unused_unsafe)]
+   |         ^^^^^^^^^^^^^
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/inline-const/pat-unsafe-err.rs b/src/test/ui/inline-const/pat-unsafe-err.rs
new file mode 100644 (file)
index 0000000..e290b43
--- /dev/null
@@ -0,0 +1,17 @@
+// ignore-test This is currently broken
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+
+#![allow(incomplete_features)]
+#![feature(inline_const_pat)]
+
+const unsafe fn require_unsafe() -> usize { 1 }
+
+fn main() {
+    match () {
+        const {
+            require_unsafe();
+            //~^ ERROR [E0133]
+        } => (),
+    }
+}
diff --git a/src/test/ui/inline-const/pat-unsafe.rs b/src/test/ui/inline-const/pat-unsafe.rs
new file mode 100644 (file)
index 0000000..bcf7f6e
--- /dev/null
@@ -0,0 +1,22 @@
+// ignore-test This is currently broken
+// check-pass
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+
+#![allow(incomplete_features)]
+#![warn(unused_unsafe)]
+#![feature(inline_const_pat)]
+
+const unsafe fn require_unsafe() -> usize { 1 }
+
+fn main() {
+    unsafe {
+        match () {
+            const {
+                require_unsafe();
+                unsafe {}
+                //~^ WARNING unnecessary `unsafe` block
+            } => (),
+        }
+    }
+}
index 94f41c92598866d4aaef7e8a1162a7de304aa3c9..034d22591b38a582360f86a5367183167019c8c6 100644 (file)
@@ -16,9 +16,6 @@ LL |     catch_unwind(|| { x.set(23); });
    |                  ^^
 note: required by a bound in `catch_unwind`
   --> $SRC_DIR/std/src/panic.rs:LL:COL
-   |
-LL | pub fn catch_unwind<F: FnOnce() -> R + UnwindSafe, R>(f: F) -> Result<R> {
-   |                                        ^^^^^^^^^^ required by this bound in `catch_unwind`
 
 error: aborting due to previous error
 
index 3720528ad4e402b0e4feb3131b1213ee50812ead..fd7d061b6b2e5627459e5ea11968c9539c345ff8 100644 (file)
@@ -37,9 +37,6 @@ LL |     const_eval_select((), 42, 0xDEADBEEF);
    = note: wrap the `{integer}` in a closure with no arguments: `|| { /* code */ }`
 note: required by a bound in `const_eval_select`
   --> $SRC_DIR/core/src/intrinsics.rs:LL:COL
-   |
-LL |         F: FnOnce<ARG, Output = RET>;
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select`
 
 error: this argument must be a function item
   --> $DIR/const-eval-select-bad.rs:10:31
@@ -62,9 +59,6 @@ LL |     const_eval_select((), 42, 0xDEADBEEF);
    = note: wrap the `{integer}` in a closure with no arguments: `|| { /* code */ }`
 note: required by a bound in `const_eval_select`
   --> $SRC_DIR/core/src/intrinsics.rs:LL:COL
-   |
-LL |         G: FnOnce<ARG, Output = RET>,
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select`
 
 error[E0271]: expected `fn(i32) -> bool {bar}` to be a fn item that returns `i32`, but it returns `bool`
   --> $DIR/const-eval-select-bad.rs:32:34
@@ -76,9 +70,6 @@ LL |     const_eval_select((1,), foo, bar);
    |
 note: required by a bound in `const_eval_select`
   --> $SRC_DIR/core/src/intrinsics.rs:LL:COL
-   |
-LL |         G: FnOnce<ARG, Output = RET>,
-   |                        ^^^^^^^^^^^^ required by this bound in `const_eval_select`
 
 error[E0631]: type mismatch in function arguments
   --> $DIR/const-eval-select-bad.rs:37:32
@@ -95,9 +86,6 @@ LL |     const_eval_select((true,), foo, baz);
               found function signature `fn(i32) -> _`
 note: required by a bound in `const_eval_select`
   --> $SRC_DIR/core/src/intrinsics.rs:LL:COL
-   |
-LL |         F: FnOnce<ARG, Output = RET>;
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select`
 
 error: this argument must be a `const fn`
   --> $DIR/const-eval-select-bad.rs:42:29
index 92f2ccb6544b10c2ba81744c921b4b945fd91d15..30c380152a5e6b88cf871a26dd82e1cf55f3403c 100644 (file)
@@ -55,8 +55,10 @@ error[E0271]: type mismatch resolving `<Demo as TraitWAssocConst>::A == 32`
   --> $DIR/issue-105330.rs:12:11
    |
 LL |     foo::<Demo>()();
-   |           ^^^^ types differ
+   |           ^^^^ expected `32`, found `<Demo as TraitWAssocConst>::A`
    |
+   = note: expected constant `32`
+              found constant `<Demo as TraitWAssocConst>::A`
 note: required by a bound in `foo`
   --> $DIR/issue-105330.rs:11:28
    |
@@ -89,8 +91,10 @@ error[E0271]: type mismatch resolving `<Demo as TraitWAssocConst>::A == 32`
   --> $DIR/issue-105330.rs:19:11
    |
 LL |     foo::<Demo>();
-   |           ^^^^ types differ
+   |           ^^^^ expected `32`, found `<Demo as TraitWAssocConst>::A`
    |
+   = note: expected constant `32`
+              found constant `<Demo as TraitWAssocConst>::A`
 note: required by a bound in `foo`
   --> $DIR/issue-105330.rs:11:28
    |
index 3ce659ccd14da3ec29b531edb83eac3fb776910e..7fa06825f0f00c38bccf22c140a3752649cf5368 100644 (file)
@@ -11,6 +11,14 @@ LL |         (&[hd1, ..], &[hd2, ..])
    |            --- ...and here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider borrowing the pattern binding
+   |
+LL |         (&[], &[ref hd, ..]) | (&[hd, ..], &[])
+   |                 +++
+help: consider borrowing the pattern binding
+   |
+LL |         (&[ref hd1, ..], &[hd2, ..])
+   |            +++
 
 error[E0508]: cannot move out of type `[T]`, a non-copy slice
   --> $DIR/issue-12567.rs:2:11
@@ -25,6 +33,14 @@ LL |         (&[hd1, ..], &[hd2, ..])
    |                        --- ...and here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider borrowing the pattern binding
+   |
+LL |         (&[], &[ref hd, ..]) | (&[hd, ..], &[])
+   |                 +++
+help: consider borrowing the pattern binding
+   |
+LL |         (&[hd1, ..], &[ref hd2, ..])
+   |                        +++
 
 error: aborting due to 2 previous errors
 
index a191afd7980c65865392a4367b064fea46a8cff4..f8375d4ef9014ba6e7dcfe0ca100c93ee114a47d 100644 (file)
@@ -9,11 +9,8 @@ note: an implementation of `Not` might be missing for `BytePos`
    |
 LL | pub struct BytePos(pub u32);
    | ^^^^^^^^^^^^^^^^^^ must implement `Not`
-note: the following trait must be implemented
+note: the trait `Not` must be implemented
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
-   |
-LL | pub trait Not {
-   | ^^^^^^^^^^^^^
    = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
index 7928b3fba2785fd2105560dd620fcba3316b9464..132e2b101a5ff1d4c207e69fa9e71951f41cb451 100644 (file)
@@ -4,13 +4,6 @@ error[E0107]: missing generics for struct `Box`
 LL | fn fn1(0: Box) {}
    |           ^^^ expected at least 1 generic argument
    |
-note: struct defined here, with at least 1 generic parameter: `T`
-  --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
-   |
-LL | pub struct Box<
-   |            ^^^
-LL |     T: ?Sized,
-   |     -
 help: add missing generic argument
    |
 LL | fn fn1(0: Box<T>) {}
index 8524a62a0a42d2cb750114c81087f487b554b2e6..60f5190dbd0d640f790cf33863fdf06bfd1dc9fa 100644 (file)
@@ -5,11 +5,6 @@ LL |     panic!(std::default::Default::default());
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `M` declared on the function `begin_panic`
    |
    = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: consider specifying the generic argument
-  --> $SRC_DIR/std/src/panic.rs:LL:COL
-   |
-LL |         $crate::rt::begin_panic::<M>($msg)
-   |                                +++++
 
 error: aborting due to previous error
 
index 16678c8c8a9028f655b95231e70b1672a0d75574..81592320a2791b414f88788ba6c2e99c5ce21e5b 100644 (file)
@@ -3,11 +3,9 @@ error[E0573]: expected type, found variant `NoResult`
    |
 LL |     fn new() -> NoResult<MyEnum, String> {
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^
+  --> $SRC_DIR/core/src/result.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL | pub enum Result<T, E> {
-   | --------------------- similarly named enum `Result` defined here
+   = note: similarly named enum `Result` defined here
    |
 help: try using the variant's enum
    |
@@ -57,11 +55,9 @@ error[E0573]: expected type, found variant `NoResult`
    |
 LL | fn newer() -> NoResult<foo::MyEnum, String> {
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  --> $SRC_DIR/core/src/result.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL | pub enum Result<T, E> {
-   | --------------------- similarly named enum `Result` defined here
+   = note: similarly named enum `Result` defined here
    |
 help: try using the variant's enum
    |
index efaaeeda2fab6798d18b0b99e1f2eee73d8f9597..b37811e19559c3bdc82fe6c1036e2b3f8883040c 100644 (file)
@@ -9,9 +9,6 @@ LL |     (|| Box::new(*(&[0][..])))();
    = help: the trait `Sized` is not implemented for `[{integer}]`
 note: required by a bound in `Box::<T>::new`
   --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
-   |
-LL | impl<T> Box<T> {
-   |      ^ required by this bound in `Box::<T>::new`
 
 error: aborting due to previous error
 
index 605ff3829d19a6a70e88f7f83fa22763a3c6e2e4..5e0589eed435d0240aefb3f4eddf4f34506f326e 100644 (file)
@@ -6,8 +6,8 @@ LL |     let x;
    |
 help: consider giving `x` an explicit type
    |
-LL |     let x: _;
-   |          +++
+LL |     let x: /* Type */;
+   |          ++++++++++++
 
 error: aborting due to previous error
 
index 4711a3f3ce07ef57db1388c1320a73036051634d..bbf79366244a01d7381b2d9504b47742bbe86c25 100644 (file)
@@ -5,12 +5,6 @@ LL |     x: Box<'a, isize>
    |        ^^^ -- help: remove this lifetime argument
    |        |
    |        expected 0 lifetime arguments
-   |
-note: struct defined here, with 0 lifetime parameters
-  --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
-   |
-LL | pub struct Box<
-   |            ^^^
 
 error: aborting due to previous error
 
index 3f9b3be98517946f728235e3e34d2956ce678b6c..1c5b76fbfc10b1e730ce7c738f264d4d5a05c998 100644 (file)
@@ -1,16 +1,11 @@
 error[E0277]: the trait bound `X: Ord` is not satisfied
-  --> $DIR/issue-20162.rs:5:5
+  --> $DIR/issue-20162.rs:5:7
    |
 LL |     b.sort();
-   |     ^ ---- required by a bound introduced by this call
-   |     |
-   |     the trait `Ord` is not implemented for `X`
+   |       ^^^^ the trait `Ord` is not implemented for `X`
    |
 note: required by a bound in `slice::<impl [T]>::sort`
   --> $SRC_DIR/alloc/src/slice.rs:LL:COL
-   |
-LL |         T: Ord,
-   |            ^^^ required by this bound in `slice::<impl [T]>::sort`
 help: consider annotating `X` with `#[derive(Ord)]`
    |
 LL | #[derive(Ord)]
index 9d3bb8b924d6161c3d2e781ef459eee6c0ab7f27..3ae952546a62dd0d652b032fa346917fca174a08 100644 (file)
@@ -7,9 +7,6 @@ LL |     fn iceman(c: Vec<[i32]>) {}
    = help: the trait `Sized` is not implemented for `[i32]`
 note: required by a bound in `Vec`
   --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
-   |
-LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
-   |                ^ required by this bound in `Vec`
 
 error: aborting due to previous error
 
index 31a8ca5fbfac887a3b0b01e5eab249ac87b113da..c75038b6169c0a227995a7c9de27ff581ca6d42a 100644 (file)
@@ -8,8 +8,8 @@ LL |     x.clone();
    |
 help: consider giving `x` an explicit type
    |
-LL |     let x: _ = panic!();
-   |          +++
+LL |     let x: /* Type */ = panic!();
+   |          ++++++++++++
 
 error: aborting due to previous error
 
index 4e010a13653e7796c0723c35125c33bdb5ce60b1..2d60b18b1f208eae86ab14800e0e4053f93304d4 100644 (file)
@@ -4,7 +4,13 @@ error[E0283]: type annotations needed: cannot satisfy `&'a T: Foo`
 LL |     where &'a T : Foo,
    |                   ^^^
    |
-   = note: cannot satisfy `&'a T: Foo`
+note: multiple `impl`s or `where` clauses satisfying `&'a T: Foo` found
+  --> $DIR/issue-21974.rs:11:19
+   |
+LL |     where &'a T : Foo,
+   |                   ^^^
+LL |           &'b T : Foo
+   |                   ^^^
 
 error: aborting due to previous error
 
index dc8b34a70c3241de9f930c078e6670aa0b0a41a7..014eb2897b488871c5f0ea563ab1a30bea8119fd 100644 (file)
@@ -13,11 +13,6 @@ error[E0107]: missing generics for trait `Fn`
 LL |     println!("{:?}",(vfnfer[0] as dyn Fn)(3));
    |                                       ^^ expected 1 generic argument
    |
-note: trait defined here, with 1 generic parameter: `Args`
-  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
-   |           ^^ ----
 help: add missing generic argument
    |
 LL |     println!("{:?}",(vfnfer[0] as dyn Fn<Args>)(3));
index 22c4055f54be31f93e2049780682bdf5a5bf255b..8f934481d85db6be1d86ae91290db0ab1fc87930 100644 (file)
@@ -9,9 +9,6 @@ LL |     "".chars().fold(|_, _| (), ());
    = help: the trait `FnMut<(_, char)>` is not implemented for `()`
 note: required by a bound in `fold`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |         F: FnMut(B, Self::Item) -> B,
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Iterator::fold`
 
 error: aborting due to previous error
 
index a42e35c4cad5c922f526b92b65dd202b08612179..0e73a51faed9ac8bf07d4e299f465ab11f114fa3 100644 (file)
@@ -19,8 +19,8 @@ LL |         1 => |c| c + 1,
    |
 help: consider giving this closure parameter an explicit type
    |
-LL |         1 => |c: _| c + 1,
-   |                +++
+LL |         1 => |c: /* Type */| c + 1,
+   |                ++++++++++++
 
 error: aborting due to 2 previous errors
 
index 8f3b2ac73199ccec1afced236ae6f1c0f0452522..50d7f988e194cdcd30d2fc72c9dd6a639eaebcd4 100644 (file)
@@ -4,7 +4,11 @@ error[E0283]: type annotations needed: cannot satisfy `T0: Trait0<'l0>`
 LL | impl <'l0, 'l1, T0> Trait1<'l0, T0> for bool where T0 : Trait0<'l0>, T0 : Trait0<'l1> {}
    |                                                         ^^^^^^^^^^^
    |
-   = note: cannot satisfy `T0: Trait0<'l0>`
+note: multiple `impl`s or `where` clauses satisfying `T0: Trait0<'l0>` found
+  --> $DIR/issue-24424.rs:4:57
+   |
+LL | impl <'l0, 'l1, T0> Trait1<'l0, T0> for bool where T0 : Trait0<'l0>, T0 : Trait0<'l1> {}
+   |                                                         ^^^^^^^^^^^       ^^^^^^^^^^^
 
 error: aborting due to previous error
 
index 9a38d49cd0c9624b4cef872e80f2ec750a0f0e11..7a0ca888d7471c3c87d81fa5ab6d5a418dedb47f 100644 (file)
@@ -3,11 +3,9 @@ error[E0530]: match bindings cannot shadow unit variants
    |
 LL |         None @ _ => {}
    |         ^^^^ cannot be named the same as a unit variant
+  --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
    |
-  ::: $SRC_DIR/std/src/prelude/mod.rs:LL:COL
-   |
-LL |     pub use super::v1::*;
-   |             ------------ the unit variant `None` is defined here
+   = note: the unit variant `None` is defined here
 
 error[E0530]: match bindings cannot shadow constants
   --> $DIR/issue-27033.rs:7:9
index e9d934332f171f6402a5f296c5bc780903aef40a..7808cbf8aa10840644bb7e85e8c9a81045adb8fc 100644 (file)
@@ -1,8 +1,8 @@
-error[E0599]: no function or associated item named `new_undirected` found for struct `issue_30123_aux::Graph<i32, i32>` in the current scope
+error[E0599]: no function or associated item named `new_undirected` found for struct `Graph<i32, i32>` in the current scope
   --> $DIR/issue-30123.rs:7:33
    |
 LL |     let ug = Graph::<i32, i32>::new_undirected();
-   |                                 ^^^^^^^^^^^^^^ function or associated item not found in `issue_30123_aux::Graph<i32, i32>`
+   |                                 ^^^^^^^^^^^^^^ function or associated item not found in `Graph<i32, i32>`
    |
    = note: the function or associated item was found for
            - `issue_30123_aux::Graph<N, E, Undirected>`
index a4c455ca1927e3fc225c5b09bf56dd344b46511c..2b142f688ecb9dcc8b844d6840767393999bc579 100644 (file)
@@ -9,9 +9,6 @@ LL | |     });
    |
 note: associated function defined here
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |     fn fold<B, F>(mut self, init: B, mut f: F) -> B
-   |        ^^^^
 help: provide the argument
    |
 LL ~     needlesArr.iter().fold(|x, y| {
index 04efa27189b746e533439c6548818dc7d1e4b17d..f678df5b42b60d927cf4386889a745d7a553e73a 100644 (file)
@@ -4,12 +4,11 @@ pub fn get_tok(it: &mut IntoIter<u8>) {
     let mut found_e = false;
 
     let temp: Vec<u8> = it
-        //~^ ERROR to be an iterator that yields `&_`, but it yields `u8`
         .take_while(|&x| {
             found_e = true;
             false
         })
-        .cloned()
+        .cloned() //~ ERROR to be an iterator that yields `&_`, but it yields `u8`
         .collect(); //~ ERROR the method
 }
 
index 58d9b564427a723fd3583c954a26eae550fbbdd4..f3be99f9bcb4b3e09efcd9029b355d188c5ba5ec 100644 (file)
@@ -1,46 +1,43 @@
-error[E0271]: expected `TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:8:21: 8:25]>` to be an iterator that yields `&_`, but it yields `u8`
-  --> $DIR/issue-31173.rs:6:25
+error[E0271]: expected `TakeWhile<&mut IntoIter<u8>, [closure@issue-31173.rs:7:21]>` to be an iterator that yields `&_`, but it yields `u8`
+  --> $DIR/issue-31173.rs:11:10
    |
-LL |       let temp: Vec<u8> = it
-   |  _________________________^
-LL | |
-LL | |         .take_while(|&x| {
-LL | |             found_e = true;
-LL | |             false
-LL | |         })
-   | |__________^ expected reference, found `u8`
-LL |           .cloned()
-   |            ------ required by a bound introduced by this call
+LL |         .cloned()
+   |          ^^^^^^ expected reference, found `u8`
    |
    = note: expected reference `&_`
                    found type `u8`
+note: the method call chain might not have had the expected associated types
+  --> $DIR/issue-31173.rs:3:20
+   |
+LL |   pub fn get_tok(it: &mut IntoIter<u8>) {
+   |                      ^^^^^^^^^^^^^^^^^ `Iterator::Item` is `u8` here
+...
+LL |           .take_while(|&x| {
+   |  __________-
+LL | |             found_e = true;
+LL | |             false
+LL | |         })
+   | |__________- `Iterator::Item` remains `u8` here
 note: required by a bound in `cloned`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |         Self: Sized + Iterator<Item = &'a T>,
-   |                                ^^^^^^^^^^^^ required by this bound in `Iterator::cloned`
 
-error[E0599]: the method `collect` exists for struct `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:8:21: 8:25]>>`, but its trait bounds were not satisfied
-  --> $DIR/issue-31173.rs:13:10
+error[E0599]: the method `collect` exists for struct `Cloned<TakeWhile<&mut IntoIter<u8>, [closure@issue-31173.rs:7:21]>>`, but its trait bounds were not satisfied
+  --> $DIR/issue-31173.rs:12:10
    |
 LL |         .collect();
-   |          ^^^^^^^ method cannot be called on `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:8:21: 8:25]>>` due to unsatisfied trait bounds
-   |
-  ::: $SRC_DIR/core/src/iter/adapters/take_while.rs:LL:COL
-   |
-LL | pub struct TakeWhile<I, P> {
-   | -------------------------- doesn't satisfy `<_ as Iterator>::Item = &_`
+   |          ^^^^^^^ method cannot be called due to unsatisfied trait bounds
+  --> $SRC_DIR/core/src/iter/adapters/take_while.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/iter/adapters/cloned.rs:LL:COL
+   = note: doesn't satisfy `<_ as Iterator>::Item = &_`
+  --> $SRC_DIR/core/src/iter/adapters/cloned.rs:LL:COL
    |
-LL | pub struct Cloned<I> {
-   | -------------------- doesn't satisfy `_: Iterator`
+   = note: doesn't satisfy `_: Iterator`
    |
    = note: the following trait bounds were not satisfied:
-           `<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:8:21: 8:25]> as Iterator>::Item = &_`
-           which is required by `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:8:21: 8:25]>>: Iterator`
-           `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:8:21: 8:25]>>: Iterator`
-           which is required by `&mut Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:8:21: 8:25]>>: Iterator`
+           `<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:7:21: 7:25]> as Iterator>::Item = &_`
+           which is required by `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:7:21: 7:25]>>: Iterator`
+           `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:7:21: 7:25]>>: Iterator`
+           which is required by `&mut Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:7:21: 7:25]>>: Iterator`
 
 error: aborting due to 2 previous errors
 
index 5a758c7002b92b6a54deb76a08a8fed43667611a..b8362499b2d0aae7aa06c2c96410d6a8e130450b 100644 (file)
@@ -6,11 +6,9 @@ LL |         #[derive_Clone]
 ...
 LL | foo!();
    | ------ in this macro invocation
+  --> $SRC_DIR/core/src/macros/mod.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/macros/mod.rs:LL:COL
-   |
-LL |     pub macro derive_const($item:item) {
-   |     ---------------------- similarly named attribute macro `derive_const` defined here
+   = note: similarly named attribute macro `derive_const` defined here
    |
    = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
 
@@ -19,11 +17,9 @@ error: cannot find attribute `derive_Clone` in this scope
    |
 LL |     #[derive_Clone]
    |       ^^^^^^^^^^^^ help: an attribute macro with a similar name exists: `derive_const`
+  --> $SRC_DIR/core/src/macros/mod.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/macros/mod.rs:LL:COL
-   |
-LL |     pub macro derive_const($item:item) {
-   |     ---------------------- similarly named attribute macro `derive_const` defined here
+   = note: similarly named attribute macro `derive_const` defined here
 
 error: aborting due to 2 previous errors
 
index 8430e85df871514f1269f49b6c7b9bccfe2b6efa..e3b6dcf55a7448296ea39c39de2c428b40e59ff2 100644 (file)
@@ -3,7 +3,7 @@
 use std::collections::HashMap;
 
 fn main() {
-    for _ in HashMap::new().iter().cloned() {} //~ ERROR expected `std::collections::hash_map::Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
-    //~^ ERROR expected `std::collections::hash_map::Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
-    //~| ERROR expected `std::collections::hash_map::Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
+    for _ in HashMap::new().iter().cloned() {} //~ ERROR expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
+    //~^ ERROR expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
+    //~| ERROR expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
 }
index c28986a29854b0dfa4a241115a2391e980bfe4ba..668eaabca4c463d450fbe59ed71e04280dd0c1e4 100644 (file)
@@ -1,20 +1,22 @@
-error[E0271]: expected `std::collections::hash_map::Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
-  --> $DIR/issue-33941.rs:6:14
+error[E0271]: expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
+  --> $DIR/issue-33941.rs:6:36
    |
 LL |     for _ in HashMap::new().iter().cloned() {}
-   |              ^^^^^^^^^^^^^^^^^^^^^ ------ required by a bound introduced by this call
-   |              |
-   |              expected reference, found tuple
+   |                                    ^^^^^^ expected reference, found tuple
    |
    = note: expected reference `&_`
                   found tuple `(&_, &_)`
+note: the method call chain might not have had the expected associated types
+  --> $DIR/issue-33941.rs:6:29
+   |
+LL |     for _ in HashMap::new().iter().cloned() {}
+   |              -------------- ^^^^^^ `Iterator::Item` is `(&_, &_)` here
+   |              |
+   |              this expression has type `HashMap<_, _>`
 note: required by a bound in `cloned`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |         Self: Sized + Iterator<Item = &'a T>,
-   |                                ^^^^^^^^^^^^ required by this bound in `Iterator::cloned`
 
-error[E0271]: expected `std::collections::hash_map::Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
+error[E0271]: expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
   --> $DIR/issue-33941.rs:6:14
    |
 LL |     for _ in HashMap::new().iter().cloned() {}
@@ -25,7 +27,7 @@ LL |     for _ in HashMap::new().iter().cloned() {}
    = note: required for `Cloned<std::collections::hash_map::Iter<'_, _, _>>` to implement `Iterator`
    = note: required for `Cloned<std::collections::hash_map::Iter<'_, _, _>>` to implement `IntoIterator`
 
-error[E0271]: expected `std::collections::hash_map::Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
+error[E0271]: expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
   --> $DIR/issue-33941.rs:6:14
    |
 LL |     for _ in HashMap::new().iter().cloned() {}
index 3188cd80cca8325037f4bf9f6a139b993b642021..9d2c315e4dbca92721686334dc03c64e4135aa47 100644 (file)
@@ -13,20 +13,25 @@ LL |     let sr: Vec<(u32, _, _)> = vec![];
    |                            +
 
 error[E0277]: a value of type `Vec<(u32, _, _)>` cannot be built from an iterator over elements of type `()`
-  --> $DIR/issue-34334.rs:5:33
+  --> $DIR/issue-34334.rs:5:87
    |
 LL |     let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_receiver)| {}).collect();
-   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------- required by a bound introduced by this call
-   |                                 |
-   |                                 value of type `Vec<(u32, _, _)>` cannot be built from `std::iter::Iterator<Item=()>`
+   |                                                                                       ^^^^^^^ value of type `Vec<(u32, _, _)>` cannot be built from `std::iter::Iterator<Item=()>`
    |
    = help: the trait `FromIterator<()>` is not implemented for `Vec<(u32, _, _)>`
    = help: the trait `FromIterator<T>` is implemented for `Vec<T>`
+note: the method call chain might not have had the expected associated types
+  --> $DIR/issue-34334.rs:5:43
+   |
+LL |     let sr: Vec<(u32, _, _) = vec![];
+   |                               ------ this expression has type `Vec<(_, _, _)>`
+...
+LL |     let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_receiver)| {}).collect();
+   |                                    ------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Iterator::Item` changed to `()` here
+   |                                    |
+   |                                    `Iterator::Item` is `&(_, _, _)` here
 note: required by a bound in `collect`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |     fn collect<B: FromIterator<Self::Item>>(self) -> B
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Iterator::collect`
 
 error: aborting due to 2 previous errors
 
index 045819061c1b044e196240b28e544f1eb0e86c1d..f2bf22227dbe47d787a16de1b781b7fd74927122 100644 (file)
@@ -13,7 +13,7 @@ LL |         };
 LL |         x.zero()
    |         ^ value used here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `x`
+note: `Foo::zero` takes ownership of the receiver `self`, which moves `x`
   --> $DIR/issue-34721.rs:4:13
    |
 LL |     fn zero(self) -> Self;
index 23090c1ed7866ce448e5f19427d7009be18f6d97..4d505784b86548137db79c04bdb22298b3f03433 100644 (file)
@@ -12,9 +12,6 @@ LL |     let a = std::sys::imp::process::process_common::StdioPipes { ..panic!()
    |
 note: the module `sys` is defined here
   --> $SRC_DIR/std/src/lib.rs:LL:COL
-   |
-LL | mod sys;
-   | ^^^^^^^
 
 error: aborting due to 2 previous errors
 
index 0a5a6b80e9b23999993a8b464a33c0c2fa27958f..e15eed6561234e91db2f6e3ab7133a630db45881 100644 (file)
@@ -2,10 +2,12 @@ error[E0507]: cannot move out of index of `Vec<String>`
   --> $DIR/issue-40402-1.rs:9:13
    |
 LL |     let e = f.v[0];
-   |             ^^^^^^
-   |             |
-   |             move occurs because value has type `String`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&f.v[0]`
+   |             ^^^^^^ move occurs because value has type `String`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     let e = &f.v[0];
+   |             +
 
 error: aborting due to previous error
 
index b6049f967ff406060e00cf45c3ecd80395178d61..1bc554efb5c3d5bfacf56e398ee2fc2a072a749d 100644 (file)
@@ -2,12 +2,16 @@ error[E0507]: cannot move out of index of `Vec<(String, String)>`
   --> $DIR/issue-40402-2.rs:5:18
    |
 LL |     let (a, b) = x[0];
-   |          -  -    ^^^^ help: consider borrowing here: `&x[0]`
+   |          -  -    ^^^^
    |          |  |
    |          |  ...and here
    |          data moved here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider borrowing here
+   |
+LL |     let (a, b) = &x[0];
+   |                  +
 
 error: aborting due to previous error
 
index fd694df30457ec11998188b8c0d61946cfaab133..00c375f8d2acfaad1da084e0f1b1e5a43c87b9e3 100644 (file)
@@ -5,7 +5,7 @@ LL | pub struct Iterate<T, F> {
    | ------------------------ method `iter` not found for this struct
 ...
 LL |     println!("{:?}", a.iter().take(10).collect::<Vec<usize>>());
-   |                        ^^^^ method not found in `Iterate<{integer}, [closure@$DIR/issue-41880.rs:26:24: 26:27]>`
+   |                        ^^^^ method not found in `Iterate<{integer}, [closure@issue-41880.rs:26:24]>`
 
 error: aborting due to previous error
 
index 7fd36676df8c17c15d84ab81d3609bd13661f8bb..da3e62e35dc81b804a35254dfe8f9797e619606c 100644 (file)
@@ -10,9 +10,6 @@ LL |     b"".starts_with(stringify!(foo))
               found reference `&'static str`
 note: associated function defined here
   --> $SRC_DIR/core/src/slice/mod.rs:LL:COL
-   |
-LL |     pub fn starts_with(&self, needle: &[T]) -> bool
-   |            ^^^^^^^^^^^
    = note: this error originates in the macro `stringify` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
index 44ec626dea5fc7f2fc6248451a00c32d74eaf903..d8a833a86f511a7c9636baa4fb6c20a2efd29eee 100644 (file)
@@ -13,9 +13,6 @@ LL |     let _: Box<F> = Box::new(|| ());
    = help: every closure has a distinct type and so could not always match the caller-chosen type of parameter `F`
 note: associated function defined here
   --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
-   |
-LL |     pub fn new(x: T) -> Self {
-   |            ^^^
 
 error: aborting due to previous error
 
index e5b671d7b7ab0b71bbf6e871864094dd35c6ed2a..3aaf5fb3f3e3a56ad455db915356733b45482d61 100644 (file)
@@ -9,11 +9,8 @@ LL |     for l in bad_letters {
 LL |     bad_letters.push('s');
    |     ^^^^^^^^^^^^^^^^^^^^^ value borrowed here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `bad_letters`
+note: `into_iter` takes ownership of the receiver `self`, which moves `bad_letters`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-   |
-LL |     fn into_iter(self) -> Self::IntoIter;
-   |                  ^^^^
 help: consider iterating over a slice of the `Vec<char>`'s content to avoid moving into the `for` loop
    |
 LL |     for l in &bad_letters {
index ef178bbd155388f94e8b832d5c48c2a6bb65ade4..386ac794d7db32f77e643edb15d9e599a69d6cad 100644 (file)
@@ -10,11 +10,8 @@ LL |     let _closure = || orig;
    |                    |
    |                    value used here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `orig`
+note: `into_iter` takes ownership of the receiver `self`, which moves `orig`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-   |
-LL |     fn into_iter(self) -> Self::IntoIter;
-   |                  ^^^^
 help: consider iterating over a slice of the `Vec<bool>`'s content to avoid moving into the `for` loop
    |
 LL |     for _val in &orig {}
index ce38c3320bb354ac11ec64c6058de2cc14254788..cec482a53baa91b3e962056d017c836247f8742a 100644 (file)
@@ -1,34 +1,39 @@
 error[E0277]: a value of type `Vec<f64>` cannot be built from an iterator over elements of type `&f64`
-  --> $DIR/issue-66923-show-error-for-correct-call.rs:8:24
+  --> $DIR/issue-66923-show-error-for-correct-call.rs:8:39
    |
 LL |     let x2: Vec<f64> = x1.into_iter().collect();
-   |                        ^^^^^^^^^^^^^^ ------- required by a bound introduced by this call
-   |                        |
-   |                        value of type `Vec<f64>` cannot be built from `std::iter::Iterator<Item=&f64>`
+   |                                       ^^^^^^^ value of type `Vec<f64>` cannot be built from `std::iter::Iterator<Item=&f64>`
    |
    = help: the trait `FromIterator<&f64>` is not implemented for `Vec<f64>`
    = help: the trait `FromIterator<T>` is implemented for `Vec<T>`
+note: the method call chain might not have had the expected associated types
+  --> $DIR/issue-66923-show-error-for-correct-call.rs:8:27
+   |
+LL |     let x1: &[f64] = &v;
+   |                      -- this expression has type `&Vec<f64>`
+LL |     let x2: Vec<f64> = x1.into_iter().collect();
+   |                           ^^^^^^^^^^^ `Iterator::Item` is `&f64` here
 note: required by a bound in `collect`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |     fn collect<B: FromIterator<Self::Item>>(self) -> B
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Iterator::collect`
 
 error[E0277]: a value of type `Vec<f64>` cannot be built from an iterator over elements of type `&f64`
-  --> $DIR/issue-66923-show-error-for-correct-call.rs:12:14
+  --> $DIR/issue-66923-show-error-for-correct-call.rs:12:29
    |
 LL |     let x3 = x1.into_iter().collect::<Vec<f64>>();
-   |              ^^^^^^^^^^^^^^ ------- required by a bound introduced by this call
-   |              |
-   |              value of type `Vec<f64>` cannot be built from `std::iter::Iterator<Item=&f64>`
+   |                             ^^^^^^^ value of type `Vec<f64>` cannot be built from `std::iter::Iterator<Item=&f64>`
    |
    = help: the trait `FromIterator<&f64>` is not implemented for `Vec<f64>`
    = help: the trait `FromIterator<T>` is implemented for `Vec<T>`
+note: the method call chain might not have had the expected associated types
+  --> $DIR/issue-66923-show-error-for-correct-call.rs:12:17
+   |
+LL |     let x1: &[f64] = &v;
+   |                      -- this expression has type `&Vec<f64>`
+...
+LL |     let x3 = x1.into_iter().collect::<Vec<f64>>();
+   |                 ^^^^^^^^^^^ `Iterator::Item` is `&f64` here
 note: required by a bound in `collect`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |     fn collect<B: FromIterator<Self::Item>>(self) -> B
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Iterator::collect`
 
 error: aborting due to 2 previous errors
 
index f1ab0ad26d7084353d96d0dd5421ce21f666fa42..c983026995b20b8b91992006de95ee9071f7d770 100644 (file)
@@ -3,11 +3,9 @@ error[E0412]: cannot find type `Fo` in this scope
    |
 LL | impl Fo {
    |      ^^ help: a trait with a similar name exists: `Fn`
+  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
-   | -------------------------------------- similarly named trait `Fn` defined here
+   = note: similarly named trait `Fn` defined here
 
 error: aborting due to previous error
 
index 767571cddbeea954c660cf9fe5f632bc0e1035be..572414df2bf9d6af0b37498610f95f9529cf0060 100644 (file)
@@ -10,11 +10,8 @@ LL |     for n in v {
 LL |     for n in v {
    |              ^ value used here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `v`
+note: `into_iter` takes ownership of the receiver `self`, which moves `v`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-   |
-LL |     fn into_iter(self) -> Self::IntoIter;
-   |                  ^^^^
 help: consider creating a fresh reborrow of `v` here
    |
 LL |     for n in &mut *v {
index 4c424999b754d5e867f0e402da5b3f318b1f33f0..99d0d9bd735532bfc8a299ba1a7d9cde7a42dc0d 100644 (file)
@@ -3,5 +3,4 @@ fn main() {
     //~^ ERROR an array of type `[u32; 10]` cannot be built directly from an iterator
     //~| NOTE try collecting into a `Vec<{integer}>`, then using `.try_into()`
     //~| NOTE required by a bound in `collect`
-    //~| NOTE required by a bound introduced by this call
 }
index 544b1da178a3d96bfed1d5f654444b110d7d07d2..e38745cc10e1f3840e1081acc2e500700d827d15 100644 (file)
@@ -1,17 +1,12 @@
 error[E0277]: an array of type `[u32; 10]` cannot be built directly from an iterator
-  --> $DIR/collect-into-array.rs:2:31
+  --> $DIR/collect-into-array.rs:2:39
    |
 LL |     let whatever: [u32; 10] = (0..10).collect();
-   |                               ^^^^^^^ ------- required by a bound introduced by this call
-   |                               |
-   |                               try collecting into a `Vec<{integer}>`, then using `.try_into()`
+   |                                       ^^^^^^^ try collecting into a `Vec<{integer}>`, then using `.try_into()`
    |
    = help: the trait `FromIterator<{integer}>` is not implemented for `[u32; 10]`
 note: required by a bound in `collect`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |     fn collect<B: FromIterator<Self::Item>>(self) -> B
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Iterator::collect`
 
 error: aborting due to previous error
 
index 09832c260d04e82e5e64d0ccc510bf49ae6a42a6..5a8aacb1a6df0bc392290c051c300d638525cb7f 100644 (file)
@@ -13,6 +13,5 @@ fn main() {
     //~| NOTE all local variables must have a statically known size
     //~| NOTE doesn't have a size known at compile-time
     //~| NOTE doesn't have a size known at compile-time
-    //~| NOTE required by a bound introduced by this call
     process_slice(&some_generated_vec);
 }
index 65ef124a46302ec2197356494f86495325f8d16e..29fff8c51c63be7ca4ee0b096c52f1ee5d522bb5 100644 (file)
@@ -17,24 +17,16 @@ LL |     let some_generated_vec = (0..10).collect();
    = help: the trait `Sized` is not implemented for `[i32]`
 note: required by a bound in `collect`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |     fn collect<B: FromIterator<Self::Item>>(self) -> B
-   |                ^ required by this bound in `Iterator::collect`
 
 error[E0277]: a slice of type `[i32]` cannot be built since `[i32]` has no definite size
-  --> $DIR/collect-into-slice.rs:6:30
+  --> $DIR/collect-into-slice.rs:6:38
    |
 LL |     let some_generated_vec = (0..10).collect();
-   |                              ^^^^^^^ ------- required by a bound introduced by this call
-   |                              |
-   |                              try explicitly collecting into a `Vec<{integer}>`
+   |                                      ^^^^^^^ try explicitly collecting into a `Vec<{integer}>`
    |
    = help: the trait `FromIterator<{integer}>` is not implemented for `[i32]`
 note: required by a bound in `collect`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |     fn collect<B: FromIterator<Self::Item>>(self) -> B
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Iterator::collect`
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/iterators/invalid-iterator-chain.rs b/src/test/ui/iterators/invalid-iterator-chain.rs
new file mode 100644 (file)
index 0000000..ebdf333
--- /dev/null
@@ -0,0 +1,53 @@
+use std::collections::hash_set::Iter;
+use std::collections::HashSet;
+
+fn iter_to_vec<'b, X>(i: Iter<'b, X>) -> Vec<X> {
+    let i = i.map(|x| x.clone());
+    i.collect() //~ ERROR E0277
+}
+
+fn main() {
+    let scores = vec![(0, 0)]
+        .iter()
+        .map(|(a, b)| {
+            a + b;
+        });
+    println!("{}", scores.sum::<i32>()); //~ ERROR E0277
+    println!(
+        "{}",
+        vec![0, 1]
+            .iter()
+            .map(|x| x * 2)
+            .map(|x| x as f64)
+            .map(|x| x as i64)
+            .filter(|x| *x > 0)
+            .map(|x| { x + 1 })
+            .map(|x| { x; })
+            .sum::<i32>(), //~ ERROR E0277
+    );
+    println!(
+        "{}",
+        vec![0, 1]
+            .iter()
+            .map(|x| x * 2)
+            .map(|x| x as f64)
+            .filter(|x| *x > 0.0)
+            .map(|x| { x + 1.0 })
+            .sum::<i32>(), //~ ERROR E0277
+    );
+    println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::<i32>()); //~ ERROR E0277
+    println!("{}", vec![(), ()].iter().sum::<i32>()); //~ ERROR E0277
+    let a = vec![0];
+    let b = a.into_iter();
+    let c = b.map(|x| x + 1);
+    let d = c.filter(|x| *x > 10 );
+    let e = d.map(|x| {
+        x + 1;
+    });
+    let f = e.filter(|_| false);
+    let g: Vec<i32> = f.collect(); //~ ERROR E0277
+
+    let mut s = HashSet::new();
+    s.insert(1u8);
+    println!("{:?}", iter_to_vec(s.iter()));
+}
diff --git a/src/test/ui/iterators/invalid-iterator-chain.stderr b/src/test/ui/iterators/invalid-iterator-chain.stderr
new file mode 100644 (file)
index 0000000..d76a4bf
--- /dev/null
@@ -0,0 +1,176 @@
+error[E0277]: a value of type `Vec<X>` cannot be built from an iterator over elements of type `&X`
+  --> $DIR/invalid-iterator-chain.rs:6:7
+   |
+LL |     i.collect()
+   |       ^^^^^^^ value of type `Vec<X>` cannot be built from `std::iter::Iterator<Item=&X>`
+   |
+   = help: the trait `FromIterator<&X>` is not implemented for `Vec<X>`
+   = help: the trait `FromIterator<T>` is implemented for `Vec<T>`
+note: the method call chain might not have had the expected associated types
+  --> $DIR/invalid-iterator-chain.rs:4:26
+   |
+LL | fn iter_to_vec<'b, X>(i: Iter<'b, X>) -> Vec<X> {
+   |                          ^^^^^^^^^^^ `Iterator::Item` is `&X` here
+LL |     let i = i.map(|x| x.clone());
+   |               ------------------ `Iterator::Item` remains `&X` here
+note: required by a bound in `collect`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+
+error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `()`
+  --> $DIR/invalid-iterator-chain.rs:15:27
+   |
+LL |     println!("{}", scores.sum::<i32>());
+   |                           ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=()>`
+   |
+   = help: the trait `Sum<()>` is not implemented for `i32`
+   = help: the following other types implement trait `Sum<A>`:
+             <i32 as Sum<&'a i32>>
+             <i32 as Sum>
+note: the method call chain might not have had the expected associated types
+  --> $DIR/invalid-iterator-chain.rs:12:10
+   |
+LL |       let scores = vec![(0, 0)]
+   |                    ------------ this expression has type `Vec<({integer}, {integer})>`
+LL |           .iter()
+   |            ------ `Iterator::Item` is `&({integer}, {integer})` here
+LL |           .map(|(a, b)| {
+   |  __________^
+LL | |             a + b;
+LL | |         });
+   | |__________^ `Iterator::Item` changed to `()` here
+note: required by a bound in `std::iter::Iterator::sum`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+
+error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `()`
+  --> $DIR/invalid-iterator-chain.rs:26:14
+   |
+LL |             .sum::<i32>(),
+   |              ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=()>`
+   |
+   = help: the trait `Sum<()>` is not implemented for `i32`
+   = help: the following other types implement trait `Sum<A>`:
+             <i32 as Sum<&'a i32>>
+             <i32 as Sum>
+note: the method call chain might not have had the expected associated types
+  --> $DIR/invalid-iterator-chain.rs:20:14
+   |
+LL |         vec![0, 1]
+   |         ---------- this expression has type `Vec<{integer}>`
+LL |             .iter()
+   |              ------ `Iterator::Item` is `&{integer}` here
+LL |             .map(|x| x * 2)
+   |              ^^^^^^^^^^^^^^ `Iterator::Item` changed to `{integer}` here
+LL |             .map(|x| x as f64)
+   |              ----------------- `Iterator::Item` changed to `f64` here
+LL |             .map(|x| x as i64)
+   |              ----------------- `Iterator::Item` changed to `i64` here
+LL |             .filter(|x| *x > 0)
+   |              ------------------ `Iterator::Item` remains `i64` here
+LL |             .map(|x| { x + 1 })
+   |              ------------------ `Iterator::Item` remains `i64` here
+LL |             .map(|x| { x; })
+   |              ^^^^^^^^^^^^^^^ `Iterator::Item` changed to `()` here
+note: required by a bound in `std::iter::Iterator::sum`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+
+error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `f64`
+  --> $DIR/invalid-iterator-chain.rs:36:14
+   |
+LL |             .sum::<i32>(),
+   |              ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=f64>`
+   |
+   = help: the trait `Sum<f64>` is not implemented for `i32`
+   = help: the following other types implement trait `Sum<A>`:
+             <i32 as Sum<&'a i32>>
+             <i32 as Sum>
+note: the method call chain might not have had the expected associated types
+  --> $DIR/invalid-iterator-chain.rs:32:14
+   |
+LL |         vec![0, 1]
+   |         ---------- this expression has type `Vec<{integer}>`
+LL |             .iter()
+   |              ------ `Iterator::Item` is `&{integer}` here
+LL |             .map(|x| x * 2)
+   |              ^^^^^^^^^^^^^^ `Iterator::Item` changed to `{integer}` here
+LL |             .map(|x| x as f64)
+   |              ^^^^^^^^^^^^^^^^^ `Iterator::Item` changed to `f64` here
+LL |             .filter(|x| *x > 0.0)
+   |              -------------------- `Iterator::Item` remains `f64` here
+LL |             .map(|x| { x + 1.0 })
+   |              -------------------- `Iterator::Item` remains `f64` here
+note: required by a bound in `std::iter::Iterator::sum`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+
+error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `()`
+  --> $DIR/invalid-iterator-chain.rs:38:54
+   |
+LL |     println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::<i32>());
+   |                                                      ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=()>`
+   |
+   = help: the trait `Sum<()>` is not implemented for `i32`
+   = help: the following other types implement trait `Sum<A>`:
+             <i32 as Sum<&'a i32>>
+             <i32 as Sum>
+note: the method call chain might not have had the expected associated types
+  --> $DIR/invalid-iterator-chain.rs:38:38
+   |
+LL |     println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::<i32>());
+   |                    ---------- ------ ^^^^^^^^^^^^^^^ `Iterator::Item` changed to `()` here
+   |                    |          |
+   |                    |          `Iterator::Item` is `&{integer}` here
+   |                    this expression has type `Vec<{integer}>`
+note: required by a bound in `std::iter::Iterator::sum`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+
+error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `&()`
+  --> $DIR/invalid-iterator-chain.rs:39:40
+   |
+LL |     println!("{}", vec![(), ()].iter().sum::<i32>());
+   |                                        ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=&()>`
+   |
+   = help: the trait `Sum<&()>` is not implemented for `i32`
+   = help: the following other types implement trait `Sum<A>`:
+             <i32 as Sum<&'a i32>>
+             <i32 as Sum>
+note: the method call chain might not have had the expected associated types
+  --> $DIR/invalid-iterator-chain.rs:39:33
+   |
+LL |     println!("{}", vec![(), ()].iter().sum::<i32>());
+   |                    ------------ ^^^^^^ `Iterator::Item` is `&()` here
+   |                    |
+   |                    this expression has type `Vec<()>`
+note: required by a bound in `std::iter::Iterator::sum`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+
+error[E0277]: a value of type `Vec<i32>` cannot be built from an iterator over elements of type `()`
+  --> $DIR/invalid-iterator-chain.rs:48:25
+   |
+LL |     let g: Vec<i32> = f.collect();
+   |                         ^^^^^^^ value of type `Vec<i32>` cannot be built from `std::iter::Iterator<Item=()>`
+   |
+   = help: the trait `FromIterator<()>` is not implemented for `Vec<i32>`
+   = help: the trait `FromIterator<T>` is implemented for `Vec<T>`
+note: the method call chain might not have had the expected associated types
+  --> $DIR/invalid-iterator-chain.rs:44:15
+   |
+LL |       let a = vec![0];
+   |               ------- this expression has type `Vec<{integer}>`
+LL |       let b = a.into_iter();
+   |                 ----------- `Iterator::Item` is `{integer}` here
+LL |       let c = b.map(|x| x + 1);
+   |                 -------------- `Iterator::Item` remains `{integer}` here
+LL |       let d = c.filter(|x| *x > 10 );
+   |                 -------------------- `Iterator::Item` remains `{integer}` here
+LL |       let e = d.map(|x| {
+   |  _______________^
+LL | |         x + 1;
+LL | |     });
+   | |______^ `Iterator::Item` changed to `()` here
+LL |       let f = e.filter(|_| false);
+   |                 ----------------- `Iterator::Item` remains `()` here
+note: required by a bound in `collect`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
index afcce5c30ca021f7d53fd95ee0d52ead498b812f..a7d9c481a1a662cbceb90e4a820a47f2c96c9376 100644 (file)
@@ -3,11 +3,9 @@ error[E0599]: `Vec<bool>` is not an iterator
    |
 LL |     vec![true, false].map(|v| !v).collect::<Vec<_>>();
    |                       ^^^ `Vec<bool>` is not an iterator; try calling `.into_iter()` or `.iter()`
+  --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
    |
-  ::: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
-   |
-LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
-   | ------------------------------------------------------------------------------------------------ doesn't satisfy `Vec<bool>: Iterator`
+   = note: doesn't satisfy `Vec<bool>: Iterator`
    |
    = note: the following trait bounds were not satisfied:
            `Vec<bool>: Iterator`
index 5a46027dd52ba9c8fd50cb06bc0805267f01987b..0b206f31e7b6ebdd1f3c083c63eaa4bb9a947ce9 100644 (file)
@@ -1,17 +1,12 @@
 error[E0277]: a value of type `Bar` cannot be built from an iterator over elements of type `_`
-  --> $DIR/branches.rs:19:9
+  --> $DIR/branches.rs:19:28
    |
 LL |         std::iter::empty().collect()
-   |         ^^^^^^^^^^^^^^^^^^ ------- required by a bound introduced by this call
-   |         |
-   |         value of type `Bar` cannot be built from `std::iter::Iterator<Item=_>`
+   |                            ^^^^^^^ value of type `Bar` cannot be built from `std::iter::Iterator<Item=_>`
    |
    = help: the trait `FromIterator<_>` is not implemented for `Bar`
 note: required by a bound in `collect`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |     fn collect<B: FromIterator<Self::Item>>(self) -> B
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Iterator::collect`
 
 error: aborting due to previous error
 
index 420104e526d9b8dbb889f23550535e6ca56cf5b7..fe2631f9474205a617c9398f0cfb5709aa8875f4 100644 (file)
@@ -6,8 +6,8 @@ LL |         |s| s.len()
    |
 help: consider giving this closure parameter an explicit type
    |
-LL |         |s: _| s.len()
-   |           +++
+LL |         |s: /* Type */| s.len()
+   |           ++++++++++++
 
 error[E0282]: type annotations needed
   --> $DIR/branches3.rs:15:10
@@ -17,8 +17,8 @@ LL |         |s| s.len()
    |
 help: consider giving this closure parameter an explicit type
    |
-LL |         |s: _| s.len()
-   |           +++
+LL |         |s: /* Type */| s.len()
+   |           ++++++++++++
 
 error[E0282]: type annotations needed
   --> $DIR/branches3.rs:23:10
@@ -28,8 +28,8 @@ LL |         |s| s.len()
    |
 help: consider giving this closure parameter an explicit type
    |
-LL |         |s: _| s.len()
-   |           +++
+LL |         |s: /* Type */| s.len()
+   |           ++++++++++++
 
 error[E0282]: type annotations needed
   --> $DIR/branches3.rs:30:10
@@ -39,8 +39,8 @@ LL |         |s| s.len()
    |
 help: consider giving this closure parameter an explicit type
    |
-LL |         |s: _| s.len()
-   |           +++
+LL |         |s: /* Type */| s.len()
+   |           ++++++++++++
 
 error: aborting due to 4 previous errors
 
index a4b4968b7d24c98011d4184c5ad7af63024ab124..d8ac39a4f27a37869e5b72fab32d9d38730e42a3 100644 (file)
@@ -1,32 +1,22 @@
 error[E0277]: a value of type `Foo` cannot be built from an iterator over elements of type `_`
-  --> $DIR/recursion4.rs:10:9
+  --> $DIR/recursion4.rs:10:28
    |
 LL |     x = std::iter::empty().collect();
-   |         ^^^^^^^^^^^^^^^^^^ ------- required by a bound introduced by this call
-   |         |
-   |         value of type `Foo` cannot be built from `std::iter::Iterator<Item=_>`
+   |                            ^^^^^^^ value of type `Foo` cannot be built from `std::iter::Iterator<Item=_>`
    |
    = help: the trait `FromIterator<_>` is not implemented for `Foo`
 note: required by a bound in `collect`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |     fn collect<B: FromIterator<Self::Item>>(self) -> B
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Iterator::collect`
 
 error[E0277]: a value of type `impl Debug` cannot be built from an iterator over elements of type `_`
-  --> $DIR/recursion4.rs:19:9
+  --> $DIR/recursion4.rs:19:28
    |
 LL |     x = std::iter::empty().collect();
-   |         ^^^^^^^^^^^^^^^^^^ ------- required by a bound introduced by this call
-   |         |
-   |         value of type `impl Debug` cannot be built from `std::iter::Iterator<Item=_>`
+   |                            ^^^^^^^ value of type `impl Debug` cannot be built from `std::iter::Iterator<Item=_>`
    |
    = help: the trait `FromIterator<_>` is not implemented for `impl Debug`
 note: required by a bound in `collect`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |     fn collect<B: FromIterator<Self::Item>>(self) -> B
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Iterator::collect`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/lifetimes/conflicting-bounds.rs b/src/test/ui/lifetimes/conflicting-bounds.rs
new file mode 100644 (file)
index 0000000..f37f163
--- /dev/null
@@ -0,0 +1,11 @@
+//~ type annotations needed: cannot satisfy `Self: Gen<'source>`
+
+pub trait Gen<'source> {
+    type Output;
+
+    fn gen<T>(&self) -> T
+    where
+        Self: for<'s> Gen<'s, Output = T>;
+}
+
+fn main() {}
diff --git a/src/test/ui/lifetimes/conflicting-bounds.stderr b/src/test/ui/lifetimes/conflicting-bounds.stderr
new file mode 100644 (file)
index 0000000..42aa393
--- /dev/null
@@ -0,0 +1,14 @@
+error[E0283]: type annotations needed: cannot satisfy `Self: Gen<'source>`
+   |
+note: multiple `impl`s or `where` clauses satisfying `Self: Gen<'source>` found
+  --> $DIR/conflicting-bounds.rs:3:1
+   |
+LL | pub trait Gen<'source> {
+   | ^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |         Self: for<'s> Gen<'s, Output = T>;
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0283`.
index 5832c4d173c10245c4574f5c47a058be2ad345eb..3d4208031cd06b9879de3326b066a2b0a81bec8a 100644 (file)
@@ -4,7 +4,16 @@ error[E0283]: type annotations needed: cannot satisfy `&'a (): Foo`
 LL |     &'a (): Foo,
    |             ^^^
    |
-   = note: cannot satisfy `&'a (): Foo`
+note: multiple `impl`s or `where` clauses satisfying `&'a (): Foo` found
+  --> $DIR/issue-34979.rs:2:1
+   |
+LL | impl<'a, T> Foo for &'a T {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     &'a (): Foo,
+   |             ^^^
+LL |     &'static (): Foo;
+   |                  ^^^
 
 error: aborting due to previous error
 
index f17f8141b909a442c7897f818c30e2090c90df23..f455dcb06f79dc97aa9e3072699154a3bb8121e5 100644 (file)
@@ -1,14 +1,8 @@
 error[E0080]: values of the type `[u8; SIZE]` are too big for the current architecture
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
    |
-LL |     intrinsics::size_of::<T>()
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
 note: inside `std::mem::size_of::<[u8; SIZE]>`
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
-   |
-LL |     intrinsics::size_of::<T>()
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `main`
   --> $DIR/issue-55878.rs:7:26
    |
index 5370660d6c185ecc51db76349bce46394cd410a4..48fd4169da7c975aedc0bd24c0040d30c4d98f6c 100644 (file)
@@ -604,9 +604,6 @@ LL |         let _val: Result<i32, i32> = mem::uninitialized();
    |
 note: enums with multiple inhabited variants have to be initialized to a variant
   --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL | pub enum Result<T, E> {
-   | ^^^^^^^^^^^^^^^^^^^^^
 
 error: the type `&i32` does not permit zero-initialization
   --> $DIR/invalid_value.rs:152:34
index 9f4360e676382859b177b169a17f2f0c9f938385..747c38b800764a36a3f786d3fc76565fe3ffe0ac 100644 (file)
@@ -108,9 +108,6 @@ LL |     VEC.push(0);
    = note: the mutable reference will refer to this temporary, not the original `const` item
 note: mutable reference created due to call to this method
   --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
-   |
-LL |     pub fn push(&mut self, value: T) {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: `const` item defined here
   --> $DIR/lint-const-item-mutation.rs:31:1
    |
index 57d76016c4539d3e8ff8f0623af847d73ae30a08..e6a60d7bc4072378f2cf91a1e01e95f258d02a55 100644 (file)
@@ -9,11 +9,8 @@ LL |     for y in x {
 LL |     let z = x;
    |             ^ value used here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `x`
+note: `into_iter` takes ownership of the receiver `self`, which moves `x`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-   |
-LL |     fn into_iter(self) -> Self::IntoIter;
-   |                  ^^^^
 help: consider iterating over a slice of the `Vec<S>`'s content to avoid moving into the `for` loop
    |
 LL |     for y in &x {
index 03ecc4b4418c61aa25f065301dfd25f89ad619e2..287cd7d67044eb824eba79c53b7c89130d356c27 100644 (file)
@@ -12,11 +12,6 @@ LL |     };
    |     |
    |     `mutex` dropped here while still borrowed
    |
-help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped
-  --> $SRC_DIR/core/src/macros/mod.rs:LL:COL
-   |
-LL |         $dst.write_fmt($crate::format_args!($($arg)*));
-   |                                                       +
 
 error[E0597]: `mutex` does not live long enough
   --> $DIR/format-args-temporaries-in-write.rs:47:29
@@ -32,11 +27,6 @@ LL |     };
    |     |
    |     `mutex` dropped here while still borrowed
    |
-help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped
-  --> $SRC_DIR/core/src/macros/mod.rs:LL:COL
-   |
-LL |         $dst.write_fmt($crate::format_args_nl!($($arg)*));
-   |                                                          +
 
 error: aborting due to 2 previous errors
 
index 3e8cfb3f0e97fba429aca99931f3de4959c64d86..d7c8aaae22e1e1cf0e4ff3d74488ee324c58443a 100644 (file)
@@ -3,11 +3,9 @@ error: cannot find macro `printlx` in this scope
    |
 LL |     printlx!("oh noes!");
    |     ^^^^^^^ help: a macro with a similar name exists: `println`
+  --> $SRC_DIR/std/src/macros.rs:LL:COL
    |
-  ::: $SRC_DIR/std/src/macros.rs:LL:COL
-   |
-LL | macro_rules! println {
-   | -------------------- similarly named macro `println` defined here
+   = note: similarly named macro `println` defined here
 
 error: aborting due to previous error
 
index 70900a6bc81d3a1468003c2dda68f9781d1fc505..f1c3512bc9b8ee39fba96b9bf7b545e84d5ca1cc 100644 (file)
@@ -3,11 +3,9 @@ error: cannot find macro `inline` in this scope
    |
 LL |     inline!();
    |     ^^^^^^ help: a macro with a similar name exists: `line`
+  --> $SRC_DIR/core/src/macros/mod.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/macros/mod.rs:LL:COL
-   |
-LL |     macro_rules! line {
-   |     ----------------- similarly named macro `line` defined here
+   = note: similarly named macro `line` defined here
    |
    = note: `inline` is in scope, but it is an attribute: `#[inline]`
 
index 8f9dba16578eb9b4ad184f86c3f6b4f575c7359c..22f54e04e54c3dc118db8bef42677a0309d58d2e 100644 (file)
@@ -7,9 +7,6 @@ LL | macro_rules! unknown { () => () }
 error[E0773]: attempted to define built-in macro more than once
   --> $SRC_DIR/core/src/macros/mod.rs:LL:COL
    |
-LL |     macro_rules! line {
-   |     ^^^^^^^^^^^^^^^^^
-   |
 note: previously defined here
   --> $DIR/unknown-builtin.rs:9:1
    |
index 803883460f08f4074adf2752a500673820a37b2c..6ff6fbabb4a5f3ac04ccdaae843f7b9a233310e2 100644 (file)
@@ -24,9 +24,6 @@ LL | #[derive(Copy(Bad))]
    |
 note: required by a bound in `Copy`
   --> $SRC_DIR/core/src/marker.rs:LL:COL
-   |
-LL | pub trait Copy: Clone {
-   |                 ^^^^^ required by this bound in `Copy`
    = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider annotating `Test1` with `#[derive(Clone)]`
    |
@@ -41,9 +38,6 @@ LL | #[derive(Copy="bad")]
    |
 note: required by a bound in `Copy`
   --> $SRC_DIR/core/src/marker.rs:LL:COL
-   |
-LL | pub trait Copy: Clone {
-   |                 ^^^^^ required by this bound in `Copy`
    = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider annotating `Test2` with `#[derive(Clone)]`
    |
index 9eadb88a8ba814d6ce7b6fa01365f3f2571c0ac8..e3b501b2fd558c42ad720ba709aac0abf2d327d1 100644 (file)
@@ -6,8 +6,8 @@ LL |     let x = match () {
    |
 help: consider giving `x` an explicit type
    |
-LL |     let x: _ = match () {
-   |          +++
+LL |     let x: /* Type */ = match () {
+   |          ++++++++++++
 
 error: aborting due to previous error
 
index a4ffb864dad9cb3848684ef77fa542e1ef4a386d..3f4e647491eb7390efc4ba288ba0a788b0bd2484 100644 (file)
@@ -61,11 +61,8 @@ LL |      .take()
    = note: the following trait bounds were not satisfied:
            `Foo: Iterator`
            which is required by `&mut Foo: Iterator`
-note: the following trait must be implemented
+note: the trait `Iterator` must be implemented
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL | pub trait Iterator {
-   | ^^^^^^^^^^^^^^^^^^
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the following trait defines an item `take`, perhaps you need to implement it:
            candidate #1: `Iterator`
index 62f20d6d50c040019439f817f08e9d198945e014..25ad360b329aad8ecba8dbf4591f15c8a572f1e9 100644 (file)
@@ -11,11 +11,9 @@ warning: cannot specify lifetime arguments explicitly if late bound lifetime par
    |
 LL |     0.clone::<'a>();
    |               ^^
+  --> $SRC_DIR/core/src/clone.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/clone.rs:LL:COL
-   |
-LL |     fn clone(&self) -> Self;
-   |              - the late bound lifetime parameter is introduced here
+   = note: the late bound lifetime parameter is introduced here
    |
    = 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 #42868 <https://github.com/rust-lang/rust/issues/42868>
index fc42d1a4dcd08136374b9ab6203cd4de854dbd23..8846efba871b9cd1f845b86b58dfbaa5a0880d1b 100644 (file)
@@ -23,7 +23,7 @@ error[E0599]: no method named `extend` found for struct `Map` in the current sco
   --> $DIR/method-not-found-generic-arg-elision.rs:87:29
    |
 LL |     v.iter().map(|x| x * x).extend(std::iter::once(100));
-   |                             ^^^^^^ method not found in `Map<std::slice::Iter<'_, i32>, [closure@$DIR/method-not-found-generic-arg-elision.rs:87:18: 87:21]>`
+   |                             ^^^^^^ method not found in `Map<Iter<'_, i32>, [closure@method-not-found-generic-arg-elision.rs:87:18]>`
 
 error[E0599]: no method named `method` found for struct `Wrapper<bool>` in the current scope
   --> $DIR/method-not-found-generic-arg-elision.rs:90:13
index ffd95b48ac2b72992ba581014f459a8becfc47df..2393791a9b2a81106ad423e13de7bb2f245282ff 100644 (file)
@@ -11,11 +11,8 @@ note: an implementation of `AddAssign<_>` might be missing for `Foo`
    |
 LL | struct Foo;
    | ^^^^^^^^^^ must implement `AddAssign<_>`
-note: the following trait must be implemented
+note: the trait `AddAssign` must be implemented
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL | pub trait AddAssign<Rhs = Self> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index a2bf2e8d5b7b330661a6ff1e753bcf7127a076eb..2ecab9f024a123a2de0b9d45eac0b9846ddfb9e8 100644 (file)
@@ -128,9 +128,6 @@ LL | fn foo() {}
    |
 note: required by a bound in `map`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |         F: FnMut(Self::Item) -> B,
-   |            ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Iterator::map`
 
 error[E0593]: closure is expected to take a single 2-tuple as argument, but it takes 3 distinct arguments
   --> $DIR/closure-arg-count.rs:27:57
@@ -144,9 +141,6 @@ LL |     let _it = vec![1, 2, 3].into_iter().enumerate().map(bar);
    |
 note: required by a bound in `map`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |         F: FnMut(Self::Item) -> B,
-   |            ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Iterator::map`
 
 error[E0593]: function is expected to take a single 2-tuple as argument, but it takes 2 distinct arguments
   --> $DIR/closure-arg-count.rs:29:57
@@ -161,9 +155,6 @@ LL | fn qux(x: usize, y: usize) {}
    |
 note: required by a bound in `map`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |         F: FnMut(Self::Item) -> B,
-   |            ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Iterator::map`
 
 error[E0593]: function is expected to take 1 argument, but it takes 2 arguments
   --> $DIR/closure-arg-count.rs:32:45
@@ -175,9 +166,6 @@ LL |     let _it = vec![1, 2, 3].into_iter().map(usize::checked_add);
    |
 note: required by a bound in `map`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |         F: FnMut(Self::Item) -> B,
-   |            ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Iterator::map`
 
 error[E0593]: function is expected to take 0 arguments, but it takes 1 argument
   --> $DIR/closure-arg-count.rs:35:10
index f2e2a4c7fd5fe3671451333ade9f09ed547a89a1..fab9b7edc0cc5a38bb0c6ab566171b51fa5a4b62 100644 (file)
@@ -2,17 +2,16 @@ error[E0631]: type mismatch in closure arguments
   --> $DIR/closure-arg-type-mismatch.rs:3:14
    |
 LL |     a.iter().map(|_: (u32, u32)| 45);
-   |              ^^^ --------------- found signature defined here
-   |              |
+   |              ^^^ ---------------
+   |              |   |   |
+   |              |   |   help: consider borrowing the argument: `&(u32, u32)`
+   |              |   found signature defined here
    |              expected due to this
    |
    = note: expected closure signature `fn(&(u32, u32)) -> _`
               found closure signature `fn((u32, u32)) -> _`
 note: required by a bound in `map`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |         F: FnMut(Self::Item) -> B,
-   |            ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Iterator::map`
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/closure-arg-type-mismatch.rs:4:14
@@ -26,9 +25,6 @@ LL |     a.iter().map(|_: &(u16, u16)| 45);
               found closure signature `for<'a> fn(&'a (u16, u16)) -> _`
 note: required by a bound in `map`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |         F: FnMut(Self::Item) -> B,
-   |            ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Iterator::map`
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/closure-arg-type-mismatch.rs:5:14
@@ -42,9 +38,6 @@ LL |     a.iter().map(|_: (u16, u16)| 45);
               found closure signature `fn((u16, u16)) -> _`
 note: required by a bound in `map`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |         F: FnMut(Self::Item) -> B,
-   |            ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Iterator::map`
 
 error: aborting due to 3 previous errors
 
index 5ea9bcfc122cb31df5cd24b3c9467a8672d01adb..680aff1726f9f905e056c800fad7a27206bfa5f5 100644 (file)
@@ -13,9 +13,6 @@ LL |         Some(true)
                         found type `bool` (`bool`)
 note: tuple variant defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^^^
 
 error: aborting due to previous error
 
index b3509abbf84eb9a1841125543b1094e404fd48d3..72fb0e4d774312780cb81e6e5f8fc1617f0d8113 100644 (file)
@@ -2,31 +2,28 @@ error[E0631]: type mismatch in closure arguments
   --> $DIR/issue-36053-2.rs:7:32
    |
 LL |     once::<&str>("str").fuse().filter(|a: &str| true).count();
-   |                                ^^^^^^ --------- found signature defined here
-   |                                |
+   |                                ^^^^^^ ---------
+   |                                |      |   |
+   |                                |      |   help: consider borrowing the argument: `&&str`
+   |                                |      found signature defined here
    |                                expected due to this
    |
    = note: expected closure signature `for<'a> fn(&'a &str) -> _`
               found closure signature `for<'a> fn(&'a str) -> _`
 note: required by a bound in `filter`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |         P: FnMut(&Self::Item) -> bool,
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Iterator::filter`
 
-error[E0599]: the method `count` exists for struct `Filter<Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:7:39: 7:48]>`, but its trait bounds were not satisfied
+error[E0599]: the method `count` exists for struct `Filter<Fuse<Once<&str>>, [closure@issue-36053-2.rs:7:39]>`, but its trait bounds were not satisfied
   --> $DIR/issue-36053-2.rs:7:55
    |
 LL |     once::<&str>("str").fuse().filter(|a: &str| true).count();
-   |                                       ---------       ^^^^^ method cannot be called on `Filter<Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:7:39: 7:48]>` due to unsatisfied trait bounds
+   |                                       ---------       ^^^^^ method cannot be called due to unsatisfied trait bounds
    |                                       |
    |                                       doesn't satisfy `<_ as FnOnce<(&&str,)>>::Output = bool`
    |                                       doesn't satisfy `_: FnMut<(&&str,)>`
+  --> $SRC_DIR/core/src/iter/adapters/filter.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/iter/adapters/filter.rs:LL:COL
-   |
-LL | pub struct Filter<I, P> {
-   | ----------------------- doesn't satisfy `_: Iterator`
+   = note: doesn't satisfy `_: Iterator`
    |
    = note: the following trait bounds were not satisfied:
            `<[closure@$DIR/issue-36053-2.rs:7:39: 7:48] as FnOnce<(&&str,)>>::Output = bool`
index d596b4a69f34a89c1c352dab236708feb6da91a4..a5f38dd53666151a272d2893d6c2447b0895f5e8 100644 (file)
@@ -10,9 +10,6 @@ LL |         None::<()>.map(Self::f);
    |
 note: required by a bound in `Option::<T>::map`
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |         F: ~const FnOnce(T) -> U,
-   |            ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Option::<T>::map`
 
 error: aborting due to previous error
 
index 8b8563684014dbf633909ab7825dcf7c52cffac8..d9d408844d0a49140737ca05f8007dfa68541174 100644 (file)
@@ -11,9 +11,6 @@ LL |         self.foo.map(Foo::new)
    |
 note: required by a bound in `Option::<T>::map`
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |         F: ~const FnOnce(T) -> U,
-   |            ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Option::<T>::map`
 
 error[E0593]: function is expected to take 0 arguments, but it takes 1 argument
   --> $DIR/issue-47706.rs:27:9
index 94a9c97576f674b186ef8d7c14f12441860191c5..b75c7a99fdd334c98fc8d956c9310233a24fc7d0 100644 (file)
@@ -14,11 +14,9 @@ error: `impl` item signature doesn't match `trait` item signature
    |
 LL |     fn next(&mut self) -> Option<IteratorChunk<T, S>> {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&'1 mut ChunkingIterator<T, S>) -> Option<IteratorChunk<'1, T, S>>`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |     fn next(&mut self) -> Option<Self::Item>;
-   |     ----------------------------------------- expected `fn(&'1 mut ChunkingIterator<T, S>) -> Option<IteratorChunk<'static, T, S>>`
+   = note: expected `fn(&'1 mut ChunkingIterator<T, S>) -> Option<IteratorChunk<'static, T, S>>`
    |
    = note: expected `fn(&'1 mut ChunkingIterator<T, S>) -> Option<IteratorChunk<'static, T, S>>`
               found `fn(&'1 mut ChunkingIterator<T, S>) -> Option<IteratorChunk<'1, T, S>>`
index 36748fae13c9413fae09d3b016b6ed0776b460fa..d3b7525072ff4748addf112f24b185d8ac0e0238 100644 (file)
@@ -1,18 +1,13 @@
 error[E0277]: `Foo` doesn't implement `Debug`
-  --> $DIR/method-help-unsatisfied-bound.rs:5:5
+  --> $DIR/method-help-unsatisfied-bound.rs:5:7
    |
 LL |     a.unwrap();
-   |     ^ ------ required by a bound introduced by this call
-   |     |
-   |     `Foo` cannot be formatted using `{:?}`
+   |       ^^^^^^ `Foo` cannot be formatted using `{:?}`
    |
    = help: the trait `Debug` is not implemented for `Foo`
    = note: add `#[derive(Debug)]` to `Foo` or manually `impl Debug for Foo`
 note: required by a bound in `Result::<T, E>::unwrap`
   --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL |         E: fmt::Debug,
-   |            ^^^^^^^^^^ required by this bound in `Result::<T, E>::unwrap`
 help: consider annotating `Foo` with `#[derive(Debug)]`
    |
 LL | #[derive(Debug)]
index e65ae58d4ce96ab55d5db11fc6c64c0d9b5de25c..46a383325526db3371d9a1eb99bf66d534fa1f4e 100644 (file)
@@ -9,9 +9,6 @@ LL |     Some(42_u8)
    = note: enum `std::option::Option` and enum `Option` have similar names, but are actually distinct types
 note: enum `std::option::Option` is defined in crate `core`
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL | pub enum Option<T> {
-   | ^^^^^^^^^^^^^^^^^^
 note: enum `Option` is defined in the current crate
   --> $DIR/similar_paths.rs:1:1
    |
index 6e4a4e5ba22c100872731b44911e34d57d260fd1..c5159471fe3e405bf9775d8ca1eb16f39433840f 100644 (file)
@@ -5,11 +5,16 @@ LL |     match x {
    |           ^
 LL |
 LL |         &Some(_y) => (),
-   |         ---------
-   |         |     |
-   |         |     data moved here
-   |         |     move occurs because `_y` has type `Box<i32>`, which does not implement the `Copy` trait
-   |         help: consider removing the `&`: `Some(_y)`
+   |               --
+   |               |
+   |               data moved here
+   |               move occurs because `_y` has type `Box<i32>`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -         &Some(_y) => (),
+LL +         Some(_y) => (),
+   |
 
 error: aborting due to previous error
 
index c13dc58826eb83bfa27ff49b2575db210dd877ee..b3f95ee192a565e85a6bc7647068168fd46e203f 100644 (file)
@@ -6,11 +6,8 @@ LL |     val.0.into_iter().next();
 LL |     val.0;
    |     ^^^^^ value used here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `val.0`
+note: `into_iter` takes ownership of the receiver `self`, which moves `val.0`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-   |
-LL |     fn into_iter(self) -> Self::IntoIter;
-   |                  ^^^^
    = note: move occurs because `val.0` has type `Vec<bool>`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `foo`
@@ -23,7 +20,7 @@ LL |     foo.use_self();
 LL |     foo;
    |     ^^^ value used here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `foo`
+note: `Foo::use_self` takes ownership of the receiver `self`, which moves `foo`
   --> $DIR/move-fn-self-receiver.rs:13:17
    |
 LL |     fn use_self(self) {}
@@ -49,7 +46,7 @@ LL |     boxed_foo.use_box_self();
 LL |     boxed_foo;
    |     ^^^^^^^^^ value used here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `boxed_foo`
+note: `Foo::use_box_self` takes ownership of the receiver `self`, which moves `boxed_foo`
   --> $DIR/move-fn-self-receiver.rs:14:21
    |
 LL |     fn use_box_self(self: Box<Self>) {}
@@ -65,7 +62,7 @@ LL |     pin_box_foo.use_pin_box_self();
 LL |     pin_box_foo;
    |     ^^^^^^^^^^^ value used here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `pin_box_foo`
+note: `Foo::use_pin_box_self` takes ownership of the receiver `self`, which moves `pin_box_foo`
   --> $DIR/move-fn-self-receiver.rs:15:25
    |
 LL |     fn use_pin_box_self(self: Pin<Box<Self>>) {}
@@ -91,7 +88,7 @@ LL |     rc_foo.use_rc_self();
 LL |     rc_foo;
    |     ^^^^^^ value used here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `rc_foo`
+note: `Foo::use_rc_self` takes ownership of the receiver `self`, which moves `rc_foo`
   --> $DIR/move-fn-self-receiver.rs:16:20
    |
 LL |     fn use_rc_self(self: Rc<Self>) {}
@@ -113,9 +110,6 @@ LL |     foo_add;
    |
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL |     fn add(self, rhs: Rhs) -> Self::Output;
-   |            ^^^^
 
 error[E0382]: use of moved value: `implicit_into_iter`
   --> $DIR/move-fn-self-receiver.rs:63:5
@@ -157,7 +151,7 @@ LL |     for _val in container.custom_into_iter() {}
 LL |     container;
    |     ^^^^^^^^^ value used here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `container`
+note: `Container::custom_into_iter` takes ownership of the receiver `self`, which moves `container`
   --> $DIR/move-fn-self-receiver.rs:23:25
    |
 LL |     fn custom_into_iter(self) -> impl Iterator<Item = bool> {
index 0caa0b83a4c7cbe00939ab4cc0ed8a43ec7de3db..26d4996d6cb1d7dc18b578eab8071f9fca446abf 100644 (file)
@@ -2,45 +2,61 @@ error[E0508]: cannot move out of type `[D; 4]`, a non-copy array
   --> $DIR/move-out-of-array-ref.rs:8:24
    |
 LL |     let [_, e, _, _] = *a;
-   |             -          ^^
-   |             |          |
-   |             |          cannot move out of here
-   |             |          help: consider borrowing here: `&*a`
+   |             -          ^^ cannot move out of here
+   |             |
    |             data moved here
    |             move occurs because `e` has type `D`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let [_, e, _, _] = *a;
+LL +     let [_, e, _, _] = a;
+   |
 
 error[E0508]: cannot move out of type `[D; 4]`, a non-copy array
   --> $DIR/move-out-of-array-ref.rs:13:27
    |
 LL |     let [_, s @ .. , _] = *a;
-   |             -             ^^
-   |             |             |
-   |             |             cannot move out of here
-   |             |             help: consider borrowing here: `&*a`
+   |             -             ^^ cannot move out of here
+   |             |
    |             data moved here
    |             move occurs because `s` has type `[D; 2]`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let [_, s @ .. , _] = *a;
+LL +     let [_, s @ .. , _] = a;
+   |
 
 error[E0508]: cannot move out of type `[D; 4]`, a non-copy array
   --> $DIR/move-out-of-array-ref.rs:18:24
    |
 LL |     let [_, e, _, _] = *a;
-   |             -          ^^
-   |             |          |
-   |             |          cannot move out of here
-   |             |          help: consider borrowing here: `&*a`
+   |             -          ^^ cannot move out of here
+   |             |
    |             data moved here
    |             move occurs because `e` has type `D`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let [_, e, _, _] = *a;
+LL +     let [_, e, _, _] = a;
+   |
 
 error[E0508]: cannot move out of type `[D; 4]`, a non-copy array
   --> $DIR/move-out-of-array-ref.rs:23:27
    |
 LL |     let [_, s @ .. , _] = *a;
-   |             -             ^^
-   |             |             |
-   |             |             cannot move out of here
-   |             |             help: consider borrowing here: `&*a`
+   |             -             ^^ cannot move out of here
+   |             |
    |             data moved here
    |             move occurs because `s` has type `[D; 2]`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let [_, s @ .. , _] = *a;
+LL +     let [_, s @ .. , _] = a;
+   |
 
 error: aborting due to 4 previous errors
 
index ce5ddb3e183b10ed1ca113fe70ca8aa6baa21ac1..5a0357cf567da1e86140d5638d5ab64fb410b658 100644 (file)
@@ -8,6 +8,11 @@ LL |         box [a] => {},
    |              |
    |              data moved here
    |              move occurs because `a` has type `A`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |         box [ref a] => {},
+   |              +++
 
 error: aborting due to previous error
 
index 59c02d42bf17ebe844771f6b20b27b313be15fed..2f7394fbfd36ceba4c381151f17ab6e3460744a4 100644 (file)
@@ -1,5 +1,6 @@
 #![feature(unsized_locals)]
 //~^ WARN the feature `unsized_locals` is incomplete
+#![allow(unused)]
 
 struct A;
 #[derive(Clone, Copy)]
index 46357ce6f2eacaaf80828bb0183554baa9c6a74a..b46854cd6b4584390f90b0be37a6e752a602e575 100644 (file)
@@ -8,7 +8,7 @@ LL | #![feature(unsized_locals)]
    = note: `#[warn(incomplete_features)]` on by default
 
 error[E0508]: cannot move out of type `[A]`, a non-copy slice
-  --> $DIR/move-out-of-slice-2.rs:10:11
+  --> $DIR/move-out-of-slice-2.rs:11:11
    |
 LL |     match *a {
    |           ^^ cannot move out of here
@@ -18,9 +18,14 @@ LL |         [a @ ..] => {}
    |          |
    |          data moved here
    |          move occurs because `a` has type `[A]`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |         [ref a @ ..] => {}
+   |          +++
 
 error[E0508]: cannot move out of type `[A]`, a non-copy slice
-  --> $DIR/move-out-of-slice-2.rs:16:11
+  --> $DIR/move-out-of-slice-2.rs:17:11
    |
 LL |     match *b {
    |           ^^ cannot move out of here
@@ -30,9 +35,14 @@ LL |         [_, _, b @ .., _] => {}
    |                |
    |                data moved here
    |                move occurs because `b` has type `[A]`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |         [_, _, ref b @ .., _] => {}
+   |                +++
 
 error[E0508]: cannot move out of type `[C]`, a non-copy slice
-  --> $DIR/move-out-of-slice-2.rs:24:11
+  --> $DIR/move-out-of-slice-2.rs:25:11
    |
 LL |     match *c {
    |           ^^ cannot move out of here
@@ -42,9 +52,14 @@ LL |         [c @ ..] => {}
    |          |
    |          data moved here
    |          move occurs because `c` has type `[C]`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |         [ref c @ ..] => {}
+   |          +++
 
 error[E0508]: cannot move out of type `[C]`, a non-copy slice
-  --> $DIR/move-out-of-slice-2.rs:30:11
+  --> $DIR/move-out-of-slice-2.rs:31:11
    |
 LL |     match *d {
    |           ^^ cannot move out of here
@@ -54,6 +69,11 @@ LL |         [_, _, d @ .., _] => {}
    |                |
    |                data moved here
    |                move occurs because `d` has type `[C]`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |         [_, _, ref d @ .., _] => {}
+   |                +++
 
 error: aborting due to 4 previous errors; 1 warning emitted
 
index a49ee31b46622c8570e21cd0969b656e176437d3..0b1a623a01345d75294e7bbe31faf28963421782 100644 (file)
@@ -8,11 +8,8 @@ LL |     consume(x.into_iter().next().unwrap());
 LL |     touch(&x[0]);
    |            ^ value borrowed here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `x`
+note: `into_iter` takes ownership of the receiver `self`, which moves `x`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-   |
-LL |     fn into_iter(self) -> Self::IntoIter;
-   |                  ^^^^
 help: consider cloning the value if the performance cost is acceptable
    |
 LL |     consume(x.clone().into_iter().next().unwrap());
index 5ed91a0d5596340888162fbf5dcef12579104f49..df09ababa5a01f2718d12830aeaa82f944fab49d 100644 (file)
@@ -2,13 +2,18 @@ error[E0507]: cannot move out of `hellothere.x` as enum variant `Bar` which is b
   --> $DIR/moves-based-on-type-block-bad.rs:22:19
    |
 LL |             match hellothere.x {
-   |                   ^^^^^^^^^^^^ help: consider borrowing here: `&hellothere.x`
+   |                   ^^^^^^^^^^^^
 LL |                 box E::Foo(_) => {}
 LL |                 box E::Bar(x) => println!("{}", x.to_string()),
    |                            -
    |                            |
    |                            data moved here
    |                            move occurs because `x` has type `Box<isize>`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |             match &hellothere.x {
+   |                   +
 
 error: aborting due to previous error
 
index 838b1282cb4ed883de4561af3c7104e08b719655..ae76889f104c89a80910e73028a8675818094e8d 100644 (file)
@@ -160,11 +160,8 @@ LL |     let _y = x.into_iter().next().unwrap();
 LL |     touch(&x);
    |           ^^ value borrowed here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `x`
+note: `into_iter` takes ownership of the receiver `self`, which moves `x`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-   |
-LL |     fn into_iter(self) -> Self::IntoIter;
-   |                  ^^^^
 help: consider cloning the value if the performance cost is acceptable
    |
 LL |     let _y = x.clone().into_iter().next().unwrap();
@@ -180,11 +177,8 @@ LL |     let _y = [x.into_iter().next().unwrap(); 1];
 LL |     touch(&x);
    |           ^^ value borrowed here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `x`
+note: `into_iter` takes ownership of the receiver `self`, which moves `x`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-   |
-LL |     fn into_iter(self) -> Self::IntoIter;
-   |                  ^^^^
 help: consider cloning the value if the performance cost is acceptable
    |
 LL |     let _y = [x.clone().into_iter().next().unwrap(); 1];
index 45cf3723483f3a05f0ca60546bc6c949bb7df68a..a0f790dba15ed21adddebbcb5daf9faa8cd909ef 100644 (file)
@@ -1,4 +1,4 @@
-error[E0271]: expected `[closure@$DIR/fallback-closure-wrap.rs:18:40: 18:47]` to be a closure that returns `()`, but it returns `!`
+error[E0271]: expected `[closure@fallback-closure-wrap.rs:18:40]` to be a closure that returns `()`, but it returns `!`
   --> $DIR/fallback-closure-wrap.rs:18:31
    |
 LL |       let error = Closure::wrap(Box::new(move || {
index 6dc039fc35db7c3294c82b065ec17706d83dfc81..2db1cc4b776905e8fdb3c0086602a1057a91e607 100644 (file)
@@ -5,7 +5,7 @@ LL |     foo(panic!())
    |     --- ^^^^^^^^
    |     |   |
    |     |   the trait `T` is not implemented for `()`
-   |     |   this tail expression is of type `_`
+   |     |   this tail expression is of type `()`
    |     required by a bound introduced by this call
    |
 note: required by a bound in `foo`
index 0910e9ad77a846a00e90a4a53b43f89998855eec..de5c9c5601635eedef6cc14e9900d98d61414691 100644 (file)
@@ -46,9 +46,6 @@ LL |     [(); { for _ in 0usize.. {}; 0}];
    |
 note: impl defined here, but it is not `const`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-   |
-LL | impl<I: Iterator> const IntoIterator for I {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: calls in constants are limited to constant functions, tuple structs and tuple variants
 
 error[E0658]: mutable references are not allowed in constants
index 168cf2f83535d3558848392d29d3c6632edf9e40..e148b983e8e9da2836c479cc0bfd21ee3b872b8f 100644 (file)
@@ -26,9 +26,6 @@ LL |     0.....{loop{}1};
             found struct `RangeTo<{integer}>`
 note: associated function defined here
   --> $SRC_DIR/core/src/ops/range.rs:LL:COL
-   |
-LL |     pub const fn new(start: Idx, end: Idx) -> Self {
-   |                  ^^^
 
 error: aborting due to 2 previous errors
 
index 56a5cdff073e48aceffb69519776de9c0ed680c9..0dc5c08ea5f08d76ffe34d4b550e0075a836e91b 100644 (file)
@@ -2,28 +2,37 @@ error[E0507]: cannot move out of `*r` which is behind a shared reference
   --> $DIR/cannot-move-block-spans.rs:5:15
    |
 LL |     let x = { *r };
-   |               ^^
-   |               |
-   |               move occurs because `*r` has type `String`, which does not implement the `Copy` trait
-   |               help: consider borrowing here: `&*r`
+   |               ^^ move occurs because `*r` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let x = { *r };
+LL +     let x = { r };
+   |
 
 error[E0507]: cannot move out of `*r` which is behind a shared reference
   --> $DIR/cannot-move-block-spans.rs:6:22
    |
 LL |     let y = unsafe { *r };
-   |                      ^^
-   |                      |
-   |                      move occurs because `*r` has type `String`, which does not implement the `Copy` trait
-   |                      help: consider borrowing here: `&*r`
+   |                      ^^ move occurs because `*r` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let y = unsafe { *r };
+LL +     let y = unsafe { r };
+   |
 
 error[E0507]: cannot move out of `*r` which is behind a shared reference
   --> $DIR/cannot-move-block-spans.rs:7:26
    |
 LL |     let z = loop { break *r; };
-   |                          ^^
-   |                          |
-   |                          move occurs because `*r` has type `String`, which does not implement the `Copy` trait
-   |                          help: consider borrowing here: `&*r`
+   |                          ^^ move occurs because `*r` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let z = loop { break *r; };
+LL +     let z = loop { break r; };
+   |
 
 error[E0508]: cannot move out of type `[String; 2]`, a non-copy array
   --> $DIR/cannot-move-block-spans.rs:11:15
@@ -33,7 +42,11 @@ LL |     let x = { arr[0] };
    |               |
    |               cannot move out of here
    |               move occurs because `arr[_]` has type `String`, which does not implement the `Copy` trait
-   |               help: consider borrowing here: `&arr[0]`
+   |
+help: consider borrowing here
+   |
+LL |     let x = { &arr[0] };
+   |               +
 
 error[E0508]: cannot move out of type `[String; 2]`, a non-copy array
   --> $DIR/cannot-move-block-spans.rs:12:22
@@ -43,7 +56,11 @@ LL |     let y = unsafe { arr[0] };
    |                      |
    |                      cannot move out of here
    |                      move occurs because `arr[_]` has type `String`, which does not implement the `Copy` trait
-   |                      help: consider borrowing here: `&arr[0]`
+   |
+help: consider borrowing here
+   |
+LL |     let y = unsafe { &arr[0] };
+   |                      +
 
 error[E0508]: cannot move out of type `[String; 2]`, a non-copy array
   --> $DIR/cannot-move-block-spans.rs:13:26
@@ -53,34 +70,47 @@ LL |     let z = loop { break arr[0]; };
    |                          |
    |                          cannot move out of here
    |                          move occurs because `arr[_]` has type `String`, which does not implement the `Copy` trait
-   |                          help: consider borrowing here: `&arr[0]`
+   |
+help: consider borrowing here
+   |
+LL |     let z = loop { break &arr[0]; };
+   |                          +
 
 error[E0507]: cannot move out of `*r` which is behind a shared reference
   --> $DIR/cannot-move-block-spans.rs:17:38
    |
 LL |     let x = { let mut u = 0; u += 1; *r };
-   |                                      ^^
-   |                                      |
-   |                                      move occurs because `*r` has type `String`, which does not implement the `Copy` trait
-   |                                      help: consider borrowing here: `&*r`
+   |                                      ^^ move occurs because `*r` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let x = { let mut u = 0; u += 1; *r };
+LL +     let x = { let mut u = 0; u += 1; r };
+   |
 
 error[E0507]: cannot move out of `*r` which is behind a shared reference
   --> $DIR/cannot-move-block-spans.rs:18:45
    |
 LL |     let y = unsafe { let mut u = 0; u += 1; *r };
-   |                                             ^^
-   |                                             |
-   |                                             move occurs because `*r` has type `String`, which does not implement the `Copy` trait
-   |                                             help: consider borrowing here: `&*r`
+   |                                             ^^ move occurs because `*r` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let y = unsafe { let mut u = 0; u += 1; *r };
+LL +     let y = unsafe { let mut u = 0; u += 1; r };
+   |
 
 error[E0507]: cannot move out of `*r` which is behind a shared reference
   --> $DIR/cannot-move-block-spans.rs:19:49
    |
 LL |     let z = loop { let mut u = 0; u += 1; break *r; u += 2; };
-   |                                                 ^^
-   |                                                 |
-   |                                                 move occurs because `*r` has type `String`, which does not implement the `Copy` trait
-   |                                                 help: consider borrowing here: `&*r`
+   |                                                 ^^ move occurs because `*r` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let z = loop { let mut u = 0; u += 1; break *r; u += 2; };
+LL +     let z = loop { let mut u = 0; u += 1; break r; u += 2; };
+   |
 
 error: aborting due to 9 previous errors
 
index c0a17a67ee269771867b0903945dd9b55717c06d..7f9cbc3c30a92a9ddabcc689bcbb159685ff5acc 100644 (file)
@@ -36,7 +36,11 @@ LL |     let p = s.url; p
    |             |
    |             cannot move out of here
    |             move occurs because `s.url` has type `&mut String`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&s.url`
+   |
+help: consider borrowing here
+   |
+LL |     let p = &s.url; p
+   |             +
 
 error: aborting due to 4 previous errors
 
index b03fcf70babe25850fcc3d068e15a4e282b63dda..58b8aa31d4c2d26c5c140de80b8c1d6ca28fb192 100644 (file)
@@ -2,10 +2,13 @@ error[E0507]: cannot move out of `*a` which is behind a shared reference
   --> $DIR/move-errors.rs:6:13
    |
 LL |     let b = *a;
-   |             ^^
-   |             |
-   |             move occurs because `*a` has type `A`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&*a`
+   |             ^^ move occurs because `*a` has type `A`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let b = *a;
+LL +     let b = a;
+   |
 
 error[E0508]: cannot move out of type `[A; 1]`, a non-copy array
   --> $DIR/move-errors.rs:12:13
@@ -15,25 +18,35 @@ LL |     let b = a[0];
    |             |
    |             cannot move out of here
    |             move occurs because `a[_]` has type `A`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&a[0]`
+   |
+help: consider borrowing here
+   |
+LL |     let b = &a[0];
+   |             +
 
 error[E0507]: cannot move out of `**r` which is behind a shared reference
   --> $DIR/move-errors.rs:19:13
    |
 LL |     let s = **r;
-   |             ^^^
-   |             |
-   |             move occurs because `**r` has type `A`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&**r`
+   |             ^^^ move occurs because `**r` has type `A`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let s = **r;
+LL +     let s = *r;
+   |
 
 error[E0507]: cannot move out of an `Rc`
   --> $DIR/move-errors.rs:27:13
    |
 LL |     let s = *r;
-   |             ^^
-   |             |
-   |             move occurs because value has type `A`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&*r`
+   |             ^^ move occurs because value has type `A`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let s = *r;
+LL +     let s = r;
+   |
 
 error[E0508]: cannot move out of type `[A; 1]`, a non-copy array
   --> $DIR/move-errors.rs:32:13
@@ -43,16 +56,26 @@ LL |     let a = [A("".to_string())][0];
    |             |
    |             cannot move out of here
    |             move occurs because value has type `A`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&[A("".to_string())][0]`
+   |
+help: consider borrowing here
+   |
+LL |     let a = &[A("".to_string())][0];
+   |             +
 
 error[E0507]: cannot move out of `a` which is behind a shared reference
   --> $DIR/move-errors.rs:38:16
    |
 LL |     let A(s) = *a;
-   |           -    ^^ help: consider borrowing here: `&*a`
+   |           -    ^^
    |           |
    |           data moved here
    |           move occurs because `s` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let A(s) = *a;
+LL +     let A(s) = a;
+   |
 
 error[E0509]: cannot move out of type `D`, which implements the `Drop` trait
   --> $DIR/move-errors.rs:44:19
@@ -62,6 +85,11 @@ LL |     let C(D(s)) = c;
    |             |
    |             data moved here
    |             move occurs because `s` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |     let C(D(ref s)) = c;
+   |             +++
 
 error[E0507]: cannot move out of `*a` which is behind a shared reference
   --> $DIR/move-errors.rs:51:9
@@ -73,10 +101,7 @@ error[E0508]: cannot move out of type `[B; 1]`, a non-copy array
   --> $DIR/move-errors.rs:74:11
    |
 LL |     match x[0] {
-   |           ^^^^
-   |           |
-   |           cannot move out of here
-   |           help: consider borrowing here: `&x[0]`
+   |           ^^^^ cannot move out of here
 LL |
 LL |         B::U(d) => (),
    |              - data moved here
@@ -84,6 +109,10 @@ LL |         B::V(s) => (),
    |              - ...and here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider borrowing here
+   |
+LL |     match &x[0] {
+   |           +
 
 error[E0509]: cannot move out of type `D`, which implements the `Drop` trait
   --> $DIR/move-errors.rs:83:11
@@ -96,6 +125,11 @@ LL |         B::U(D(s)) => (),
    |                |
    |                data moved here
    |                move occurs because `s` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |         B::U(D(ref s)) => (),
+   |                +++
 
 error[E0509]: cannot move out of type `D`, which implements the `Drop` trait
   --> $DIR/move-errors.rs:92:11
@@ -108,6 +142,11 @@ LL |         (D(s), &t) => (),
    |            |
    |            data moved here
    |            move occurs because `s` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |         (D(ref s), &t) => (),
+   |            +++
 
 error[E0507]: cannot move out of `*x.1` which is behind a shared reference
   --> $DIR/move-errors.rs:92:11
@@ -120,6 +159,11 @@ LL |         (D(s), &t) => (),
    |                 |
    |                 data moved here
    |                 move occurs because `t` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |         (D(s), &ref t) => (),
+   |                 +++
 
 error[E0509]: cannot move out of type `F`, which implements the `Drop` trait
   --> $DIR/move-errors.rs:102:11
@@ -133,18 +177,32 @@ LL |         F(s, mut t) => (),
    |           data moved here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider borrowing the pattern binding
+   |
+LL |         F(ref s, mut t) => (),
+   |           +++
+help: consider borrowing the pattern binding
+   |
+LL |         F(s, ref mut t) => (),
+   |              +++
 
 error[E0507]: cannot move out of `x` as enum variant `Err` which is behind a shared reference
   --> $DIR/move-errors.rs:110:11
    |
 LL |     match *x {
-   |           ^^ help: consider borrowing here: `&*x`
+   |           ^^
 LL |
 LL |         Ok(s) | Err(s) => (),
    |            -
    |            |
    |            data moved here
    |            move occurs because `s` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     match *x {
+LL +     match x {
+   |
 
 error: aborting due to 14 previous errors
 
index 9ae41e78c227dc769e9b2bde8ea00f4a6dcb6131..296e1fb3f26fe01319e36320608ee1c6365f6536 100644 (file)
@@ -13,11 +13,6 @@ LL |     assert_eq!((*arc_v)[2], 3);
    |                ^^^^^^^^ value borrowed here after move
    |
    = note: borrow occurs due to deref coercion to `Vec<i32>`
-note: deref defined here
-  --> $SRC_DIR/alloc/src/sync.rs:LL:COL
-   |
-LL |     type Target = T;
-   |     ^^^^^^^^^^^
 
 error: aborting due to previous error
 
index 564b05854740ccfc6b63771872fc52337c71d500..bcd481c33f361b374b7ee26aea00c8ce50a99a9e 100644 (file)
@@ -13,11 +13,6 @@ LL |     assert_eq!((*arc_v)[2], 3);
    |                ^^^^^^^^ value borrowed here after move
    |
    = note: borrow occurs due to deref coercion to `Vec<i32>`
-note: deref defined here
-  --> $SRC_DIR/alloc/src/sync.rs:LL:COL
-   |
-LL |     type Target = T;
-   |     ^^^^^^^^^^^
 
 error: aborting due to previous error
 
index c864b93dbbbe17aef49193dbc69acc3f43930b30..75561f4119aa543d432b53da3df5bdf2957a5074 100644 (file)
@@ -31,9 +31,6 @@ LL |     thread::spawn(move|| {
    |                   ^^^^^^
 note: required by a bound in `spawn`
   --> $SRC_DIR/std/src/thread/mod.rs:LL:COL
-   |
-LL |     F: Send + 'static,
-   |        ^^^^ required by this bound in `spawn`
 
 error: aborting due to previous error
 
index f61ee661bb7edbe205b97b68bcb99383eca8ae8c..37d94cf0ebd8c515e7c1d1db7fb7a01ad1276c34 100644 (file)
@@ -1,13 +1,11 @@
 error[E0277]: the trait bound `S: Clone` is not satisfied in `[closure@$DIR/not-clone-closure.rs:7:17: 7:24]`
-  --> $DIR/not-clone-closure.rs:11:17
+  --> $DIR/not-clone-closure.rs:11:23
    |
 LL |     let hello = move || {
    |                 ------- within this `[closure@$DIR/not-clone-closure.rs:7:17: 7:24]`
 ...
 LL |     let hello = hello.clone();
-   |                 ^^^^^ ----- required by a bound introduced by this call
-   |                 |
-   |                 within `[closure@$DIR/not-clone-closure.rs:7:17: 7:24]`, the trait `Clone` is not implemented for `S`
+   |                       ^^^^^ within `[closure@$DIR/not-clone-closure.rs:7:17: 7:24]`, the trait `Clone` is not implemented for `S`
    |
 note: required because it's used within this closure
   --> $DIR/not-clone-closure.rs:7:17
diff --git a/src/test/ui/numeric/uppercase-base-prefix-invalid-no-fix.rs b/src/test/ui/numeric/uppercase-base-prefix-invalid-no-fix.rs
new file mode 100644 (file)
index 0000000..f00cde4
--- /dev/null
@@ -0,0 +1,34 @@
+// Checks that integers with seeming uppercase base prefixes do not get bogus capitalization
+// suggestions.
+
+fn main() {
+    _ = 123X1a3;
+    //~^ ERROR invalid suffix `X1a3` for number literal
+    //~| NOTE invalid suffix `X1a3`
+    //~| HELP the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
+
+    _ = 456O123;
+    //~^ ERROR invalid suffix `O123` for number literal
+    //~| NOTE invalid suffix `O123`
+    //~| HELP the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
+
+    _ = 789B101;
+    //~^ ERROR invalid suffix `B101` for number literal
+    //~| NOTE invalid suffix `B101`
+    //~| HELP the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
+
+    _ = 0XYZ;
+    //~^ ERROR invalid suffix `XYZ` for number literal
+    //~| NOTE invalid suffix `XYZ`
+    //~| HELP the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
+
+    _ = 0OPQ;
+    //~^ ERROR invalid suffix `OPQ` for number literal
+    //~| NOTE invalid suffix `OPQ`
+    //~| HELP the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
+
+    _ = 0BCD;
+    //~^ ERROR invalid suffix `BCD` for number literal
+    //~| NOTE invalid suffix `BCD`
+    //~| HELP the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
+}
diff --git a/src/test/ui/numeric/uppercase-base-prefix-invalid-no-fix.stderr b/src/test/ui/numeric/uppercase-base-prefix-invalid-no-fix.stderr
new file mode 100644 (file)
index 0000000..380c16c
--- /dev/null
@@ -0,0 +1,50 @@
+error: invalid suffix `X1a3` for number literal
+  --> $DIR/uppercase-base-prefix-invalid-no-fix.rs:5:9
+   |
+LL |     _ = 123X1a3;
+   |         ^^^^^^^ invalid suffix `X1a3`
+   |
+   = help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
+
+error: invalid suffix `O123` for number literal
+  --> $DIR/uppercase-base-prefix-invalid-no-fix.rs:10:9
+   |
+LL |     _ = 456O123;
+   |         ^^^^^^^ invalid suffix `O123`
+   |
+   = help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
+
+error: invalid suffix `B101` for number literal
+  --> $DIR/uppercase-base-prefix-invalid-no-fix.rs:15:9
+   |
+LL |     _ = 789B101;
+   |         ^^^^^^^ invalid suffix `B101`
+   |
+   = help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
+
+error: invalid suffix `XYZ` for number literal
+  --> $DIR/uppercase-base-prefix-invalid-no-fix.rs:20:9
+   |
+LL |     _ = 0XYZ;
+   |         ^^^^ invalid suffix `XYZ`
+   |
+   = help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
+
+error: invalid suffix `OPQ` for number literal
+  --> $DIR/uppercase-base-prefix-invalid-no-fix.rs:25:9
+   |
+LL |     _ = 0OPQ;
+   |         ^^^^ invalid suffix `OPQ`
+   |
+   = help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
+
+error: invalid suffix `BCD` for number literal
+  --> $DIR/uppercase-base-prefix-invalid-no-fix.rs:30:9
+   |
+LL |     _ = 0BCD;
+   |         ^^^^ invalid suffix `BCD`
+   |
+   = help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
+
+error: aborting due to 6 previous errors
+
index c3103671178b5adc7e06d7e19decb33b13745048..2a316dba778fe8f0163c50c5178e3ae22e287f7f 100644 (file)
@@ -1,38 +1,42 @@
 error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `&()`
-  --> $DIR/sum.rs:4:5
+  --> $DIR/sum.rs:4:25
    |
 LL |     vec![(), ()].iter().sum::<i32>();
-   |     ^^^^^^^^^^^^^^^^^^^ --- required by a bound introduced by this call
-   |     |
-   |     value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=&()>`
+   |                         ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=&()>`
    |
    = help: the trait `Sum<&()>` is not implemented for `i32`
    = help: the following other types implement trait `Sum<A>`:
              <i32 as Sum<&'a i32>>
              <i32 as Sum>
+note: the method call chain might not have had the expected associated types
+  --> $DIR/sum.rs:4:18
+   |
+LL |     vec![(), ()].iter().sum::<i32>();
+   |     ------------ ^^^^^^ `Iterator::Item` is `&()` here
+   |     |
+   |     this expression has type `Vec<()>`
 note: required by a bound in `std::iter::Iterator::sum`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |         S: Sum<Self::Item>,
-   |            ^^^^^^^^^^^^^^^ required by this bound in `Iterator::sum`
 
 error[E0277]: a value of type `i32` cannot be made by multiplying all elements of type `&()` from an iterator
-  --> $DIR/sum.rs:7:5
+  --> $DIR/sum.rs:7:25
    |
 LL |     vec![(), ()].iter().product::<i32>();
-   |     ^^^^^^^^^^^^^^^^^^^ ------- required by a bound introduced by this call
-   |     |
-   |     value of type `i32` cannot be made by multiplying all elements from a `std::iter::Iterator<Item=&()>`
+   |                         ^^^^^^^ value of type `i32` cannot be made by multiplying all elements from a `std::iter::Iterator<Item=&()>`
    |
    = help: the trait `Product<&()>` is not implemented for `i32`
    = help: the following other types implement trait `Product<A>`:
              <i32 as Product<&'a i32>>
              <i32 as Product>
+note: the method call chain might not have had the expected associated types
+  --> $DIR/sum.rs:7:18
+   |
+LL |     vec![(), ()].iter().product::<i32>();
+   |     ------------ ^^^^^^ `Iterator::Item` is `&()` here
+   |     |
+   |     this expression has type `Vec<()>`
 note: required by a bound in `std::iter::Iterator::product`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |         P: Product<Self::Item>,
-   |            ^^^^^^^^^^^^^^^^^^^ required by this bound in `Iterator::product`
 
 error: aborting due to 2 previous errors
 
index 920720a4f53e2558afea17f400dfa896c3ee91cc..10d42b7e3c0b8de4892a98ee411bb38e709c8198 100644 (file)
@@ -35,11 +35,8 @@ note: an implementation of `BitOr<_>` might be missing for `E`
    |
 LL | enum E { A, B }
    | ^^^^^^ must implement `BitOr<_>`
-note: the following trait must be implemented
+note: the trait `BitOr` must be implemented
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
-   |
-LL | pub trait BitOr<Rhs = Self> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 5 previous errors
 
index 794535aeb11052adbc69329dfb59cb4727791172..2e16007825935a159bf5d213f332dd096b54d483 100644 (file)
@@ -6,9 +6,6 @@ LL | impl FnMut<isize> for S {
    |
 note: required by a bound in `FnMut`
   --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-LL | pub trait FnMut<Args: Tuple>: FnOnce<Args> {
-   |                       ^^^^^ required by this bound in `FnMut`
 
 error[E0059]: type parameter to bare `FnOnce` trait must be a tuple
   --> $DIR/overloaded-calls-nontuple.rs:18:6
@@ -18,9 +15,6 @@ LL | impl FnOnce<isize> for S {
    |
 note: required by a bound in `FnOnce`
   --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-LL | pub trait FnOnce<Args: Tuple> {
-   |                        ^^^^^ required by this bound in `FnOnce`
 
 error[E0277]: functions with the "rust-call" ABI must take a single non-self tuple argument
   --> $DIR/overloaded-calls-nontuple.rs:12:5
diff --git a/src/test/ui/parser/increment-autofix-2.fixed b/src/test/ui/parser/increment-autofix-2.fixed
new file mode 100644 (file)
index 0000000..580ebaf
--- /dev/null
@@ -0,0 +1,63 @@
+// run-rustfix
+
+struct Foo {
+    bar: Bar,
+}
+
+struct Bar {
+    qux: i32,
+}
+
+pub fn post_regular() {
+    let mut i = 0;
+    i += 1; //~ ERROR Rust has no postfix increment operator
+    println!("{}", i);
+}
+
+pub fn post_while() {
+    let mut i = 0;
+    while { let tmp = i; i += 1; tmp } < 5 {
+        //~^ ERROR Rust has no postfix increment operator
+        println!("{}", i);
+    }
+}
+
+pub fn post_regular_tmp() {
+    let mut tmp = 0;
+    tmp += 1; //~ ERROR Rust has no postfix increment operator
+    println!("{}", tmp);
+}
+
+pub fn post_while_tmp() {
+    let mut tmp = 0;
+    while { let tmp_ = tmp; tmp += 1; tmp_ } < 5 {
+        //~^ ERROR Rust has no postfix increment operator
+        println!("{}", tmp);
+    }
+}
+
+pub fn post_field() {
+    let mut foo = Foo { bar: Bar { qux: 0 } };
+    foo.bar.qux += 1;
+    //~^ ERROR Rust has no postfix increment operator
+    println!("{}", foo.bar.qux);
+}
+
+pub fn post_field_tmp() {
+    struct S {
+        tmp: i32
+    }
+    let mut s = S { tmp: 0 };
+    s.tmp += 1;
+    //~^ ERROR Rust has no postfix increment operator
+    println!("{}", s.tmp);
+}
+
+pub fn pre_field() {
+    let mut foo = Foo { bar: Bar { qux: 0 } };
+    foo.bar.qux += 1;
+    //~^ ERROR Rust has no prefix increment operator
+    println!("{}", foo.bar.qux);
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/increment-autofix-2.rs b/src/test/ui/parser/increment-autofix-2.rs
new file mode 100644 (file)
index 0000000..ebe5fa6
--- /dev/null
@@ -0,0 +1,63 @@
+// run-rustfix
+
+struct Foo {
+    bar: Bar,
+}
+
+struct Bar {
+    qux: i32,
+}
+
+pub fn post_regular() {
+    let mut i = 0;
+    i++; //~ ERROR Rust has no postfix increment operator
+    println!("{}", i);
+}
+
+pub fn post_while() {
+    let mut i = 0;
+    while i++ < 5 {
+        //~^ ERROR Rust has no postfix increment operator
+        println!("{}", i);
+    }
+}
+
+pub fn post_regular_tmp() {
+    let mut tmp = 0;
+    tmp++; //~ ERROR Rust has no postfix increment operator
+    println!("{}", tmp);
+}
+
+pub fn post_while_tmp() {
+    let mut tmp = 0;
+    while tmp++ < 5 {
+        //~^ ERROR Rust has no postfix increment operator
+        println!("{}", tmp);
+    }
+}
+
+pub fn post_field() {
+    let mut foo = Foo { bar: Bar { qux: 0 } };
+    foo.bar.qux++;
+    //~^ ERROR Rust has no postfix increment operator
+    println!("{}", foo.bar.qux);
+}
+
+pub fn post_field_tmp() {
+    struct S {
+        tmp: i32
+    }
+    let mut s = S { tmp: 0 };
+    s.tmp++;
+    //~^ ERROR Rust has no postfix increment operator
+    println!("{}", s.tmp);
+}
+
+pub fn pre_field() {
+    let mut foo = Foo { bar: Bar { qux: 0 } };
+    ++foo.bar.qux;
+    //~^ ERROR Rust has no prefix increment operator
+    println!("{}", foo.bar.qux);
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/increment-autofix-2.stderr b/src/test/ui/parser/increment-autofix-2.stderr
new file mode 100644 (file)
index 0000000..11e9854
--- /dev/null
@@ -0,0 +1,84 @@
+error: Rust has no postfix increment operator
+  --> $DIR/increment-autofix-2.rs:13:6
+   |
+LL |     i++;
+   |      ^^ not a valid postfix operator
+   |
+help: use `+= 1` instead
+   |
+LL |     i += 1;
+   |       ~~~~
+
+error: Rust has no postfix increment operator
+  --> $DIR/increment-autofix-2.rs:19:12
+   |
+LL |     while i++ < 5 {
+   |     -----  ^^ not a valid postfix operator
+   |     |
+   |     while parsing the condition of this `while` expression
+   |
+help: use `+= 1` instead
+   |
+LL |     while { let tmp = i; i += 1; tmp } < 5 {
+   |           +++++++++++  ~~~~~~~~~~~~~~~
+
+error: Rust has no postfix increment operator
+  --> $DIR/increment-autofix-2.rs:27:8
+   |
+LL |     tmp++;
+   |        ^^ not a valid postfix operator
+   |
+help: use `+= 1` instead
+   |
+LL |     tmp += 1;
+   |         ~~~~
+
+error: Rust has no postfix increment operator
+  --> $DIR/increment-autofix-2.rs:33:14
+   |
+LL |     while tmp++ < 5 {
+   |     -----    ^^ not a valid postfix operator
+   |     |
+   |     while parsing the condition of this `while` expression
+   |
+help: use `+= 1` instead
+   |
+LL |     while { let tmp_ = tmp; tmp += 1; tmp_ } < 5 {
+   |           ++++++++++++    ~~~~~~~~~~~~~~~~~~
+
+error: Rust has no postfix increment operator
+  --> $DIR/increment-autofix-2.rs:41:16
+   |
+LL |     foo.bar.qux++;
+   |                ^^ not a valid postfix operator
+   |
+help: use `+= 1` instead
+   |
+LL |     foo.bar.qux += 1;
+   |                 ~~~~
+
+error: Rust has no postfix increment operator
+  --> $DIR/increment-autofix-2.rs:51:10
+   |
+LL |     s.tmp++;
+   |          ^^ not a valid postfix operator
+   |
+help: use `+= 1` instead
+   |
+LL |     s.tmp += 1;
+   |           ~~~~
+
+error: Rust has no prefix increment operator
+  --> $DIR/increment-autofix-2.rs:58:5
+   |
+LL |     ++foo.bar.qux;
+   |     ^^ not a valid prefix operator
+   |
+help: use `+= 1` instead
+   |
+LL -     ++foo.bar.qux;
+LL +     foo.bar.qux += 1;
+   |
+
+error: aborting due to 7 previous errors
+
diff --git a/src/test/ui/parser/increment-notfixed.rs b/src/test/ui/parser/increment-notfixed.rs
deleted file mode 100644 (file)
index 15f159e..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-struct Foo {
-    bar: Bar,
-}
-
-struct Bar {
-    qux: i32,
-}
-
-pub fn post_regular() {
-    let mut i = 0;
-    i++; //~ ERROR Rust has no postfix increment operator
-    println!("{}", i);
-}
-
-pub fn post_while() {
-    let mut i = 0;
-    while i++ < 5 {
-        //~^ ERROR Rust has no postfix increment operator
-        println!("{}", i);
-    }
-}
-
-pub fn post_regular_tmp() {
-    let mut tmp = 0;
-    tmp++; //~ ERROR Rust has no postfix increment operator
-    println!("{}", tmp);
-}
-
-pub fn post_while_tmp() {
-    let mut tmp = 0;
-    while tmp++ < 5 {
-        //~^ ERROR Rust has no postfix increment operator
-        println!("{}", tmp);
-    }
-}
-
-pub fn post_field() {
-    let foo = Foo { bar: Bar { qux: 0 } };
-    foo.bar.qux++;
-    //~^ ERROR Rust has no postfix increment operator
-    println!("{}", foo.bar.qux);
-}
-
-pub fn post_field_tmp() {
-    struct S {
-        tmp: i32
-    }
-    let s = S { tmp: 0 };
-    s.tmp++;
-    //~^ ERROR Rust has no postfix increment operator
-    println!("{}", s.tmp);
-}
-
-pub fn pre_field() {
-    let foo = Foo { bar: Bar { qux: 0 } };
-    ++foo.bar.qux;
-    //~^ ERROR Rust has no prefix increment operator
-    println!("{}", foo.bar.qux);
-}
-
-fn main() {}
diff --git a/src/test/ui/parser/increment-notfixed.stderr b/src/test/ui/parser/increment-notfixed.stderr
deleted file mode 100644 (file)
index ae55ae0..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-error: Rust has no postfix increment operator
-  --> $DIR/increment-notfixed.rs:11:6
-   |
-LL |     i++;
-   |      ^^ not a valid postfix operator
-   |
-help: use `+= 1` instead
-   |
-LL |     { let tmp = i; i += 1; tmp };
-   |     +++++++++++  ~~~~~~~~~~~~~~~
-LL |     i += 1;
-   |       ~~~~
-
-error: Rust has no postfix increment operator
-  --> $DIR/increment-notfixed.rs:17:12
-   |
-LL |     while i++ < 5 {
-   |     -----  ^^ not a valid postfix operator
-   |     |
-   |     while parsing the condition of this `while` expression
-   |
-help: use `+= 1` instead
-   |
-LL |     while { let tmp = i; i += 1; tmp } < 5 {
-   |           +++++++++++  ~~~~~~~~~~~~~~~
-LL |     while i += 1 < 5 {
-   |             ~~~~
-
-error: Rust has no postfix increment operator
-  --> $DIR/increment-notfixed.rs:25:8
-   |
-LL |     tmp++;
-   |        ^^ not a valid postfix operator
-   |
-help: use `+= 1` instead
-   |
-LL |     { let tmp_ = tmp; tmp += 1; tmp_ };
-   |     ++++++++++++    ~~~~~~~~~~~~~~~~~~
-LL |     tmp += 1;
-   |         ~~~~
-
-error: Rust has no postfix increment operator
-  --> $DIR/increment-notfixed.rs:31:14
-   |
-LL |     while tmp++ < 5 {
-   |     -----    ^^ not a valid postfix operator
-   |     |
-   |     while parsing the condition of this `while` expression
-   |
-help: use `+= 1` instead
-   |
-LL |     while { let tmp_ = tmp; tmp += 1; tmp_ } < 5 {
-   |           ++++++++++++    ~~~~~~~~~~~~~~~~~~
-LL |     while tmp += 1 < 5 {
-   |               ~~~~
-
-error: Rust has no postfix increment operator
-  --> $DIR/increment-notfixed.rs:39:16
-   |
-LL |     foo.bar.qux++;
-   |                ^^ not a valid postfix operator
-   |
-help: use `+= 1` instead
-   |
-LL |     { let tmp = foo.bar.qux; foo.bar.qux += 1; tmp };
-   |     +++++++++++            ~~~~~~~~~~~~~~~~~~~~~~~~~
-LL |     foo.bar.qux += 1;
-   |                 ~~~~
-
-error: Rust has no postfix increment operator
-  --> $DIR/increment-notfixed.rs:49:10
-   |
-LL |     s.tmp++;
-   |          ^^ not a valid postfix operator
-   |
-help: use `+= 1` instead
-   |
-LL |     { let tmp = s.tmp; s.tmp += 1; tmp };
-   |     +++++++++++      ~~~~~~~~~~~~~~~~~~~
-LL |     s.tmp += 1;
-   |           ~~~~
-
-error: Rust has no prefix increment operator
-  --> $DIR/increment-notfixed.rs:56:5
-   |
-LL |     ++foo.bar.qux;
-   |     ^^ not a valid prefix operator
-   |
-help: use `+= 1` instead
-   |
-LL -     ++foo.bar.qux;
-LL +     foo.bar.qux += 1;
-   |
-
-error: aborting due to 7 previous errors
-
diff --git a/src/test/ui/parser/issue-104867-inc-dec-2.rs b/src/test/ui/parser/issue-104867-inc-dec-2.rs
new file mode 100644 (file)
index 0000000..a006421
--- /dev/null
@@ -0,0 +1,52 @@
+fn test1() {
+    let mut i = 0;
+    let _ = i + ++i; //~ ERROR Rust has no prefix increment operator
+}
+
+fn test2() {
+    let mut i = 0;
+    let _ = ++i + i; //~ ERROR Rust has no prefix increment operator
+}
+
+fn test3() {
+    let mut i = 0;
+    let _ = ++i + ++i; //~ ERROR Rust has no prefix increment operator
+}
+
+fn test4() {
+    let mut i = 0;
+    let _ = i + i++; //~ ERROR Rust has no postfix increment operator
+    // won't suggest since we can not handle the precedences
+}
+
+fn test5() {
+    let mut i = 0;
+    let _ = i++ + i; //~ ERROR Rust has no postfix increment operator
+}
+
+fn test6() {
+    let mut i = 0;
+    let _ = i++ + i++; //~ ERROR Rust has no postfix increment operator
+}
+
+fn test7() {
+    let mut i = 0;
+    let _ = ++i + i++; //~ ERROR Rust has no prefix increment operator
+}
+
+fn test8() {
+    let mut i = 0;
+    let _ = i++ + ++i; //~ ERROR Rust has no postfix increment operator
+}
+
+fn test9() {
+    let mut i = 0;
+    let _ = (1 + 2 + i)++; //~ ERROR Rust has no postfix increment operator
+}
+
+fn test10() {
+    let mut i = 0;
+    let _ = (i++ + 1) + 2; //~ ERROR Rust has no postfix increment operator
+}
+
+fn main() { }
diff --git a/src/test/ui/parser/issue-104867-inc-dec-2.stderr b/src/test/ui/parser/issue-104867-inc-dec-2.stderr
new file mode 100644 (file)
index 0000000..4e2d054
--- /dev/null
@@ -0,0 +1,107 @@
+error: Rust has no prefix increment operator
+  --> $DIR/issue-104867-inc-dec-2.rs:3:17
+   |
+LL |     let _ = i + ++i;
+   |                 ^^ not a valid prefix operator
+   |
+help: use `+= 1` instead
+   |
+LL |     let _ = i + { i += 1; i };
+   |                 ~   +++++++++
+
+error: Rust has no prefix increment operator
+  --> $DIR/issue-104867-inc-dec-2.rs:8:13
+   |
+LL |     let _ = ++i + i;
+   |             ^^ not a valid prefix operator
+   |
+help: use `+= 1` instead
+   |
+LL |     let _ = { i += 1; i } + i;
+   |             ~   +++++++++
+
+error: Rust has no prefix increment operator
+  --> $DIR/issue-104867-inc-dec-2.rs:13:13
+   |
+LL |     let _ = ++i + ++i;
+   |             ^^ not a valid prefix operator
+   |
+help: use `+= 1` instead
+   |
+LL |     let _ = { i += 1; i } + ++i;
+   |             ~   +++++++++
+
+error: Rust has no postfix increment operator
+  --> $DIR/issue-104867-inc-dec-2.rs:18:18
+   |
+LL |     let _ = i + i++;
+   |                  ^^ not a valid postfix operator
+
+error: Rust has no postfix increment operator
+  --> $DIR/issue-104867-inc-dec-2.rs:24:14
+   |
+LL |     let _ = i++ + i;
+   |              ^^ not a valid postfix operator
+   |
+help: use `+= 1` instead
+   |
+LL |     let _ = { let tmp = i; i += 1; tmp } + i;
+   |             +++++++++++  ~~~~~~~~~~~~~~~
+
+error: Rust has no postfix increment operator
+  --> $DIR/issue-104867-inc-dec-2.rs:29:14
+   |
+LL |     let _ = i++ + i++;
+   |              ^^ not a valid postfix operator
+   |
+help: use `+= 1` instead
+   |
+LL |     let _ = { let tmp = i; i += 1; tmp } + i++;
+   |             +++++++++++  ~~~~~~~~~~~~~~~
+
+error: Rust has no prefix increment operator
+  --> $DIR/issue-104867-inc-dec-2.rs:34:13
+   |
+LL |     let _ = ++i + i++;
+   |             ^^ not a valid prefix operator
+   |
+help: use `+= 1` instead
+   |
+LL |     let _ = { i += 1; i } + i++;
+   |             ~   +++++++++
+
+error: Rust has no postfix increment operator
+  --> $DIR/issue-104867-inc-dec-2.rs:39:14
+   |
+LL |     let _ = i++ + ++i;
+   |              ^^ not a valid postfix operator
+   |
+help: use `+= 1` instead
+   |
+LL |     let _ = { let tmp = i; i += 1; tmp } + ++i;
+   |             +++++++++++  ~~~~~~~~~~~~~~~
+
+error: Rust has no postfix increment operator
+  --> $DIR/issue-104867-inc-dec-2.rs:44:24
+   |
+LL |     let _ = (1 + 2 + i)++;
+   |                        ^^ not a valid postfix operator
+   |
+help: use `+= 1` instead
+   |
+LL |     let _ = { let tmp = (1 + 2 + i); (1 + 2 + i) += 1; tmp };
+   |             +++++++++++            ~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: Rust has no postfix increment operator
+  --> $DIR/issue-104867-inc-dec-2.rs:49:15
+   |
+LL |     let _ = (i++ + 1) + 2;
+   |               ^^ not a valid postfix operator
+   |
+help: use `+= 1` instead
+   |
+LL |     let _ = ({ let tmp = i; i += 1; tmp } + 1) + 2;
+   |              +++++++++++  ~~~~~~~~~~~~~~~
+
+error: aborting due to 10 previous errors
+
diff --git a/src/test/ui/parser/issue-104867-inc-dec.rs b/src/test/ui/parser/issue-104867-inc-dec.rs
new file mode 100644 (file)
index 0000000..760c67b
--- /dev/null
@@ -0,0 +1,45 @@
+struct S {
+    x: i32,
+}
+
+fn test1() {
+    let mut i = 0;
+    i++; //~ ERROR Rust has no postfix increment operator
+}
+
+fn test2() {
+    let s = S { x: 0 };
+    s.x++; //~ ERROR Rust has no postfix increment operator
+}
+
+fn test3() {
+    let mut i = 0;
+    if i++ == 1 {} //~ ERROR Rust has no postfix increment operator
+}
+
+fn test4() {
+    let mut i = 0;
+    ++i; //~ ERROR Rust has no prefix increment operator
+}
+
+fn test5() {
+    let mut i = 0;
+    if ++i == 1 { } //~ ERROR Rust has no prefix increment operator
+}
+
+fn test6() {
+    let mut i = 0;
+    loop { break; }
+    i++; //~ ERROR Rust has no postfix increment operator
+    loop { break; }
+    ++i;
+}
+
+fn test7() {
+    let mut i = 0;
+    loop { break; }
+    ++i; //~ ERROR Rust has no prefix increment operator
+}
+
+
+fn main() {}
diff --git a/src/test/ui/parser/issue-104867-inc-dec.stderr b/src/test/ui/parser/issue-104867-inc-dec.stderr
new file mode 100644 (file)
index 0000000..78bfd3e
--- /dev/null
@@ -0,0 +1,81 @@
+error: Rust has no postfix increment operator
+  --> $DIR/issue-104867-inc-dec.rs:7:6
+   |
+LL |     i++;
+   |      ^^ not a valid postfix operator
+   |
+help: use `+= 1` instead
+   |
+LL |     i += 1;
+   |       ~~~~
+
+error: Rust has no postfix increment operator
+  --> $DIR/issue-104867-inc-dec.rs:12:8
+   |
+LL |     s.x++;
+   |        ^^ not a valid postfix operator
+   |
+help: use `+= 1` instead
+   |
+LL |     s.x += 1;
+   |         ~~~~
+
+error: Rust has no postfix increment operator
+  --> $DIR/issue-104867-inc-dec.rs:17:9
+   |
+LL |     if i++ == 1 {}
+   |         ^^ not a valid postfix operator
+   |
+help: use `+= 1` instead
+   |
+LL |     if { let tmp = i; i += 1; tmp } == 1 {}
+   |        +++++++++++  ~~~~~~~~~~~~~~~
+
+error: Rust has no prefix increment operator
+  --> $DIR/issue-104867-inc-dec.rs:22:5
+   |
+LL |     ++i;
+   |     ^^ not a valid prefix operator
+   |
+help: use `+= 1` instead
+   |
+LL -     ++i;
+LL +     i += 1;
+   |
+
+error: Rust has no prefix increment operator
+  --> $DIR/issue-104867-inc-dec.rs:27:8
+   |
+LL |     if ++i == 1 { }
+   |        ^^ not a valid prefix operator
+   |
+help: use `+= 1` instead
+   |
+LL |     if { i += 1; i } == 1 { }
+   |        ~   +++++++++
+
+error: Rust has no postfix increment operator
+  --> $DIR/issue-104867-inc-dec.rs:33:6
+   |
+LL |     i++;
+   |      ^^ not a valid postfix operator
+   |
+help: use `+= 1` instead
+   |
+LL |     i += 1;
+   |       ~~~~
+
+error: Rust has no prefix increment operator
+  --> $DIR/issue-104867-inc-dec.rs:41:5
+   |
+LL |     ++i;
+   |     ^^ not a valid prefix operator
+   |
+help: use `+= 1` instead
+   |
+LL -     ++i;
+LL +     i += 1;
+   |
+
+error: aborting due to 7 previous errors
+
diff --git a/src/test/ui/parser/issue-105366.fixed b/src/test/ui/parser/issue-105366.fixed
new file mode 100644 (file)
index 0000000..ad26643
--- /dev/null
@@ -0,0 +1,12 @@
+// run-rustfix
+
+struct Foo;
+
+impl From<i32> for Foo {
+    //~^ ERROR you might have meant to write `impl` instead of `fn`
+    fn from(_a: i32) -> Self {
+        Foo
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/issue-105366.rs b/src/test/ui/parser/issue-105366.rs
new file mode 100644 (file)
index 0000000..311b6a6
--- /dev/null
@@ -0,0 +1,12 @@
+// run-rustfix
+
+struct Foo;
+
+fn From<i32> for Foo {
+    //~^ ERROR you might have meant to write `impl` instead of `fn`
+    fn from(_a: i32) -> Self {
+        Foo
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/issue-105366.stderr b/src/test/ui/parser/issue-105366.stderr
new file mode 100644 (file)
index 0000000..0a7408e
--- /dev/null
@@ -0,0 +1,13 @@
+error: you might have meant to write `impl` instead of `fn`
+  --> $DIR/issue-105366.rs:5:1
+   |
+LL | fn From<i32> for Foo {
+   | ^^
+   |
+help: replace `fn` with `impl` here
+   |
+LL | impl From<i32> for Foo {
+   | ~~~~
+
+error: aborting due to previous error
+
index ae89926914ebaa7d6c4592d6df24afdf2ea2e64f..07a203bf416eada152c3ca9da8e11d59d0c7ccd3 100644 (file)
@@ -42,11 +42,9 @@ LL | fn f() { assert_eq!(f(), (), assert_eq!(assert_eq!
 LL |
 LL | fn main() {}
    | ^^ unexpected token
+  --> $SRC_DIR/core/src/macros/mod.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/macros/mod.rs:LL:COL
-   |
-LL |     ($left:expr, $right:expr $(,)?) => {
-   |      ---------- while parsing argument for this `expr` macro fragment
+   = note: while parsing argument for this `expr` macro fragment
 
 error: aborting due to 4 previous errors
 
index 546ad84eeee7bf25abbb3c1caa44db0dc7f3b224..79643660e8b0078c73e70de919e0fd285dc0f415 100644 (file)
@@ -91,44 +91,36 @@ error[E0405]: cannot find trait `r#fn` in this scope
    |
 LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
    |          ^^ help: a trait with a similar name exists (notice the capitalization): `Fn`
+  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
-   | -------------------------------------- similarly named trait `Fn` defined here
+   = note: similarly named trait `Fn` defined here
 
 error[E0405]: cannot find trait `r#fn` in this scope
   --> $DIR/kw-in-trait-bounds.rs:17:4
    |
 LL | G: fn(),
    |    ^^ help: a trait with a similar name exists (notice the capitalization): `Fn`
+  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
-   | -------------------------------------- similarly named trait `Fn` defined here
+   = note: similarly named trait `Fn` defined here
 
 error[E0405]: cannot find trait `r#fn` in this scope
   --> $DIR/kw-in-trait-bounds.rs:3:27
    |
 LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
    |                           ^^ help: a trait with a similar name exists (notice the capitalization): `Fn`
+  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
-   | -------------------------------------- similarly named trait `Fn` defined here
+   = note: similarly named trait `Fn` defined here
 
 error[E0405]: cannot find trait `r#fn` in this scope
   --> $DIR/kw-in-trait-bounds.rs:3:41
    |
 LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
    |                                         ^^ help: a trait with a similar name exists (notice the capitalization): `Fn`
+  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
-   | -------------------------------------- similarly named trait `Fn` defined here
+   = note: similarly named trait `Fn` defined here
 
 error[E0405]: cannot find trait `r#struct` in this scope
   --> $DIR/kw-in-trait-bounds.rs:24:10
diff --git a/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.fixed b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.fixed
new file mode 100644 (file)
index 0000000..5f04fc8
--- /dev/null
@@ -0,0 +1,12 @@
+// run-rustfix
+#![allow(unused_variables)]
+fn main() {
+    struct U;
+
+    // A tuple is a "non-reference pattern".
+    // A `mut` binding pattern resets the binding mode to by-value.
+
+    let mut p = (U, U);
+    let (a, ref mut b) = &mut p;
+    //~^ ERROR cannot move out of a mutable reference
+}
diff --git a/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.rs b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.rs
new file mode 100644 (file)
index 0000000..5dc1ae2
--- /dev/null
@@ -0,0 +1,12 @@
+// run-rustfix
+#![allow(unused_variables)]
+fn main() {
+    struct U;
+
+    // A tuple is a "non-reference pattern".
+    // A `mut` binding pattern resets the binding mode to by-value.
+
+    let mut p = (U, U);
+    let (a, mut b) = &mut p;
+    //~^ ERROR cannot move out of a mutable reference
+}
diff --git a/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.stderr b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.stderr
new file mode 100644 (file)
index 0000000..d3ab533
--- /dev/null
@@ -0,0 +1,17 @@
+error[E0507]: cannot move out of a mutable reference
+  --> $DIR/move-ref-patterns-default-binding-modes-fixable.rs:10:22
+   |
+LL |     let (a, mut b) = &mut p;
+   |             -----    ^^^^^^
+   |             |
+   |             data moved here
+   |             move occurs because `b` has type `U`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |     let (a, ref mut b) = &mut p;
+   |             +++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
index 1dd66aad57a33f71afe27f1c0362f54c064db53b..6c913c245130d7307b7c8361731568bbc76385b1 100644 (file)
@@ -7,8 +7,4 @@ fn main() {
     let p = (U, U);
     let (a, mut b) = &p;
     //~^ ERROR cannot move out of a shared reference
-
-    let mut p = (U, U);
-    let (a, mut b) = &mut p;
-    //~^ ERROR cannot move out of a mutable reference
 }
index 6952c743a3069e5d6dd1f8072abcb8d47e24f6bb..65030b62250012729961a9f6938d6d012a4b1dd0 100644 (file)
@@ -6,16 +6,12 @@ LL |     let (a, mut b) = &p;
    |             |
    |             data moved here
    |             move occurs because `b` has type `U`, which does not implement the `Copy` trait
-
-error[E0507]: cannot move out of a mutable reference
-  --> $DIR/move-ref-patterns-default-binding-modes.rs:12:22
    |
-LL |     let (a, mut b) = &mut p;
-   |             -----    ^^^^^^
-   |             |
-   |             data moved here
-   |             move occurs because `b` has type `U`, which does not implement the `Copy` trait
+help: consider borrowing the pattern binding
+   |
+LL |     let (a, ref mut b) = &p;
+   |             +++
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0507`.
index 3342b8e4002b909ce770b6aceeef2b8aaec128a9..da369d33397fc0c5df6f2b6739a727b920d9e86c 100644 (file)
@@ -9,8 +9,8 @@ LL |         (..) => {}
    |
 help: consider giving `x` an explicit type
    |
-LL |     let x: _;
-   |          +++
+LL |     let x: /* Type */;
+   |          ++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/pat-tuple-bad-type.rs:10:9
index e6a4e5f19b716ecd44949a0fe713ab756944fc41..beba7def96f5236034d546819979f3e0f4b7eb17 100644 (file)
@@ -193,8 +193,8 @@ LL |     let x @ ..;
    |
 help: consider giving this pattern a type
    |
-LL |     let x @ ..: _;
-   |               +++
+LL |     let x @ ..: /* Type */;
+   |               ++++++++++++
 
 error: aborting due to 23 previous errors
 
index f3dca9bcb07d1f42b6ca0e3b628cefea64441f43..2a016048f2f7a03c38464de94af8c4ba0d0021a0 100644 (file)
@@ -6,12 +6,9 @@ LL |     match Some(1) {
    |
 note: `Option<i32>` defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
+  ::: $SRC_DIR/core/src/option.rs:LL:COL
    |
-LL | pub enum Option<T> {
-   | ------------------
-...
-LL |     None,
-   |     ^^^^ not covered
+   = note: not covered
    = note: the matched value is of type `Option<i32>`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
index b450a9aeddf8d71f5cfd19de3a4ab80e7e3306c3..17e1a2304a13c0c8011481553170e1886fc11e5e 100644 (file)
@@ -66,12 +66,9 @@ LL |     match None {
    |
 note: `Option<HiddenEnum>` defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
+  ::: $SRC_DIR/core/src/option.rs:LL:COL
    |
-LL | pub enum Option<T> {
-   | ------------------
-...
-LL |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^^^ not covered
+   = note: not covered
    = note: the matched value is of type `Option<HiddenEnum>`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
    |
index c9781d52e6dcf529a79639257c79e9a238be0e5b..12113957d6340dbc0862060d0b2072ed0ba124d4 100644 (file)
@@ -107,9 +107,6 @@ LL |     match Some(A) {
    |
 note: `Option<Enum>` defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL | pub enum Option<T> {
-   | ^^^^^^^^^^^^^^^^^^
    = note: the matched value is of type `Option<Enum>`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
    |
index eb8c63919b6445fbd4576ffec0af6968e62a3a7f..59d7bcd4b5e799d443b90374b7b18d6b2eef5d10 100644 (file)
@@ -6,12 +6,6 @@ LL |         box NodeKind::Element(ed) => match ed.kind {
    |
 note: `Box<ElementKind>` defined here
   --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
-   |
-LL | / pub struct Box<
-LL | |     T: ?Sized,
-LL | |     #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
-LL | | >(Unique<T>, A);
-   | |_^
    = note: the matched value is of type `Box<ElementKind>`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
index b0d7fe5eb6892174c9c92821a39d7abdf9cdbc31..e4dd35a59958ef37f2dc2ed58508168472bec0af 100644 (file)
@@ -19,15 +19,11 @@ LL |     match Some(Some(North)) {
    |
 note: `Option<Option<Direction>>` defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
+  ::: $SRC_DIR/core/src/option.rs:LL:COL
    |
-LL | pub enum Option<T> {
-   | ------------------
-...
-LL |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^^^
-   |     |
-   |     not covered
-   |     not covered
+   = note: not covered
+   |
+   = note: not covered
    = note: the matched value is of type `Option<Option<Direction>>`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
index 4607cfaae1719db36dfec2abc9bc7270ab8fb073..86f75d15cfde7736c2294be1373bd6c9b605993b 100644 (file)
@@ -6,12 +6,9 @@ LL |     match private::DATA {
    |
 note: `Option<Private>` defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
+  ::: $SRC_DIR/core/src/option.rs:LL:COL
    |
-LL | pub enum Option<T> {
-   | ------------------
-...
-LL |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^^^ not covered
+   = note: not covered
    = note: the matched value is of type `Option<Private>`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
index 4234600d0d02f75144dd41ef900ea1681d522aa6..e2260f50bfef2b462fa795ace1352d6a714f7916 100644 (file)
@@ -36,12 +36,9 @@ LL |     match Some(10) {
    |
 note: `Option<i32>` defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
+  ::: $SRC_DIR/core/src/option.rs:LL:COL
    |
-LL | pub enum Option<T> {
-   | ------------------
-...
-LL |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^^^ not covered
+   = note: not covered
    = note: the matched value is of type `Option<i32>`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
index 3491ad5afbc1501100d192a234e567a7f892bf47..1598b0696913b6e18dc59a2ed556a3505b3f9367 100644 (file)
@@ -1,19 +1,11 @@
-// compile-flags: -Z print-type-sizes
+// compile-flags: -Z print-type-sizes --crate-type lib
 // edition:2021
 // build-pass
 // ignore-pass
 
-#![feature(start)]
-
 async fn wait() {}
 
-async fn test(arg: [u8; 8192]) {
+pub async fn test(arg: [u8; 8192]) {
     wait().await;
     drop(arg);
 }
-
-#[start]
-fn start(_: isize, _: *const *const u8) -> isize {
-    let _ = test([0; 8192]);
-    0
-}
index 94ad09ef296d3b15b713c3e5dc68adf8596671eb..6e47bb4930dc5306e8666c1e8fb7d407706398bc 100644 (file)
@@ -1,4 +1,4 @@
-print-type-size type: `[async fn body@$DIR/async.rs:10:32: 13:2]`: 16386 bytes, alignment: 1 bytes
+print-type-size type: `[async fn body@$DIR/async.rs:8:36: 11:2]`: 16386 bytes, alignment: 1 bytes
 print-type-size     discriminant: 1 bytes
 print-type-size     variant `Suspend0`: 16385 bytes
 print-type-size         field `.arg`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
@@ -16,14 +16,14 @@ print-type-size type: `std::mem::MaybeUninit<[u8; 8192]>`: 8192 bytes, alignment
 print-type-size     variant `MaybeUninit`: 8192 bytes
 print-type-size         field `.uninit`: 0 bytes
 print-type-size         field `.value`: 8192 bytes
-print-type-size type: `[async fn body@$DIR/async.rs:8:17: 8:19]`: 1 bytes, alignment: 1 bytes
+print-type-size type: `[async fn body@$DIR/async.rs:6:17: 6:19]`: 1 bytes, alignment: 1 bytes
 print-type-size     discriminant: 1 bytes
 print-type-size     variant `Unresumed`: 0 bytes
 print-type-size     variant `Returned`: 0 bytes
 print-type-size     variant `Panicked`: 0 bytes
-print-type-size type: `std::mem::ManuallyDrop<[async fn body@$DIR/async.rs:8:17: 8:19]>`: 1 bytes, alignment: 1 bytes
+print-type-size type: `std::mem::ManuallyDrop<[async fn body@$DIR/async.rs:6:17: 6:19]>`: 1 bytes, alignment: 1 bytes
 print-type-size     field `.value`: 1 bytes
-print-type-size type: `std::mem::MaybeUninit<[async fn body@$DIR/async.rs:8:17: 8:19]>`: 1 bytes, alignment: 1 bytes
+print-type-size type: `std::mem::MaybeUninit<[async fn body@$DIR/async.rs:6:17: 6:19]>`: 1 bytes, alignment: 1 bytes
 print-type-size     variant `MaybeUninit`: 1 bytes
 print-type-size         field `.uninit`: 0 bytes
 print-type-size         field `.value`: 1 bytes
index a46db6121046b999834f4ab76759263a687accc4..d1cd36274ef3e88970904b45708405415f0fa959 100644 (file)
@@ -1,8 +1,8 @@
-// compile-flags: -Z print-type-sizes
+// compile-flags: -Z print-type-sizes --crate-type=lib
 // build-pass
 // ignore-pass
 
-#![feature(start, generators, generator_trait)]
+#![feature(generators, generator_trait)]
 
 use std::ops::Generator;
 
@@ -13,8 +13,6 @@
     }
 }
 
-#[start]
-fn start(_: isize, _: *const *const u8) -> isize {
+pub fn foo() {
     let _ = generator([0; 8192]);
-    0
 }
diff --git a/src/test/ui/print_type_sizes/generator_discr_placement.rs b/src/test/ui/print_type_sizes/generator_discr_placement.rs
new file mode 100644 (file)
index 0000000..1a85fe9
--- /dev/null
@@ -0,0 +1,23 @@
+// compile-flags: -Z print-type-sizes --crate-type lib
+// build-pass
+// ignore-pass
+
+// Tests a generator that has its discriminant as the *final* field.
+
+// Avoid emitting panic handlers, like the rest of these tests...
+#![feature(generators)]
+
+pub fn foo() {
+    let a = || {
+        {
+            let w: i32 = 4;
+            yield;
+            drop(w);
+        }
+        {
+            let z: i32 = 7;
+            yield;
+            drop(z);
+        }
+    };
+}
diff --git a/src/test/ui/print_type_sizes/generator_discr_placement.stdout b/src/test/ui/print_type_sizes/generator_discr_placement.stdout
new file mode 100644 (file)
index 0000000..7f8f4cc
--- /dev/null
@@ -0,0 +1,11 @@
+print-type-size type: `[generator@$DIR/generator_discr_placement.rs:11:13: 11:15]`: 8 bytes, alignment: 4 bytes
+print-type-size     discriminant: 1 bytes
+print-type-size     variant `Suspend0`: 7 bytes
+print-type-size         padding: 3 bytes
+print-type-size         field `.w`: 4 bytes, alignment: 4 bytes
+print-type-size     variant `Suspend1`: 7 bytes
+print-type-size         padding: 3 bytes
+print-type-size         field `.z`: 4 bytes, alignment: 4 bytes
+print-type-size     variant `Unresumed`: 0 bytes
+print-type-size     variant `Returned`: 0 bytes
+print-type-size     variant `Panicked`: 0 bytes
index 3ef7b60db2caee840885f4631d0b169f90fc3757..05097087d5a811e1c07a8e36bb50b755aa0941e6 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: -Z print-type-sizes
+// compile-flags: -Z print-type-sizes --crate-type=lib
 // build-pass
 // ignore-pass
 // ^-- needed because `--pass check` does not emit the output needed.
@@ -8,24 +8,6 @@
 // monomorphized, in the MIR of the original function in which they
 // occur, to have their size reported.
 
-#![feature(start)]
-
-// In an ad-hoc attempt to avoid the injection of unwinding code
-// (which clutters the output of `-Z print-type-sizes` with types from
-// `unwind::libunwind`):
-//
-//   * I am not using Default to build values because that seems to
-//     cause the injection of unwinding code. (Instead I just make `fn new`
-//     methods.)
-//
-//   * Pair derive Copy to ensure that we don't inject
-//     unwinding code into generic uses of Pair when T itself is also
-//     Copy.
-//
-//     (I suspect this reflect some naivety within the rust compiler
-//      itself; it should be checking for drop glue, i.e., a destructor
-//      somewhere in the monomorphized types. It should not matter whether
-//      the type is Copy.)
 #[derive(Copy, Clone)]
 pub struct Pair<T> {
     _car: T,
@@ -61,11 +43,9 @@ pub fn f1<T:Copy>(x: T) {
         Pair::new(FiftyBytes::new(), FiftyBytes::new());
 }
 
-#[start]
-fn start(_: isize, _: *const *const u8) -> isize {
+pub fn start() {
     let _b: Pair<u8> = Pair::new(0, 0);
     let _s: Pair<SevenBytes> = Pair::new(SevenBytes::new(), SevenBytes::new());
     let ref _z: ZeroSized = ZeroSized;
     f1::<SevenBytes>(SevenBytes::new());
-    0
 }
index f1ad27ec131371988f2e0810fc4c709646dfb28b..9159038924719f288091a30166a4a362b2a7fc07 100644 (file)
@@ -1,11 +1,9 @@
-// compile-flags: -Z print-type-sizes
+// compile-flags: -Z print-type-sizes --crate-type=lib
 // build-pass
 
 // This file illustrates that when multiple structural types occur in
 // a function, every one of them is included in the output.
 
-#![feature(start)]
-
 pub struct SevenBytes([u8;  7]);
 pub struct FiftyBytes([u8; 50]);
 
@@ -13,11 +11,3 @@ pub enum Enum {
     Small(SevenBytes),
     Large(FiftyBytes),
 }
-
-#[start]
-fn start(_: isize, _: *const *const u8) -> isize {
-    let _e: Enum;
-    let _f: FiftyBytes;
-    let _s: SevenBytes;
-    0
-}
index 0716cee21c6626a71670081e752d2abdddc11775..5e620f248b65d35b1dd4243686249b7cb44aac46 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: -Z print-type-sizes
+// compile-flags: -Z print-type-sizes --crate-type=lib
 // build-pass
 // ignore-pass
 // ^-- needed because `--pass check` does not emit the output needed.
@@ -14,7 +14,6 @@
 // aligned (while on most it is 8-byte aligned) and so the resulting
 // padding and overall computed sizes can be quite different.
 
-#![feature(start)]
 #![feature(rustc_attrs)]
 #![allow(dead_code)]
 
@@ -56,7 +55,7 @@ pub struct NestedNonZero {
 
 impl Default for NestedNonZero {
     fn default() -> Self {
-        NestedNonZero { pre: 0, val: NonZeroU32::new(1).unwrap(), post: 0 }
+        NestedNonZero { pre: 0, val: unsafe { NonZeroU32::new_unchecked(1) }, post: 0 }
     }
 }
 
@@ -76,8 +75,7 @@ pub union Union2<A: Copy, B: Copy> {
     b: B,
 }
 
-#[start]
-fn start(_: isize, _: *const *const u8) -> isize {
+pub fn test() {
     let _x: MyOption<NonZeroU32> = Default::default();
     let _y: EmbeddedDiscr = Default::default();
     let _z: MyOption<IndirectNonZero> = Default::default();
@@ -96,6 +94,4 @@ fn start(_: isize, _: *const *const u8) -> isize {
     // ...even when theoretically possible.
     let _j: MyOption<Union1<NonZeroU32>> = Default::default();
     let _k: MyOption<Union2<NonZeroU32, NonZeroU32>> = Default::default();
-
-    0
 }
index e45e4794a3526a754357c88511c647a8d5637677..2ec5d9e64bfbfbad3de1496e7cdf2773002d6194 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: -Z print-type-sizes
+// compile-flags: -Z print-type-sizes --crate-type=lib
 // build-pass
 // ignore-pass
 // ^-- needed because `--pass check` does not emit the output needed.
@@ -8,16 +8,12 @@
 // (even if multiple functions), it is only printed once in the
 // print-type-sizes output.
 
-#![feature(start)]
-
 pub struct SevenBytes([u8; 7]);
 
 pub fn f1() {
     let _s: SevenBytes = SevenBytes([0; 7]);
 }
 
-#[start]
-fn start(_: isize, _: *const *const u8) -> isize {
+pub fn test() {
     let _s: SevenBytes = SevenBytes([0; 7]);
-    0
 }
index 269cc3cc2825fccc97c3991c15f7c61f43ba6705..5ddfe4bf4dbb0a9bfaed5ac3a2a0a95547de2da9 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: -Z print-type-sizes
+// compile-flags: -Z print-type-sizes --crate-type=lib
 // build-pass
 // ignore-pass
 // ^-- needed because `--pass check` does not emit the output needed.
 // padding and overall computed sizes can be quite different.
 
 #![allow(dead_code)]
-#![feature(start)]
 
 #[derive(Default)]
 #[repr(packed)]
-struct Packed1 {
+pub struct Packed1 {
     a: u8,
     b: u8,
     g: i32,
@@ -28,7 +27,7 @@ struct Packed1 {
 
 #[derive(Default)]
 #[repr(packed(2))]
-struct Packed2 {
+pub struct Packed2 {
     a: u8,
     b: u8,
     g: i32,
@@ -40,7 +39,7 @@ struct Packed2 {
 #[derive(Default)]
 #[repr(packed(2))]
 #[repr(C)]
-struct Packed2C {
+pub struct Packed2C {
     a: u8,
     b: u8,
     g: i32,
@@ -50,7 +49,7 @@ struct Packed2C {
 }
 
 #[derive(Default)]
-struct Padded {
+pub struct Padded {
     a: u8,
     b: u8,
     g: i32,
@@ -58,12 +57,3 @@ struct Padded {
     h: i16,
     d: u8,
 }
-
-#[start]
-fn start(_: isize, _: *const *const u8) -> isize {
-    let _c: Packed1 = Default::default();
-    let _d: Packed2 = Default::default();
-    let _e: Packed2C = Default::default();
-    let _f: Padded = Default::default();
-    0
-}
index d1acad16d7e1d3a60a13b290408b751f2f1ae406..f41c677dc6c08ff7bd0a0b61c489b677fbd89b2c 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: -Z print-type-sizes
+// compile-flags: -Z print-type-sizes --crate-type=lib
 // build-pass
 
 // This file illustrates how padding is handled: alignment
@@ -9,7 +9,6 @@
 // aligned (while on most it is 8-byte aligned) and so the resulting
 // padding and overall computed sizes can be quite different.
 
-#![feature(start)]
 #![allow(dead_code)]
 
 struct S {
@@ -27,8 +26,3 @@ enum E2 {
     A(i8, i32),
     B(S),
 }
-
-#[start]
-fn start(_: isize, _: *const *const u8) -> isize {
-    0
-}
index 07544935b2f828480eafeceff869d76898ff001b..0bd11ebc958433a3369b7addf8a8d2213be792d2 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: -Z print-type-sizes
+// compile-flags: -Z print-type-sizes --crate-type=lib
 // build-pass
 // ignore-pass
 // ^-- needed because `--pass check` does not emit the output needed.
@@ -11,7 +11,7 @@
 // It avoids using u64/i64 because on some targets that is only 4-byte
 // aligned (while on most it is 8-byte aligned) and so the resulting
 // padding and overall computed sizes can be quite different.
-#![feature(start)]
+
 #![allow(dead_code)]
 
 #[repr(align(16))]
@@ -24,15 +24,9 @@ enum E {
 }
 
 #[derive(Default)]
-struct S {
+pub struct S {
     a: i32,
     b: i32,
     c: A,
     d: i8,
 }
-
-#[start]
-fn start(_: isize, _: *const *const u8) -> isize {
-    let _s: S = Default::default();
-    0
-}
index b8067c112eef13c974e2d8f12afeba90feb80c40..6b103776a30d3c6c700a85cf3a242f4661edc8ee 100644 (file)
@@ -1,10 +1,9 @@
-// compile-flags: -Z print-type-sizes
+// compile-flags: -Z print-type-sizes --crate-type=lib
 // build-pass
 
 // This test makes sure that the tag is not grown for `repr(C)` or `repr(u8)`
 // variants (see https://github.com/rust-lang/rust/issues/50098 for the original bug).
 
-#![feature(start)]
 #![allow(dead_code)]
 
 #[repr(C, u8)]
@@ -18,8 +17,3 @@ enum Repru8 {
     A(u16),
     B,
 }
-
-#[start]
-fn start(_: isize, _: *const *const u8) -> isize {
-    0
-}
index 06a62db4ebb0f37014d835f0e71fc2f2fe85ad25..86fab7b500af08030a7acca69d30b776a5724a3a 100644 (file)
@@ -1,14 +1,12 @@
-// compile-flags: -Z print-type-sizes
+// compile-flags: -Z print-type-sizes --crate-type=lib
 // build-pass
 // ignore-pass
 // ^-- needed because `--pass check` does not emit the output needed.
 //     FIXME: consider using an attribute instead of side-effects.
 
 #![feature(never_type)]
-#![feature(start)]
 
-#[start]
-fn start(_: isize, _: *const *const u8) -> isize {
+pub fn test() {
     let _x: Option<!> = None;
     let _y: Result<u32, !> = Ok(42);
     let _z: Result<!, !> = loop {};
index 6c8553cc23ded83bffdef6a0a643b9bd099970df..5a3020520265db95a15f4857f10cfa2f0655e1ba 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: -Z print-type-sizes
+// compile-flags: -Z print-type-sizes --crate-type=lib
 // build-pass
 
 // This file illustrates two things:
@@ -9,8 +9,6 @@
 // 2. For an enum, the print-type-sizes output will also include the
 //    size of each variant.
 
-#![feature(start)]
-
 pub struct SevenBytes([u8;  7]);
 pub struct FiftyBytes([u8; 50]);
 
@@ -18,9 +16,3 @@ pub enum Enum {
     Small(SevenBytes),
     Large(FiftyBytes),
 }
-
-#[start]
-fn start(_: isize, _: *const *const u8) -> isize {
-    let _e: Enum;
-    0
-}
index e02a33109e56af728bd6776cf7b576290a0e27df..09415824d5df00835f9cda3dabbd4f5b9c4bc467 100644 (file)
@@ -1,12 +1,10 @@
-// compile-flags: -Z print-type-sizes
+// compile-flags: -Z print-type-sizes --crate-type=lib
 // build-pass
 // ignore-pass
 
 // At one point, zero-sized fields such as those in this file were causing
 // incorrect output from `-Z print-type-sizes`.
 
-#![feature(start)]
-
 struct S1 {
     x: u32,
     y: u32,
@@ -28,8 +26,7 @@ struct S5<TagW, TagZ> {
     tagz: TagZ,
 }
 
-#[start]
-fn start(_: isize, _: *const *const u8) -> isize {
+pub fn test() {
     let _s1: S1 = S1 { x: 0, y: 0, tag: () };
 
     let _s5: S5<(), Empty> = S5 {
@@ -43,5 +40,4 @@ fn start(_: isize, _: *const *const u8) -> isize {
         z: 4,
         tagz: Empty {},
     };
-    0
 }
index ad9a5e15c4e6e4376ff1d1e9dc014a34f4c4ebf9..c686a21772e0ed4e7ebfb3026779ff712d183222 100644 (file)
@@ -19,9 +19,9 @@ pub trait PubTr: PrivTr {}
         Pub.method();
         //~^ ERROR type `for<'a> fn(&'a Self) {<Self as PrivTr>::method}` is private
         <Pub as PrivTr>::CONST;
-        //~^ ERROR associated constant `<Pub as PrivTr>::CONST` is private
+        //~^ ERROR associated constant `PrivTr::CONST` is private
         let _: <Pub as PrivTr>::AssocTy;
-        //~^ ERROR associated type `<Pub as PrivTr>::AssocTy` is private
+        //~^ ERROR associated type `PrivTr::AssocTy` is private
         pub type InSignatureTy = <Pub as PrivTr>::AssocTy;
         //~^ ERROR trait `PrivTr` is private
         pub trait InSignatureTr: PrivTr {}
index c4be1a9d9a2027ddc6f9eae41386b5793ea302cb..eb905bf7ef85890d7783430b9db3e206c5eda39f 100644 (file)
@@ -31,7 +31,7 @@ LL |     priv_trait::mac!();
    |
    = note: this error originates in the macro `priv_trait::mac` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: associated constant `<Pub as PrivTr>::CONST` is private
+error: associated constant `PrivTr::CONST` is private
   --> $DIR/associated-item-privacy-trait.rs:21:9
    |
 LL |         <Pub as PrivTr>::CONST;
@@ -42,7 +42,7 @@ LL |     priv_trait::mac!();
    |
    = note: this error originates in the macro `priv_trait::mac` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: associated type `<Pub as PrivTr>::AssocTy` is private
+error: associated type `PrivTr::AssocTy` is private
   --> $DIR/associated-item-privacy-trait.rs:23:16
    |
 LL |         let _: <Pub as PrivTr>::AssocTy;
index 0337aedd0088165222b794c3327254c51b8947e7..cdbdcf60b2c540f78ffe6643c9b4745a38957ff1 100644 (file)
@@ -1,7 +1,7 @@
 // aux-build:private-inferred-type.rs
 
 // error-pattern:type `fn() {ext::priv_fn}` is private
-// error-pattern:static `PRIV_STATIC` is private
+// error-pattern:static `ext::PRIV_STATIC` is private
 // error-pattern:type `ext::PrivEnum` is private
 // error-pattern:type `fn() {<u8 as ext::PrivTrait>::method}` is private
 // error-pattern:type `fn(u8) -> ext::PrivTupleStruct {ext::PrivTupleStruct}` is private
index 00b61512de6b4d3176a3a509dc348b45505335e5..42faeb4bf341dea982b44442d2cbec0061059d1a 100644 (file)
@@ -6,7 +6,7 @@ LL |     ext::m!();
    |
    = note: this error originates in the macro `ext::m` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: static `PRIV_STATIC` is private
+error: static `ext::PRIV_STATIC` is private
   --> $DIR/private-inferred-type-3.rs:16:5
    |
 LL |     ext::m!();
index ac49e04e3c0a9ed21ddafd652569e9b9c48454be..14e5df21ef651a2e5d3c24e520770a77720b4105 100644 (file)
@@ -7,9 +7,6 @@ LL | #[derive(PartialOrd, AddImpl)]
    = help: the trait `PartialEq` is not implemented for `PriorityQueue<T>`
 note: required by a bound in `PartialOrd`
   --> $SRC_DIR/core/src/cmp.rs:LL:COL
-   |
-LL | pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
-   |                                           ^^^^^^^^^^^^^^ required by this bound in `PartialOrd`
    = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0277]: the trait bound `PriorityQueue<T>: Eq` is not satisfied
@@ -20,9 +17,6 @@ LL | #[derive(PartialOrd, AddImpl)]
    |
 note: required by a bound in `Ord`
   --> $SRC_DIR/core/src/cmp.rs:LL:COL
-   |
-LL | pub trait Ord: Eq + PartialOrd<Self> {
-   |                ^^ required by this bound in `Ord`
    = note: this error originates in the derive macro `AddImpl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0277]: can't compare `T` with `T`
@@ -38,9 +32,6 @@ LL | #[derive(PartialOrd, AddImpl)]
    |          ^^^^^^^^^^
 note: required by a bound in `Ord`
   --> $SRC_DIR/core/src/cmp.rs:LL:COL
-   |
-LL | pub trait Ord: Eq + PartialOrd<Self> {
-   |                     ^^^^^^^^^^^^^^^^ required by this bound in `Ord`
    = note: this error originates in the derive macro `AddImpl` which comes from the expansion of the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 3 previous errors
index 65ce24e55229684d72a7d7c01e20b1c9c41afbae..a3b27fd7bcc1bd5997b83c9fb567a6a0b9973ca6 100644 (file)
@@ -144,11 +144,9 @@ LL |     parent_source_spans!($($tokens)*);
 ...
 LL |     one!("hello", "world");
    |     ---------------------- in this macro invocation
+  --> $SRC_DIR/core/src/result.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL |     Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     -- similarly named tuple variant `Ok` defined here
+   = note: similarly named tuple variant `Ok` defined here
    |
    = note: this error originates in the macro `parent_source_spans` which comes from the expansion of the macro `one` (in Nightly builds, run with -Z macro-backtrace for more info)
 
@@ -160,11 +158,9 @@ LL |     parent_source_spans!($($tokens)*);
 ...
 LL |     two!("yay", "rust");
    |     ------------------- in this macro invocation
+  --> $SRC_DIR/core/src/result.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL |     Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     -- similarly named tuple variant `Ok` defined here
+   = note: similarly named tuple variant `Ok` defined here
    |
    = note: this error originates in the macro `parent_source_spans` which comes from the expansion of the macro `two` (in Nightly builds, run with -Z macro-backtrace for more info)
 
@@ -176,11 +172,9 @@ LL |     parent_source_spans!($($tokens)*);
 ...
 LL |     three!("hip", "hop");
    |     -------------------- in this macro invocation
+  --> $SRC_DIR/core/src/result.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL |     Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     -- similarly named tuple variant `Ok` defined here
+   = note: similarly named tuple variant `Ok` defined here
    |
    = note: this error originates in the macro `parent_source_spans` which comes from the expansion of the macro `three` (in Nightly builds, run with -Z macro-backtrace for more info)
 
index a534b9d5377adbecec406d3010981e73a020bf65..3c3f24d0ff22e319e72c930a6b0462aa69423db9 100644 (file)
@@ -72,22 +72,18 @@ error: cannot find derive macro `Dlone` in this scope
    |
 LL | #[derive(Dlone)]
    |          ^^^^^ help: a derive macro with a similar name exists: `Clone`
+  --> $SRC_DIR/core/src/clone.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/clone.rs:LL:COL
-   |
-LL | pub macro Clone($item:item) {
-   | --------------- similarly named derive macro `Clone` defined here
+   = note: similarly named derive macro `Clone` defined here
 
 error: cannot find derive macro `Dlone` in this scope
   --> $DIR/resolve-error.rs:35:10
    |
 LL | #[derive(Dlone)]
    |          ^^^^^ help: a derive macro with a similar name exists: `Clone`
+  --> $SRC_DIR/core/src/clone.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/clone.rs:LL:COL
-   |
-LL | pub macro Clone($item:item) {
-   | --------------- similarly named derive macro `Clone` defined here
+   = note: similarly named derive macro `Clone` defined here
 
 error: cannot find attribute `FooWithLongNan` in this scope
   --> $DIR/resolve-error.rs:32:3
index 59b3e44c74a52270e2e87b2d9f205072e2fd4b59..79f2001da005510f915eb3f696d550df0364f3c8 100644 (file)
@@ -14,9 +14,6 @@ LL | | }
    = note: unsafe function cannot be called generically without an unsafe block
 note: required by a bound in `ProcMacro::custom_derive`
   --> $SRC_DIR/proc_macro/src/bridge/client.rs:LL:COL
-   |
-LL |         expand: impl Fn(crate::TokenStream) -> crate::TokenStream + Copy,
-   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `ProcMacro::custom_derive`
 
 error: aborting due to previous error
 
index 914ad54ed0370513b3b5c1460d96277fa17948b2..3f04ba866b7d6952addcbf0faf54f006c94b903c 100644 (file)
@@ -2,6 +2,7 @@
 // ignore-pretty
 // aux-build:span-api-tests.rs
 // aux-build:span-test-macros.rs
+// compile-flags: -Ztranslate-remapped-path-to-local-path=yes
 
 #[macro_use]
 extern crate span_test_macros;
index aaea91ce0cbae15aac806d8e64ab459fbd531233..3956390368f7f132ab5b975d168a06516ba8ae4f 100644 (file)
@@ -32,9 +32,6 @@ LL |     let range = *arr..;
    = help: the trait `Sized` is not implemented for `[{integer}]`
 note: required by a bound in `RangeFrom`
   --> $SRC_DIR/core/src/ops/range.rs:LL:COL
-   |
-LL | pub struct RangeFrom<Idx> {
-   |                      ^^^ required by this bound in `RangeFrom`
 
 error: aborting due to 3 previous errors
 
index f2307899d3c47e0a074dcf4e7ab111d75b4e68b1..86ad6aa847c9fe5adfeb0947cd19d921ffe62b3d 100644 (file)
@@ -8,12 +8,9 @@ LL |     let Ok(x) = res;
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
 note: `Result<u32, &R<'_>>` defined here
   --> $SRC_DIR/core/src/result.rs:LL:COL
+  ::: $SRC_DIR/core/src/result.rs:LL:COL
    |
-LL | pub enum Result<T, E> {
-   | ---------------------
-...
-LL |     Err(#[stable(feature = "rust1", since = "1.0.0")] E),
-   |     ^^^ not covered
+   = note: not covered
    = note: the matched value is of type `Result<u32, &R<'_>>`
 help: you might want to use `if let` to ignore the variant that isn't matched
    |
diff --git a/src/test/ui/resolve/issue-104700-inner_scope.rs b/src/test/ui/resolve/issue-104700-inner_scope.rs
new file mode 100644 (file)
index 0000000..e8f28c1
--- /dev/null
@@ -0,0 +1,11 @@
+fn main() {
+    let foo = 1;
+    {
+        let bar = 2;
+        let test_func = |x| x > 3;
+    }
+    if bar == 2 { //~ ERROR cannot find value
+        println!("yes");
+    }
+    test_func(1); //~ ERROR cannot find function
+}
diff --git a/src/test/ui/resolve/issue-104700-inner_scope.stderr b/src/test/ui/resolve/issue-104700-inner_scope.stderr
new file mode 100644 (file)
index 0000000..051b234
--- /dev/null
@@ -0,0 +1,21 @@
+error[E0425]: cannot find value `bar` in this scope
+  --> $DIR/issue-104700-inner_scope.rs:7:8
+   |
+LL |     if bar == 2 {
+   |        ^^^
+   |
+help: the binding `bar` is available in a different scope in the same function
+  --> $DIR/issue-104700-inner_scope.rs:4:13
+   |
+LL |         let bar = 2;
+   |             ^^^
+
+error[E0425]: cannot find function `test_func` in this scope
+  --> $DIR/issue-104700-inner_scope.rs:10:5
+   |
+LL |     test_func(1);
+   |     ^^^^^^^^^ not found in this scope
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0425`.
index f839dd927db999b883504950badb49cf32a914e8..42b43f825d10c28711b7f3f450da977f855124fe 100644 (file)
@@ -21,8 +21,8 @@ LL |         let mut N;
    |
 help: consider giving `N` an explicit type
    |
-LL |         let mut N: _;
-   |                  +++
+LL |         let mut N: /* Type */;
+   |                  ++++++++++++
 
 error: aborting due to 3 previous errors
 
index 9a2d61ea4054b52f83eb6075e074d3aea85fd09c..cf478210132ede5fbc5eeaffb7f8168dd08c27ef 100644 (file)
@@ -18,11 +18,9 @@ error[E0412]: cannot find type `Opiton` in this scope
    |
 LL | type B = Opiton<u8>; // Misspelled type name from the prelude.
    |          ^^^^^^ help: an enum with a similar name exists: `Option`
+  --> $SRC_DIR/core/src/option.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL | pub enum Option<T> {
-   | ------------------ similarly named enum `Option` defined here
+   = note: similarly named enum `Option` defined here
 
 error[E0412]: cannot find type `Baz` in this scope
   --> $DIR/levenshtein.rs:16:14
index 6d5d5bad9fe1a342f67b5b581035203fccda800d..964302e924c8ae7cdd987f2590bd4adfb52949e1 100644 (file)
@@ -28,9 +28,6 @@ LL |     std::mem::size_of(u16);
    |
 note: function defined here
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
-   |
-LL | pub const fn size_of<T>() -> usize {
-   |              ^^^^^^^
 help: remove the extra argument
    |
 LL |     std::mem::size_of();
index 9577952119adb2c480bc9b2caf5731574304da51..a19750cc73aa559b5d33ae614d3cf920134b95c0 100644 (file)
@@ -9,9 +9,6 @@ LL | fn can_parse_zero_as_f32() -> Result<f32, ParseFloatError> {
    = note: required for `Result<f32, ParseFloatError>` to implement `Termination`
 note: required by a bound in `assert_test_result`
   --> $SRC_DIR/test/src/lib.rs:LL:COL
-   |
-LL | pub fn assert_test_result<T: Termination>(result: T) -> Result<(), String> {
-   |                              ^^^^^^^^^^^ required by this bound in `assert_test_result`
    = note: this error originates in the attribute macro `test` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
index 9cc20a7bf3144ffa05e86a1452db184d4a4fbc9e..07991af6ef97c60bd5314f186fdcee1175de73c6 100644 (file)
@@ -6,6 +6,11 @@ LL |     for (n, mut m) in &tups {
    |             |
    |             data moved here
    |             move occurs because `m` has type `Foo`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |     for (n, ref mut m) in &tups {
+   |             +++
 
 error: aborting due to previous error
 
index 06699b947be40f2bb66426cfde35e04c8de7d81e..e97fdcce1c18f0913a55090db7eb2d05ffd80ec2 100644 (file)
@@ -8,11 +8,6 @@ LL |     let _ = dbg!(a);
 LL |     let _ = dbg!(a);
    |                  ^ value used here after move
    |
-help: borrow this binding in the pattern to avoid moving the value
-  --> $SRC_DIR/std/src/macros.rs:LL:COL
-   |
-LL |             ref tmp => {
-   |             +++
 
 error: aborting due to previous error
 
index c64930db9bee2ee1b695337ff1f12ed29c797e2e..f9d0d1f7875fb891b4016ed2078de369beeecca8 100644 (file)
@@ -1,10 +1,8 @@
 error[E0277]: the trait bound `NonConstImpl: ~const ConstDefaultFn` is not satisfied
-  --> $DIR/const-default-method-bodies.rs:24:5
+  --> $DIR/const-default-method-bodies.rs:24:18
    |
 LL |     NonConstImpl.a();
-   |     ^^^^^^^^^^^^ - required by a bound introduced by this call
-   |     |
-   |     the trait `~const ConstDefaultFn` is not implemented for `NonConstImpl`
+   |                  ^ the trait `~const ConstDefaultFn` is not implemented for `NonConstImpl`
    |
 note: the trait `ConstDefaultFn` is implemented for `NonConstImpl`, but that implementation is not `const`
   --> $DIR/const-default-method-bodies.rs:24:5
index 925ae53e3249961c776b16e6d3e0de54ecb03ffc..633b7cc255a52a817a20a02d03afbdf079247331 100644 (file)
@@ -1,10 +1,8 @@
 error[E0277]: the trait bound `cross_crate::NonConst: ~const cross_crate::MyTrait` is not satisfied
-  --> $DIR/cross-crate.rs:17:5
+  --> $DIR/cross-crate.rs:17:14
    |
 LL |     NonConst.func();
-   |     ^^^^^^^^ ---- required by a bound introduced by this call
-   |     |
-   |     the trait `~const cross_crate::MyTrait` is not implemented for `cross_crate::NonConst`
+   |              ^^^^ the trait `~const cross_crate::MyTrait` is not implemented for `cross_crate::NonConst`
    |
 note: the trait `cross_crate::MyTrait` is implemented for `cross_crate::NonConst`, but that implementation is not `const`
   --> $DIR/cross-crate.rs:17:5
index 11db0c2b8f290bff0447a0cc2a7cb3a6b2ac6e7d..9e97d3f11376014a3f08bd9eb596d664e70c0e4a 100644 (file)
@@ -1,10 +1,8 @@
 error[E0277]: the trait bound `cross_crate::NonConst: cross_crate::MyTrait` is not satisfied
-  --> $DIR/cross-crate.rs:17:5
+  --> $DIR/cross-crate.rs:17:14
    |
 LL |     NonConst.func();
-   |     ^^^^^^^^ ---- required by a bound introduced by this call
-   |     |
-   |     the trait `~const cross_crate::MyTrait` is not implemented for `cross_crate::NonConst`
+   |              ^^^^ the trait `~const cross_crate::MyTrait` is not implemented for `cross_crate::NonConst`
    |
 note: the trait `cross_crate::MyTrait` is implemented for `cross_crate::NonConst`, but that implementation is not `const`
   --> $DIR/cross-crate.rs:17:5
index c2c16921c2eb233fb9ef3ea76cc96e0f25dddd26..21ecddaffbb6517c64933d1c5114bed8bd42eb38 100644 (file)
@@ -1,10 +1,8 @@
 error[E0277]: the trait bound `(): ~const Tr` is not satisfied
-  --> $DIR/default-method-body-is-const-same-trait-ck.rs:8:9
+  --> $DIR/default-method-body-is-const-same-trait-ck.rs:8:12
    |
 LL |         ().a()
-   |         ^^ - required by a bound introduced by this call
-   |         |
-   |         the trait `~const Tr` is not implemented for `()`
+   |            ^ the trait `~const Tr` is not implemented for `()`
    |
 note: the trait `Tr` is implemented for `()`, but that implementation is not `const`
   --> $DIR/default-method-body-is-const-same-trait-ck.rs:8:9
index b52eb2c0332fd460e93f5f2b5d1586e4036a6c9f..13fc719f28c5c2ad681a357c78c1df7170f691d7 100644 (file)
@@ -1,10 +1,8 @@
 error[E0277]: the trait bound `T: ~const Foo` is not satisfied
-  --> $DIR/super-traits-fail-2.rs:15:5
+  --> $DIR/super-traits-fail-2.rs:15:7
    |
 LL |     x.a();
-   |     ^ - required by a bound introduced by this call
-   |     |
-   |     the trait `~const Foo` is not implemented for `T`
+   |       ^ the trait `~const Foo` is not implemented for `T`
    |
 note: the trait `Foo` is implemented for `T`, but that implementation is not `const`
   --> $DIR/super-traits-fail-2.rs:15:5
index b52eb2c0332fd460e93f5f2b5d1586e4036a6c9f..13fc719f28c5c2ad681a357c78c1df7170f691d7 100644 (file)
@@ -1,10 +1,8 @@
 error[E0277]: the trait bound `T: ~const Foo` is not satisfied
-  --> $DIR/super-traits-fail-2.rs:15:5
+  --> $DIR/super-traits-fail-2.rs:15:7
    |
 LL |     x.a();
-   |     ^ - required by a bound introduced by this call
-   |     |
-   |     the trait `~const Foo` is not implemented for `T`
+   |       ^ the trait `~const Foo` is not implemented for `T`
    |
 note: the trait `Foo` is implemented for `T`, but that implementation is not `const`
   --> $DIR/super-traits-fail-2.rs:15:5
index eea94643e0a0aeb427d4472e6226097c3d6d60b3..5d4d692b2cffb7e5c39ccc0754002018c7ca9ed1 100644 (file)
@@ -26,11 +26,8 @@ note: an implementation of `Add<_>` might be missing for `World`
    |
 LL | enum World {
    | ^^^^^^^^^^ must implement `Add<_>`
-note: the following trait must be implemented
+note: the trait `Add` must be implemented
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL | pub trait Add<Rhs = Self> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0369]: cannot add `String` to `&str`
   --> $DIR/issue-39018.rs:11:22
index f187d0efa8451abe60bfae1fe0f013ac6439b06d..8014f3796250a1c5c217a24c6e0977c089abbf88 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: -Z simulate-remapped-rust-src-base=/rustc/FAKE_PREFIX -Z translate-remapped-path-to-local-path=no -Z ui-testing=no
+// compile-flags: -Z ui-testing=no
 
 struct MyError;
 impl std::error::Error for MyError {}
index 7d240589a3f133647b2b85ccfe61f504d6f47bf7..f6efbe40bc23457047427cfc5a90cb9af723d3f6 100644 (file)
@@ -9,8 +9,8 @@ LL |     x.0;
    |
 help: consider giving `x` an explicit type
    |
-LL |     let mut x: _ = Default::default();
-   |              +++
+LL |     let mut x: /* Type */ = Default::default();
+   |              ++++++++++++
 
 error[E0282]: type annotations needed
   --> $DIR/method-and-field-eager-resolution.rs:11:9
@@ -23,8 +23,8 @@ LL |     x[0];
    |
 help: consider giving `x` an explicit type
    |
-LL |     let mut x: _ = Default::default();
-   |              +++
+LL |     let mut x: /* Type */ = Default::default();
+   |              ++++++++++++
 
 error: aborting due to 2 previous errors
 
index b76a3ab307ae458bc091ec8a5b0f22099e82a962..48a2e763af615a23e15104e5ffcf57f0c127cf30 100644 (file)
@@ -6,9 +6,6 @@ LL |     let _: Result<(), String> = Ok();
    |
 note: tuple variant defined here
   --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL |     Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^
 help: provide the argument
    |
 LL |     let _: Result<(), String> = Ok(());
index 33ca7a2c210d680ec7d7f664fae9aca585c0b029..37788612f4371dd6ce95af228211a59799424d6a 100644 (file)
@@ -27,7 +27,7 @@ LL | default impl<T> Foo for T {
    | ^^^^^^^^^^^^^^^^---^^^^^-
    | |
    | unsatisfied trait bound introduced here
-note: the following trait must be implemented
+note: the trait `Foo` must be implemented
   --> $DIR/specialization-trait-not-implemented.rs:7:1
    |
 LL | trait Foo {
index e64f2acbd351d1bc2d160c860e06074a19332679..2f02a24960e01af20612e1bd026baf58e6df45f9 100644 (file)
@@ -6,9 +6,6 @@ LL |     let _ = std::thread::thread_info::current_thread();
    |
 note: the module `thread_info` is defined here
   --> $SRC_DIR/std/src/thread/mod.rs:LL:COL
-   |
-LL | use crate::sys_common::thread_info;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index 9db9fcf40f82c0d34bddd0eb2d2322eff055090f..8c5d0b9609627f04d183d7223c52d5bb7006d4b0 100644 (file)
@@ -2,37 +2,49 @@ error[E0507]: cannot move out of a shared reference
   --> $DIR/std-uncopyable-atomics.rs:9:13
    |
 LL |     let x = *&x;
-   |             ^^^
-   |             |
-   |             move occurs because value has type `std::sync::atomic::AtomicBool`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&*&x`
+   |             ^^^ move occurs because value has type `std::sync::atomic::AtomicBool`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let x = *&x;
+LL +     let x = &x;
+   |
 
 error[E0507]: cannot move out of a shared reference
   --> $DIR/std-uncopyable-atomics.rs:11:13
    |
 LL |     let x = *&x;
-   |             ^^^
-   |             |
-   |             move occurs because value has type `std::sync::atomic::AtomicIsize`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&*&x`
+   |             ^^^ move occurs because value has type `std::sync::atomic::AtomicIsize`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let x = *&x;
+LL +     let x = &x;
+   |
 
 error[E0507]: cannot move out of a shared reference
   --> $DIR/std-uncopyable-atomics.rs:13:13
    |
 LL |     let x = *&x;
-   |             ^^^
-   |             |
-   |             move occurs because value has type `std::sync::atomic::AtomicUsize`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&*&x`
+   |             ^^^ move occurs because value has type `std::sync::atomic::AtomicUsize`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let x = *&x;
+LL +     let x = &x;
+   |
 
 error[E0507]: cannot move out of a shared reference
   --> $DIR/std-uncopyable-atomics.rs:15:13
    |
 LL |     let x = *&x;
-   |             ^^^
-   |             |
-   |             move occurs because value has type `std::sync::atomic::AtomicPtr<usize>`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&*&x`
+   |             ^^^ move occurs because value has type `std::sync::atomic::AtomicPtr<usize>`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let x = *&x;
+LL +     let x = &x;
+   |
 
 error: aborting due to 4 previous errors
 
index 019305def2932ec3ce768e2895b19d86cf07cccb..cb1a6fcacfc9b5d24d8d6caae1a5f53e63304074 100644 (file)
@@ -24,9 +24,6 @@ LL |     let _ = s.get(4);
    = help: the trait `SliceIndex<[T]>` is implemented for `usize`
 note: required by a bound in `core::str::<impl str>::get`
   --> $SRC_DIR/core/src/str/mod.rs:LL:COL
-   |
-LL |     pub const fn get<I: ~const SliceIndex<str>>(&self, i: I) -> Option<&I::Output> {
-   |                         ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `core::str::<impl str>::get`
 
 error[E0277]: the type `str` cannot be indexed by `{integer}`
   --> $DIR/str-idx.rs:5:29
@@ -42,9 +39,6 @@ LL |     let _ = s.get_unchecked(4);
    = help: the trait `SliceIndex<[T]>` is implemented for `usize`
 note: required by a bound in `core::str::<impl str>::get_unchecked`
   --> $SRC_DIR/core/src/str/mod.rs:LL:COL
-   |
-LL |     pub const unsafe fn get_unchecked<I: ~const SliceIndex<str>>(&self, i: I) -> &I::Output {
-   |                                          ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `core::str::<impl str>::get_unchecked`
 
 error[E0277]: the type `str` cannot be indexed by `char`
   --> $DIR/str-idx.rs:6:19
index b165c482590a253babc0ea50d99126542b863e65..ca4b86ba3065b79af5c536f86b0f061e3743cd8e 100644 (file)
@@ -48,9 +48,6 @@ LL |     s.get_mut(1);
    = help: the trait `SliceIndex<[T]>` is implemented for `usize`
 note: required by a bound in `core::str::<impl str>::get_mut`
   --> $SRC_DIR/core/src/str/mod.rs:LL:COL
-   |
-LL |     pub const fn get_mut<I: ~const SliceIndex<str>>(&mut self, i: I) -> Option<&mut I::Output> {
-   |                             ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `core::str::<impl str>::get_mut`
 
 error[E0277]: the type `str` cannot be indexed by `{integer}`
   --> $DIR/str-mut-idx.rs:11:25
@@ -66,9 +63,6 @@ LL |     s.get_unchecked_mut(1);
    = help: the trait `SliceIndex<[T]>` is implemented for `usize`
 note: required by a bound in `core::str::<impl str>::get_unchecked_mut`
   --> $SRC_DIR/core/src/str/mod.rs:LL:COL
-   |
-LL |     pub const unsafe fn get_unchecked_mut<I: ~const SliceIndex<str>>(
-   |                                              ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `core::str::<impl str>::get_unchecked_mut`
 
 error[E0277]: the type `str` cannot be indexed by `char`
   --> $DIR/str-mut-idx.rs:13:7
index 0a91c442d2c6f0e45dd21bc6d8212c9dc8b7265e..44a39efdf25425015543ec99292f7e9c78ad7ed3 100644 (file)
@@ -13,9 +13,6 @@ LL |     let _: Option<(i32, bool)> = Some(1, 2);
                found type `{integer}`
 note: tuple variant defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^^^
 help: remove the extra argument
    |
 LL |     let _: Option<(i32, bool)> = Some(/* (i32, bool) */);
@@ -52,9 +49,6 @@ LL |     let _: Option<(i8,)> = Some();
    |
 note: tuple variant defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^^^
 help: provide the argument
    |
 LL |     let _: Option<(i8,)> = Some(/* (i8,) */);
@@ -72,9 +66,6 @@ LL |     let _: Option<(i32,)> = Some(5_usize);
                found type `usize`
 note: tuple variant defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^^^
 
 error[E0308]: mismatched types
   --> $DIR/args-instead-of-tuple-errors.rs:17:34
@@ -88,9 +79,6 @@ LL |     let _: Option<(i32,)> = Some((5_usize));
                found type `usize`
 note: tuple variant defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^^^
 
 error: aborting due to 5 previous errors
 
index 20f9e5259a4e2c050427970dec7b033a07d699ba..c8499010d6896365bccf42f5689638ca088156e0 100644 (file)
@@ -6,9 +6,6 @@ LL |     let _: Result<(i32, i8), ()> = Ok(1, 2);
    |
 note: tuple variant defined here
   --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL |     Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^
 help: wrap these arguments in parentheses to construct a tuple
    |
 LL |     let _: Result<(i32, i8), ()> = Ok((1, 2));
@@ -22,9 +19,6 @@ LL |     let _: Option<(i32, i8, &'static str)> = Some(1, 2, "hi");
    |
 note: tuple variant defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^^^
 help: wrap these arguments in parentheses to construct a tuple
    |
 LL |     let _: Option<(i32, i8, &'static str)> = Some((1, 2, "hi"));
@@ -38,9 +32,6 @@ LL |     let _: Option<()> = Some();
    |
 note: tuple variant defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^^^
 help: provide the argument
    |
 LL |     let _: Option<()> = Some(());
@@ -58,9 +49,6 @@ LL |     let _: Option<(i32,)> = Some(3);
                found type `{integer}`
 note: tuple variant defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^^^
 help: use a trailing comma to create a tuple with one element
    |
 LL |     let _: Option<(i32,)> = Some((3,));
@@ -78,9 +66,6 @@ LL |     let _: Option<(i32,)> = Some((3));
                found type `{integer}`
 note: tuple variant defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^^^
 help: use a trailing comma to create a tuple with one element
    |
 LL |     let _: Option<(i32,)> = Some((3,));
index e15e45d86b992c64fe39afe87742e96a62a18b9e..e2129b4502abea13774d1917bbf23c3eedbb8bee 100644 (file)
@@ -10,11 +10,8 @@ LL |     let _x: Option<Struct> = foo.map(|s| bar(&s));
 LL |     let _y = foo;
    |              ^^^ value used here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `foo`
+note: `Option::<T>::map` takes ownership of the receiver `self`, which moves `foo`
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |     pub const fn map<U, F>(self, f: F) -> Option<U>
-   |                            ^^^^
 
 error: aborting due to previous error
 
index 54122cb7360b438912caf6e4aafc7bcdf7f050b9..b871c9b45a56c7c675c5d8ec6476c41298585bc0 100644 (file)
@@ -15,11 +15,9 @@ error: cannot find attribute `tests` in this scope
    |
 LL | #[tests]
    |   ^^^^^ help: an attribute macro with a similar name exists: `test`
+  --> $SRC_DIR/core/src/macros/mod.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/macros/mod.rs:LL:COL
-   |
-LL |     pub macro test($item:item) {
-   |     -------------- similarly named attribute macro `test` defined here
+   = note: similarly named attribute macro `test` defined here
 
 error: cannot find attribute `deprcated` in this scope
   --> $DIR/attribute-typos.rs:1:3
index 0cc8994fe1f2d7589f564287f46c730d45824769..cbdb94877bdb7fbf897d0020c928bc6d718646a8 100644 (file)
@@ -16,11 +16,8 @@ LL |     for i in &a {
 LL |         for j in a {
    |                  ^ `a` moved due to this implicit call to `.into_iter()`, in previous iteration of loop
    |
-note: this function takes ownership of the receiver `self`, which moves `a`
+note: `into_iter` takes ownership of the receiver `self`, which moves `a`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-   |
-LL |     fn into_iter(self) -> Self::IntoIter;
-   |                  ^^^^
 help: consider iterating over a slice of the `Vec<i32>`'s content to avoid moving into the `for` loop
    |
 LL |         for j in &a {
index 4cb595c32c0611ebad6ca6950c6eb56ebac0f969..cd27947f02fad5cc111ec107e250eaf82c8fb4ce 100644 (file)
@@ -78,9 +78,6 @@ LL |     const SIZE: usize = core::mem::size_of::<Self>();
    |
 note: required by a bound in `std::mem::size_of`
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
-   |
-LL | pub const fn size_of<T>() -> usize {
-   |                      ^ required by this bound in `size_of`
 help: consider further restricting `Self`
    |
 LL | trait Foo<T>: Sized {
@@ -94,9 +91,6 @@ LL |     const SIZE: usize = core::mem::size_of::<Self>();
    |
 note: required by a bound in `std::mem::size_of`
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
-   |
-LL | pub const fn size_of<T>() -> usize {
-   |                      ^ required by this bound in `size_of`
 help: consider further restricting `Self`
    |
 LL | trait Bar: std::fmt::Display + Sized {
@@ -110,9 +104,6 @@ LL |     const SIZE: usize = core::mem::size_of::<Self>();
    |
 note: required by a bound in `std::mem::size_of`
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
-   |
-LL | pub const fn size_of<T>() -> usize {
-   |                      ^ required by this bound in `size_of`
 help: consider further restricting `Self`
    |
 LL | trait Baz: Sized where Self: std::fmt::Display {
@@ -126,9 +117,6 @@ LL |     const SIZE: usize = core::mem::size_of::<Self>();
    |
 note: required by a bound in `std::mem::size_of`
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
-   |
-LL | pub const fn size_of<T>() -> usize {
-   |                      ^ required by this bound in `size_of`
 help: consider further restricting `Self`
    |
 LL | trait Qux<T>: Sized where Self: std::fmt::Display {
@@ -142,9 +130,6 @@ LL |     const SIZE: usize = core::mem::size_of::<Self>();
    |
 note: required by a bound in `std::mem::size_of`
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
-   |
-LL | pub const fn size_of<T>() -> usize {
-   |                      ^ required by this bound in `size_of`
 help: consider further restricting `Self`
    |
 LL | trait Bat<T>: std::fmt::Display + Sized {
diff --git a/src/test/ui/suggestions/clone-on-unconstrained-borrowed-type-param.fixed b/src/test/ui/suggestions/clone-on-unconstrained-borrowed-type-param.fixed
new file mode 100644 (file)
index 0000000..4f9e93a
--- /dev/null
@@ -0,0 +1,16 @@
+// run-rustfix
+fn wat<T: Clone>(t: &T) -> T {
+    t.clone() //~ ERROR E0308
+}
+
+#[derive(Clone)]
+struct Foo;
+
+fn wut(t: &Foo) -> Foo {
+    t.clone() //~ ERROR E0308
+}
+
+fn main() {
+    wat(&42);
+    wut(&Foo);
+}
diff --git a/src/test/ui/suggestions/clone-on-unconstrained-borrowed-type-param.rs b/src/test/ui/suggestions/clone-on-unconstrained-borrowed-type-param.rs
new file mode 100644 (file)
index 0000000..89b077d
--- /dev/null
@@ -0,0 +1,15 @@
+// run-rustfix
+fn wat<T>(t: &T) -> T {
+    t.clone() //~ ERROR E0308
+}
+
+struct Foo;
+
+fn wut(t: &Foo) -> Foo {
+    t.clone() //~ ERROR E0308
+}
+
+fn main() {
+    wat(&42);
+    wut(&Foo);
+}
diff --git a/src/test/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr b/src/test/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr
new file mode 100644 (file)
index 0000000..26ab515
--- /dev/null
@@ -0,0 +1,43 @@
+error[E0308]: mismatched types
+  --> $DIR/clone-on-unconstrained-borrowed-type-param.rs:3:5
+   |
+LL | fn wat<T>(t: &T) -> T {
+   |        -            - expected `T` because of return type
+   |        |
+   |        this type parameter
+LL |     t.clone()
+   |     ^^^^^^^^^ expected type parameter `T`, found `&T`
+   |
+   = note: expected type parameter `T`
+                   found reference `&T`
+note: `T` does not implement `Clone`, so `&T` was cloned instead
+  --> $DIR/clone-on-unconstrained-borrowed-type-param.rs:3:5
+   |
+LL |     t.clone()
+   |     ^
+help: consider restricting type parameter `T`
+   |
+LL | fn wat<T: Clone>(t: &T) -> T {
+   |         +++++++
+
+error[E0308]: mismatched types
+  --> $DIR/clone-on-unconstrained-borrowed-type-param.rs:9:5
+   |
+LL | fn wut(t: &Foo) -> Foo {
+   |                    --- expected `Foo` because of return type
+LL |     t.clone()
+   |     ^^^^^^^^^ expected struct `Foo`, found `&Foo`
+   |
+note: `Foo` does not implement `Clone`, so `&Foo` was cloned instead
+  --> $DIR/clone-on-unconstrained-borrowed-type-param.rs:9:5
+   |
+LL |     t.clone()
+   |     ^
+help: consider annotating `Foo` with `#[derive(Clone)]`
+   |
+LL | #[derive(Clone)]
+   |
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
index 0645f0cdde7c0b31e5b70ed146fc5d03d10a02d9..0a18b770405c1d2629d319478030493fcd6b3f3a 100644 (file)
@@ -11,9 +11,6 @@ LL | impl<T: Clone, U> PartialEq<U> for Struct<T>
    |                   ^^^^^^^^^^^^     ^^^^^^^^^
 note: required by a bound in `Eq`
   --> $SRC_DIR/core/src/cmp.rs:LL:COL
-   |
-LL | pub trait Eq: PartialEq<Self> {
-   |               ^^^^^^^^^^^^^^^ required by this bound in `Eq`
    = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider restricting type parameter `T`
    |
index 7cc372f2422aebdd730376b951fe295834869466..14e8a2675dd18dca6b2dc57fc4c4a973d1d2ebee 100644 (file)
@@ -20,11 +20,8 @@ LL |     let y = x.test();
            `Enum: Clone`
            `Enum: Default`
            `CloneEnum: Default`
-note: the following trait must be implemented
+note: the trait `Default` must be implemented
   --> $SRC_DIR/core/src/default.rs:LL:COL
-   |
-LL | pub trait Default: Sized {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^
 help: consider annotating `Enum` with `#[derive(Clone)]`
    |
 LL | #[derive(Clone)]
@@ -69,16 +66,12 @@ LL | struct Foo<X, Y> (X, Y);
 ...
 LL |     let y = x.test();
    |               ^^^^ method cannot be called on `Foo<Vec<Enum>, Instant>` due to unsatisfied trait bounds
+  --> $SRC_DIR/std/src/time.rs:LL:COL
    |
-  ::: $SRC_DIR/std/src/time.rs:LL:COL
-   |
-LL | pub struct Instant(time::Instant);
-   | ------------------ doesn't satisfy `Instant: Default`
-   |
-  ::: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
+   = note: doesn't satisfy `Instant: Default`
+  --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
    |
-LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
-   | ------------------------------------------------------------------------------------------------ doesn't satisfy `Vec<Enum>: Clone`
+   = note: doesn't satisfy `Vec<Enum>: Clone`
    |
    = note: the following trait bounds were not satisfied:
            `Vec<Enum>: Clone`
index 7bdc8e00f447dc2ec308fd02fa5f922cb51161a2..0cd6267b3b313ebfa8f50125af998bdef20a1d8f 100644 (file)
@@ -3,11 +3,9 @@ error[E0573]: expected type, found module `result`
    |
 LL | impl result {
    |      ^^^^^^ help: an enum with a similar name exists: `Result`
+  --> $SRC_DIR/core/src/result.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL | pub enum Result<T, E> {
-   | --------------------- similarly named enum `Result` defined here
+   = note: similarly named enum `Result` defined here
 
 error[E0573]: expected type, found variant `Err`
   --> $DIR/do-not-attempt-to-add-suggestions-with-no-changes.rs:3:25
index bf0c1dc27ce43e9a0fbea89f23ffceab736a3f77..e19d497f21d29f9386a85308ee6c3e027ed5d960 100644 (file)
@@ -38,31 +38,25 @@ pub fn main() {
 
     let &(X(_t), X(_u)) = &(x.clone(), x.clone());
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&`
-    //~| SUGGESTION (X(_t), X(_u))
+    //~| HELP consider removing the borrow
     if let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&`
-    //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+    //~| HELP consider removing the borrow
     while let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&`
-    //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+    //~| HELP consider removing the borrow
     match &(e.clone(), e.clone()) {
         //~^ ERROR cannot move
         &(Either::One(_t), Either::Two(_u)) => (),
-        //~^ HELP consider removing the `&`
-        //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+        //~^ HELP consider removing the borrow
         &(Either::Two(_t), Either::One(_u)) => (),
-        //~^ HELP consider removing the `&`
-        //~| SUGGESTION (Either::Two(_t), Either::One(_u))
+        //~^ HELP consider removing the borrow
         _ => (),
     }
     match &(e.clone(), e.clone()) {
         //~^ ERROR cannot move
         &(Either::One(_t), Either::Two(_u))
-        //~^ HELP consider removing the `&`
-        //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+        //~^ HELP consider removing the borrow
         | &(Either::Two(_t), Either::One(_u)) => (),
         // FIXME: would really like a suggestion here too
         _ => (),
@@ -70,51 +64,42 @@ pub fn main() {
     match &(e.clone(), e.clone()) {
         //~^ ERROR cannot move
         &(Either::One(_t), Either::Two(_u)) => (),
-        //~^ HELP consider removing the `&`
-        //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+        //~^ HELP consider removing the borrow
         &(Either::Two(ref _t), Either::One(ref _u)) => (),
         _ => (),
     }
     match &(e.clone(), e.clone()) {
         //~^ ERROR cannot move
         &(Either::One(_t), Either::Two(_u)) => (),
-        //~^ HELP consider removing the `&`
-        //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+        //~^ HELP consider removing the borrow
         (Either::Two(_t), Either::One(_u)) => (),
         _ => (),
     }
     fn f5(&(X(_t), X(_u)): &(X, X)) { }
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&`
-    //~| SUGGESTION (X(_t), X(_u))
+    //~| HELP consider removing the borrow
 
     let &mut (X(_t), X(_u)) = &mut (xm.clone(), xm.clone());
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&mut`
-    //~| SUGGESTION (X(_t), X(_u))
+    //~| HELP consider removing the mutable borrow
     if let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&mut`
-    //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+    //~| HELP consider removing the mutable borrow
     while let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&mut`
-    //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+    //~| HELP consider removing the mutable borrow
     match &mut (em.clone(), em.clone()) {
         //~^ ERROR cannot move
         &mut (Either::One(_t), Either::Two(_u)) => (),
-        //~^ HELP consider removing the `&mut`
-        //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+        //~^ HELP consider removing the mutable borrow
         &mut (Either::Two(_t), Either::One(_u)) => (),
-        //~^ HELP consider removing the `&mut`
-        //~| SUGGESTION (Either::Two(_t), Either::One(_u))
+        //~^ HELP consider removing the mutable borrow
         _ => (),
     }
     match &mut (em.clone(), em.clone()) {
         //~^ ERROR cannot move
         &mut (Either::One(_t), Either::Two(_u))
-        //~^ HELP consider removing the `&mut`
-        //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+        //~^ HELP consider removing the mutable borrow
         | &mut (Either::Two(_t), Either::One(_u)) => (),
         // FIXME: would really like a suggestion here too
         _ => (),
@@ -122,29 +107,25 @@ fn f5(&(X(_t), X(_u)): &(X, X)) { }
     match &mut (em.clone(), em.clone()) {
         //~^ ERROR cannot move
         &mut (Either::One(_t), Either::Two(_u)) => (),
-        //~^ HELP consider removing the `&mut`
-        //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+        //~^ HELP consider removing the mutable borrow
         &mut (Either::Two(ref _t), Either::One(ref _u)) => (),
         _ => (),
     }
     match &mut (em.clone(), em.clone()) {
         //~^ ERROR cannot move
         &mut (Either::One(_t), Either::Two(_u)) => (),
-        //~^ HELP consider removing the `&mut`
-        //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+        //~^ HELP consider removing the mutable borrow
         &mut (Either::Two(ref mut _t), Either::One(ref mut _u)) => (),
         _ => (),
     }
     match &mut (em.clone(), em.clone()) {
         //~^ ERROR cannot move
         &mut (Either::One(_t), Either::Two(_u)) => (),
-        //~^ HELP consider removing the `&mut`
-        //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+        //~^ HELP consider removing the mutable borrow
         (Either::Two(_t), Either::One(_u)) => (),
         _ => (),
     }
     fn f6(&mut (X(_t), X(_u)): &mut (X, X)) { }
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&mut`
-    //~| SUGGESTION (X(_t), X(_u))
+    //~| HELP consider removing the mutable borrow
 }
index 40ad671f9663029c6d0790cd0d4ea87433403378..b96b3713f2a7ab74d37d5763832a0d2198a04462 100644 (file)
@@ -2,40 +2,52 @@ error[E0507]: cannot move out of a shared reference
   --> $DIR/duplicate-suggestions.rs:39:27
    |
 LL |     let &(X(_t), X(_u)) = &(x.clone(), x.clone());
-   |         ---------------   ^^^^^^^^^^^^^^^^^^^^^^^
-   |         |   |      |
-   |         |   |      ...and here
-   |         |   data moved here
-   |         help: consider removing the `&`: `(X(_t), X(_u))`
+   |             --     --     ^^^^^^^^^^^^^^^^^^^^^^^
+   |             |      |
+   |             |      ...and here
+   |             data moved here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the borrow
+   |
+LL -     let &(X(_t), X(_u)) = &(x.clone(), x.clone());
+LL +     let (X(_t), X(_u)) = &(x.clone(), x.clone());
+   |
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/duplicate-suggestions.rs:43:50
+  --> $DIR/duplicate-suggestions.rs:42:50
    |
 LL |     if let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
-   |            -----------------------------------   ^^^^^^^^^^^^^^^^^^^^^^^
-   |            |             |                |
-   |            |             |                ...and here
-   |            |             data moved here
-   |            help: consider removing the `&`: `(Either::One(_t), Either::Two(_u))`
+   |                          --               --     ^^^^^^^^^^^^^^^^^^^^^^^
+   |                          |                |
+   |                          |                ...and here
+   |                          data moved here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the borrow
+   |
+LL -     if let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
+LL +     if let (Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
+   |
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/duplicate-suggestions.rs:47:53
+  --> $DIR/duplicate-suggestions.rs:45:53
    |
 LL |     while let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
-   |               -----------------------------------   ^^^^^^^^^^^^^^^^^^^^^^^
-   |               |             |                |
-   |               |             |                ...and here
-   |               |             data moved here
-   |               help: consider removing the `&`: `(Either::One(_t), Either::Two(_u))`
+   |                             --               --     ^^^^^^^^^^^^^^^^^^^^^^^
+   |                             |                |
+   |                             |                ...and here
+   |                             data moved here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the borrow
+   |
+LL -     while let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
+LL +     while let (Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
+   |
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/duplicate-suggestions.rs:51:11
+  --> $DIR/duplicate-suggestions.rs:48:11
    |
 LL |     match &(e.clone(), e.clone()) {
    |           ^^^^^^^^^^^^^^^^^^^^^^^
@@ -44,22 +56,24 @@ LL |         &(Either::One(_t), Either::Two(_u)) => (),
    |                       --               -- ...and here
    |                       |
    |                       data moved here
-...
+LL |
 LL |         &(Either::Two(_t), Either::One(_u)) => (),
    |                       -- ...and here   -- ...and here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
-help: consider removing the `&`
+help: consider removing the borrow
    |
-LL |         (Either::One(_t), Either::Two(_u)) => (),
-   |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-help: consider removing the `&`
+LL -         &(Either::One(_t), Either::Two(_u)) => (),
+LL +         (Either::One(_t), Either::Two(_u)) => (),
+   |
+help: consider removing the borrow
+   |
+LL -         &(Either::Two(_t), Either::One(_u)) => (),
+LL +         (Either::Two(_t), Either::One(_u)) => (),
    |
-LL |         (Either::Two(_t), Either::One(_u)) => (),
-   |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/duplicate-suggestions.rs:61:11
+  --> $DIR/duplicate-suggestions.rs:56:11
    |
 LL |     match &(e.clone(), e.clone()) {
    |           ^^^^^^^^^^^^^^^^^^^^^^^
@@ -70,82 +84,98 @@ LL |         &(Either::One(_t), Either::Two(_u))
    |                       data moved here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
-help: consider removing the `&`
+help: consider removing the borrow
    |
-LL ~         (Either::One(_t), Either::Two(_u))
-LL +
-LL +
-LL ~         | &(Either::Two(_t), Either::One(_u)) => (),
+LL -         &(Either::One(_t), Either::Two(_u))
+LL +         (Either::One(_t), Either::Two(_u))
    |
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/duplicate-suggestions.rs:70:11
+  --> $DIR/duplicate-suggestions.rs:64:11
    |
 LL |     match &(e.clone(), e.clone()) {
    |           ^^^^^^^^^^^^^^^^^^^^^^^
 LL |
 LL |         &(Either::One(_t), Either::Two(_u)) => (),
-   |         -----------------------------------
-   |         |             |                |
-   |         |             |                ...and here
-   |         |             data moved here
-   |         help: consider removing the `&`: `(Either::One(_t), Either::Two(_u))`
+   |                       --               -- ...and here
+   |                       |
+   |                       data moved here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the borrow
+   |
+LL -         &(Either::One(_t), Either::Two(_u)) => (),
+LL +         (Either::One(_t), Either::Two(_u)) => (),
+   |
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/duplicate-suggestions.rs:78:11
+  --> $DIR/duplicate-suggestions.rs:71:11
    |
 LL |     match &(e.clone(), e.clone()) {
    |           ^^^^^^^^^^^^^^^^^^^^^^^
 LL |
 LL |         &(Either::One(_t), Either::Two(_u)) => (),
-   |         -----------------------------------
-   |         |             |                |
-   |         |             |                ...and here
-   |         |             data moved here
-   |         help: consider removing the `&`: `(Either::One(_t), Either::Two(_u))`
+   |                       --               -- ...and here
+   |                       |
+   |                       data moved here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the borrow
+   |
+LL -         &(Either::One(_t), Either::Two(_u)) => (),
+LL +         (Either::One(_t), Either::Two(_u)) => (),
+   |
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/duplicate-suggestions.rs:91:31
+  --> $DIR/duplicate-suggestions.rs:82:31
    |
 LL |     let &mut (X(_t), X(_u)) = &mut (xm.clone(), xm.clone());
-   |         -------------------   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |         |       |      |
-   |         |       |      ...and here
-   |         |       data moved here
-   |         help: consider removing the `&mut`: `(X(_t), X(_u))`
+   |                 --     --     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                 |      |
+   |                 |      ...and here
+   |                 data moved here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the mutable borrow
+   |
+LL -     let &mut (X(_t), X(_u)) = &mut (xm.clone(), xm.clone());
+LL +     let (X(_t), X(_u)) = &mut (xm.clone(), xm.clone());
+   |
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/duplicate-suggestions.rs:95:54
+  --> $DIR/duplicate-suggestions.rs:85:54
    |
 LL |     if let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
-   |            ---------------------------------------   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |            |                 |                |
-   |            |                 |                ...and here
-   |            |                 data moved here
-   |            help: consider removing the `&mut`: `(Either::One(_t), Either::Two(_u))`
+   |                              --               --     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                              |                |
+   |                              |                ...and here
+   |                              data moved here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the mutable borrow
+   |
+LL -     if let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
+LL +     if let (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
+   |
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/duplicate-suggestions.rs:99:57
+  --> $DIR/duplicate-suggestions.rs:88:57
    |
 LL |     while let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
-   |               ---------------------------------------   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |               |                 |                |
-   |               |                 |                ...and here
-   |               |                 data moved here
-   |               help: consider removing the `&mut`: `(Either::One(_t), Either::Two(_u))`
+   |                                 --               --     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                 |                |
+   |                                 |                ...and here
+   |                                 data moved here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the mutable borrow
+   |
+LL -     while let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
+LL +     while let (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
+   |
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/duplicate-suggestions.rs:103:11
+  --> $DIR/duplicate-suggestions.rs:91:11
    |
 LL |     match &mut (em.clone(), em.clone()) {
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -154,22 +184,24 @@ LL |         &mut (Either::One(_t), Either::Two(_u)) => (),
    |                           --               -- ...and here
    |                           |
    |                           data moved here
-...
+LL |
 LL |         &mut (Either::Two(_t), Either::One(_u)) => (),
    |                           -- ...and here   -- ...and here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
-help: consider removing the `&mut`
+help: consider removing the mutable borrow
+   |
+LL -         &mut (Either::One(_t), Either::Two(_u)) => (),
+LL +         (Either::One(_t), Either::Two(_u)) => (),
    |
-LL |         (Either::One(_t), Either::Two(_u)) => (),
-   |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-help: consider removing the `&mut`
+help: consider removing the mutable borrow
+   |
+LL -         &mut (Either::Two(_t), Either::One(_u)) => (),
+LL +         (Either::Two(_t), Either::One(_u)) => (),
    |
-LL |         (Either::Two(_t), Either::One(_u)) => (),
-   |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/duplicate-suggestions.rs:113:11
+  --> $DIR/duplicate-suggestions.rs:99:11
    |
 LL |     match &mut (em.clone(), em.clone()) {
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -180,82 +212,97 @@ LL |         &mut (Either::One(_t), Either::Two(_u))
    |                           data moved here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
-help: consider removing the `&mut`
+help: consider removing the mutable borrow
    |
-LL ~         (Either::One(_t), Either::Two(_u))
-LL +
-LL +
-LL ~         | &mut (Either::Two(_t), Either::One(_u)) => (),
+LL -         &mut (Either::One(_t), Either::Two(_u))
+LL +         (Either::One(_t), Either::Two(_u))
    |
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/duplicate-suggestions.rs:122:11
+  --> $DIR/duplicate-suggestions.rs:107:11
    |
 LL |     match &mut (em.clone(), em.clone()) {
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 LL |
 LL |         &mut (Either::One(_t), Either::Two(_u)) => (),
-   |         ---------------------------------------
-   |         |                 |                |
-   |         |                 |                ...and here
-   |         |                 data moved here
-   |         help: consider removing the `&mut`: `(Either::One(_t), Either::Two(_u))`
+   |                           --               -- ...and here
+   |                           |
+   |                           data moved here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the mutable borrow
+   |
+LL -         &mut (Either::One(_t), Either::Two(_u)) => (),
+LL +         (Either::One(_t), Either::Two(_u)) => (),
+   |
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/duplicate-suggestions.rs:130:11
+  --> $DIR/duplicate-suggestions.rs:114:11
    |
 LL |     match &mut (em.clone(), em.clone()) {
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 LL |
 LL |         &mut (Either::One(_t), Either::Two(_u)) => (),
-   |         ---------------------------------------
-   |         |                 |                |
-   |         |                 |                ...and here
-   |         |                 data moved here
-   |         help: consider removing the `&mut`: `(Either::One(_t), Either::Two(_u))`
+   |                           --               -- ...and here
+   |                           |
+   |                           data moved here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the mutable borrow
+   |
+LL -         &mut (Either::One(_t), Either::Two(_u)) => (),
+LL +         (Either::One(_t), Either::Two(_u)) => (),
+   |
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/duplicate-suggestions.rs:138:11
+  --> $DIR/duplicate-suggestions.rs:121:11
    |
 LL |     match &mut (em.clone(), em.clone()) {
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 LL |
 LL |         &mut (Either::One(_t), Either::Two(_u)) => (),
-   |         ---------------------------------------
-   |         |                 |                |
-   |         |                 |                ...and here
-   |         |                 data moved here
-   |         help: consider removing the `&mut`: `(Either::One(_t), Either::Two(_u))`
+   |                           --               -- ...and here
+   |                           |
+   |                           data moved here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the mutable borrow
+   |
+LL -         &mut (Either::One(_t), Either::Two(_u)) => (),
+LL +         (Either::One(_t), Either::Two(_u)) => (),
+   |
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/duplicate-suggestions.rs:86:11
+  --> $DIR/duplicate-suggestions.rs:78:11
    |
 LL |     fn f5(&(X(_t), X(_u)): &(X, X)) { }
    |           ^^^^--^^^^^--^^
-   |           |   |      |
-   |           |   |      ...and here
-   |           |   data moved here
-   |           help: consider removing the `&`: `(X(_t), X(_u))`
+   |               |      |
+   |               |      ...and here
+   |               data moved here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the borrow
+   |
+LL -     fn f5(&(X(_t), X(_u)): &(X, X)) { }
+LL +     fn f5((X(_t), X(_u)): &(X, X)) { }
+   |
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/duplicate-suggestions.rs:146:11
+  --> $DIR/duplicate-suggestions.rs:128:11
    |
 LL |     fn f6(&mut (X(_t), X(_u)): &mut (X, X)) { }
    |           ^^^^^^^^--^^^^^--^^
-   |           |       |      |
-   |           |       |      ...and here
-   |           |       data moved here
-   |           help: consider removing the `&mut`: `(X(_t), X(_u))`
+   |                   |      |
+   |                   |      ...and here
+   |                   data moved here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the mutable borrow
+   |
+LL -     fn f6(&mut (X(_t), X(_u)): &mut (X, X)) { }
+LL +     fn f6((X(_t), X(_u)): &mut (X, X)) { }
+   |
 
 error: aborting due to 17 previous errors
 
index f1e043c30f213e99e4fddaede6937b5ec9644a17..44eac3691a3beb89ab81bb4b7f882dc35bd55dd5 100644 (file)
@@ -28,26 +28,21 @@ fn move_into_fn() {
         let X(_t) = x;
         //~^ ERROR cannot move
         //~| HELP consider borrowing here
-        //~| SUGGESTION &x
         if let Either::One(_t) = e { }
         //~^ ERROR cannot move
         //~| HELP consider borrowing here
-        //~| SUGGESTION &e
         while let Either::One(_t) = e { }
         //~^ ERROR cannot move
         //~| HELP consider borrowing here
-        //~| SUGGESTION &e
         match e {
             //~^ ERROR cannot move
             //~| HELP consider borrowing here
-            //~| SUGGESTION &e
             Either::One(_t)
             | Either::Two(_t) => (),
         }
         match e {
             //~^ ERROR cannot move
             //~| HELP consider borrowing here
-            //~| SUGGESTION &e
             Either::One(_t) => (),
             Either::Two(ref _t) => (),
             // FIXME: should suggest removing `ref` too
@@ -56,26 +51,21 @@ fn move_into_fn() {
         let X(mut _t) = x;
         //~^ ERROR cannot move
         //~| HELP consider borrowing here
-        //~| SUGGESTION &x
         if let Either::One(mut _t) = em { }
         //~^ ERROR cannot move
         //~| HELP consider borrowing here
-        //~| SUGGESTION &em
         while let Either::One(mut _t) = em { }
         //~^ ERROR cannot move
         //~| HELP consider borrowing here
-        //~| SUGGESTION &em
         match em {
             //~^ ERROR cannot move
             //~| HELP consider borrowing here
-            //~| SUGGESTION &em
             Either::One(mut _t)
             | Either::Two(mut _t) => (),
         }
         match em {
             //~^ ERROR cannot move
             //~| HELP consider borrowing here
-            //~| SUGGESTION &em
             Either::One(mut _t) => (),
             Either::Two(ref _t) => (),
             // FIXME: should suggest removing `ref` too
@@ -95,26 +85,21 @@ fn move_into_fnmut() {
         let X(_t) = x;
         //~^ ERROR cannot move
         //~| HELP consider borrowing here
-        //~| SUGGESTION &x
         if let Either::One(_t) = e { }
         //~^ ERROR cannot move
         //~| HELP consider borrowing here
-        //~| SUGGESTION &e
         while let Either::One(_t) = e { }
         //~^ ERROR cannot move
         //~| HELP consider borrowing here
-        //~| SUGGESTION &e
         match e {
             //~^ ERROR cannot move
             //~| HELP consider borrowing here
-            //~| SUGGESTION &e
             Either::One(_t)
             | Either::Two(_t) => (),
         }
         match e {
             //~^ ERROR cannot move
             //~| HELP consider borrowing here
-            //~| SUGGESTION &e
             Either::One(_t) => (),
             Either::Two(ref _t) => (),
             // FIXME: should suggest removing `ref` too
@@ -123,26 +108,21 @@ fn move_into_fnmut() {
         let X(mut _t) = x;
         //~^ ERROR cannot move
         //~| HELP consider borrowing here
-        //~| SUGGESTION &x
         if let Either::One(mut _t) = em { }
         //~^ ERROR cannot move
         //~| HELP consider borrowing here
-        //~| SUGGESTION &em
         while let Either::One(mut _t) = em { }
         //~^ ERROR cannot move
         //~| HELP consider borrowing here
-        //~| SUGGESTION &em
         match em {
             //~^ ERROR cannot move
             //~| HELP consider borrowing here
-            //~| SUGGESTION &em
             Either::One(mut _t)
             | Either::Two(mut _t) => (),
         }
         match em {
             //~^ ERROR cannot move
             //~| HELP consider borrowing here
-            //~| SUGGESTION &em
             Either::One(mut _t) => (),
             Either::Two(ref _t) => (),
             // FIXME: should suggest removing `ref` too
@@ -150,7 +130,6 @@ fn move_into_fnmut() {
         match em {
             //~^ ERROR cannot move
             //~| HELP consider borrowing here
-            //~| SUGGESTION &em
             Either::One(mut _t) => (),
             Either::Two(ref mut _t) => (),
             // FIXME: should suggest removing `ref` too
index e06ee4290abd801d35092d3f3f03f3c1ec3921a7..edda2cbc735a25dc541d5ff80cbf0642bb634224 100644 (file)
@@ -7,13 +7,18 @@ LL |     let x = X(Y);
 LL |     consume_fn(|| {
    |                -- captured by this `Fn` closure
 LL |         let X(_t) = x;
-   |               --    ^ help: consider borrowing here: `&x`
+   |               --    ^
    |               |
    |               data moved here
    |               move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         let X(_t) = &x;
+   |                     +
 
 error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `Fn` closure
-  --> $DIR/move-into-closure.rs:32:34
+  --> $DIR/move-into-closure.rs:31:34
    |
 LL |     let e = Either::One(X(Y));
    |         - captured outer variable
@@ -22,13 +27,18 @@ LL |     consume_fn(|| {
    |                -- captured by this `Fn` closure
 ...
 LL |         if let Either::One(_t) = e { }
-   |                            --    ^ help: consider borrowing here: `&e`
+   |                            --    ^
    |                            |
    |                            data moved here
    |                            move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         if let Either::One(_t) = &e { }
+   |                                  +
 
 error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `Fn` closure
-  --> $DIR/move-into-closure.rs:36:37
+  --> $DIR/move-into-closure.rs:34:37
    |
 LL |     let e = Either::One(X(Y));
    |         - captured outer variable
@@ -37,13 +47,18 @@ LL |     consume_fn(|| {
    |                -- captured by this `Fn` closure
 ...
 LL |         while let Either::One(_t) = e { }
-   |                               --    ^ help: consider borrowing here: `&e`
+   |                               --    ^
    |                               |
    |                               data moved here
    |                               move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         while let Either::One(_t) = &e { }
+   |                                     +
 
 error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `Fn` closure
-  --> $DIR/move-into-closure.rs:40:15
+  --> $DIR/move-into-closure.rs:37:15
    |
 LL |     let e = Either::One(X(Y));
    |         - captured outer variable
@@ -52,16 +67,21 @@ LL |     consume_fn(|| {
    |                -- captured by this `Fn` closure
 ...
 LL |         match e {
-   |               ^ help: consider borrowing here: `&e`
+   |               ^
 ...
 LL |             Either::One(_t)
    |                         --
    |                         |
    |                         data moved here
    |                         move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         match &e {
+   |               +
 
 error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `Fn` closure
-  --> $DIR/move-into-closure.rs:47:15
+  --> $DIR/move-into-closure.rs:43:15
    |
 LL |     let e = Either::One(X(Y));
    |         - captured outer variable
@@ -70,16 +90,21 @@ LL |     consume_fn(|| {
    |                -- captured by this `Fn` closure
 ...
 LL |         match e {
-   |               ^ help: consider borrowing here: `&e`
+   |               ^
 ...
 LL |             Either::One(_t) => (),
    |                         --
    |                         |
    |                         data moved here
    |                         move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         match &e {
+   |               +
 
 error[E0507]: cannot move out of `x.0`, as `x` is a captured variable in an `Fn` closure
-  --> $DIR/move-into-closure.rs:56:25
+  --> $DIR/move-into-closure.rs:51:25
    |
 LL |     let x = X(Y);
    |         - captured outer variable
@@ -88,13 +113,18 @@ LL |     consume_fn(|| {
    |                -- captured by this `Fn` closure
 ...
 LL |         let X(mut _t) = x;
-   |               ------    ^ help: consider borrowing here: `&x`
+   |               ------    ^
    |               |
    |               data moved here
    |               move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         let X(mut _t) = &x;
+   |                         +
 
 error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `Fn` closure
-  --> $DIR/move-into-closure.rs:60:38
+  --> $DIR/move-into-closure.rs:54:38
    |
 LL |     let mut em = Either::One(X(Y));
    |         ------ captured outer variable
@@ -103,13 +133,18 @@ LL |     consume_fn(|| {
    |                -- captured by this `Fn` closure
 ...
 LL |         if let Either::One(mut _t) = em { }
-   |                            ------    ^^ help: consider borrowing here: `&em`
+   |                            ------    ^^
    |                            |
    |                            data moved here
    |                            move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         if let Either::One(mut _t) = &em { }
+   |                                      +
 
 error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `Fn` closure
-  --> $DIR/move-into-closure.rs:64:41
+  --> $DIR/move-into-closure.rs:57:41
    |
 LL |     let mut em = Either::One(X(Y));
    |         ------ captured outer variable
@@ -118,13 +153,18 @@ LL |     consume_fn(|| {
    |                -- captured by this `Fn` closure
 ...
 LL |         while let Either::One(mut _t) = em { }
-   |                               ------    ^^ help: consider borrowing here: `&em`
+   |                               ------    ^^
    |                               |
    |                               data moved here
    |                               move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         while let Either::One(mut _t) = &em { }
+   |                                         +
 
 error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `Fn` closure
-  --> $DIR/move-into-closure.rs:68:15
+  --> $DIR/move-into-closure.rs:60:15
    |
 LL |     let mut em = Either::One(X(Y));
    |         ------ captured outer variable
@@ -133,16 +173,21 @@ LL |     consume_fn(|| {
    |                -- captured by this `Fn` closure
 ...
 LL |         match em {
-   |               ^^ help: consider borrowing here: `&em`
+   |               ^^
 ...
 LL |             Either::One(mut _t)
    |                         ------
    |                         |
    |                         data moved here
    |                         move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         match &em {
+   |               +
 
 error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `Fn` closure
-  --> $DIR/move-into-closure.rs:75:15
+  --> $DIR/move-into-closure.rs:66:15
    |
 LL |     let mut em = Either::One(X(Y));
    |         ------ captured outer variable
@@ -151,16 +196,21 @@ LL |     consume_fn(|| {
    |                -- captured by this `Fn` closure
 ...
 LL |         match em {
-   |               ^^ help: consider borrowing here: `&em`
+   |               ^^
 ...
 LL |             Either::One(mut _t) => (),
    |                         ------
    |                         |
    |                         data moved here
    |                         move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         match &em {
+   |               +
 
 error[E0507]: cannot move out of `x.0`, as `x` is a captured variable in an `FnMut` closure
-  --> $DIR/move-into-closure.rs:95:21
+  --> $DIR/move-into-closure.rs:85:21
    |
 LL |     let x = X(Y);
    |         - captured outer variable
@@ -168,13 +218,18 @@ LL |     let x = X(Y);
 LL |     consume_fnmut(|| {
    |                   -- captured by this `FnMut` closure
 LL |         let X(_t) = x;
-   |               --    ^ help: consider borrowing here: `&x`
+   |               --    ^
    |               |
    |               data moved here
    |               move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         let X(_t) = &x;
+   |                     +
 
 error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `FnMut` closure
-  --> $DIR/move-into-closure.rs:99:34
+  --> $DIR/move-into-closure.rs:88:34
    |
 LL |     let e = Either::One(X(Y));
    |         - captured outer variable
@@ -183,13 +238,18 @@ LL |     consume_fnmut(|| {
    |                   -- captured by this `FnMut` closure
 ...
 LL |         if let Either::One(_t) = e { }
-   |                            --    ^ help: consider borrowing here: `&e`
+   |                            --    ^
    |                            |
    |                            data moved here
    |                            move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         if let Either::One(_t) = &e { }
+   |                                  +
 
 error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `FnMut` closure
-  --> $DIR/move-into-closure.rs:103:37
+  --> $DIR/move-into-closure.rs:91:37
    |
 LL |     let e = Either::One(X(Y));
    |         - captured outer variable
@@ -198,13 +258,18 @@ LL |     consume_fnmut(|| {
    |                   -- captured by this `FnMut` closure
 ...
 LL |         while let Either::One(_t) = e { }
-   |                               --    ^ help: consider borrowing here: `&e`
+   |                               --    ^
    |                               |
    |                               data moved here
    |                               move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         while let Either::One(_t) = &e { }
+   |                                     +
 
 error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `FnMut` closure
-  --> $DIR/move-into-closure.rs:107:15
+  --> $DIR/move-into-closure.rs:94:15
    |
 LL |     let e = Either::One(X(Y));
    |         - captured outer variable
@@ -213,16 +278,21 @@ LL |     consume_fnmut(|| {
    |                   -- captured by this `FnMut` closure
 ...
 LL |         match e {
-   |               ^ help: consider borrowing here: `&e`
+   |               ^
 ...
 LL |             Either::One(_t)
    |                         --
    |                         |
    |                         data moved here
    |                         move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         match &e {
+   |               +
 
 error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `FnMut` closure
-  --> $DIR/move-into-closure.rs:114:15
+  --> $DIR/move-into-closure.rs:100:15
    |
 LL |     let e = Either::One(X(Y));
    |         - captured outer variable
@@ -231,16 +301,21 @@ LL |     consume_fnmut(|| {
    |                   -- captured by this `FnMut` closure
 ...
 LL |         match e {
-   |               ^ help: consider borrowing here: `&e`
+   |               ^
 ...
 LL |             Either::One(_t) => (),
    |                         --
    |                         |
    |                         data moved here
    |                         move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         match &e {
+   |               +
 
 error[E0507]: cannot move out of `x.0`, as `x` is a captured variable in an `FnMut` closure
-  --> $DIR/move-into-closure.rs:123:25
+  --> $DIR/move-into-closure.rs:108:25
    |
 LL |     let x = X(Y);
    |         - captured outer variable
@@ -249,13 +324,18 @@ LL |     consume_fnmut(|| {
    |                   -- captured by this `FnMut` closure
 ...
 LL |         let X(mut _t) = x;
-   |               ------    ^ help: consider borrowing here: `&x`
+   |               ------    ^
    |               |
    |               data moved here
    |               move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         let X(mut _t) = &x;
+   |                         +
 
 error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure
-  --> $DIR/move-into-closure.rs:127:38
+  --> $DIR/move-into-closure.rs:111:38
    |
 LL |     let mut em = Either::One(X(Y));
    |         ------ captured outer variable
@@ -264,13 +344,18 @@ LL |     consume_fnmut(|| {
    |                   -- captured by this `FnMut` closure
 ...
 LL |         if let Either::One(mut _t) = em { }
-   |                            ------    ^^ help: consider borrowing here: `&em`
+   |                            ------    ^^
    |                            |
    |                            data moved here
    |                            move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         if let Either::One(mut _t) = &em { }
+   |                                      +
 
 error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure
-  --> $DIR/move-into-closure.rs:131:41
+  --> $DIR/move-into-closure.rs:114:41
    |
 LL |     let mut em = Either::One(X(Y));
    |         ------ captured outer variable
@@ -279,13 +364,18 @@ LL |     consume_fnmut(|| {
    |                   -- captured by this `FnMut` closure
 ...
 LL |         while let Either::One(mut _t) = em { }
-   |                               ------    ^^ help: consider borrowing here: `&em`
+   |                               ------    ^^
    |                               |
    |                               data moved here
    |                               move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         while let Either::One(mut _t) = &em { }
+   |                                         +
 
 error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure
-  --> $DIR/move-into-closure.rs:135:15
+  --> $DIR/move-into-closure.rs:117:15
    |
 LL |     let mut em = Either::One(X(Y));
    |         ------ captured outer variable
@@ -294,16 +384,21 @@ LL |     consume_fnmut(|| {
    |                   -- captured by this `FnMut` closure
 ...
 LL |         match em {
-   |               ^^ help: consider borrowing here: `&em`
+   |               ^^
 ...
 LL |             Either::One(mut _t)
    |                         ------
    |                         |
    |                         data moved here
    |                         move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         match &em {
+   |               +
 
 error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure
-  --> $DIR/move-into-closure.rs:142:15
+  --> $DIR/move-into-closure.rs:123:15
    |
 LL |     let mut em = Either::One(X(Y));
    |         ------ captured outer variable
@@ -312,16 +407,21 @@ LL |     consume_fnmut(|| {
    |                   -- captured by this `FnMut` closure
 ...
 LL |         match em {
-   |               ^^ help: consider borrowing here: `&em`
+   |               ^^
 ...
 LL |             Either::One(mut _t) => (),
    |                         ------
    |                         |
    |                         data moved here
    |                         move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         match &em {
+   |               +
 
 error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure
-  --> $DIR/move-into-closure.rs:150:15
+  --> $DIR/move-into-closure.rs:130:15
    |
 LL |     let mut em = Either::One(X(Y));
    |         ------ captured outer variable
@@ -330,13 +430,18 @@ LL |     consume_fnmut(|| {
    |                   -- captured by this `FnMut` closure
 ...
 LL |         match em {
-   |               ^^ help: consider borrowing here: `&em`
+   |               ^^
 ...
 LL |             Either::One(mut _t) => (),
    |                         ------
    |                         |
    |                         data moved here
    |                         move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         match &em {
+   |               +
 
 error: aborting due to 21 previous errors
 
index c53ac3d2cd684fcecf5de1061354ee5254a94ec5..1e40e60a1ce12c4785d17e5b7c61ee5dc3fa5b52 100644 (file)
@@ -37,27 +37,22 @@ pub fn main() {
 
     let X(_t) = *s;
     //~^ ERROR cannot move
-    //~| HELP consider borrowing here
-    //~| SUGGESTION s
+    //~| HELP consider removing the dereference here
     if let Either::One(_t) = *r { }
     //~^ ERROR cannot move
-    //~| HELP consider borrowing here
-    //~| SUGGESTION r
+    //~| HELP consider removing the dereference here
     while let Either::One(_t) = *r { }
     //~^ ERROR cannot move
-    //~| HELP consider borrowing here
-    //~| SUGGESTION r
+    //~| HELP consider removing the dereference here
     match *r {
         //~^ ERROR cannot move
-        //~| HELP consider borrowing here
-        //~| SUGGESTION r
+        //~| HELP consider removing the dereference here
         Either::One(_t)
         | Either::Two(_t) => (),
     }
     match *r {
         //~^ ERROR cannot move
-        //~| HELP consider borrowing here
-        //~| SUGGESTION r
+        //~| HELP consider removing the dereference here
         Either::One(_t) => (),
         Either::Two(ref _t) => (),
         // FIXME: should suggest removing `ref` too
@@ -65,35 +60,29 @@ pub fn main() {
 
     let X(_t) = *sm;
     //~^ ERROR cannot move
-    //~| HELP consider borrowing here
-    //~| SUGGESTION sm
+    //~| HELP consider removing the dereference here
     if let Either::One(_t) = *rm { }
     //~^ ERROR cannot move
-    //~| HELP consider borrowing here
-    //~| SUGGESTION rm
+    //~| HELP consider removing the dereference here
     while let Either::One(_t) = *rm { }
     //~^ ERROR cannot move
-    //~| HELP consider borrowing here
-    //~| SUGGESTION rm
+    //~| HELP consider removing the dereference here
     match *rm {
         //~^ ERROR cannot move
-        //~| HELP consider borrowing here
-        //~| SUGGESTION rm
+        //~| HELP consider removing the dereference here
         Either::One(_t)
         | Either::Two(_t) => (),
     }
     match *rm {
         //~^ ERROR cannot move
-        //~| HELP consider borrowing here
-        //~| SUGGESTION rm
+        //~| HELP consider removing the dereference here
         Either::One(_t) => (),
         Either::Two(ref _t) => (),
         // FIXME: should suggest removing `ref` too
     }
     match *rm {
         //~^ ERROR cannot move
-        //~| HELP consider borrowing here
-        //~| SUGGESTION rm
+        //~| HELP consider removing the dereference here
         Either::One(_t) => (),
         Either::Two(ref mut _t) => (),
         // FIXME: should suggest removing `ref` too
@@ -102,26 +91,21 @@ pub fn main() {
     let X(_t) = vs[0];
     //~^ ERROR cannot move
     //~| HELP consider borrowing here
-    //~| SUGGESTION &vs[0]
     if let Either::One(_t) = vr[0] { }
     //~^ ERROR cannot move
     //~| HELP consider borrowing here
-    //~| SUGGESTION &vr[0]
     while let Either::One(_t) = vr[0] { }
     //~^ ERROR cannot move
     //~| HELP consider borrowing here
-    //~| SUGGESTION &vr[0]
     match vr[0] {
         //~^ ERROR cannot move
         //~| HELP consider borrowing here
-        //~| SUGGESTION &vr[0]
         Either::One(_t)
         | Either::Two(_t) => (),
     }
     match vr[0] {
         //~^ ERROR cannot move
         //~| HELP consider borrowing here
-        //~| SUGGESTION &vr[0]
         Either::One(_t) => (),
         Either::Two(ref _t) => (),
         // FIXME: should suggest removing `ref` too
@@ -130,26 +114,21 @@ pub fn main() {
     let X(_t) = vsm[0];
     //~^ ERROR cannot move
     //~| HELP consider borrowing here
-    //~| SUGGESTION &vsm[0]
     if let Either::One(_t) = vrm[0] { }
     //~^ ERROR cannot move
     //~| HELP consider borrowing here
-    //~| SUGGESTION &vrm[0]
     while let Either::One(_t) = vrm[0] { }
     //~^ ERROR cannot move
     //~| HELP consider borrowing here
-    //~| SUGGESTION &vrm[0]
     match vrm[0] {
         //~^ ERROR cannot move
         //~| HELP consider borrowing here
-        //~| SUGGESTION &vrm[0]
         Either::One(_t)
         | Either::Two(_t) => (),
     }
     match vrm[0] {
         //~^ ERROR cannot move
         //~| HELP consider borrowing here
-        //~| SUGGESTION &vrm[0]
         Either::One(_t) => (),
         Either::Two(ref _t) => (),
         // FIXME: should suggest removing `ref` too
@@ -157,7 +136,6 @@ pub fn main() {
     match vrm[0] {
         //~^ ERROR cannot move
         //~| HELP consider borrowing here
-        //~| SUGGESTION &vrm[0]
         Either::One(_t) => (),
         Either::Two(ref mut _t) => (),
         // FIXME: should suggest removing `ref` too
@@ -167,89 +145,73 @@ pub fn main() {
 
     let &X(_t) = s;
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&`
-    //~| SUGGESTION X(_t)
+    //~| HELP consider removing
     if let &Either::One(_t) = r { }
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&`
-    //~| SUGGESTION Either::One(_t)
+    //~| HELP consider removing
     while let &Either::One(_t) = r { }
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&`
-    //~| SUGGESTION Either::One(_t)
+    //~| HELP consider removing
     match r {
         //~^ ERROR cannot move
         &Either::One(_t)
-        //~^ HELP consider removing the `&`
-        //~| SUGGESTION Either::One(_t)
+        //~^ HELP consider removing
         | &Either::Two(_t) => (),
         // FIXME: would really like a suggestion here too
     }
     match r {
         //~^ ERROR cannot move
         &Either::One(_t) => (),
-        //~^ HELP consider removing the `&`
-        //~| SUGGESTION Either::One(_t)
+        //~^ HELP consider removing
         &Either::Two(ref _t) => (),
     }
     match r {
         //~^ ERROR cannot move
         &Either::One(_t) => (),
-        //~^ HELP consider removing the `&`
-        //~| SUGGESTION Either::One(_t)
+        //~^ HELP consider removing
         Either::Two(_t) => (),
     }
     fn f1(&X(_t): &X) { }
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&`
-    //~| SUGGESTION X(_t)
+    //~| HELP consider removing
 
     let &mut X(_t) = sm;
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&mut`
-    //~| SUGGESTION X(_t)
+    //~| HELP consider removing
     if let &mut Either::One(_t) = rm { }
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&mut`
-    //~| SUGGESTION Either::One(_t)
+    //~| HELP consider removing
     while let &mut Either::One(_t) = rm { }
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&mut`
-    //~| SUGGESTION Either::One(_t)
+    //~| HELP consider removing
     match rm {
         //~^ ERROR cannot move
         &mut Either::One(_t) => (),
-        //~^ HELP consider removing the `&mut`
-        //~| SUGGESTION Either::One(_t)
+        //~^ HELP consider removing
         &mut Either::Two(_t) => (),
-        //~^ HELP consider removing the `&mut`
-        //~| SUGGESTION Either::Two(_t)
+        //~^ HELP consider removing
     }
     match rm {
         //~^ ERROR cannot move
         &mut Either::One(_t) => (),
-        //~^ HELP consider removing the `&mut`
-        //~| SUGGESTION Either::One(_t)
+        //~^ HELP consider removing
         &mut Either::Two(ref _t) => (),
     }
     match rm {
         //~^ ERROR cannot move
         &mut Either::One(_t) => (),
-        //~^ HELP consider removing the `&mut`
-        //~| SUGGESTION Either::One(_t)
+        //~^ HELP consider removing
         &mut Either::Two(ref mut _t) => (),
     }
     match rm {
         //~^ ERROR cannot move
         &mut Either::One(_t) => (),
-        //~^ HELP consider removing the `&mut`
-        //~| SUGGESTION Either::One(_t)
+        //~^ HELP consider removing
         Either::Two(_t) => (),
     }
     fn f2(&mut X(_t): &mut X) { }
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&mut`
-    //~| SUGGESTION X(_t)
+    //~| HELP consider removing
 
     // move from tuple of &Either/&X
 
@@ -257,108 +219,118 @@ fn f2(&mut X(_t): &mut X) { }
 
     let (&X(_t),) = (&x.clone(),);
     //~^ ERROR cannot move
+    //~| HELP consider borrowing the pattern binding
     if let (&Either::One(_t),) = (&e.clone(),) { }
     //~^ ERROR cannot move
+    //~| HELP consider borrowing the pattern binding
     while let (&Either::One(_t),) = (&e.clone(),) { }
     //~^ ERROR cannot move
+    //~| HELP consider borrowing the pattern binding
     match (&e.clone(),) {
         //~^ ERROR cannot move
         (&Either::One(_t),)
+        //~^ HELP consider borrowing the pattern binding
         | (&Either::Two(_t),) => (),
     }
     fn f3((&X(_t),): (&X,)) { }
     //~^ ERROR cannot move
+    //~| HELP consider borrowing the pattern binding
 
     let (&mut X(_t),) = (&mut xm.clone(),);
     //~^ ERROR cannot move
+    //~| HELP consider borrowing the pattern binding
     if let (&mut Either::One(_t),) = (&mut em.clone(),) { }
     //~^ ERROR cannot move
+    //~| HELP consider borrowing the pattern binding
     while let (&mut Either::One(_t),) = (&mut em.clone(),) { }
     //~^ ERROR cannot move
+    //~| HELP consider borrowing the pattern binding
     match (&mut em.clone(),) {
         //~^ ERROR cannot move
         (&mut Either::One(_t),) => (),
+        //~^ HELP consider borrowing the pattern binding
         (&mut Either::Two(_t),) => (),
+        //~^ HELP consider borrowing the pattern binding
     }
     fn f4((&mut X(_t),): (&mut X,)) { }
     //~^ ERROR cannot move
+    //~| HELP consider borrowing the pattern binding
 
     // move from &Either/&X value
 
     let &X(_t) = &x;
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&`
-    //~| SUGGESTION X(_t)
+    //~| HELP consider removing
     if let &Either::One(_t) = &e { }
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&`
-    //~| SUGGESTION Either::One(_t)
+    //~| HELP consider removing
     while let &Either::One(_t) = &e { }
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&`
-    //~| SUGGESTION Either::One(_t)
+    //~| HELP consider removing
     match &e {
         //~^ ERROR cannot move
         &Either::One(_t)
-        //~^ HELP consider removing the `&`
-        //~| SUGGESTION Either::One(_t)
+        //~^ HELP consider removing
         | &Either::Two(_t) => (),
         // FIXME: would really like a suggestion here too
     }
     match &e {
         //~^ ERROR cannot move
         &Either::One(_t) => (),
-        //~^ HELP consider removing the `&`
-        //~| SUGGESTION Either::One(_t)
+        //~^ HELP consider removing
         &Either::Two(ref _t) => (),
     }
     match &e {
         //~^ ERROR cannot move
         &Either::One(_t) => (),
-        //~^ HELP consider removing the `&`
-        //~| SUGGESTION Either::One(_t)
+        //~^ HELP consider removing
         Either::Two(_t) => (),
     }
 
     let &mut X(_t) = &mut xm;
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&mut`
-    //~| SUGGESTION X(_t)
+    //~| HELP consider removing
     if let &mut Either::One(_t) = &mut em { }
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&mut`
-    //~| SUGGESTION Either::One(_t)
+    //~| HELP consider removing
     while let &mut Either::One(_t) = &mut em { }
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&mut`
-    //~| SUGGESTION Either::One(_t)
+    //~| HELP consider removing
     match &mut em {
         //~^ ERROR cannot move
         &mut Either::One(_t)
-        //~^ HELP consider removing the `&mut`
-        //~| SUGGESTION Either::One(_t)
+        //~^ HELP consider removing
         | &mut Either::Two(_t) => (),
         // FIXME: would really like a suggestion here too
     }
     match &mut em {
         //~^ ERROR cannot move
         &mut Either::One(_t) => (),
-        //~^ HELP consider removing the `&mut`
-        //~| SUGGESTION Either::One(_t)
+        //~^ HELP consider removing
         &mut Either::Two(ref _t) => (),
     }
     match &mut em {
         //~^ ERROR cannot move
         &mut Either::One(_t) => (),
-        //~^ HELP consider removing the `&mut`
-        //~| SUGGESTION Either::One(_t)
+        //~^ HELP consider removing
         &mut Either::Two(ref mut _t) => (),
     }
     match &mut em {
         //~^ ERROR cannot move
         &mut Either::One(_t) => (),
-        //~^ HELP consider removing the `&mut`
-        //~| SUGGESTION Either::One(_t)
+        //~^ HELP consider removing
         Either::Two(_t) => (),
     }
 }
+
+struct Testing {
+    a: Option<String>
+}
+
+fn testing(a: &Testing) {
+    let Some(_s) = a.a else {
+        //~^ ERROR cannot move
+        //~| HELP consider borrowing the pattern binding
+        return;
+    };
+}
index e5443290f9e7a603f60dec3ac74f75d5a3233c47..5263265242318f13d4a9cfe85abda0446f15424b 100644 (file)
@@ -2,262 +2,398 @@ error[E0507]: cannot move out of `s` which is behind a shared reference
   --> $DIR/simple.rs:38:17
    |
 LL |     let X(_t) = *s;
-   |           --    ^^ help: consider borrowing here: `&*s`
+   |           --    ^^
    |           |
    |           data moved here
    |           move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let X(_t) = *s;
+LL +     let X(_t) = s;
+   |
 
 error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference
-  --> $DIR/simple.rs:42:30
+  --> $DIR/simple.rs:41:30
    |
 LL |     if let Either::One(_t) = *r { }
-   |                        --    ^^ help: consider borrowing here: `&*r`
+   |                        --    ^^
    |                        |
    |                        data moved here
    |                        move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     if let Either::One(_t) = *r { }
+LL +     if let Either::One(_t) = r { }
+   |
 
 error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference
-  --> $DIR/simple.rs:46:33
+  --> $DIR/simple.rs:44:33
    |
 LL |     while let Either::One(_t) = *r { }
-   |                           --    ^^ help: consider borrowing here: `&*r`
+   |                           --    ^^
    |                           |
    |                           data moved here
    |                           move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     while let Either::One(_t) = *r { }
+LL +     while let Either::One(_t) = r { }
+   |
 
 error[E0507]: cannot move out of `r` as enum variant `Two` which is behind a shared reference
-  --> $DIR/simple.rs:50:11
+  --> $DIR/simple.rs:47:11
    |
 LL |     match *r {
-   |           ^^ help: consider borrowing here: `&*r`
+   |           ^^
 ...
 LL |         Either::One(_t)
    |                     --
    |                     |
    |                     data moved here
    |                     move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     match *r {
+LL +     match r {
+   |
 
 error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference
-  --> $DIR/simple.rs:57:11
+  --> $DIR/simple.rs:53:11
    |
 LL |     match *r {
-   |           ^^ help: consider borrowing here: `&*r`
+   |           ^^
 ...
 LL |         Either::One(_t) => (),
    |                     --
    |                     |
    |                     data moved here
    |                     move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     match *r {
+LL +     match r {
+   |
 
 error[E0507]: cannot move out of `sm` which is behind a mutable reference
-  --> $DIR/simple.rs:66:17
+  --> $DIR/simple.rs:61:17
    |
 LL |     let X(_t) = *sm;
-   |           --    ^^^ help: consider borrowing here: `&*sm`
+   |           --    ^^^
    |           |
    |           data moved here
    |           move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let X(_t) = *sm;
+LL +     let X(_t) = sm;
+   |
 
 error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference
-  --> $DIR/simple.rs:70:30
+  --> $DIR/simple.rs:64:30
    |
 LL |     if let Either::One(_t) = *rm { }
-   |                        --    ^^^ help: consider borrowing here: `&*rm`
+   |                        --    ^^^
    |                        |
    |                        data moved here
    |                        move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     if let Either::One(_t) = *rm { }
+LL +     if let Either::One(_t) = rm { }
+   |
 
 error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference
-  --> $DIR/simple.rs:74:33
+  --> $DIR/simple.rs:67:33
    |
 LL |     while let Either::One(_t) = *rm { }
-   |                           --    ^^^ help: consider borrowing here: `&*rm`
+   |                           --    ^^^
    |                           |
    |                           data moved here
    |                           move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     while let Either::One(_t) = *rm { }
+LL +     while let Either::One(_t) = rm { }
+   |
 
 error[E0507]: cannot move out of `rm` as enum variant `Two` which is behind a mutable reference
-  --> $DIR/simple.rs:78:11
+  --> $DIR/simple.rs:70:11
    |
 LL |     match *rm {
-   |           ^^^ help: consider borrowing here: `&*rm`
+   |           ^^^
 ...
 LL |         Either::One(_t)
    |                     --
    |                     |
    |                     data moved here
    |                     move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     match *rm {
+LL +     match rm {
+   |
 
 error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference
-  --> $DIR/simple.rs:85:11
+  --> $DIR/simple.rs:76:11
    |
 LL |     match *rm {
-   |           ^^^ help: consider borrowing here: `&*rm`
+   |           ^^^
 ...
 LL |         Either::One(_t) => (),
    |                     --
    |                     |
    |                     data moved here
    |                     move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     match *rm {
+LL +     match rm {
+   |
 
 error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference
-  --> $DIR/simple.rs:93:11
+  --> $DIR/simple.rs:83:11
    |
 LL |     match *rm {
-   |           ^^^ help: consider borrowing here: `&*rm`
+   |           ^^^
 ...
 LL |         Either::One(_t) => (),
    |                     --
    |                     |
    |                     data moved here
    |                     move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     match *rm {
+LL +     match rm {
+   |
 
 error[E0507]: cannot move out of index of `Vec<X>`
-  --> $DIR/simple.rs:102:17
+  --> $DIR/simple.rs:91:17
    |
 LL |     let X(_t) = vs[0];
-   |           --    ^^^^^ help: consider borrowing here: `&vs[0]`
+   |           --    ^^^^^
    |           |
    |           data moved here
    |           move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     let X(_t) = &vs[0];
+   |                 +
 
 error[E0507]: cannot move out of index of `Vec<Either>`
-  --> $DIR/simple.rs:106:30
+  --> $DIR/simple.rs:94:30
    |
 LL |     if let Either::One(_t) = vr[0] { }
-   |                        --    ^^^^^ help: consider borrowing here: `&vr[0]`
+   |                        --    ^^^^^
    |                        |
    |                        data moved here
    |                        move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     if let Either::One(_t) = &vr[0] { }
+   |                              +
 
 error[E0507]: cannot move out of index of `Vec<Either>`
-  --> $DIR/simple.rs:110:33
+  --> $DIR/simple.rs:97:33
    |
 LL |     while let Either::One(_t) = vr[0] { }
-   |                           --    ^^^^^ help: consider borrowing here: `&vr[0]`
+   |                           --    ^^^^^
    |                           |
    |                           data moved here
    |                           move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     while let Either::One(_t) = &vr[0] { }
+   |                                 +
 
 error[E0507]: cannot move out of index of `Vec<Either>`
-  --> $DIR/simple.rs:114:11
+  --> $DIR/simple.rs:100:11
    |
 LL |     match vr[0] {
-   |           ^^^^^ help: consider borrowing here: `&vr[0]`
+   |           ^^^^^
 ...
 LL |         Either::One(_t)
    |                     --
    |                     |
    |                     data moved here
    |                     move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     match &vr[0] {
+   |           +
 
 error[E0507]: cannot move out of index of `Vec<Either>`
-  --> $DIR/simple.rs:121:11
+  --> $DIR/simple.rs:106:11
    |
 LL |     match vr[0] {
-   |           ^^^^^ help: consider borrowing here: `&vr[0]`
+   |           ^^^^^
 ...
 LL |         Either::One(_t) => (),
    |                     --
    |                     |
    |                     data moved here
    |                     move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     match &vr[0] {
+   |           +
 
 error[E0507]: cannot move out of index of `Vec<X>`
-  --> $DIR/simple.rs:130:17
+  --> $DIR/simple.rs:114:17
    |
 LL |     let X(_t) = vsm[0];
-   |           --    ^^^^^^ help: consider borrowing here: `&vsm[0]`
+   |           --    ^^^^^^
    |           |
    |           data moved here
    |           move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     let X(_t) = &vsm[0];
+   |                 +
 
 error[E0507]: cannot move out of index of `Vec<Either>`
-  --> $DIR/simple.rs:134:30
+  --> $DIR/simple.rs:117:30
    |
 LL |     if let Either::One(_t) = vrm[0] { }
-   |                        --    ^^^^^^ help: consider borrowing here: `&vrm[0]`
+   |                        --    ^^^^^^
    |                        |
    |                        data moved here
    |                        move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     if let Either::One(_t) = &vrm[0] { }
+   |                              +
 
 error[E0507]: cannot move out of index of `Vec<Either>`
-  --> $DIR/simple.rs:138:33
+  --> $DIR/simple.rs:120:33
    |
 LL |     while let Either::One(_t) = vrm[0] { }
-   |                           --    ^^^^^^ help: consider borrowing here: `&vrm[0]`
+   |                           --    ^^^^^^
    |                           |
    |                           data moved here
    |                           move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     while let Either::One(_t) = &vrm[0] { }
+   |                                 +
 
 error[E0507]: cannot move out of index of `Vec<Either>`
-  --> $DIR/simple.rs:142:11
+  --> $DIR/simple.rs:123:11
    |
 LL |     match vrm[0] {
-   |           ^^^^^^ help: consider borrowing here: `&vrm[0]`
+   |           ^^^^^^
 ...
 LL |         Either::One(_t)
    |                     --
    |                     |
    |                     data moved here
    |                     move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     match &vrm[0] {
+   |           +
 
 error[E0507]: cannot move out of index of `Vec<Either>`
-  --> $DIR/simple.rs:149:11
+  --> $DIR/simple.rs:129:11
    |
 LL |     match vrm[0] {
-   |           ^^^^^^ help: consider borrowing here: `&vrm[0]`
+   |           ^^^^^^
 ...
 LL |         Either::One(_t) => (),
    |                     --
    |                     |
    |                     data moved here
    |                     move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     match &vrm[0] {
+   |           +
 
 error[E0507]: cannot move out of index of `Vec<Either>`
-  --> $DIR/simple.rs:157:11
+  --> $DIR/simple.rs:136:11
    |
 LL |     match vrm[0] {
-   |           ^^^^^^ help: consider borrowing here: `&vrm[0]`
+   |           ^^^^^^
 ...
 LL |         Either::One(_t) => (),
    |                     --
    |                     |
    |                     data moved here
    |                     move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     match &vrm[0] {
+   |           +
 
 error[E0507]: cannot move out of `s` which is behind a shared reference
-  --> $DIR/simple.rs:168:18
+  --> $DIR/simple.rs:146:18
    |
 LL |     let &X(_t) = s;
-   |         ------   ^
-   |         |  |
-   |         |  data moved here
-   |         |  move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
-   |         help: consider removing the `&`: `X(_t)`
+   |            --    ^
+   |            |
+   |            data moved here
+   |            move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -     let &X(_t) = s;
+LL +     let X(_t) = s;
+   |
 
 error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference
-  --> $DIR/simple.rs:172:31
+  --> $DIR/simple.rs:149:31
    |
 LL |     if let &Either::One(_t) = r { }
-   |            ----------------   ^
-   |            |            |
-   |            |            data moved here
-   |            |            move occurs because `_t` has type `X`, which does not implement the `Copy` trait
-   |            help: consider removing the `&`: `Either::One(_t)`
+   |                         --    ^
+   |                         |
+   |                         data moved here
+   |                         move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -     if let &Either::One(_t) = r { }
+LL +     if let Either::One(_t) = r { }
+   |
 
 error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference
-  --> $DIR/simple.rs:176:34
+  --> $DIR/simple.rs:152:34
    |
 LL |     while let &Either::One(_t) = r { }
-   |               ----------------   ^
-   |               |            |
-   |               |            data moved here
-   |               |            move occurs because `_t` has type `X`, which does not implement the `Copy` trait
-   |               help: consider removing the `&`: `Either::One(_t)`
+   |                            --    ^
+   |                            |
+   |                            data moved here
+   |                            move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -     while let &Either::One(_t) = r { }
+LL +     while let Either::One(_t) = r { }
+   |
 
 error[E0507]: cannot move out of `r` as enum variant `Two` which is behind a shared reference
-  --> $DIR/simple.rs:180:11
+  --> $DIR/simple.rs:155:11
    |
 LL |     match r {
    |           ^
@@ -268,160 +404,215 @@ LL |         &Either::One(_t)
    |                      data moved here
    |                      move occurs because `_t` has type `X`, which does not implement the `Copy` trait
    |
-help: consider removing the `&`
+help: consider removing the borrow
    |
-LL ~         Either::One(_t)
-LL +
-LL +
-LL ~         | &Either::Two(_t) => (),
+LL -         &Either::One(_t)
+LL +         Either::One(_t)
    |
 
 error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference
-  --> $DIR/simple.rs:188:11
+  --> $DIR/simple.rs:162:11
    |
 LL |     match r {
    |           ^
 LL |
 LL |         &Either::One(_t) => (),
-   |         ----------------
-   |         |            |
-   |         |            data moved here
-   |         |            move occurs because `_t` has type `X`, which does not implement the `Copy` trait
-   |         help: consider removing the `&`: `Either::One(_t)`
+   |                      --
+   |                      |
+   |                      data moved here
+   |                      move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -         &Either::One(_t) => (),
+LL +         Either::One(_t) => (),
+   |
 
 error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference
-  --> $DIR/simple.rs:195:11
+  --> $DIR/simple.rs:168:11
    |
 LL |     match r {
    |           ^
 LL |
 LL |         &Either::One(_t) => (),
-   |         ----------------
-   |         |            |
-   |         |            data moved here
-   |         |            move occurs because `_t` has type `X`, which does not implement the `Copy` trait
-   |         help: consider removing the `&`: `Either::One(_t)`
+   |                      --
+   |                      |
+   |                      data moved here
+   |                      move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -         &Either::One(_t) => (),
+LL +         Either::One(_t) => (),
+   |
 
 error[E0507]: cannot move out of `sm` which is behind a mutable reference
-  --> $DIR/simple.rs:207:22
+  --> $DIR/simple.rs:178:22
    |
 LL |     let &mut X(_t) = sm;
-   |         ----------   ^^
-   |         |      |
-   |         |      data moved here
-   |         |      move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
-   |         help: consider removing the `&mut`: `X(_t)`
+   |                --    ^^
+   |                |
+   |                data moved here
+   |                move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+   |
+help: consider removing the mutable borrow
+   |
+LL -     let &mut X(_t) = sm;
+LL +     let X(_t) = sm;
+   |
 
 error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference
-  --> $DIR/simple.rs:211:35
+  --> $DIR/simple.rs:181:35
    |
 LL |     if let &mut Either::One(_t) = rm { }
-   |            --------------------   ^^
-   |            |                |
-   |            |                data moved here
-   |            |                move occurs because `_t` has type `X`, which does not implement the `Copy` trait
-   |            help: consider removing the `&mut`: `Either::One(_t)`
+   |                             --    ^^
+   |                             |
+   |                             data moved here
+   |                             move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the mutable borrow
+   |
+LL -     if let &mut Either::One(_t) = rm { }
+LL +     if let Either::One(_t) = rm { }
+   |
 
 error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference
-  --> $DIR/simple.rs:215:38
+  --> $DIR/simple.rs:184:38
    |
 LL |     while let &mut Either::One(_t) = rm { }
-   |               --------------------   ^^
-   |               |                |
-   |               |                data moved here
-   |               |                move occurs because `_t` has type `X`, which does not implement the `Copy` trait
-   |               help: consider removing the `&mut`: `Either::One(_t)`
+   |                                --    ^^
+   |                                |
+   |                                data moved here
+   |                                move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the mutable borrow
+   |
+LL -     while let &mut Either::One(_t) = rm { }
+LL +     while let Either::One(_t) = rm { }
+   |
 
 error[E0507]: cannot move out of `rm` as enum variant `Two` which is behind a mutable reference
-  --> $DIR/simple.rs:219:11
+  --> $DIR/simple.rs:187:11
    |
 LL |     match rm {
    |           ^^
 LL |
 LL |         &mut Either::One(_t) => (),
    |                          -- data moved here
-...
+LL |
 LL |         &mut Either::Two(_t) => (),
    |                          -- ...and here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
-help: consider removing the `&mut`
+help: consider removing the mutable borrow
    |
-LL |         Either::One(_t) => (),
-   |         ~~~~~~~~~~~~~~~
-help: consider removing the `&mut`
+LL -         &mut Either::One(_t) => (),
+LL +         Either::One(_t) => (),
+   |
+help: consider removing the mutable borrow
+   |
+LL -         &mut Either::Two(_t) => (),
+LL +         Either::Two(_t) => (),
    |
-LL |         Either::Two(_t) => (),
-   |         ~~~~~~~~~~~~~~~
 
 error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference
-  --> $DIR/simple.rs:228:11
+  --> $DIR/simple.rs:194:11
    |
 LL |     match rm {
    |           ^^
 LL |
 LL |         &mut Either::One(_t) => (),
-   |         --------------------
-   |         |                |
-   |         |                data moved here
-   |         |                move occurs because `_t` has type `X`, which does not implement the `Copy` trait
-   |         help: consider removing the `&mut`: `Either::One(_t)`
+   |                          --
+   |                          |
+   |                          data moved here
+   |                          move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the mutable borrow
+   |
+LL -         &mut Either::One(_t) => (),
+LL +         Either::One(_t) => (),
+   |
 
 error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference
-  --> $DIR/simple.rs:235:11
+  --> $DIR/simple.rs:200:11
    |
 LL |     match rm {
    |           ^^
 LL |
 LL |         &mut Either::One(_t) => (),
-   |         --------------------
-   |         |                |
-   |         |                data moved here
-   |         |                move occurs because `_t` has type `X`, which does not implement the `Copy` trait
-   |         help: consider removing the `&mut`: `Either::One(_t)`
+   |                          --
+   |                          |
+   |                          data moved here
+   |                          move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the mutable borrow
+   |
+LL -         &mut Either::One(_t) => (),
+LL +         Either::One(_t) => (),
+   |
 
 error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference
-  --> $DIR/simple.rs:242:11
+  --> $DIR/simple.rs:206:11
    |
 LL |     match rm {
    |           ^^
 LL |
 LL |         &mut Either::One(_t) => (),
-   |         --------------------
-   |         |                |
-   |         |                data moved here
-   |         |                move occurs because `_t` has type `X`, which does not implement the `Copy` trait
-   |         help: consider removing the `&mut`: `Either::One(_t)`
+   |                          --
+   |                          |
+   |                          data moved here
+   |                          move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the mutable borrow
+   |
+LL -         &mut Either::One(_t) => (),
+LL +         Either::One(_t) => (),
+   |
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/simple.rs:258:21
+  --> $DIR/simple.rs:220:21
    |
 LL |     let (&X(_t),) = (&x.clone(),);
    |             --      ^^^^^^^^^^^^^
    |             |
    |             data moved here
    |             move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |     let (&X(ref _t),) = (&x.clone(),);
+   |             +++
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/simple.rs:260:34
+  --> $DIR/simple.rs:223:34
    |
 LL |     if let (&Either::One(_t),) = (&e.clone(),) { }
    |                          --      ^^^^^^^^^^^^^
    |                          |
    |                          data moved here
    |                          move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |     if let (&Either::One(ref _t),) = (&e.clone(),) { }
+   |                          +++
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/simple.rs:262:37
+  --> $DIR/simple.rs:226:37
    |
 LL |     while let (&Either::One(_t),) = (&e.clone(),) { }
    |                             --      ^^^^^^^^^^^^^
    |                             |
    |                             data moved here
    |                             move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |     while let (&Either::One(ref _t),) = (&e.clone(),) { }
+   |                             +++
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/simple.rs:264:11
+  --> $DIR/simple.rs:229:11
    |
 LL |     match (&e.clone(),) {
    |           ^^^^^^^^^^^^^
@@ -431,79 +622,123 @@ LL |         (&Either::One(_t),)
    |                       |
    |                       data moved here
    |                       move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |         (&Either::One(ref _t),)
+   |                       +++
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/simple.rs:272:25
+  --> $DIR/simple.rs:239:25
    |
 LL |     let (&mut X(_t),) = (&mut xm.clone(),);
    |                 --      ^^^^^^^^^^^^^^^^^^
    |                 |
    |                 data moved here
    |                 move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |     let (&mut X(ref _t),) = (&mut xm.clone(),);
+   |                 +++
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/simple.rs:274:38
+  --> $DIR/simple.rs:242:38
    |
 LL |     if let (&mut Either::One(_t),) = (&mut em.clone(),) { }
    |                              --      ^^^^^^^^^^^^^^^^^^
    |                              |
    |                              data moved here
    |                              move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |     if let (&mut Either::One(ref _t),) = (&mut em.clone(),) { }
+   |                              +++
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/simple.rs:276:41
+  --> $DIR/simple.rs:245:41
    |
 LL |     while let (&mut Either::One(_t),) = (&mut em.clone(),) { }
    |                                 --      ^^^^^^^^^^^^^^^^^^
    |                                 |
    |                                 data moved here
    |                                 move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |     while let (&mut Either::One(ref _t),) = (&mut em.clone(),) { }
+   |                                 +++
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/simple.rs:278:11
+  --> $DIR/simple.rs:248:11
    |
 LL |     match (&mut em.clone(),) {
    |           ^^^^^^^^^^^^^^^^^^
 LL |
 LL |         (&mut Either::One(_t),) => (),
    |                           -- data moved here
+LL |
 LL |         (&mut Either::Two(_t),) => (),
    |                           -- ...and here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider borrowing the pattern binding
+   |
+LL |         (&mut Either::One(ref _t),) => (),
+   |                           +++
+help: consider borrowing the pattern binding
+   |
+LL |         (&mut Either::Two(ref _t),) => (),
+   |                           +++
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/simple.rs:288:18
+  --> $DIR/simple.rs:261:18
    |
 LL |     let &X(_t) = &x;
-   |         ------   ^^
-   |         |  |
-   |         |  data moved here
-   |         |  move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
-   |         help: consider removing the `&`: `X(_t)`
+   |            --    ^^
+   |            |
+   |            data moved here
+   |            move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -     let &X(_t) = &x;
+LL +     let X(_t) = &x;
+   |
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/simple.rs:292:31
+  --> $DIR/simple.rs:264:31
    |
 LL |     if let &Either::One(_t) = &e { }
-   |            ----------------   ^^
-   |            |            |
-   |            |            data moved here
-   |            |            move occurs because `_t` has type `X`, which does not implement the `Copy` trait
-   |            help: consider removing the `&`: `Either::One(_t)`
+   |                         --    ^^
+   |                         |
+   |                         data moved here
+   |                         move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -     if let &Either::One(_t) = &e { }
+LL +     if let Either::One(_t) = &e { }
+   |
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/simple.rs:296:34
+  --> $DIR/simple.rs:267:34
    |
 LL |     while let &Either::One(_t) = &e { }
-   |               ----------------   ^^
-   |               |            |
-   |               |            data moved here
-   |               |            move occurs because `_t` has type `X`, which does not implement the `Copy` trait
-   |               help: consider removing the `&`: `Either::One(_t)`
+   |                            --    ^^
+   |                            |
+   |                            data moved here
+   |                            move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -     while let &Either::One(_t) = &e { }
+LL +     while let Either::One(_t) = &e { }
+   |
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/simple.rs:300:11
+  --> $DIR/simple.rs:270:11
    |
 LL |     match &e {
    |           ^^
@@ -514,72 +749,95 @@ LL |         &Either::One(_t)
    |                      data moved here
    |                      move occurs because `_t` has type `X`, which does not implement the `Copy` trait
    |
-help: consider removing the `&`
+help: consider removing the borrow
    |
-LL ~         Either::One(_t)
-LL +
-LL +
-LL ~         | &Either::Two(_t) => (),
+LL -         &Either::One(_t)
+LL +         Either::One(_t)
    |
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/simple.rs:308:11
+  --> $DIR/simple.rs:277:11
    |
 LL |     match &e {
    |           ^^
 LL |
 LL |         &Either::One(_t) => (),
-   |         ----------------
-   |         |            |
-   |         |            data moved here
-   |         |            move occurs because `_t` has type `X`, which does not implement the `Copy` trait
-   |         help: consider removing the `&`: `Either::One(_t)`
+   |                      --
+   |                      |
+   |                      data moved here
+   |                      move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -         &Either::One(_t) => (),
+LL +         Either::One(_t) => (),
+   |
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/simple.rs:315:11
+  --> $DIR/simple.rs:283:11
    |
 LL |     match &e {
    |           ^^
 LL |
 LL |         &Either::One(_t) => (),
-   |         ----------------
-   |         |            |
-   |         |            data moved here
-   |         |            move occurs because `_t` has type `X`, which does not implement the `Copy` trait
-   |         help: consider removing the `&`: `Either::One(_t)`
+   |                      --
+   |                      |
+   |                      data moved here
+   |                      move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -         &Either::One(_t) => (),
+LL +         Either::One(_t) => (),
+   |
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/simple.rs:323:22
+  --> $DIR/simple.rs:290:22
    |
 LL |     let &mut X(_t) = &mut xm;
-   |         ----------   ^^^^^^^
-   |         |      |
-   |         |      data moved here
-   |         |      move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
-   |         help: consider removing the `&mut`: `X(_t)`
+   |                --    ^^^^^^^
+   |                |
+   |                data moved here
+   |                move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+   |
+help: consider removing the mutable borrow
+   |
+LL -     let &mut X(_t) = &mut xm;
+LL +     let X(_t) = &mut xm;
+   |
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/simple.rs:327:35
+  --> $DIR/simple.rs:293:35
    |
 LL |     if let &mut Either::One(_t) = &mut em { }
-   |            --------------------   ^^^^^^^
-   |            |                |
-   |            |                data moved here
-   |            |                move occurs because `_t` has type `X`, which does not implement the `Copy` trait
-   |            help: consider removing the `&mut`: `Either::One(_t)`
+   |                             --    ^^^^^^^
+   |                             |
+   |                             data moved here
+   |                             move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the mutable borrow
+   |
+LL -     if let &mut Either::One(_t) = &mut em { }
+LL +     if let Either::One(_t) = &mut em { }
+   |
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/simple.rs:331:38
+  --> $DIR/simple.rs:296:38
    |
 LL |     while let &mut Either::One(_t) = &mut em { }
-   |               --------------------   ^^^^^^^
-   |               |                |
-   |               |                data moved here
-   |               |                move occurs because `_t` has type `X`, which does not implement the `Copy` trait
-   |               help: consider removing the `&mut`: `Either::One(_t)`
+   |                                --    ^^^^^^^
+   |                                |
+   |                                data moved here
+   |                                move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the mutable borrow
+   |
+LL -     while let &mut Either::One(_t) = &mut em { }
+LL +     while let Either::One(_t) = &mut em { }
+   |
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/simple.rs:335:11
+  --> $DIR/simple.rs:299:11
    |
 LL |     match &mut em {
    |           ^^^^^^^
@@ -590,91 +848,138 @@ LL |         &mut Either::One(_t)
    |                          data moved here
    |                          move occurs because `_t` has type `X`, which does not implement the `Copy` trait
    |
-help: consider removing the `&mut`
+help: consider removing the mutable borrow
    |
-LL ~         Either::One(_t)
-LL +
-LL +
-LL ~         | &mut Either::Two(_t) => (),
+LL -         &mut Either::One(_t)
+LL +         Either::One(_t)
    |
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/simple.rs:343:11
+  --> $DIR/simple.rs:306:11
    |
 LL |     match &mut em {
    |           ^^^^^^^
 LL |
 LL |         &mut Either::One(_t) => (),
-   |         --------------------
-   |         |                |
-   |         |                data moved here
-   |         |                move occurs because `_t` has type `X`, which does not implement the `Copy` trait
-   |         help: consider removing the `&mut`: `Either::One(_t)`
+   |                          --
+   |                          |
+   |                          data moved here
+   |                          move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the mutable borrow
+   |
+LL -         &mut Either::One(_t) => (),
+LL +         Either::One(_t) => (),
+   |
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/simple.rs:350:11
+  --> $DIR/simple.rs:312:11
    |
 LL |     match &mut em {
    |           ^^^^^^^
 LL |
 LL |         &mut Either::One(_t) => (),
-   |         --------------------
-   |         |                |
-   |         |                data moved here
-   |         |                move occurs because `_t` has type `X`, which does not implement the `Copy` trait
-   |         help: consider removing the `&mut`: `Either::One(_t)`
+   |                          --
+   |                          |
+   |                          data moved here
+   |                          move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the mutable borrow
+   |
+LL -         &mut Either::One(_t) => (),
+LL +         Either::One(_t) => (),
+   |
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/simple.rs:357:11
+  --> $DIR/simple.rs:318:11
    |
 LL |     match &mut em {
    |           ^^^^^^^
 LL |
 LL |         &mut Either::One(_t) => (),
-   |         --------------------
-   |         |                |
-   |         |                data moved here
-   |         |                move occurs because `_t` has type `X`, which does not implement the `Copy` trait
-   |         help: consider removing the `&mut`: `Either::One(_t)`
+   |                          --
+   |                          |
+   |                          data moved here
+   |                          move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the mutable borrow
+   |
+LL -         &mut Either::One(_t) => (),
+LL +         Either::One(_t) => (),
+   |
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/simple.rs:202:11
+  --> $DIR/simple.rs:174:11
    |
 LL |     fn f1(&X(_t): &X) { }
    |           ^^^--^
-   |           |  |
-   |           |  data moved here
-   |           |  move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
-   |           help: consider removing the `&`: `X(_t)`
+   |              |
+   |              data moved here
+   |              move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -     fn f1(&X(_t): &X) { }
+LL +     fn f1(X(_t): &X) { }
+   |
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/simple.rs:249:11
+  --> $DIR/simple.rs:212:11
    |
 LL |     fn f2(&mut X(_t): &mut X) { }
    |           ^^^^^^^--^
-   |           |      |
-   |           |      data moved here
-   |           |      move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
-   |           help: consider removing the `&mut`: `X(_t)`
+   |                  |
+   |                  data moved here
+   |                  move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+   |
+help: consider removing the mutable borrow
+   |
+LL -     fn f2(&mut X(_t): &mut X) { }
+LL +     fn f2(X(_t): &mut X) { }
+   |
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/simple.rs:269:11
+  --> $DIR/simple.rs:235:11
    |
 LL |     fn f3((&X(_t),): (&X,)) { }
    |           ^^^^--^^^
    |               |
    |               data moved here
    |               move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |     fn f3((&X(ref _t),): (&X,)) { }
+   |               +++
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/simple.rs:283:11
+  --> $DIR/simple.rs:255:11
    |
 LL |     fn f4((&mut X(_t),): (&mut X,)) { }
    |           ^^^^^^^^--^^^
    |                   |
    |                   data moved here
    |                   move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |     fn f4((&mut X(ref _t),): (&mut X,)) { }
+   |                   +++
+
+error[E0507]: cannot move out of `a.a` as enum variant `Some` which is behind a shared reference
+  --> $DIR/simple.rs:331:20
+   |
+LL |     let Some(_s) = a.a else {
+   |              --    ^^^
+   |              |
+   |              data moved here
+   |              move occurs because `_s` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |     let Some(ref _s) = a.a else {
+   |              +++
 
-error: aborting due to 60 previous errors
+error: aborting due to 61 previous errors
 
 For more information about this error, try `rustc --explain E0507`.
index 34ff59a9bb0508185e9f889c124c8bb9c0afd458..b1e04dab8f623853794cc53cc468b1fdaf3a876d 100644 (file)
@@ -41,9 +41,6 @@ LL |     Pin::new(x)
            found type parameter `F`
 note: associated function defined here
   --> $SRC_DIR/core/src/pin.rs:LL:COL
-   |
-LL |     pub const fn new(pointer: P) -> Pin<P> {
-   |                  ^^^
 
 error[E0277]: `dyn Future<Output = i32> + Send` cannot be unpinned
   --> $DIR/expected-boxed-future-isnt-pinned.rs:19:14
@@ -56,9 +53,6 @@ LL |     Pin::new(x)
    = note: consider using `Box::pin`
 note: required by a bound in `Pin::<P>::new`
   --> $SRC_DIR/core/src/pin.rs:LL:COL
-   |
-LL | impl<P: Deref<Target: Unpin>> Pin<P> {
-   |                       ^^^^^ required by this bound in `Pin::<P>::new`
 
 error[E0277]: `dyn Future<Output = i32> + Send` cannot be unpinned
   --> $DIR/expected-boxed-future-isnt-pinned.rs:24:14
@@ -71,9 +65,6 @@ LL |     Pin::new(Box::new(x))
    = note: consider using `Box::pin`
 note: required by a bound in `Pin::<P>::new`
   --> $SRC_DIR/core/src/pin.rs:LL:COL
-   |
-LL | impl<P: Deref<Target: Unpin>> Pin<P> {
-   |                       ^^^^^ required by this bound in `Pin::<P>::new`
 
 error[E0308]: mismatched types
   --> $DIR/expected-boxed-future-isnt-pinned.rs:28:5
@@ -90,9 +81,6 @@ LL | |     }
            found `async` block `[async block@$DIR/expected-boxed-future-isnt-pinned.rs:28:5: 30:6]`
 note: function defined here
   --> $SRC_DIR/core/src/future/mod.rs:LL:COL
-   |
-LL | pub const fn identity_future<O, Fut: Future<Output = O>>(f: Fut) -> Fut {
-   |              ^^^^^^^^^^^^^^^
 help: you need to pin and box this expression
    |
 LL ~     Box::pin(async {
index 88be9e30a764125261b822c14a6e7c761d4d26a2..c5b81e6b87174d209ce65331def3447c7f8df707 100644 (file)
@@ -7,11 +7,8 @@ LL |         for _ in self.v {
    |                  `self.v` moved due to this implicit call to `.into_iter()`
    |                  move occurs because `self.v` has type `Vec<u32>`, which does not implement the `Copy` trait
    |
-note: this function takes ownership of the receiver `self`, which moves `self.v`
+note: `into_iter` takes ownership of the receiver `self`, which moves `self.v`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-   |
-LL |     fn into_iter(self) -> Self::IntoIter;
-   |                  ^^^^
 help: consider iterating over a slice of the `Vec<u32>`'s content to avoid moving into the `for` loop
    |
 LL |         for _ in &self.v {
@@ -40,11 +37,8 @@ LL |     for loader in *LOADERS {
    |                   value moved due to this implicit call to `.into_iter()`
    |                   move occurs because value has type `Vec<&u8>`, which does not implement the `Copy` trait
    |
-note: this function takes ownership of the receiver `self`, which moves value
+note: `into_iter` takes ownership of the receiver `self`, which moves value
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-   |
-LL |     fn into_iter(self) -> Self::IntoIter;
-   |                  ^^^^
 help: consider iterating over a slice of the `Vec<&u8>`'s content to avoid moving into the `for` loop
    |
 LL |     for loader in &*LOADERS {
index 42ca3a78d8f9f70ef5c222f7a7f18c30461711f9..7791b308d5d0e597a4263c6afb85570b07f1158a 100644 (file)
@@ -3,11 +3,9 @@ error: the `min` method cannot be invoked on a trait object
    |
 LL |      t.min().unwrap()
    |        ^^^
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |         Self: Sized,
-   |               ----- this has a `Sized` requirement
+   = note: this has a `Sized` requirement
    |
    = note: you need `&mut dyn Iterator<Item = &u64>` instead of `&dyn Iterator<Item = &u64>`
 
index bac8de7987256058de5b5f0312b41cdffd326ee6..f159b51a26969fec807e8cd5cb7c8dfde6fe85c9 100644 (file)
@@ -3,11 +3,9 @@ error[E0599]: no method named `finish` found for struct `DefaultHasher` in the c
    |
 LL |     h.finish()
    |       ^^^^^^ method not found in `DefaultHasher`
+  --> $SRC_DIR/core/src/hash/mod.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/hash/mod.rs:LL:COL
-   |
-LL |     fn finish(&self) -> u64;
-   |        ------ the method is available for `DefaultHasher` here
+   = note: the method is available for `DefaultHasher` here
    |
    = help: items from traits can only be used if the trait is in scope
 help: the following trait is implemented but not in scope; perhaps add a `use` for it:
index 4b302dd6509192f79b5367406b2594e248ac4f2a..79812a2985ef9444f0d46f15a698e19916fbeed3 100644 (file)
@@ -11,12 +11,6 @@ LL |     simd_gt::<()>(x);
    |     ^^^^^^^------ help: remove these generics
    |     |
    |     expected 0 generic arguments
-   |
-note: associated function defined here, with 0 generic parameters
-  --> $SRC_DIR/core/src/../../portable-simd/crates/core_simd/src/ord.rs:LL:COL
-   |
-LL |     fn simd_gt(self, other: Self) -> Self::Mask;
-   |        ^^^^^^^
 
 error[E0425]: cannot find function `simd_gt` in this scope
   --> $DIR/issue-104287.rs:6:5
index 62f0943d4c9d99f1466df7eab512747d0eaed232..b6e271de8076c700487ebea36b4c6c0c04c160f1 100644 (file)
@@ -10,9 +10,6 @@ LL |     println!("{:?}", line.find(pattern));
    = note: required for `String` to implement `Pattern<'_>`
 note: required by a bound in `core::str::<impl str>::find`
   --> $SRC_DIR/core/src/str/mod.rs:LL:COL
-   |
-LL |     pub fn find<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize> {
-   |                        ^^^^^^^^^^^ required by this bound in `core::str::<impl str>::find`
 help: consider borrowing here
    |
 LL |     println!("{:?}", line.find(&pattern));
index 684db23e1355f3ff31f596d73198298221964bd2..a5e6f5b5ffcb0a40fa7a4041ea1baff58bdd7042 100644 (file)
@@ -1,10 +1,8 @@
 error[E0277]: the trait bound `&[i8]: From<&[u8]>` is not satisfied
-  --> $DIR/issue-71394-no-from-impl.rs:3:20
+  --> $DIR/issue-71394-no-from-impl.rs:3:25
    |
 LL |     let _: &[i8] = data.into();
-   |                    ^^^^ ---- required by a bound introduced by this call
-   |                    |
-   |                    the trait `From<&[u8]>` is not implemented for `&[i8]`
+   |                         ^^^^ the trait `From<&[u8]>` is not implemented for `&[i8]`
    |
    = help: the following other types implement trait `From<T>`:
              <[T; LANES] as From<Simd<T, LANES>>>
index 8b2a388162806e86866c4da9657ffafad3b83024..93d8da226c817f35f99cd09ca8e9329881d4a47d 100644 (file)
@@ -62,11 +62,6 @@ error[E0107]: this associated function takes 0 generic arguments but 1 generic a
 LL |     let _ = 42.into::<Option<_>>();
    |                ^^^^ expected 0 generic arguments
    |
-note: associated function defined here, with 0 generic parameters
-  --> $SRC_DIR/core/src/convert/mod.rs:LL:COL
-   |
-LL |     fn into(self) -> T;
-   |        ^^^^
 help: consider moving this generic argument to the `Into` trait, which takes up to 1 argument
    |
 LL |     let _ = Into::<Option<_>>::into(42);
index d121932c842e35324a8a8f1060e4713f8dd8ab0c..6910b77d9bc3fa1874c69f464fba0e1b1444ef3b 100644 (file)
@@ -9,9 +9,6 @@ LL |     let fp = BufWriter::new(fp);
    = note: `std::io::Write` is implemented for `&mut dyn std::io::Write`, but not for `&dyn std::io::Write`
 note: required by a bound in `BufWriter::<W>::new`
   --> $SRC_DIR/std/src/io/buffered/bufwriter.rs:LL:COL
-   |
-LL | impl<W: Write> BufWriter<W> {
-   |         ^^^^^ required by this bound in `BufWriter::<W>::new`
 
 error[E0277]: the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied
   --> $DIR/mut-borrow-needed-by-trait.rs:17:14
@@ -22,20 +19,15 @@ LL |     let fp = BufWriter::new(fp);
    = note: `std::io::Write` is implemented for `&mut dyn std::io::Write`, but not for `&dyn std::io::Write`
 note: required by a bound in `BufWriter`
   --> $SRC_DIR/std/src/io/buffered/bufwriter.rs:LL:COL
-   |
-LL | pub struct BufWriter<W: Write> {
-   |                         ^^^^^ required by this bound in `BufWriter`
 
-error[E0599]: the method `write_fmt` exists for struct `BufWriter<&dyn std::io::Write>`, but its trait bounds were not satisfied
+error[E0599]: the method `write_fmt` exists for struct `BufWriter<&dyn Write>`, but its trait bounds were not satisfied
   --> $DIR/mut-borrow-needed-by-trait.rs:21:5
    |
 LL |     writeln!(fp, "hello world").unwrap();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ method cannot be called on `BufWriter<&dyn std::io::Write>` due to unsatisfied trait bounds
-   |
-  ::: $SRC_DIR/std/src/io/buffered/bufwriter.rs:LL:COL
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ method cannot be called on `BufWriter<&dyn Write>` due to unsatisfied trait bounds
+  --> $SRC_DIR/std/src/io/buffered/bufwriter.rs:LL:COL
    |
-LL | pub struct BufWriter<W: Write> {
-   | ------------------------------ doesn't satisfy `BufWriter<&dyn std::io::Write>: std::io::Write`
+   = note: doesn't satisfy `BufWriter<&dyn std::io::Write>: std::io::Write`
    |
    = note: the following trait bounds were not satisfied:
            `&dyn std::io::Write: std::io::Write`
index debb8cabaea027b557bccdb05753adc85d2678cf..97d05d9dcffaf840cef3f3640cac2fe823c63a83 100644 (file)
@@ -9,6 +9,11 @@ LL |         (None, &c) => &c.unwrap(),
    |                 |
    |                 data moved here
    |                 move occurs because `c` has type `Option<String>`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |         (None, &ref c) => &c.unwrap(),
+   |                 +++
 
 error: aborting due to previous error
 
index a6f1ebc975fd5bc450fcfadc41d43a568cb420c5..3e0271d02572b98354603945119ef6803b174d64 100644 (file)
@@ -7,11 +7,8 @@ LL |                 if selection.1.unwrap().contains(selection.0) {
    |                    help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents
    |                    move occurs because `selection.1` has type `Option<String>`, which does not implement the `Copy` trait
    |
-note: this function takes ownership of the receiver `self`, which moves `selection.1`
+note: `Option::<T>::unwrap` takes ownership of the receiver `self`, which moves `selection.1`
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |     pub const fn unwrap(self) -> T {
-   |                         ^^^^
 
 error[E0507]: cannot move out of `selection.1` which is behind a shared reference
   --> $DIR/option-content-move.rs:27:20
@@ -22,11 +19,8 @@ LL |                 if selection.1.unwrap().contains(selection.0) {
    |                    help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents
    |                    move occurs because `selection.1` has type `Result<String, String>`, which does not implement the `Copy` trait
    |
-note: this function takes ownership of the receiver `self`, which moves `selection.1`
+note: `Result::<T, E>::unwrap` takes ownership of the receiver `self`, which moves `selection.1`
   --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL |     pub fn unwrap(self) -> T
-   |                   ^^^^
 
 error: aborting due to 2 previous errors
 
index e7d9c5ecbe48208a720fac6deb23cfff4778b96a..5434472ceecc7605e3b324553e86d07a6acb0517 100644 (file)
@@ -11,11 +11,8 @@ note: an implementation of `Add<_>` might be missing for `Wrapper<T>`
    |
 LL | struct Wrapper<T>(T);
    | ^^^^^^^^^^^^^^^^^ must implement `Add<_>`
-note: the following trait must be implemented
+note: the trait `Add` must be implemented
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL | pub trait Add<Rhs = Self> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
    |
 LL | fn qux<T>(a: Wrapper<T>, b: T) -> T where Wrapper<T>: Add<T, Output = T> {
index 55a0eee18179a17b4a1afab55efbe4eafd1a389a..da4db46aad3d67d36178d0fd831f56afc1f12cec 100644 (file)
@@ -10,9 +10,6 @@ LL |     let _s = y.unwrap_or(|| x.split('.').nth(1).unwrap());
                 found closure `[closure@$DIR/sugg-else-for-closure.rs:6:26: 6:28]`
 note: associated function defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |     pub const fn unwrap_or(self, default: T) -> T
-   |                  ^^^^^^^^^
 help: try calling `unwrap_or_else` instead
    |
 LL |     let _s = y.unwrap_or_else(|| x.split('.').nth(1).unwrap());
index 889b11a741084c09f25260b17841ca65dde369e8..d194afeaf931d96f3032011e3338cd633a4645a1 100644 (file)
@@ -8,9 +8,6 @@ LL |         let mut stream_reader = BufReader::new(&stream);
    |
 note: required by a bound in `BufReader::<R>::new`
   --> $SRC_DIR/std/src/io/buffered/bufreader.rs:LL:COL
-   |
-LL | impl<R: Read> BufReader<R> {
-   |         ^^^^ required by this bound in `BufReader::<R>::new`
 help: consider removing the leading `&`-reference
    |
 LL -         let mut stream_reader = BufReader::new(&stream);
@@ -30,11 +27,9 @@ error[E0599]: the method `read_until` exists for struct `BufReader<&T>`, but its
    |
 LL |         stream_reader.read_until(b'\n', &mut buffer).expect("Reading into buffer failed");
    |                       ^^^^^^^^^^ method cannot be called on `BufReader<&T>` due to unsatisfied trait bounds
+  --> $SRC_DIR/std/src/io/buffered/bufreader.rs:LL:COL
    |
-  ::: $SRC_DIR/std/src/io/buffered/bufreader.rs:LL:COL
-   |
-LL | pub struct BufReader<R> {
-   | ----------------------- doesn't satisfy `BufReader<&T>: BufRead`
+   = note: doesn't satisfy `BufReader<&T>: BufRead`
    |
    = note: the following trait bounds were not satisfied:
            `&T: std::io::Read`
index 3d1f2492360bf29ba658b5e469f2a526f9636bc4..018083f9e03af40468b781c6ec63b4b8bdb04b8b 100644 (file)
@@ -52,11 +52,9 @@ error[E0599]: no method named `try_into` found for type `i32` in the current sco
    |
 LL |     let _i: i16 = 0_i32.try_into().unwrap();
    |                         ^^^^^^^^ method not found in `i32`
+  --> $SRC_DIR/core/src/convert/mod.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/convert/mod.rs:LL:COL
-   |
-LL |     fn try_into(self) -> Result<T, Self::Error>;
-   |        -------- the method is available for `i32` here
+   = note: the method is available for `i32` here
    |
    = help: items from traits can only be used if the trait is in scope
    = note: 'std::convert::TryInto' is included in the prelude starting in Edition 2021
index 951ff23d635635084a59d45fcd6145b7db8f19c0..fcff02e09dbb1ade66e0f1b28dfdeebc46ab4e3a 100644 (file)
@@ -24,11 +24,6 @@ error[E0107]: this struct takes at least 1 generic argument but 0 generic argume
 LL |     let _: Vec<A:B> = A::B;
    |            ^^^ expected at least 1 generic argument
    |
-note: struct defined here, with at least 1 generic parameter: `T`
-  --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
-   |
-LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
-   |            ^^^ -
 help: add missing generic argument
    |
 LL |     let _: Vec<T, A:B> = A::B;
index 76a068e864a3c6380ac1822aa379441f38ca6baf..0d3f794aa0f7af882d9da1f487bd37c13c6e14a5 100644 (file)
@@ -12,11 +12,9 @@ error[E0393]: the type parameter `Rhs` must be explicitly specified
    |
 LL | struct Foo<T>(dyn SendEqAlias<T>);
    |                   ^^^^^^^^^^^^^^ missing reference to `Rhs`
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/cmp.rs:LL:COL
-   |
-LL | pub trait PartialEq<Rhs: ?Sized = Self> {
-   | --------------------------------------- type parameter `Rhs` must be specified for this
+   = note: type parameter `Rhs` must be specified for this
    |
    = note: because of the default `Self` reference, type parameters must be specified on object types
 
@@ -25,11 +23,9 @@ error[E0393]: the type parameter `Rhs` must be explicitly specified
    |
 LL | struct Bar<T>(dyn SendEqAlias<T>, T);
    |                   ^^^^^^^^^^^^^^ missing reference to `Rhs`
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/cmp.rs:LL:COL
-   |
-LL | pub trait PartialEq<Rhs: ?Sized = Self> {
-   | --------------------------------------- type parameter `Rhs` must be specified for this
+   = note: type parameter `Rhs` must be specified for this
    |
    = note: because of the default `Self` reference, type parameters must be specified on object types
 
index 325bc6d2808595c9eaf2b34ee8a633fe2fccfe27..048a150df8c521c497d143190b8ed6c4b561e4c4 100644 (file)
@@ -7,8 +7,7 @@ LL |     let _: &dyn EqAlias = &123;
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $SRC_DIR/core/src/cmp.rs:LL:COL
    |
-LL | pub trait Eq: PartialEq<Self> {
-   |               ^^^^^^^^^^^^^^^ the trait cannot be made into an object because it uses `Self` as a type parameter
+   = note: the trait cannot be made into an object because it uses `Self` as a type parameter
 
 error[E0191]: the value of the associated type `Item` (from trait `Iterator`) must be specified
   --> $DIR/object-fail.rs:9:17
index d7d6241ef708cda1a68a922940d7a3963417a6ba..65340b2a2092ff5cdf345a4c08703603d70c0ee1 100644 (file)
@@ -10,7 +10,7 @@ pub trait Foo: Iterator<Item = <Self as Foo>::Key> {
 
 impl Foo for IntoIter<i32> {
     type Key = u32;
-    //~^ ERROR expected `std::vec::IntoIter<i32>` to be an iterator that yields `u32`, but it yields `i32`
+    //~^ ERROR expected `IntoIter<i32>` to be an iterator that yields `u32`, but it yields `i32`
 }
 
 fn main() {}
index 3e2d9d9038aa7c1e6b8655cd3fdf668cc42f6190..7fa1d2c2eed67c8fd85f48d77f1aa019a3d36fb7 100644 (file)
@@ -1,4 +1,4 @@
-error[E0271]: expected `std::vec::IntoIter<i32>` to be an iterator that yields `u32`, but it yields `i32`
+error[E0271]: expected `IntoIter<i32>` to be an iterator that yields `u32`, but it yields `i32`
   --> $DIR/assoc-type-in-superbad.rs:12:16
    |
 LL |     type Key = u32;
index 9ca446a0a891d82ecb0436977b226f971a18b68d..5be334986418292c4f98d9c4020bd7c09c17e0ca 100644 (file)
@@ -9,11 +9,9 @@ error[E0404]: expected trait, found struct `String`
    |
 LL | struct Foo<T> where T: Bar, <T as Bar>::Baz: String {
    |                                              ^^^^^^ not a trait
+  --> $SRC_DIR/alloc/src/string.rs:LL:COL
    |
-  ::: $SRC_DIR/alloc/src/string.rs:LL:COL
-   |
-LL | pub trait ToString {
-   | ------------------ similarly named trait `ToString` defined here
+   = note: similarly named trait `ToString` defined here
    |
 help: constrain the associated type to `String`
    |
@@ -29,11 +27,9 @@ error[E0404]: expected trait, found struct `String`
    |
 LL | struct Qux<'a, T> where T: Bar, <&'a T as Bar>::Baz: String {
    |                                                      ^^^^^^ not a trait
+  --> $SRC_DIR/alloc/src/string.rs:LL:COL
    |
-  ::: $SRC_DIR/alloc/src/string.rs:LL:COL
-   |
-LL | pub trait ToString {
-   | ------------------ similarly named trait `ToString` defined here
+   = note: similarly named trait `ToString` defined here
    |
 help: constrain the associated type to `String`
    |
@@ -49,11 +45,9 @@ error[E0404]: expected trait, found struct `String`
    |
 LL | fn foo<T: Bar>(_: T) where <T as Bar>::Baz: String {
    |                                             ^^^^^^ not a trait
+  --> $SRC_DIR/alloc/src/string.rs:LL:COL
    |
-  ::: $SRC_DIR/alloc/src/string.rs:LL:COL
-   |
-LL | pub trait ToString {
-   | ------------------ similarly named trait `ToString` defined here
+   = note: similarly named trait `ToString` defined here
    |
 help: constrain the associated type to `String`
    |
@@ -69,11 +63,9 @@ error[E0404]: expected trait, found struct `String`
    |
 LL | fn qux<'a, T: Bar>(_: &'a T) where <&'a T as Bar>::Baz: String {
    |                                                         ^^^^^^ not a trait
+  --> $SRC_DIR/alloc/src/string.rs:LL:COL
    |
-  ::: $SRC_DIR/alloc/src/string.rs:LL:COL
-   |
-LL | pub trait ToString {
-   | ------------------ similarly named trait `ToString` defined here
+   = note: similarly named trait `ToString` defined here
    |
 help: constrain the associated type to `String`
    |
@@ -89,11 +81,9 @@ error[E0404]: expected trait, found struct `String`
    |
 LL | fn issue_95327() where <u8 as Unresolved>::Assoc: String {}
    |                                                   ^^^^^^ help: a trait with a similar name exists: `ToString`
+  --> $SRC_DIR/alloc/src/string.rs:LL:COL
    |
-  ::: $SRC_DIR/alloc/src/string.rs:LL:COL
-   |
-LL | pub trait ToString {
-   | ------------------ similarly named trait `ToString` defined here
+   = note: similarly named trait `ToString` defined here
 
 error: aborting due to 6 previous errors
 
index 6f9113fff516193e80bdca725a5e33454a25cf74..fb9900bc57bbcddb536a3bc6e3acabb59f83793a 100644 (file)
@@ -18,9 +18,6 @@ LL |     let x: Vec<dyn Trait + Sized> = Vec::new();
    = help: the trait `Sized` is not implemented for `dyn Trait`
 note: required by a bound in `Vec`
   --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
-   |
-LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
-   |                ^ required by this bound in `Vec`
 
 error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time
   --> $DIR/bad-sized.rs:4:37
@@ -31,9 +28,6 @@ LL |     let x: Vec<dyn Trait + Sized> = Vec::new();
    = help: the trait `Sized` is not implemented for `dyn Trait`
 note: required by a bound in `Vec::<T>::new`
   --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
-   |
-LL | impl<T> Vec<T> {
-   |      ^ required by this bound in `Vec::<T>::new`
 
 error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time
   --> $DIR/bad-sized.rs:4:37
@@ -44,9 +38,6 @@ LL |     let x: Vec<dyn Trait + Sized> = Vec::new();
    = help: the trait `Sized` is not implemented for `dyn Trait`
 note: required by a bound in `Vec`
   --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
-   |
-LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
-   |                ^ required by this bound in `Vec`
 
 error: aborting due to 4 previous errors
 
index b6a04585583c933079d52ac7c76cffeefe53938e..0b57a8212bdc63495ca6cb6ee4b0a08d0056b067 100644 (file)
@@ -12,9 +12,6 @@ LL |     opts.get(opt.as_ref());
              where T: ?Sized;
 note: required by a bound in `HashMap::<K, V, S>::get`
   --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
-   |
-LL |         K: Borrow<Q>,
-   |            ^^^^^^^^^ required by this bound in `HashMap::<K, V, S>::get`
 help: consider specifying the generic argument
    |
 LL |     opts.get::<Q>(opt.as_ref());
@@ -46,7 +43,15 @@ LL |     let ips: Vec<_> = (0..100_000).map(|_| u32::from(0u32.into())).collect(
    |                                            |
    |                                            required by a bound introduced by this call
    |
-   = note: cannot satisfy `u32: From<_>`
+   = note: multiple `impl`s satisfying `u32: From<_>` found in the following crates: `core`, `std`:
+           - impl From<Ipv4Addr> for u32;
+           - impl From<NonZeroU32> for u32;
+           - impl From<bool> for u32;
+           - impl From<char> for u32;
+           - impl From<u16> for u32;
+           - impl From<u8> for u32;
+           - impl<T> From<!> for T;
+           - impl<T> From<T> for T;
 help: try using a fully qualified path to specify the expected types
    |
 LL |     let ips: Vec<_> = (0..100_000).map(|_| u32::from(<u32 as Into<T>>::into(0u32))).collect();
index fa280135beb2d98a99f1605dc79ea8c33b57b7fa..9e80497ca6e92a1cf95c3f58df7ca752a728e388 100644 (file)
@@ -4,7 +4,14 @@ error[E0283]: type annotations needed: cannot satisfy `T: FnMut<(&'a (),)>`
 LL |     T: FnMut(&'a ()),
    |        ^^^^^^^^^^^^^
    |
-   = note: cannot satisfy `T: FnMut<(&'a (),)>`
+note: multiple `impl`s or `where` clauses satisfying `T: FnMut<(&'a (),)>` found
+  --> $DIR/issue-85735.rs:7:8
+   |
+LL |     T: FnMut(&'a ()),
+   |        ^^^^^^^^^^^^^
+LL |
+LL |     T: FnMut(&'b ()),
+   |        ^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index 146d38d076a3ccb1e7696c60c940fdf82cab8773..9062a0fab630a3103d5e8ac839e5b1a54dd90b40 100644 (file)
@@ -1,10 +1,8 @@
 error[E0277]: the trait bound `String: From<impl ToString>` is not satisfied
-  --> $DIR/issue-97576.rs:8:18
+  --> $DIR/issue-97576.rs:8:22
    |
 LL |             bar: bar.into(),
-   |                  ^^^ ---- required by a bound introduced by this call
-   |                  |
-   |                  the trait `From<impl ToString>` is not implemented for `String`
+   |                      ^^^^ the trait `From<impl ToString>` is not implemented for `String`
    |
    = note: required for `impl ToString` to implement `Into<String>`
 
index 920f66121e09897094a55787cdcd975c1105cde1..23e182738f700236e158bd4f90b4c6b009d3f1aa 100644 (file)
@@ -7,9 +7,6 @@ LL |     iso(left, right)
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`mutual_recursion_issue_75860`)
 note: required by a bound in `Option`
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL | pub enum Option<T> {
-   |                 ^ required by this bound in `Option`
 
 error: aborting due to previous error
 
index eb2b88059d485e0059be5f736f5e26b96911421f..49e20c6a76ad94d871ecb9165979c3bc27eaa852 100644 (file)
@@ -9,9 +9,6 @@ LL |     let _errors = TcpListener::bind(&bad);
    = note: required for `&NoToSocketAddrs` to implement `ToSocketAddrs`
 note: required by a bound in `TcpListener::bind`
   --> $SRC_DIR/std/src/net/tcp.rs:LL:COL
-   |
-LL |     pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<TcpListener> {
-   |                    ^^^^^^^^^^^^^ required by this bound in `TcpListener::bind`
 help: consider dereferencing here
    |
 LL |     let _errors = TcpListener::bind(&*bad);
index 76663ace7edbdb013a12605ea52115dc548fea9d..1363fb8c47af8862e642a613e6e9b124cc4bdea5 100644 (file)
@@ -11,9 +11,6 @@ LL |         .filter(|c| "aeiou".contains(c))
    = note: required for `&char` to implement `Pattern<'_>`
 note: required by a bound in `core::str::<impl str>::contains`
   --> $SRC_DIR/core/src/str/mod.rs:LL:COL
-   |
-LL |     pub fn contains<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool {
-   |                            ^^^^^^^^^^^ required by this bound in `core::str::<impl str>::contains`
 help: consider dereferencing here
    |
 LL |         .filter(|c| "aeiou".contains(*c))
diff --git a/src/test/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.fixed b/src/test/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.fixed
new file mode 100644 (file)
index 0000000..ea3d1bf
--- /dev/null
@@ -0,0 +1,14 @@
+// run-rustfix
+
+struct TargetStruct;
+
+impl From<usize> for TargetStruct {
+    fn from(_unchecked: usize) -> Self {
+        TargetStruct
+    }
+}
+
+fn main() {
+    let a = &3;
+    let _b: TargetStruct = (*a).into(); //~ ERROR the trait bound `TargetStruct: From<&{integer}>` is not satisfied
+}
diff --git a/src/test/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.rs b/src/test/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.rs
new file mode 100644 (file)
index 0000000..9eda680
--- /dev/null
@@ -0,0 +1,14 @@
+// run-rustfix
+
+struct TargetStruct;
+
+impl From<usize> for TargetStruct {
+    fn from(_unchecked: usize) -> Self {
+        TargetStruct
+    }
+}
+
+fn main() {
+    let a = &3;
+    let _b: TargetStruct = a.into(); //~ ERROR the trait bound `TargetStruct: From<&{integer}>` is not satisfied
+}
diff --git a/src/test/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.stderr b/src/test/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.stderr
new file mode 100644 (file)
index 0000000..ede31a2
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `TargetStruct: From<&{integer}>` is not satisfied
+  --> $DIR/suggest-dereferencing-receiver-argument.rs:13:30
+   |
+LL |     let _b: TargetStruct = a.into();
+   |                              ^^^^ the trait `From<&{integer}>` is not implemented for `TargetStruct`
+   |
+   = note: required for `&{integer}` to implement `Into<TargetStruct>`
+help: consider dereferencing here
+   |
+LL |     let _b: TargetStruct = (*a).into();
+   |                            ++ +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
index 9765fbd47ff465daf1afaf57991872a4cb6ed83e..44e63b78cce85b7c5945f4d7a0518938a39331bf 100644 (file)
@@ -9,9 +9,6 @@ LL |     mem::size_of::<U>();
    |
 note: required by a bound in `std::mem::size_of`
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
-   |
-LL | pub const fn size_of<T>() -> usize {
-   |                      ^ required by this bound in `size_of`
 help: consider removing the `?Sized` bound to make the type parameter `Sized`
    |
 LL - fn check<T: Iterator, U: ?Sized>() {
@@ -34,9 +31,6 @@ LL | struct Misc<T:?Sized>(T);
    |        ^^^^
 note: required by a bound in `std::mem::size_of`
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
-   |
-LL | pub const fn size_of<T>() -> usize {
-   |                      ^ required by this bound in `size_of`
 help: consider removing the `?Sized` bound to make the type parameter `Sized`
    |
 LL - fn check<T: Iterator, U: ?Sized>() {
@@ -80,9 +74,6 @@ LL |     mem::size_of::<[T]>();
    = help: the trait `Sized` is not implemented for `[T]`
 note: required by a bound in `std::mem::size_of`
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
-   |
-LL | pub const fn size_of<T>() -> usize {
-   |                      ^ required by this bound in `size_of`
 
 error[E0277]: the size for values of type `[&U]` cannot be known at compilation time
   --> $DIR/suggest-where-clause.rs:31:20
@@ -93,9 +84,6 @@ LL |     mem::size_of::<[&U]>();
    = help: the trait `Sized` is not implemented for `[&U]`
 note: required by a bound in `std::mem::size_of`
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
-   |
-LL | pub const fn size_of<T>() -> usize {
-   |                      ^ required by this bound in `size_of`
 
 error: aborting due to 7 previous errors
 
index 3f83d6583b09cc6e723bfdedd1807cff6ebf50a5..1b3d202590db46d47dc31107c135a3dd169e51a5 100644 (file)
@@ -8,12 +8,6 @@ LL | /             ASSUME_LIFETIMES,
 LL | |             ASSUME_VALIDITY,
 LL | |             ASSUME_VISIBILITY,
    | |_____________________________- help: remove these generic arguments
-   |
-note: trait defined here, with at most 3 generic parameters: `Src`, `Context`, `ASSUME`
-  --> $SRC_DIR/core/src/mem/transmutability.rs:LL:COL
-   |
-LL | pub unsafe trait BikeshedIntrinsicFrom<Src, Context, const ASSUME: Assume = { Assume::NOTHING }>
-   |                  ^^^^^^^^^^^^^^^^^^^^^ ---  -------  ------------------------------------------
 
 error: aborting due to previous error
 
index f3a547fa238273c4cdd26ec2a6f21bba0c75b673..fe3712ef83917f1fb60cd082ca601f550bd7c86d 100644 (file)
@@ -13,9 +13,6 @@ LL |         groups.push(new_group, vec![process]);
              found struct `Vec<String>`
 note: associated function defined here
   --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
-   |
-LL |     pub fn push(&mut self, value: T) {
-   |            ^^^^
 help: remove the extra argument
    |
 LL |         groups.push(/* (Vec<String>, Vec<Process>) */);
index ec07f1e70cff6a135376c7f51c3529237dfdd66c..452413fc51679bd93f90cba315007b01f3b72367 100644 (file)
@@ -6,9 +6,6 @@ LL |         self.acc.push_back(self.current_provides, self.current_requires);
    |
 note: associated function defined here
   --> $SRC_DIR/alloc/src/collections/vec_deque/mod.rs:LL:COL
-   |
-LL |     pub fn push_back(&mut self, value: T) {
-   |            ^^^^^^^^^
 help: wrap these arguments in parentheses to construct a tuple
    |
 LL |         self.acc.push_back((self.current_provides, self.current_requires));
index 48b7946ea820e8b6d328520786965cef37fecbdf..9cc15f14a991d5516050b277133921024cfbd0cd 100644 (file)
@@ -6,8 +6,8 @@ LL |         |x| x.len()
    |
 help: consider giving this closure parameter an explicit type
    |
-LL |         |x: _| x.len()
-   |           +++
+LL |         |x: /* Type */| x.len()
+   |           ++++++++++++
 
 error[E0282]: type annotations needed
   --> $DIR/closures_in_branches.rs:21:10
@@ -17,8 +17,8 @@ LL |         |x| x.len()
    |
 help: consider giving this closure parameter an explicit type
    |
-LL |         |x: _| x.len()
-   |           +++
+LL |         |x: /* Type */| x.len()
+   |           ++++++++++++
 
 error: aborting due to 2 previous errors
 
index 24b3a045856a6accd5656b25a2531e4afae89465..4aa5966ff25d4cedac7d9db5a84b39087a0ef0f9 100644 (file)
@@ -8,7 +8,7 @@ trait Foo {
 
 impl Foo for () {
     type Bar = std::vec::IntoIter<u32>;
-    //~^ ERROR expected `std::vec::IntoIter<u32>` to be an iterator that yields `X`, but it yields `u32`
+    //~^ ERROR expected `IntoIter<u32>` to be an iterator that yields `X`, but it yields `u32`
 }
 
 fn incoherent() {
index fb40895c49f15d13e28a81527f3ef4ac2e159014..8d11b48888947d91bce4b7039892a34a8cc72b15 100644 (file)
@@ -1,4 +1,4 @@
-error[E0271]: expected `std::vec::IntoIter<u32>` to be an iterator that yields `X`, but it yields `u32`
+error[E0271]: expected `IntoIter<u32>` to be an iterator that yields `X`, but it yields `u32`
   --> $DIR/issue-57961.rs:10:16
    |
 LL | type X = impl Sized;
index 6819d14bb010690472625fcd338fcb03861a8698..fd43e1114c8912769e8b06fbad8aae279f66cd88 100644 (file)
@@ -25,11 +25,6 @@ error[E0107]: missing generics for struct `Vec`
 LL |         input_cells: Vec::new()
    |                      ^^^ expected at least 1 generic argument
    |
-note: struct defined here, with at least 1 generic parameter: `T`
-  --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
-   |
-LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
-   |            ^^^ -
 help: add missing generic argument
    |
 LL |         input_cells: Vec<T>::new()
index 4af4c22f75166153ab35739f1c1c2fd8ac3869df..87bba3166be6a3cde426e54f1b4f57c8023bd791 100644 (file)
@@ -10,7 +10,7 @@ note: required by a bound in `foo`
    |
 LL | fn foo<T: Into<String>>(x: i32) {}
    |           ^^^^^^^^^^^^ required by this bound in `foo`
-help: consider specifying the type argument in the function call
+help: consider specifying the generic argument
    |
 LL |     foo::<T>(42);
    |        +++++
index de578ca93ed59b827d3ab48bb0086eb619d77c03..ba8d15d0b7317f1a557c11dac272e5b886b10951 100644 (file)
@@ -15,9 +15,6 @@ LL |     let x: Vec::with_capacity(10, 20);
    |
 note: associated function defined here
   --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
-   |
-LL |     pub fn with_capacity(capacity: usize) -> Self {
-   |            ^^^^^^^^^^^^^
 help: remove the extra argument
    |
 LL |     let x: Vec::with_capacity(10);
index fc85ec933155621972a0d939cfa0e981f1741dc1..edc5aeffdcd65fda4697a7fcc12895bd9ca88f54 100644 (file)
@@ -33,11 +33,8 @@ note: an implementation of `std::ops::Neg` might be missing for `Z`
    |
 LL | struct Z;
    | ^^^^^^^^ must implement `std::ops::Neg`
-note: the following trait must be implemented
+note: the trait `std::ops::Neg` must be implemented
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL | pub trait Neg {
-   | ^^^^^^^^^^^^^
 
 error[E0308]: mismatched types
   --> $DIR/type-ascription-precedence.rs:45:5
index 75feb5698eb630ea2e868cfb5cf4ea6d0e0b1eb5..d15fd23418bb0be17020759ab5df157b6891b0b3 100644 (file)
@@ -4,7 +4,13 @@ error[E0283]: type annotations needed: cannot satisfy `&'a T: Foo`
 LL |     where &'a T : Foo,
    |                   ^^^
    |
-   = note: cannot satisfy `&'a T: Foo`
+note: multiple `impl`s or `where` clauses satisfying `&'a T: Foo` found
+  --> $DIR/issue-40294.rs:6:19
+   |
+LL |     where &'a T : Foo,
+   |                   ^^^
+LL |           &'b T : Foo
+   |                   ^^^
 
 error: aborting due to previous error
 
index 9ae97f390d3e4bcb04fb13431c64092f8fc4051e..e5e29aabf374b03d7609c70f75b12fd2dd40322c 100644 (file)
@@ -12,8 +12,8 @@ LL |     let x = |_| {};
    |
 help: consider giving this closure parameter an explicit type
    |
-LL |     let x = |_: _| {};
-   |               +++
+LL |     let x = |_: /* Type */| {};
+   |               ++++++++++++
 
 error[E0282]: type annotations needed
   --> $DIR/unknown_type_for_closure.rs:10:14
index c1ae10efac4b4e874169caf6729eb77e2e8af666..1aed1dbe4babd21662ce83308a7bcdc0f1e66983 100644 (file)
@@ -30,8 +30,8 @@ LL |     let _ = |a, b: _| -> _ { 0 };
    |
 help: consider giving this closure parameter an explicit type
    |
-LL |     let _ = |a: _, b: _| -> _ { 0 };
-   |               +++
+LL |     let _ = |a: /* Type */, b: _| -> _ { 0 };
+   |               ++++++++++++
 
 error: aborting due to 5 previous errors
 
index ff487466902236425d4be9180f9fb20f71ac6bd2..5b00d387aba5dd0e115f117006f0186f7fd3f962 100644 (file)
@@ -1,9 +1,6 @@
 error: reached the type-length limit while instantiating `std::mem::drop::<Option<((((..., ..., ...), ..., ...), ..., ...), ..., ...)>>`
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
    |
-LL | pub fn drop<T>(_x: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^
-   |
    = help: consider adding a `#![type_length_limit="10"]` attribute to your crate
    = note: the full type name has been written to '$TEST_BUILD_DIR/type_length_limit/type_length_limit.long-type.txt'
 
index faac680ea19318f02e674ec0e5ddb67ad34cf9eb..ff36e18d28301ef3b1934208e8ed2175a8ecbe9f 100644 (file)
@@ -12,6 +12,10 @@ note: `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead
    |
 LL |     nc.clone()
    |     ^^
+help: consider annotating `NotClone` with `#[derive(Clone)]`
+   |
+LL | #[derive(Clone)]
+   |
 
 error: aborting due to previous error
 
index 91381e8ef4acf6ebff0d94551cacae652a7a5f6b..f488463ae3ce9faedbd67b008ae8cac5468b11bd 100644 (file)
@@ -10,9 +10,6 @@ LL | fn main() { test(Ok(())); }
            found unit type `()`
 note: tuple variant defined here
   --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL |     Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^
 help: try wrapping the expression in `Some`
    |
 LL | fn main() { test(Ok(Some(()))); }
index 3861e0507f6ddeb6b8d313d76db226b38f6b601b..f5adcabe3e91e0c89ab5a471e4eb5d41ec601832 100644 (file)
@@ -6,11 +6,6 @@ LL |     pub fn run() -> Result<_> {
    |                     |
    |                     expected 2 generic arguments
    |
-note: enum defined here, with 2 generic parameters: `T`, `E`
-  --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL | pub enum Result<T, E> {
-   |          ^^^^^^ -  -
 help: add missing generic argument
    |
 LL |     pub fn run() -> Result<_, E> {
@@ -24,11 +19,6 @@ LL |     pub fn interact(&mut self) -> Result<_> {
    |                                   |
    |                                   expected 2 generic arguments
    |
-note: enum defined here, with 2 generic parameters: `T`, `E`
-  --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL | pub enum Result<T, E> {
-   |          ^^^^^^ -  -
 help: add missing generic argument
    |
 LL |     pub fn interact(&mut self) -> Result<_, E> {
index 1e45c2d35dfdc13cbd0d769b66e350232a713adb..ce4f73b820a18c1d26a6dde668cd1fc7b21d1c02 100644 (file)
@@ -3,11 +3,9 @@ error[E0412]: cannot find type `F` in this scope
    |
 LL | impl F {
    |      ^ help: a trait with a similar name exists: `Fn`
+  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
-   | -------------------------------------- similarly named trait `Fn` defined here
+   = note: similarly named trait `Fn` defined here
 
 error[E0412]: cannot find type `TestResult` in this scope
   --> $DIR/issue-83693.rs:9:22
index 04dc0e36520b4e7e9b5033f746c8270b3abeedce..00d23389720b9d636cd2272e0686d5361dd2bdbe 100644 (file)
@@ -16,9 +16,6 @@ LL |     <F as FnOnce(&mut u8)>::call_once(f, 1)
                found type `{integer}`
 note: associated function defined here
   --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-LL |     extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
-   |                           ^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/typeck/issue-92481.rs b/src/test/ui/typeck/issue-92481.rs
new file mode 100644 (file)
index 0000000..0a6b184
--- /dev/null
@@ -0,0 +1,14 @@
+//check-fail
+
+#![crate_type="lib"]
+
+fn r({) {
+    Ok {             //~ ERROR mismatched types [E0308]
+        d..||_=m
+    }
+}
+//~^^^^^ ERROR expected parameter name, found `{`
+//~| ERROR expected one of `,`, `:`, or `}`, found `..`
+//~^^^^^ ERROR cannot find value `d` in this scope [E0425]
+//~| ERROR cannot find value `m` in this scope [E0425]
+//~| ERROR variant `Result<_, _>::Ok` has no field named `d` [E0559]
diff --git a/src/test/ui/typeck/issue-92481.stderr b/src/test/ui/typeck/issue-92481.stderr
new file mode 100644 (file)
index 0000000..cd778a6
--- /dev/null
@@ -0,0 +1,60 @@
+error: expected parameter name, found `{`
+  --> $DIR/issue-92481.rs:5:6
+   |
+LL | fn r({) {
+   |      ^ expected parameter name
+
+error: expected one of `,`, `:`, or `}`, found `..`
+  --> $DIR/issue-92481.rs:5:6
+   |
+LL | fn r({) {
+   |      ^ unclosed delimiter
+LL |     Ok {
+LL |         d..||_=m
+   |          -^
+   |          |
+   |          help: `}` may belong here
+
+error[E0425]: cannot find value `d` in this scope
+  --> $DIR/issue-92481.rs:7:9
+   |
+LL |         d..||_=m
+   |         ^ not found in this scope
+
+error[E0425]: cannot find value `m` in this scope
+  --> $DIR/issue-92481.rs:7:16
+   |
+LL |         d..||_=m
+   |                ^ not found in this scope
+
+error[E0559]: variant `Result<_, _>::Ok` has no field named `d`
+  --> $DIR/issue-92481.rs:7:9
+   |
+LL |         d..||_=m
+   |         ^ field does not exist
+  --> $SRC_DIR/core/src/result.rs:LL:COL
+   |
+   = note: `Result<_, _>::Ok` defined here
+   |
+help: `Result<_, _>::Ok` is a tuple variant, use the appropriate syntax
+   |
+LL |     Result<_, _>::Ok(/* fields */)
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/issue-92481.rs:6:5
+   |
+LL |   fn r({) {
+   |           - help: a return type might be missing here: `-> _`
+LL | /     Ok {
+LL | |         d..||_=m
+LL | |     }
+   | |_____^ expected `()`, found enum `Result`
+   |
+   = note: expected unit type `()`
+                   found enum `Result<_, _>`
+
+error: aborting due to 6 previous errors
+
+Some errors have detailed explanations: E0308, E0425, E0559.
+For more information about an error, try `rustc --explain E0308`.
index ea94bcbc2903058476c441be1bab37ab14807f52..fbced928a8a9b78bc2fc46811a741243fba31d50 100644 (file)
@@ -6,9 +6,6 @@ LL |     let _ = Some(3, 2);
    |
 note: tuple variant defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^^^
 help: remove the extra argument
    |
 LL |     let _ = Some(3);
@@ -24,9 +21,6 @@ LL |     let _ = Ok(3, 6, 2);
    |
 note: tuple variant defined here
   --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL |     Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^
 help: remove the extra arguments
    |
 LL |     let _ = Ok(3);
@@ -40,9 +34,6 @@ LL |     let _ = Ok();
    |
 note: tuple variant defined here
   --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL |     Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^
 help: provide the argument
    |
 LL |     let _ = Ok(/* value */);
index bf74dd7dec0040ede852fdd6ab1bc4f8db2e2f2d..331540d1e4204217151cc6851df288af765987b1 100644 (file)
@@ -5,12 +5,6 @@ LL | fn foo1<T:Copy<U>, U>(x: T) {}
    |           ^^^^--- help: remove these generics
    |           |
    |           expected 0 generic arguments
-   |
-note: trait defined here, with 0 generic parameters
-  --> $SRC_DIR/core/src/marker.rs:LL:COL
-   |
-LL | pub trait Copy: Clone {
-   |           ^^^^
 
 error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied
   --> $DIR/typeck-builtin-bound-type-parameters.rs:4:14
@@ -19,12 +13,6 @@ LL | trait Trait: Copy<dyn Send> {}
    |              ^^^^---------- help: remove these generics
    |              |
    |              expected 0 generic arguments
-   |
-note: trait defined here, with 0 generic parameters
-  --> $SRC_DIR/core/src/marker.rs:LL:COL
-   |
-LL | pub trait Copy: Clone {
-   |           ^^^^
 
 error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied
   --> $DIR/typeck-builtin-bound-type-parameters.rs:7:21
@@ -33,12 +21,6 @@ LL | struct MyStruct1<T: Copy<T>>;
    |                     ^^^^--- help: remove these generics
    |                     |
    |                     expected 0 generic arguments
-   |
-note: trait defined here, with 0 generic parameters
-  --> $SRC_DIR/core/src/marker.rs:LL:COL
-   |
-LL | pub trait Copy: Clone {
-   |           ^^^^
 
 error[E0107]: this trait takes 0 lifetime arguments but 1 lifetime argument was supplied
   --> $DIR/typeck-builtin-bound-type-parameters.rs:10:25
@@ -47,12 +29,6 @@ LL | struct MyStruct2<'a, T: Copy<'a>>;
    |                         ^^^^---- help: remove these generics
    |                         |
    |                         expected 0 lifetime arguments
-   |
-note: trait defined here, with 0 lifetime parameters
-  --> $SRC_DIR/core/src/marker.rs:LL:COL
-   |
-LL | pub trait Copy: Clone {
-   |           ^^^^
 
 error[E0107]: this trait takes 0 lifetime arguments but 1 lifetime argument was supplied
   --> $DIR/typeck-builtin-bound-type-parameters.rs:13:15
@@ -61,12 +37,6 @@ LL | fn foo2<'a, T:Copy<'a, U>, U>(x: T) {}
    |               ^^^^ -- help: remove this lifetime argument
    |               |
    |               expected 0 lifetime arguments
-   |
-note: trait defined here, with 0 lifetime parameters
-  --> $SRC_DIR/core/src/marker.rs:LL:COL
-   |
-LL | pub trait Copy: Clone {
-   |           ^^^^
 
 error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied
   --> $DIR/typeck-builtin-bound-type-parameters.rs:13:15
@@ -75,12 +45,6 @@ LL | fn foo2<'a, T:Copy<'a, U>, U>(x: T) {}
    |               ^^^^     - help: remove this generic argument
    |               |
    |               expected 0 generic arguments
-   |
-note: trait defined here, with 0 generic parameters
-  --> $SRC_DIR/core/src/marker.rs:LL:COL
-   |
-LL | pub trait Copy: Clone {
-   |           ^^^^
 
 error: aborting due to 6 previous errors
 
index ed56e1cf957f5c719c0b3ea01f37448ae2b2a354..a2fe627868aeb36faef45712e678d61e0e83064f 100644 (file)
@@ -23,9 +23,6 @@ LL |     <i32 as Add<i32>>::add(1u32, 2);
    |
 note: associated function defined here
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL |     fn add(self, rhs: Rhs) -> Self::Output;
-   |        ^^^
 help: change the type of the numeric literal from `u32` to `i32`
    |
 LL |     <i32 as Add<i32>>::add(1i32, 2);
@@ -41,9 +38,6 @@ LL |     <i32 as Add<i32>>::add(1, 2u32);
    |
 note: associated function defined here
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL |     fn add(self, rhs: Rhs) -> Self::Output;
-   |        ^^^
 help: change the type of the numeric literal from `u32` to `i32`
    |
 LL |     <i32 as Add<i32>>::add(1, 2i32);
index 1c18eb0fc4905bbf8c1a41c8acd8cb546cf48bab..cfbe1c6f2cbbc91ba63662d821c2e98aa9a36776 100644 (file)
@@ -6,9 +6,6 @@ LL | fn a<F: Fn<usize>>(f: F) {}
    |
 note: required by a bound in `Fn`
   --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
-   |                    ^^^^^ required by this bound in `Fn`
 
 error: aborting due to previous error
 
index e5ca0edd7a91c62826aa111d4be9dada4161bb37..99ec5178340030d15ca4cac950f747182a9e36cc 100644 (file)
@@ -1,8 +1,8 @@
-error[E0599]: no method named `call` found for closure `[closure@$DIR/unboxed-closures-static-call-wrong-trait.rs:6:26: 6:29]` in the current scope
+error[E0599]: no method named `call` found for closure `[closure@unboxed-closures-static-call-wrong-trait.rs:6:26]` in the current scope
   --> $DIR/unboxed-closures-static-call-wrong-trait.rs:7:10
    |
 LL |     mut_.call((0, ));
-   |          ^^^^ method not found in `[closure@$DIR/unboxed-closures-static-call-wrong-trait.rs:6:26: 6:29]`
+   |          ^^^^ method not found in `[closure@unboxed-closures-static-call-wrong-trait.rs:6:26]`
 
 error: aborting due to previous error
 
index c7882963407f707b03e986b06fb2ca70f430ebb1..d33a61ca8485cbf36db95e3b18ee082188679d02 100644 (file)
@@ -6,12 +6,9 @@ LL |     let _ = match x {
    |
 note: `Result<u32, &Void>` defined here
   --> $SRC_DIR/core/src/result.rs:LL:COL
+  ::: $SRC_DIR/core/src/result.rs:LL:COL
    |
-LL | pub enum Result<T, E> {
-   | ---------------------
-...
-LL |     Err(#[stable(feature = "rust1", since = "1.0.0")] E),
-   |     ^^^ not covered
+   = note: not covered
    = note: the matched value is of type `Result<u32, &Void>`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
@@ -88,12 +85,9 @@ LL |     let _ = match x {
    |
 note: `Result<u32, Void>` defined here
   --> $SRC_DIR/core/src/result.rs:LL:COL
+  ::: $SRC_DIR/core/src/result.rs:LL:COL
    |
-LL | pub enum Result<T, E> {
-   | ---------------------
-...
-LL |     Err(#[stable(feature = "rust1", since = "1.0.0")] E),
-   |     ^^^ not covered
+   = note: not covered
    = note: the matched value is of type `Result<u32, Void>`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
@@ -111,12 +105,9 @@ LL |     let Ok(x) = x;
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
 note: `Result<u32, Void>` defined here
   --> $SRC_DIR/core/src/result.rs:LL:COL
+  ::: $SRC_DIR/core/src/result.rs:LL:COL
    |
-LL | pub enum Result<T, E> {
-   | ---------------------
-...
-LL |     Err(#[stable(feature = "rust1", since = "1.0.0")] E),
-   |     ^^^ not covered
+   = note: not covered
    = note: the matched value is of type `Result<u32, Void>`
 help: you might want to use `if let` to ignore the variant that isn't matched
    |
index ca02de4c61bb8d660b4b942736cea88ae12c0f1c..7f931b49a58f5553434b9c525595358e659d9ca3 100644 (file)
@@ -14,10 +14,12 @@ error[E0507]: cannot move out of dereference of `ManuallyDrop<((MockVec<u8>, Moc
   --> $DIR/union-borrow-move-parent-sibling.rs:62:13
    |
 LL |     let a = u.x.0;
-   |             ^^^^^
-   |             |
-   |             move occurs because value has type `(MockVec<u8>, MockVec<u8>)`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&u.x.0`
+   |             ^^^^^ move occurs because value has type `(MockVec<u8>, MockVec<u8>)`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     let a = &u.x.0;
+   |             +
 
 error[E0382]: use of moved value: `u`
   --> $DIR/union-borrow-move-parent-sibling.rs:64:13
@@ -46,10 +48,12 @@ error[E0507]: cannot move out of dereference of `ManuallyDrop<((MockVec<u8>, Moc
   --> $DIR/union-borrow-move-parent-sibling.rs:76:13
    |
 LL |     let a = (u.x.0).0;
-   |             ^^^^^^^^^
-   |             |
-   |             move occurs because value has type `MockVec<u8>`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&(u.x.0).0`
+   |             ^^^^^^^^^ move occurs because value has type `MockVec<u8>`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     let a = &(u.x.0).0;
+   |             +
 
 error[E0382]: use of moved value: `u`
   --> $DIR/union-borrow-move-parent-sibling.rs:78:13
index ca02de4c61bb8d660b4b942736cea88ae12c0f1c..7f931b49a58f5553434b9c525595358e659d9ca3 100644 (file)
@@ -14,10 +14,12 @@ error[E0507]: cannot move out of dereference of `ManuallyDrop<((MockVec<u8>, Moc
   --> $DIR/union-borrow-move-parent-sibling.rs:62:13
    |
 LL |     let a = u.x.0;
-   |             ^^^^^
-   |             |
-   |             move occurs because value has type `(MockVec<u8>, MockVec<u8>)`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&u.x.0`
+   |             ^^^^^ move occurs because value has type `(MockVec<u8>, MockVec<u8>)`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     let a = &u.x.0;
+   |             +
 
 error[E0382]: use of moved value: `u`
   --> $DIR/union-borrow-move-parent-sibling.rs:64:13
@@ -46,10 +48,12 @@ error[E0507]: cannot move out of dereference of `ManuallyDrop<((MockVec<u8>, Moc
   --> $DIR/union-borrow-move-parent-sibling.rs:76:13
    |
 LL |     let a = (u.x.0).0;
-   |             ^^^^^^^^^
-   |             |
-   |             move occurs because value has type `MockVec<u8>`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&(u.x.0).0`
+   |             ^^^^^^^^^ move occurs because value has type `MockVec<u8>`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     let a = &(u.x.0).0;
+   |             +
 
 error[E0382]: use of moved value: `u`
   --> $DIR/union-borrow-move-parent-sibling.rs:78:13
index 148fb5046705bf6265734a1586f09556bd73a58f..65ff72fe474b18b683e5bdd6f85ac0fdd68b90fb 100644 (file)
@@ -6,9 +6,6 @@ LL | #[derive(Clone)]
    |
 note: required by a bound in `AssertParamIsCopy`
   --> $SRC_DIR/core/src/clone.rs:LL:COL
-   |
-LL | pub struct AssertParamIsCopy<T: Copy + ?Sized> {
-   |                                 ^^^^ required by this bound in `AssertParamIsCopy`
    = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider annotating `U1` with `#[derive(Copy)]`
    |
index 148fb5046705bf6265734a1586f09556bd73a58f..65ff72fe474b18b683e5bdd6f85ac0fdd68b90fb 100644 (file)
@@ -6,9 +6,6 @@ LL | #[derive(Clone)]
    |
 note: required by a bound in `AssertParamIsCopy`
   --> $SRC_DIR/core/src/clone.rs:LL:COL
-   |
-LL | pub struct AssertParamIsCopy<T: Copy + ?Sized> {
-   |                                 ^^^^ required by this bound in `AssertParamIsCopy`
    = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider annotating `U1` with `#[derive(Copy)]`
    |
index 99505f31639686770f8ecfb51ebb5daea54bd266..9e55390b54dbe2751229c317b2a487a47385402b 100644 (file)
@@ -9,9 +9,6 @@ LL |     a: PartialEqNotEq,
    |
 note: required by a bound in `AssertParamIsEq`
   --> $SRC_DIR/core/src/cmp.rs:LL:COL
-   |
-LL | pub struct AssertParamIsEq<T: Eq + ?Sized> {
-   |                               ^^ required by this bound in `AssertParamIsEq`
    = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider annotating `PartialEqNotEq` with `#[derive(Eq)]`
    |
index 99505f31639686770f8ecfb51ebb5daea54bd266..9e55390b54dbe2751229c317b2a487a47385402b 100644 (file)
@@ -9,9 +9,6 @@ LL |     a: PartialEqNotEq,
    |
 note: required by a bound in `AssertParamIsEq`
   --> $SRC_DIR/core/src/cmp.rs:LL:COL
-   |
-LL | pub struct AssertParamIsEq<T: Eq + ?Sized> {
-   |                               ^^ required by this bound in `AssertParamIsEq`
    = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider annotating `PartialEqNotEq` with `#[derive(Eq)]`
    |
index 98a9bd07ed21d0ca5d3bfee529a37cd3c42d9635..db42ed9baf1ed4e3fe6d1655866f02847c37b4d1 100644 (file)
@@ -9,14 +9,10 @@ LL |   trait Foo {
 ...
 LL |       let _z = y.clone();
    |                  ^^^^^ method cannot be called on `Box<dyn Foo>` due to unsatisfied trait bounds
-   |
+  --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
   ::: $SRC_DIR/alloc/src/boxed.rs:LL:COL
    |
-LL | / pub struct Box<
-LL | |     T: ?Sized,
-LL | |     #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
-LL | | >(Unique<T>, A);
-   | |_- doesn't satisfy `Box<dyn Foo>: Clone`
+   = note: doesn't satisfy `Box<dyn Foo>: Clone`
    |
    = note: the following trait bounds were not satisfied:
            `dyn Foo: Sized`
index 7af9c684b72e3b7e3e809085e1b3f53e015a4b5e..de6611324cac137c006a4ff24f9ad56470c9c13b 100644 (file)
@@ -6,14 +6,10 @@ LL |   struct R {
 ...
 LL |       let _j = i.clone();
    |                  ^^^^^ method cannot be called on `Box<R>` due to unsatisfied trait bounds
-   |
+  --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
   ::: $SRC_DIR/alloc/src/boxed.rs:LL:COL
    |
-LL | / pub struct Box<
-LL | |     T: ?Sized,
-LL | |     #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
-LL | | >(Unique<T>, A);
-   | |_- doesn't satisfy `Box<R>: Clone`
+   = note: doesn't satisfy `Box<R>: Clone`
    |
    = note: the following trait bounds were not satisfied:
            `R: Clone`
index d52a92b8888e8dde0ec433d54af6072b6b5be0cd..2a3ca14433f62ffeaec52fb189a016064eda8d35 100644 (file)
@@ -11,9 +11,6 @@ LL |     x.clone();
    |
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
-   |
-LL |     fn not(self) -> Self::Output;
-   |            ^^^^
 help: consider cloning the value if the performance cost is acceptable
    |
 LL |     !x.clone();
@@ -57,9 +54,6 @@ LL |     !*m;
    |
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
-   |
-LL |     fn not(self) -> Self::Output;
-   |            ^^^^
 
 error[E0507]: cannot move out of `*n` which is behind a shared reference
   --> $DIR/unop-move-semantics.rs:26:6
index d8bffd4f9cf3e51f94559b79fcd34feec564898d..9e3c345dd80011636573cd4f6601187545fdf9b1 100644 (file)
@@ -59,7 +59,7 @@ LL |         y.foo();
 LL |         println!("{}", &y);
    |                        ^^ value borrowed here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `y`
+note: `Foo::foo` takes ownership of the receiver `self`, which moves `y`
   --> $DIR/borrow-after-move.rs:5:12
    |
 LL |     fn foo(self) -> String;
index 71534818141caeb3fc06791687887b757dd799ca..49b906bbe02b725c0f9d1e806a470949c55d591a 100644 (file)
@@ -55,7 +55,7 @@ LL |         y.foo();
 LL |         y.foo();
    |         ^ value used here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `y`
+note: `Foo::foo` takes ownership of the receiver `self`, which moves `y`
   --> $DIR/double-move.rs:5:12
    |
 LL |     fn foo(self) -> String;
index 50060e53a49d64fe15b62716e0de51e8545baa98..d7b95f55769fdc600f7b37ff9ec22b43e9844215 100644 (file)
@@ -1,10 +1,8 @@
 error[E0277]: the trait bound `dyn Foo: CastTo<[i32]>` is not satisfied
-  --> $DIR/issue-71659.rs:30:13
+  --> $DIR/issue-71659.rs:30:15
    |
 LL |     let x = x.cast::<[i32]>();
-   |             ^ ---- required by a bound introduced by this call
-   |             |
-   |             the trait `CastTo<[i32]>` is not implemented for `dyn Foo`
+   |               ^^^^ the trait `CastTo<[i32]>` is not implemented for `dyn Foo`
    |
 note: required by a bound in `Cast::cast`
   --> $DIR/issue-71659.rs:19:15
index 7fdc4ab251fe8ad5b2f93102c959ecb7c1f5346a..1bdf49801f975ba72192dfb6d72324d316c04324 100644 (file)
@@ -8,7 +8,7 @@ LL |         self.bar();
 LL |         return self.x;
    |                ^^^^^^ value used here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `self`
+note: `S::bar` takes ownership of the receiver `self`, which moves `self`
   --> $DIR/use-after-move-self-based-on-type.rs:15:16
    |
 LL |     pub fn bar(self) {}
index 073deee63b98c763a35049c2a377af3925f3a5eb..59cc22eadb0153c8bd3903278f649ccdc13ab133 100644 (file)
@@ -8,7 +8,7 @@ LL |         self.bar();
 LL |         return *self.x;
    |                ^^^^^^^ value used here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `self`
+note: `S::bar` takes ownership of the receiver `self`, which moves `self`
   --> $DIR/use-after-move-self.rs:13:16
    |
 LL |     pub fn bar(self) {}
index 4384e345e85c72cbb24ed3e3e68e1f4e8c237fb7..2b85fa9bed480df4bf954d69decde3dfeeb292cf 100644 (file)
@@ -8,7 +8,7 @@ LL |     let end = Mine{other_val:1, ..start.make_string_bar()};
 LL |     println!("{}", start.test);
    |                    ^^^^^^^^^^ value borrowed here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `start`
+note: `Mine::make_string_bar` takes ownership of the receiver `self`, which moves `start`
   --> $DIR/walk-struct-literal-with.rs:7:28
    |
 LL |     fn make_string_bar(mut self) -> Mine{
index b04588c5716150a43ed078d7d2ffc4a968e550b4..7bc19dd2e2162de72de9a84446393042e1c8d63c 100644 (file)
@@ -9,9 +9,6 @@ LL |     type IntoIter = std::iter::Flatten<std::slice::Iter<'a, T>>;
    = note: required for `&T` to implement `IntoIterator`
 note: required by a bound in `Flatten`
   --> $SRC_DIR/core/src/iter/adapters/flatten.rs:LL:COL
-   |
-LL | pub struct Flatten<I: Iterator<Item: IntoIterator>> {
-   |                                      ^^^^^^^^^^^^ required by this bound in `Flatten`
 
 error[E0277]: `&T` is not an iterator
   --> $DIR/hir-wf-check-erase-regions.rs:10:27
@@ -24,9 +21,6 @@ LL |     fn into_iter(self) -> Self::IntoIter {
    = note: required for `&T` to implement `IntoIterator`
 note: required by a bound in `Flatten`
   --> $SRC_DIR/core/src/iter/adapters/flatten.rs:LL:COL
-   |
-LL | pub struct Flatten<I: Iterator<Item: IntoIterator>> {
-   |                                      ^^^^^^^^^^^^ required by this bound in `Flatten`
 
 error: aborting due to 2 previous errors
 
index 371321793adf89f5c54c4cd13534f84376ed96a1..1ca368729fe6fb6b5f57a791801d950df12fa83d 100644 (file)
@@ -7,9 +7,6 @@ LL | impl Foo for Option<[u8]> {}
    = help: the trait `Sized` is not implemented for `[u8]`
 note: required by a bound in `Option`
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL | pub enum Option<T> {
-   |                 ^ required by this bound in `Option`
 
 error: aborting due to previous error
 
index 70898e522116f6c23971e2a554b2dc85fd4c84cd..cc0a320879c17207bbfb96b5d778e28a2c62030d 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 70898e522116f6c23971e2a554b2dc85fd4c84cd
+Subproject commit cc0a320879c17207bbfb96b5d778e28a2c62030d
index 38329659e02b76108ed46d071dd49f38c2a04650..31183266acfcba44236911f54cd37d25113dc8ef 100644 (file)
@@ -1244,7 +1244,7 @@ fn is_mixed_projection_predicate<'tcx>(
         let mut projection_ty = projection_predicate.projection_ty;
         loop {
             match projection_ty.self_ty().kind() {
-                ty::Projection(inner_projection_ty) => {
+                ty::Alias(ty::Projection, inner_projection_ty) => {
                     projection_ty = *inner_projection_ty;
                 }
                 ty::Param(param_ty) => {
@@ -1330,7 +1330,7 @@ fn replace_types<'tcx>(
                     && let Some(term_ty) = projection_predicate.term.ty()
                     && let ty::Param(term_param_ty) = term_ty.kind()
                 {
-                    let item_def_id = projection_predicate.projection_ty.item_def_id;
+                    let item_def_id = projection_predicate.projection_ty.def_id;
                     let assoc_item = cx.tcx.associated_item(item_def_id);
                     let projection = cx.tcx
                         .mk_projection(assoc_item.def_id, cx.tcx.mk_substs_trait(new_ty, []));
@@ -1390,8 +1390,8 @@ fn ty_auto_deref_stability<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, precedenc
                 continue;
             },
             ty::Param(_) => TyPosition::new_deref_stable_for_result(precedence, ty),
-            ty::Projection(_) if ty.has_non_region_param() => TyPosition::new_deref_stable_for_result(precedence, ty),
-            ty::Infer(_) | ty::Error(_) | ty::Bound(..) | ty::Opaque(..) | ty::Placeholder(_) | ty::Dynamic(..) => {
+            ty::Alias(ty::Projection, _) if ty.has_non_region_param() => TyPosition::new_deref_stable_for_result(precedence, ty),
+            ty::Infer(_) | ty::Error(_) | ty::Bound(..) | ty::Alias(ty::Opaque, ..) | ty::Placeholder(_) | ty::Dynamic(..) => {
                 Position::ReborrowStable(precedence).into()
             },
             ty::Adt(..) if ty.has_placeholders() || ty.has_opaque_types() => {
@@ -1417,7 +1417,7 @@ fn ty_auto_deref_stability<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, precedenc
             | ty::Closure(..)
             | ty::Never
             | ty::Tuple(_)
-            | ty::Projection(_) => {
+            | ty::Alias(ty::Projection, _) => {
                 Position::DerefStable(precedence, ty.is_sized(cx.tcx, cx.param_env.without_caller_bounds())).into()
             },
         };
index 9e596ca8157eb93b58fc827d6c4d3eda261a116c..3f0b165f2b604a006e253bf4972c458611599212 100644 (file)
@@ -15,7 +15,7 @@
 use rustc_middle::traits::Reveal;
 use rustc_middle::ty::{
     self, Binder, BoundConstness, Clause, GenericParamDefKind, ImplPolarity, ParamEnv, PredicateKind, TraitPredicate,
-    TraitRef, Ty, TyCtxt,
+    Ty, TyCtxt,
 };
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::source_map::Span;
@@ -513,9 +513,9 @@ fn param_env_for_derived_eq(tcx: TyCtxt<'_>, did: DefId, eq_trait_id: DefId) ->
         tcx.mk_predicates(ty_predicates.iter().map(|&(p, _)| p).chain(
             params.iter().filter(|&&(_, needs_eq)| needs_eq).map(|&(param, _)| {
                 tcx.mk_predicate(Binder::dummy(PredicateKind::Clause(Clause::Trait(TraitPredicate {
-                    trait_ref: TraitRef::new(
+                    trait_ref: tcx.mk_trait_ref(
                         eq_trait_id,
-                        tcx.mk_substs(std::iter::once(tcx.mk_param_from_def(param))),
+                        [tcx.mk_param_from_def(param)],
                     ),
                     constness: BoundConstness::NotConst,
                     polarity: ImplPolarity::Positive,
index 61934a9142633003f805f421ea4f9855451e76f3..989f83cf80d5972301fc06eef9604796f674a7b8 100644 (file)
@@ -4,7 +4,7 @@
 use rustc_hir::{Body, FnDecl, HirId};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::{Clause, EarlyBinder, Opaque, PredicateKind};
+use rustc_middle::ty::{self, AliasTy, Clause, EarlyBinder, PredicateKind};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::{sym, Span};
 use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt;
@@ -62,11 +62,11 @@ fn check_fn(
             return;
         }
         let ret_ty = return_ty(cx, hir_id);
-        if let Opaque(id, subst) = *ret_ty.kind() {
-            let preds = cx.tcx.explicit_item_bounds(id);
+        if let ty::Alias(ty::Opaque, AliasTy { def_id, substs, .. }) = *ret_ty.kind() {
+            let preds = cx.tcx.explicit_item_bounds(def_id);
             let mut is_future = false;
             for &(p, _span) in preds {
-                let p = EarlyBinder(p).subst(cx.tcx, subst);
+                let p = EarlyBinder(p).subst(cx.tcx, substs);
                 if let Some(trait_pred) = p.to_opt_poly_trait_pred() {
                     if Some(trait_pred.skip_binder().trait_ref.def_id) == cx.tcx.lang_items().future_trait() {
                         is_future = true;
index 4c133c06a157ac9e0fcc6ce422bc1c2191404536..73841f9aa9a2112a626dd86e95b34779d90b33ff 100644 (file)
@@ -493,7 +493,7 @@ fn has_is_empty_impl(cx: &LateContext<'_>, id: DefId) -> bool {
                 .filter_by_name_unhygienic(is_empty)
                 .any(|item| is_is_empty(cx, item))
         }),
-        ty::Projection(ref proj) => has_is_empty_impl(cx, proj.item_def_id),
+        ty::Alias(ty::Projection, ref proj) => has_is_empty_impl(cx, proj.def_id),
         ty::Adt(id, _) => has_is_empty_impl(cx, id.did()),
         ty::Array(..) | ty::Slice(..) | ty::Str => true,
         _ => false,
index b088e642e0e9acd258e5e422ce1984d08b06d226..f4d3ef3b742509f40debe7616bb272b7f295f274 100644 (file)
@@ -151,7 +151,7 @@ fn iterates_same_ty<'tcx>(cx: &LateContext<'tcx>, iter_ty: Ty<'tcx>, collect_ty:
         && let Some(into_iter_item_proj) = make_projection(cx.tcx, into_iter_trait, item, [collect_ty])
         && let Ok(into_iter_item_ty) = cx.tcx.try_normalize_erasing_regions(
             cx.param_env,
-            cx.tcx.mk_projection(into_iter_item_proj.item_def_id, into_iter_item_proj.substs)
+            cx.tcx.mk_projection(into_iter_item_proj.def_id, into_iter_item_proj.substs)
         )
     {
         iter_item_ty == into_iter_item_ty
index e053a9dc8881ab2a0cd2adf7eb52bf71436b8d37..8bf542ada04dd80ace50f751c29337d8ecdd71d4 100644 (file)
@@ -82,7 +82,7 @@ fn check_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span) -> McfResult {
             ty::Ref(_, _, hir::Mutability::Mut) => {
                 return Err((span, "mutable references in const fn are unstable".into()));
             },
-            ty::Opaque(..) => return Err((span, "`impl Trait` in const fn is unstable".into())),
+            ty::Alias(ty::Opaque, ..) => return Err((span, "`impl Trait` in const fn is unstable".into())),
             ty::FnPtr(..) => {
                 return Err((span, "function pointers in const fn are unstable".into()));
             },
index bfb2d472a393cf0525955de8f38dce24e0f270b2..a6bcb134d408096099ddd5d13263a68e28688fa1 100644 (file)
@@ -17,7 +17,7 @@
 use rustc_middle::mir::interpret::{ConstValue, Scalar};
 use rustc_middle::ty::{
     self, AdtDef, AssocKind, Binder, BoundRegion, DefIdTree, FnSig, IntTy, List, ParamEnv, Predicate, PredicateKind,
-    ProjectionTy, Region, RegionKind, SubstsRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, UintTy,
+    AliasTy, Region, RegionKind, SubstsRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, UintTy,
     VariantDef, VariantDiscr,
 };
 use rustc_middle::ty::{GenericArg, GenericArgKind};
@@ -79,7 +79,7 @@ pub fn contains_ty_adt_constructor_opaque<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'
                 return true;
             }
 
-            if let ty::Opaque(def_id, _) = *inner_ty.kind() {
+            if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = *inner_ty.kind() {
                 for &(predicate, _span) in cx.tcx.explicit_item_bounds(def_id) {
                     match predicate.kind().skip_binder() {
                         // For `impl Trait<U>`, it will register a predicate of `T: Trait<U>`, so we go through
@@ -250,7 +250,7 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
             is_must_use_ty(cx, *ty)
         },
         ty::Tuple(substs) => substs.iter().any(|ty| is_must_use_ty(cx, ty)),
-        ty::Opaque(def_id, _) => {
+        ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => {
             for (predicate, _) in cx.tcx.explicit_item_bounds(*def_id) {
                 if let ty::PredicateKind::Clause(ty::Clause::Trait(trait_predicate)) = predicate.kind().skip_binder() {
                     if cx.tcx.has_attr(trait_predicate.trait_ref.def_id, sym::must_use) {
@@ -631,7 +631,7 @@ pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<ExprFnSig<'t
             Some(ExprFnSig::Closure(decl, subs.as_closure().sig()))
         },
         ty::FnDef(id, subs) => Some(ExprFnSig::Sig(cx.tcx.bound_fn_sig(id).subst(cx.tcx, subs), Some(id))),
-        ty::Opaque(id, _) => sig_from_bounds(cx, ty, cx.tcx.item_bounds(id), cx.tcx.opt_parent(id)),
+        ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => sig_from_bounds(cx, ty, cx.tcx.item_bounds(def_id), cx.tcx.opt_parent(def_id)),
         ty::FnPtr(sig) => Some(ExprFnSig::Sig(sig, None)),
         ty::Dynamic(bounds, _, _) => {
             let lang_items = cx.tcx.lang_items();
@@ -650,7 +650,7 @@ pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<ExprFnSig<'t
                 _ => None,
             }
         },
-        ty::Projection(proj) => match cx.tcx.try_normalize_erasing_regions(cx.param_env, ty) {
+        ty::Alias(ty::Projection, proj) => match cx.tcx.try_normalize_erasing_regions(cx.param_env, ty) {
             Ok(normalized_ty) if normalized_ty != ty => ty_sig(cx, normalized_ty),
             _ => sig_for_projection(cx, proj).or_else(|| sig_from_bounds(cx, ty, cx.param_env.caller_bounds(), None)),
         },
@@ -685,7 +685,7 @@ fn sig_from_bounds<'tcx>(
                 inputs = Some(i);
             },
             PredicateKind::Clause(ty::Clause::Projection(p))
-                if Some(p.projection_ty.item_def_id) == lang_items.fn_once_output()
+                if Some(p.projection_ty.def_id) == lang_items.fn_once_output()
                     && p.projection_ty.self_ty() == ty =>
             {
                 if output.is_some() {
@@ -701,14 +701,14 @@ fn sig_from_bounds<'tcx>(
     inputs.map(|ty| ExprFnSig::Trait(ty, output, predicates_id))
 }
 
-fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: ProjectionTy<'tcx>) -> Option<ExprFnSig<'tcx>> {
+fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: AliasTy<'tcx>) -> Option<ExprFnSig<'tcx>> {
     let mut inputs = None;
     let mut output = None;
     let lang_items = cx.tcx.lang_items();
 
     for (pred, _) in cx
         .tcx
-        .bound_explicit_item_bounds(ty.item_def_id)
+        .bound_explicit_item_bounds(ty.def_id)
         .subst_iter_copied(cx.tcx, ty.substs)
     {
         match pred.kind().skip_binder() {
@@ -726,7 +726,7 @@ fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: ProjectionTy<'tcx>) -> O
                 inputs = Some(i);
             },
             PredicateKind::Clause(ty::Clause::Projection(p))
-                if Some(p.projection_ty.item_def_id) == lang_items.fn_once_output() =>
+                if Some(p.projection_ty.def_id) == lang_items.fn_once_output() =>
             {
                 if output.is_some() {
                     // Multiple different fn trait impls. Is this even allowed?
@@ -980,13 +980,13 @@ pub fn make_projection<'tcx>(
     container_id: DefId,
     assoc_ty: Symbol,
     substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
-) -> Option<ProjectionTy<'tcx>> {
+) -> Option<AliasTy<'tcx>> {
     fn helper<'tcx>(
         tcx: TyCtxt<'tcx>,
         container_id: DefId,
         assoc_ty: Symbol,
         substs: SubstsRef<'tcx>,
-    ) -> Option<ProjectionTy<'tcx>> {
+    ) -> Option<AliasTy<'tcx>> {
         let Some(assoc_item) = tcx
             .associated_items(container_id)
             .find_by_name_and_kind(tcx, Ident::with_dummy_span(assoc_ty), AssocKind::Type, container_id)
@@ -1039,10 +1039,10 @@ fn helper<'tcx>(
             }
         }
 
-        Some(ProjectionTy {
+        Some(tcx.mk_alias_ty(
+            assoc_item.def_id,
             substs,
-            item_def_id: assoc_item.def_id,
-        })
+        ))
     }
     helper(
         tcx,
@@ -1065,7 +1065,7 @@ pub fn make_normalized_projection<'tcx>(
     assoc_ty: Symbol,
     substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
 ) -> Option<Ty<'tcx>> {
-    fn helper<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: ProjectionTy<'tcx>) -> Option<Ty<'tcx>> {
+    fn helper<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: AliasTy<'tcx>) -> Option<Ty<'tcx>> {
         #[cfg(debug_assertions)]
         if let Some((i, subst)) = ty
             .substs
@@ -1081,7 +1081,7 @@ fn helper<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: ProjectionTy<'
             );
             return None;
         }
-        match tcx.try_normalize_erasing_regions(param_env, tcx.mk_projection(ty.item_def_id, ty.substs)) {
+        match tcx.try_normalize_erasing_regions(param_env, tcx.mk_projection(ty.def_id, ty.substs)) {
             Ok(ty) => Some(ty),
             Err(e) => {
                 debug_assert!(false, "failed to normalize type `{ty}`: {e:#?}");
index 1542b1c17ad112006df87805d19e354b82bd6fc8..72a43108dc480666e595112eb63a92bdf6d144c4 100644 (file)
@@ -1924,7 +1924,15 @@ fn make_compile_args(
                     rustc.args(&["--json", "future-incompat"]);
                 }
                 rustc.arg("-Ccodegen-units=1");
+                // Hide line numbers to reduce churn
                 rustc.arg("-Zui-testing");
+                // Hide libstd sources from ui tests to make sure we generate the stderr
+                // output that users will see.
+                // Without this, we may be producing good diagnostics in-tree but users
+                // will not see half the information.
+                rustc.arg("-Zsimulate-remapped-rust-src-base=/rustc/FAKE_PREFIX");
+                rustc.arg("-Ztranslate-remapped-path-to-local-path=no");
+
                 rustc.arg("-Zdeduplicate-diagnostics=no");
                 // FIXME: use this for other modes too, for perf?
                 rustc.arg("-Cstrip=debuginfo");
index e5b1eb2e4870696691a5f1672ea90f194665a865..ab629e4711b10c0e2ca8e5fec502336575f2ab9a 100644 (file)
@@ -22,8 +22,9 @@
 };
 use rustc_span::def_id::{CrateNum, DefId};
 use rustc_span::Symbol;
-use rustc_target::abi::Size;
+use rustc_target::abi::{Size, Align};
 use rustc_target::spec::abi::Abi;
+use rustc_const_eval::const_eval::CheckAlignment;
 
 use crate::{
     concurrency::{data_race, weak_memory},
@@ -752,8 +753,12 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
     const PANIC_ON_ALLOC_FAIL: bool = false;
 
     #[inline(always)]
-    fn enforce_alignment(ecx: &MiriInterpCx<'mir, 'tcx>) -> bool {
-        ecx.machine.check_alignment != AlignmentCheck::None
+    fn enforce_alignment(ecx: &MiriInterpCx<'mir, 'tcx>) -> CheckAlignment {
+        if ecx.machine.check_alignment == AlignmentCheck::None {
+            CheckAlignment::No
+        } else {
+            CheckAlignment::Error
+        }
     }
 
     #[inline(always)]
@@ -761,6 +766,15 @@ fn use_addr_for_alignment_check(ecx: &MiriInterpCx<'mir, 'tcx>) -> bool {
         ecx.machine.check_alignment == AlignmentCheck::Int
     }
 
+    fn alignment_check_failed(
+        _ecx: &InterpCx<'mir, 'tcx, Self>,
+        has: Align,
+        required: Align,
+        _check: CheckAlignment,
+    ) -> InterpResult<'tcx, ()> {
+        throw_ub!(AlignmentCheckFailed { has, required })
+    }
+
     #[inline(always)]
     fn enforce_validity(ecx: &MiriInterpCx<'mir, 'tcx>) -> bool {
         ecx.machine.validate
index 7ee8c5d3bad1510fe76e701e8c78671ffbb15a9d..75454cbdc5fe6a6f5288adda9f3ebc7399e0ce83 100644 (file)
@@ -57,6 +57,7 @@
     ("cranelift-codegen", "Apache-2.0 WITH LLVM-exception"),
     ("cranelift-codegen-meta", "Apache-2.0 WITH LLVM-exception"),
     ("cranelift-codegen-shared", "Apache-2.0 WITH LLVM-exception"),
+    ("cranelift-egraph", "Apache-2.0 WITH LLVM-exception"),
     ("cranelift-entity", "Apache-2.0 WITH LLVM-exception"),
     ("cranelift-frontend", "Apache-2.0 WITH LLVM-exception"),
     ("cranelift-isle", "Apache-2.0 WITH LLVM-exception"),
@@ -67,6 +68,7 @@
     ("mach", "BSD-2-Clause"),
     ("regalloc2", "Apache-2.0 WITH LLVM-exception"),
     ("target-lexicon", "Apache-2.0 WITH LLVM-exception"),
+    ("wasmtime-jit-icache-coherence", "Apache-2.0 WITH LLVM-exception"),
 ];
 
 const EXCEPTIONS_BOOTSTRAP: &[(&str, &str)] = &[
     "cranelift-codegen",
     "cranelift-codegen-meta",
     "cranelift-codegen-shared",
+    "cranelift-egraph",
     "cranelift-entity",
     "cranelift-frontend",
     "cranelift-isle",
     "cranelift-native",
     "cranelift-object",
     "crc32fast",
+    "fallible-iterator",
     "fxhash",
     "getrandom",
     "gimli",
     "region",
     "slice-group-by",
     "smallvec",
+    "stable_deref_trait",
     "target-lexicon",
     "version_check",
     "wasi",
+    "wasmtime-jit-icache-coherence",
     "winapi",
     "winapi-i686-pc-windows-gnu",
     "winapi-x86_64-pc-windows-gnu",
index 19e8334fc1aa30bf5d753edb1e5b8a94016824e2..46a3bab42a17e21364007d6c5657b206012a99e6 100644 (file)
@@ -467,7 +467,6 @@ compiler-team-contributors = [
     "@compiler-errors",
     "@eholk",
     "@jackh726",
-    "@fee1-dead",
     "@TaKO8Ki",
     "@Nilstrieb",
 ]